Skip to content

Commit 65b696c

Browse files
Filter list of candidate invocations for parsing in binding generator (#89266)
Co-authored-by: Layomi Akinrinade <[email protected]>
1 parent 77f7f9e commit 65b696c

File tree

2 files changed

+74
-4
lines changed

2 files changed

+74
-4
lines changed

src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/MethodsToGen.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ internal enum MethodsToGen_Extensions_OptionsBuilder
111111
// Method group. BindConfiguration_T is its own method group.
112112
Bind = Bind_T | Bind_T_BinderOptions,
113113

114-
Any = Bind | BindConfiguration_T_path_BinderOptions,
114+
BindConfiguration = BindConfiguration_T_path_BinderOptions,
115+
116+
Any = Bind | BindConfiguration,
115117
}
116118

117119
/// <summary>

src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/BinderInvocation.cs

+71-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Threading;
45
using Microsoft.CodeAnalysis.CSharp.Syntax;
56
using Microsoft.CodeAnalysis.Operations;
67
using Microsoft.CodeAnalysis;
7-
using System.Threading;
88

99
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
1010
{
@@ -15,8 +15,9 @@ internal sealed record BinderInvocation
1515

1616
public static BinderInvocation? Create(GeneratorSyntaxContext context, CancellationToken cancellationToken)
1717
{
18-
if (context.Node is not InvocationExpressionSyntax { Expression: MemberAccessExpressionSyntax } invocationSyntax ||
19-
context.SemanticModel.GetOperation(invocationSyntax, cancellationToken) is not IInvocationOperation operation)
18+
if (!IsCandidateInvocationExpressionSyntax(context.Node, out InvocationExpressionSyntax? invocationSyntax) ||
19+
context.SemanticModel.GetOperation(invocationSyntax, cancellationToken) is not IInvocationOperation operation ||
20+
!IsCandidateInvocation(operation))
2021
{
2122
return null;
2223
}
@@ -27,5 +28,72 @@ internal sealed record BinderInvocation
2728
Location = invocationSyntax.GetLocation()
2829
};
2930
}
31+
32+
private static bool IsCandidateInvocationExpressionSyntax(SyntaxNode node, out InvocationExpressionSyntax? invocationSyntax)
33+
{
34+
if (node is InvocationExpressionSyntax
35+
{
36+
Expression: MemberAccessExpressionSyntax
37+
{
38+
Name.Identifier.ValueText: string memberName
39+
}
40+
} syntax && IsCandidateBindingMethodName(memberName))
41+
{
42+
invocationSyntax = syntax;
43+
return true;
44+
}
45+
46+
invocationSyntax = null;
47+
return false;
48+
49+
static bool IsCandidateBindingMethodName(string name) =>
50+
IsCandidateMethodName_ConfigurationBinder(name) ||
51+
IsCandidateMethodName_OptionsBuilderConfigurationExtensions(name) ||
52+
IsValidMethodName_OptionsConfigurationServiceCollectionExtensions(name);
53+
}
54+
55+
private static bool IsCandidateInvocation(IInvocationOperation operation)
56+
{
57+
if (operation.TargetMethod is not IMethodSymbol
58+
{
59+
IsExtensionMethod: true,
60+
Name: string methodName,
61+
ContainingType: ITypeSymbol
62+
{
63+
Name: string containingTypeName,
64+
ContainingNamespace: INamespaceSymbol { } containingNamespace,
65+
} containingType
66+
} method ||
67+
containingNamespace.ToDisplayString() is not string containingNamespaceName)
68+
{
69+
return false;
70+
}
71+
72+
return (containingTypeName) switch
73+
{
74+
"ConfigurationBinder" =>
75+
containingNamespaceName is "Microsoft.Extensions.Configuration" &&
76+
IsCandidateMethodName_ConfigurationBinder(methodName),
77+
"OptionsBuilderConfigurationExtensions" =>
78+
containingNamespaceName is "Microsoft.Extensions.DependencyInjection" &&
79+
IsCandidateMethodName_OptionsBuilderConfigurationExtensions(methodName),
80+
"OptionsConfigurationServiceCollectionExtensions" =>
81+
containingNamespaceName is "Microsoft.Extensions.DependencyInjection" &&
82+
IsValidMethodName_OptionsConfigurationServiceCollectionExtensions(methodName),
83+
_ => false,
84+
};
85+
}
86+
87+
private static bool IsCandidateMethodName_ConfigurationBinder(string name) => name is
88+
nameof(MethodsToGen_ConfigurationBinder.Bind) or
89+
nameof(MethodsToGen_ConfigurationBinder.Get) or
90+
nameof(MethodsToGen_ConfigurationBinder.GetValue);
91+
92+
private static bool IsCandidateMethodName_OptionsBuilderConfigurationExtensions(string name) => name is
93+
nameof(MethodsToGen_Extensions_OptionsBuilder.Bind) or
94+
nameof(MethodsToGen_Extensions_OptionsBuilder.BindConfiguration);
95+
96+
private static bool IsValidMethodName_OptionsConfigurationServiceCollectionExtensions(string name) => name is
97+
nameof(MethodsToGen_Extensions_ServiceCollection.Configure);
3098
}
3199
}

0 commit comments

Comments
 (0)