22// The .NET Foundation licenses this file to you under the MIT license.
33
44using System ;
5+ using System . Collections . Immutable ;
56using System . Diagnostics ;
67using System . Text . RegularExpressions ;
78using Microsoft . CodeAnalysis ;
@@ -17,7 +18,6 @@ private sealed partial class Emitter
1718 private readonly SourceGenerationSpec _sourceGenSpec ;
1819
1920 private bool _emitBlankLineBeforeNextStatement ;
20- private bool _useFullyQualifiedNames ;
2121 private int _valueSuffixIndex ;
2222
2323 private static readonly Regex s_arrayBracketsRegex = new ( Regex . Escape ( "[]" ) ) ;
@@ -32,7 +32,7 @@ public Emitter(SourceProductionContext context, SourceGenerationSpec sourceGenSp
3232
3333 public void Emit ( )
3434 {
35- if ( ! ShouldEmitBinders ( ) )
35+ if ( ! ShouldEmitBindingExtensions ( ) )
3636 {
3737 return ;
3838 }
@@ -42,17 +42,26 @@ public void Emit()
4242 #nullable enable
4343 #pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
4444 """ ) ;
45- _writer . WriteLine ( ) ;
4645
47- _useFullyQualifiedNames = true ;
48- EmitBinder_Extensions_IConfiguration ( ) ;
49- EmitBinder_Extensions_OptionsBuilder ( ) ;
50- EmitBinder_Extensions_IServiceCollection ( ) ;
46+ EmitInterceptsLocationAttrDecl ( ) ;
47+
48+ EmitStartBlock ( $ "namespace { ProjectName } ") ;
49+ EmitUsingStatements ( ) ;
50+
51+ _writer . WriteLine ( ) ;
52+ EmitStartBlock ( $$ """
53+ {{ Expression . GeneratedCodeAnnotation }}
54+ file static class {{ Identifier . BindingExtensions }}
55+ """ ) ;
56+ EmitBindingExtensions_IConfiguration ( ) ;
57+ EmitBindingExtensions_OptionsBuilder ( ) ;
58+ EmitBindingExtensions_IServiceCollection ( ) ;
59+ EmitCoreBindingHelpers ( ) ;
60+ EmitEndBlock ( ) ; // BindingExtensions class
5161
52- _useFullyQualifiedNames = false ;
53- Emit_CoreBindingHelper ( ) ;
62+ EmitEndBlock ( ) ; // Binding namespace.
5463
55- _context . AddSource ( $ "{ Identifier . GeneratedConfigurationBinder } .g.cs", _writer . ToSourceText ( ) ) ;
64+ _context . AddSource ( $ "{ Identifier . BindingExtensions } .g.cs", _writer . ToSourceText ( ) ) ;
5665 }
5766
5867 private void EmitBindCoreCall (
@@ -74,7 +83,7 @@ private void EmitBindCoreCall(
7483 if ( initKind is InitializationKind . AssignmentWithNullCheck )
7584 {
7685 Debug . Assert ( ! type . IsValueType ) ;
77- _writer . WriteLine ( $ "{ type . MinimalDisplayString } ? { tempIdentifier } = { memberAccessExpr } ;") ;
86+ _writer . WriteLine ( $ "{ type . DisplayString } ? { tempIdentifier } = { memberAccessExpr } ;") ;
7887 EmitBindCoreCall ( tempIdentifier , InitializationKind . AssignmentWithNullCheck ) ;
7988 }
8089 else if ( initKind is InitializationKind . None && type . IsValueType )
@@ -89,9 +98,7 @@ private void EmitBindCoreCall(
8998
9099 void EmitBindCoreCall ( string objExpression , InitializationKind initKind )
91100 {
92- string methodDisplayString = GetHelperMethodDisplayString ( nameof ( MethodsToGen_CoreBindingHelper . BindCore ) ) ;
93- string bindCoreCall = $@ "{ methodDisplayString } ({ configArgExpr } , ref { objExpression } , { Identifier . binderOptions } );";
94-
101+ string bindCoreCall = $@ "{ nameof ( MethodsToGen_CoreBindingHelper . BindCore ) } ({ configArgExpr } , ref { objExpression } , { Identifier . binderOptions } );";
95102 EmitObjectInit ( objExpression , initKind ) ;
96103 _writer . WriteLine ( bindCoreCall ) ;
97104 writeOnSuccess ? . Invoke ( objExpression ) ;
@@ -127,12 +134,11 @@ private void EmitBindLogicFromString(
127134 }
128135 else if ( typeKind is StringParsableTypeKind . Enum )
129136 {
130- parsedValueExpr = $ "ParseEnum<{ type . MinimalDisplayString } >({ stringValueToParse_Expr } , () => { sectionPathExpr } )";
137+ parsedValueExpr = $ "ParseEnum<{ type . DisplayString } >({ stringValueToParse_Expr } , () => { sectionPathExpr } )";
131138 }
132139 else
133140 {
134- string helperMethodDisplayString = GetHelperMethodDisplayString ( type . ParseMethodName ) ;
135- parsedValueExpr = $ "{ helperMethodDisplayString } ({ stringValueToParse_Expr } , () => { sectionPathExpr } )";
141+ parsedValueExpr = $ "{ type . ParseMethodName } ({ stringValueToParse_Expr } , () => { sectionPathExpr } )";
136142 }
137143
138144 if ( ! checkForNullSectionValue )
@@ -156,7 +162,7 @@ private bool EmitObjectInit(TypeSpec type, string memberAccessExpr, Initializati
156162 string initExpr ;
157163 CollectionSpec ? collectionType = type as CollectionSpec ;
158164
159- string effectiveDisplayString = GetTypeDisplayString ( type ) ;
165+ string effectiveDisplayString = type . DisplayString ;
160166 if ( collectionType is not null )
161167 {
162168 if ( collectionType is EnumerableSpec { InitializationStrategy : InitializationStrategy . Array } )
@@ -165,7 +171,7 @@ private bool EmitObjectInit(TypeSpec type, string memberAccessExpr, Initializati
165171 }
166172 else
167173 {
168- effectiveDisplayString = GetTypeDisplayString ( collectionType . ConcreteType ?? collectionType ) ;
174+ effectiveDisplayString = ( collectionType . ConcreteType ?? collectionType ) . DisplayString ;
169175 initExpr = $ "new { effectiveDisplayString } ()";
170176 }
171177 }
@@ -215,36 +221,41 @@ private bool EmitObjectInit(TypeSpec type, string memberAccessExpr, Initializati
215221 return true ;
216222 }
217223
218- private void EmitCastToIConfigurationSection ( )
224+ private void EmitInterceptsLocationAttrDecl ( )
219225 {
220- string sectionTypeDisplayString ;
221- string exceptionTypeDisplayString ;
222- if ( _useFullyQualifiedNames )
223- {
224- sectionTypeDisplayString = "global::Microsoft.Extensions.Configuration.IConfigurationSection" ;
225- exceptionTypeDisplayString = FullyQualifiedDisplayString . InvalidOperationException ;
226- }
227- else
228- {
229- sectionTypeDisplayString = Identifier . IConfigurationSection ;
230- exceptionTypeDisplayString = nameof ( InvalidOperationException ) ;
231- }
232-
226+ _writer . WriteLine ( ) ;
233227 _writer . WriteLine ( $$ """
234- if ( {{ Identifier . configuration }} is not {{ sectionTypeDisplayString }} {{ Identifier . section }} )
228+ namespace System.Runtime.CompilerServices
235229 {
236- throw new {{ exceptionTypeDisplayString }} ();
230+ using System;
231+ using System.CodeDom.Compiler;
232+
233+ {{ Expression . GeneratedCodeAnnotation }}
234+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
235+ file sealed class InterceptsLocationAttribute : Attribute
236+ {
237+ public InterceptsLocationAttribute(string filePath, int line, int column)
238+ {
239+ }
240+ }
237241 }
238242 """ ) ;
243+ _writer . WriteLine ( ) ;
244+ }
245+
246+ private void EmitUsingStatements ( )
247+ {
248+ foreach ( string @namespace in _sourceGenSpec . Namespaces . ToImmutableSortedSet ( ) )
249+ {
250+ _writer . WriteLine ( $ "using { @namespace } ;") ;
251+ }
239252 }
240253
241254 private void EmitIConfigurationHasValueOrChildrenCheck ( bool voidReturn )
242255 {
243256 string returnPostfix = voidReturn ? string . Empty : " null" ;
244- string methodDisplayString = GetHelperMethodDisplayString ( Identifier . HasValueOrChildren ) ;
245-
246257 _writer . WriteLine ( $$ """
247- if (!{{ methodDisplayString }} ({{ Identifier . configuration }} ))
258+ if (!{{ Identifier . HasValueOrChildren }} ({{ Identifier . configuration }} ))
248259 {
249260 return{{ returnPostfix }} ;
250261 }
0 commit comments