Skip to content

Commit

Permalink
Filter list of candidate invocations for parsing in binding generator (
Browse files Browse the repository at this point in the history
…#89266)

Co-authored-by: Layomi Akinrinade <laakinri@microsoft.com>
  • Loading branch information
github-actions[bot] and layomia committed Jul 25, 2023
1 parent 77f7f9e commit 65b696c
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ internal enum MethodsToGen_Extensions_OptionsBuilder
// Method group. BindConfiguration_T is its own method group.
Bind = Bind_T | Bind_T_BinderOptions,

Any = Bind | BindConfiguration_T_path_BinderOptions,
BindConfiguration = BindConfiguration_T_path_BinderOptions,

Any = Bind | BindConfiguration,
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis;
using System.Threading;

namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
Expand All @@ -15,8 +15,9 @@ internal sealed record BinderInvocation

public static BinderInvocation? Create(GeneratorSyntaxContext context, CancellationToken cancellationToken)
{
if (context.Node is not InvocationExpressionSyntax { Expression: MemberAccessExpressionSyntax } invocationSyntax ||
context.SemanticModel.GetOperation(invocationSyntax, cancellationToken) is not IInvocationOperation operation)
if (!IsCandidateInvocationExpressionSyntax(context.Node, out InvocationExpressionSyntax? invocationSyntax) ||
context.SemanticModel.GetOperation(invocationSyntax, cancellationToken) is not IInvocationOperation operation ||
!IsCandidateInvocation(operation))
{
return null;
}
Expand All @@ -27,5 +28,72 @@ internal sealed record BinderInvocation
Location = invocationSyntax.GetLocation()
};
}

private static bool IsCandidateInvocationExpressionSyntax(SyntaxNode node, out InvocationExpressionSyntax? invocationSyntax)
{
if (node is InvocationExpressionSyntax
{
Expression: MemberAccessExpressionSyntax
{
Name.Identifier.ValueText: string memberName
}
} syntax && IsCandidateBindingMethodName(memberName))
{
invocationSyntax = syntax;
return true;
}

invocationSyntax = null;
return false;

static bool IsCandidateBindingMethodName(string name) =>
IsCandidateMethodName_ConfigurationBinder(name) ||
IsCandidateMethodName_OptionsBuilderConfigurationExtensions(name) ||
IsValidMethodName_OptionsConfigurationServiceCollectionExtensions(name);
}

private static bool IsCandidateInvocation(IInvocationOperation operation)
{
if (operation.TargetMethod is not IMethodSymbol
{
IsExtensionMethod: true,
Name: string methodName,
ContainingType: ITypeSymbol
{
Name: string containingTypeName,
ContainingNamespace: INamespaceSymbol { } containingNamespace,
} containingType
} method ||
containingNamespace.ToDisplayString() is not string containingNamespaceName)
{
return false;
}

return (containingTypeName) switch
{
"ConfigurationBinder" =>
containingNamespaceName is "Microsoft.Extensions.Configuration" &&
IsCandidateMethodName_ConfigurationBinder(methodName),
"OptionsBuilderConfigurationExtensions" =>
containingNamespaceName is "Microsoft.Extensions.DependencyInjection" &&
IsCandidateMethodName_OptionsBuilderConfigurationExtensions(methodName),
"OptionsConfigurationServiceCollectionExtensions" =>
containingNamespaceName is "Microsoft.Extensions.DependencyInjection" &&
IsValidMethodName_OptionsConfigurationServiceCollectionExtensions(methodName),
_ => false,
};
}

private static bool IsCandidateMethodName_ConfigurationBinder(string name) => name is
nameof(MethodsToGen_ConfigurationBinder.Bind) or
nameof(MethodsToGen_ConfigurationBinder.Get) or
nameof(MethodsToGen_ConfigurationBinder.GetValue);

private static bool IsCandidateMethodName_OptionsBuilderConfigurationExtensions(string name) => name is
nameof(MethodsToGen_Extensions_OptionsBuilder.Bind) or
nameof(MethodsToGen_Extensions_OptionsBuilder.BindConfiguration);

private static bool IsValidMethodName_OptionsConfigurationServiceCollectionExtensions(string name) => name is
nameof(MethodsToGen_Extensions_ServiceCollection.Configure);
}
}

0 comments on commit 65b696c

Please sign in to comment.