| File: Parser\OptionsBuilderConfigurationExtensions.cs | Web Access |
| Project: src\runtime\src\libraries\Microsoft.Extensions.Configuration.Binder\gen\Microsoft.Extensions.Configuration.Binder.SourceGeneration.csproj (Microsoft.Extensions.Configuration.Binder.SourceGeneration) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { public sealed partial class ConfigurationBindingGenerator { internal sealed partial class Parser { private void ParseInvocation_OptionsBuilderExt(BinderInvocation invocation) { IMethodSymbol targetMethod = invocation.Operation.TargetMethod; ImmutableArray<IParameterSymbol> @params = targetMethod.Parameters; if (!targetMethod.IsGenericMethod || @params.Length < 2 || @params[0].Type is not INamedTypeSymbol { IsGenericType: true } genericType || !SymbolEqualityComparer.Default.Equals(_typeSymbols.OptionsBuilderOfT_Unbound, genericType.ConstructUnboundGenericType())) { return; } ITypeSymbol? typeSymbol = targetMethod.TypeArguments[0].WithNullableAnnotation(NullableAnnotation.None); // This would violate generic type constraint; any such invocation could not have been included in the initial parser. Debug.Assert(typeSymbol?.IsValueType is not true); if (targetMethod.Name is "Bind") { ParseBindInvocation_OptionsBuilderExt(invocation, typeSymbol); } else if (targetMethod.Name is "BindConfiguration") { ParseBindConfigurationInvocation(invocation, typeSymbol); } } private void ParseBindInvocation_OptionsBuilderExt(BinderInvocation invocation, ITypeSymbol? type) { IInvocationOperation operation = invocation.Operation!; IMethodSymbol targetMethod = operation.TargetMethod; ImmutableArray<IParameterSymbol> @params = targetMethod.Parameters; int paramCount = @params.Length; Debug.Assert(paramCount >= 2); if (!SymbolEqualityComparer.Default.Equals(_typeSymbols.IConfiguration, @params[1].Type)) { return; } MethodsToGen overload = paramCount switch { 2 => MethodsToGen.OptionsBuilderExt_Bind_T, 3 when SymbolEqualityComparer.Default.Equals(_typeSymbols.ActionOfBinderOptions, @params[2].Type) => MethodsToGen.OptionsBuilderExt_Bind_T_BinderOptions, _ => MethodsToGen.None }; if (overload is not MethodsToGen.None) { EnqueueTargetTypeForRootInvocation(type, overload, invocation); } } private void ParseBindConfigurationInvocation(BinderInvocation invocation, ITypeSymbol? type) { IMethodSymbol targetMethod = invocation.Operation.TargetMethod; ImmutableArray<IParameterSymbol> @params = targetMethod.Parameters; int paramCount = @params.Length; Debug.Assert(paramCount >= 2); if (paramCount is 3 && @params[1].Type.SpecialType is SpecialType.System_String && SymbolEqualityComparer.Default.Equals(_typeSymbols.ActionOfBinderOptions, @params[2].Type)) { EnqueueTargetTypeForRootInvocation(type, MethodsToGen.OptionsBuilderExt_BindConfiguration_T_path_BinderOptions, invocation); } } private void RegisterInterceptor_OptionsBuilderExt(TypeParseInfo typeParseInfo, TypeSpec typeSpec) { MethodsToGen overload = typeParseInfo.BindingOverload; Debug.Assert((MethodsToGen.OptionsBuilderExt_Any & overload) is not 0); if (typeSpec is not ComplexTypeSpec complexTypeSpec) { return; } if ((MethodsToGen.OptionsBuilderExt_Bind & overload) is not 0) { if (!TryRegisterTypeForOverloadGen_ServiceCollectionExt(MethodsToGen.ServiceCollectionExt_Configure_T_name_BinderOptions, complexTypeSpec)) { return; } } else if (!_helperInfoBuilder!.TryRegisterTypeForBindCoreMainGen(complexTypeSpec)) { return; } _interceptorInfoBuilder.RegisterInterceptor(typeParseInfo.BindingOverload, typeParseInfo.BinderInvocation.Operation); // Emitting refs to IOptionsChangeTokenSource, ConfigurationChangeTokenSource. _helperInfoBuilder!.RegisterNamespace("Microsoft.Extensions.Options"); // Emitting refs to OptionsBuilder<T>. _helperInfoBuilder!.RegisterNamespace("Microsoft.Extensions.DependencyInjection"); } } } }