Repository: dotnet/roslyn
File: src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/CollectionExpressionUtilities.cs (C#)

Code before:
    {
        var readonlySpanOfTType = compilation.ReadOnlySpanOfTType();
        var attribute = collectionExpressionType.GetAttributes().FirstOrDefault(
            static a => a.AttributeClass.IsCollectionBuilderAttribute());

        // https://github.com/dotnet/csharplang/blob/main/proposals/collection-expression-arguments.md#create-method-candidates
        // A [CollectionBuilder(...)] attribute specifies the builder type and method name of a method to be invoked to
        // construct an instance of the collection type.
        if (attribute is not { ConstructorArguments: [{ Value: INamedTypeSymbol builderType }, { Value: string builderMethodName }] })
            return null;

        // Find all the static methods in the builder type with the given name that have a ReadOnlySpan<T> as their last
        // parameter, matching the arity of the returned collection type.  Then construct the construction method if
        // generic. And filter to only those that return the collection type being created.

        var builderMethods = builderType
            .GetMembers(builderMethodName)
            .OfType<IMethodSymbol>()
            .Where(m =>
                m.IsStatic &&
                m.Arity == collectionExpressionType.Arity &&
                m.Parameters is [.., var lastParameter] &&
                Equals(lastParameter.Type.OriginalDefinition, readonlySpanOfTType))
            .Select(m => m.Arity == 0 ? m : m.Construct(ImmutableCollectionsMarshal.AsArray(collectionExpressionType.TypeArguments)!))
            .Where(m => compilation.ClassifyCommonConversion(m.ReturnType, collectionExpressionType).IsIdentityOrImplicitReference());

        return [.. builderMethods];
    }
}


Review comment (suggestion):
1. this code was written at the time when we didn't know if `with(...)` would require the ROS at the start or end of the factory method.  We concluded in ldm/spec that the ROS had to be at the end.
2. avoided intermediary immutable array.

Code after:
    /// Gets the collection builder factory methods for the given collection expression type, if any.  Or <see
    /// langword="null"/> if the type does not have a valid <see cref="CollectionBuilderAttribute"/> that can be
    /// resolved.  The returned methods are guaranteed to match the language rules about what a factory method
    /// must look like.  That means, at a minimum:
    /// <list type="number">
    /// <item>they must be static</item>
    /// <item>their <see cref="IMethodSymbol.Arity"/> must match that of <paramref
    /// name="collectionExpressionType"/></item>
    /// <item>They must have a final parameter that is the <see cref="ReadOnlySpan{T}"/> containing the elements of the
    /// collection</item>
    /// </list>
    /// 
    /// Generic factory methods will be appropriately constructed to match the type arguments of <paramref
    /// name="collectionExpressionType"/>.
    /// </summary>
    public static ImmutableArray<IMethodSymbol>? TryGetCollectionBuilderFactoryMethods(
        Compilation compilation, INamedTypeSymbol collectionExpressionType)
    {
        var readonlySpanOfTType = compilation.ReadOnlySpanOfTType();
        var attribute = collectionExpressionType.GetAttributes().FirstOrDefault(
            static a => a.AttributeClass.IsCollectionBuilderAttribute());

        // https://github.com/dotnet/csharplang/blob/main/proposals/collection-expression-arguments.md#create-method-candidates
        // A [CollectionBuilder(...)] attribute specifies the builder type and method name of a method to be invoked to
        // construct an instance of the collection type.
        if (attribute is not { ConstructorArguments: [{ Value: INamedTypeSymbol builderType }, { Value: string builderMethodName }] })
            return null;

        // Find all the static methods in the builder type with the given name that have a ReadOnlySpan<T> as their last
        // parameter, matching the arity of the returned collection type.  Then construct the construction method if
        // generic. And filter to only those that return the collection type being created.

        var builderMethods = builderType
            .GetMembers(builderMethodName)
            .OfType<IMethodSymbol>()
            .Where(m =>
                m.IsStatic &&
                m.Arity == collectionExpressionType.Arity &&
                m.Parameters is [.., var lastParameter] &&
                Equals(lastParameter.Type.OriginalDefinition, readonlySpanOfTType))
            .Select(m => m.Arity == 0 ? m : m.Construct(ImmutableCollectionsMarshal.AsArray(collectionExpressionType.TypeArguments)!))
            .Where(m => compilation.ClassifyCommonConversion(m.ReturnType, collectionExpressionType).IsIdentityOrImplicitReference());

        return [.. builderMethods];
    }
}