22// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33
44using System ;
5+ using System . Collections . Generic ;
56using System . Collections . Immutable ;
6- using System . Diagnostics ;
77using System . IO ;
88using System . Linq ;
99using Microsoft . AspNetCore . Razor . Language ;
10- using Microsoft . AspNetCore . Razor . PooledObjects ;
1110using Microsoft . CodeAnalysis ;
1211using Microsoft . CodeAnalysis . CSharp ;
13- using Microsoft . CodeAnalysis . CSharp . Syntax ;
1412
1513namespace Microsoft . NET . Sdk . Razor . SourceGenerators
1614{
@@ -68,83 +66,69 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
6866 var generatedDeclarationCode = componentFiles
6967 . Combine ( importFiles . Collect ( ) )
7068 . Combine ( razorSourceGeneratorOptions )
71- . WithLambdaComparer ( ( old , @new ) => ( old . Right . Equals ( @new . Right ) && old . Left . Left . Equals ( @new . Left . Left ) && old . Left . Right . SequenceEqual ( @new . Left . Right ) ) , ( a ) => a . GetHashCode ( ) )
7269 . Select ( static ( pair , _ ) =>
7370 {
7471
7572 var ( ( sourceItem , importFiles ) , razorSourceGeneratorOptions ) = pair ;
76- RazorSourceGeneratorEventSource . Log . GenerateDeclarationCodeStart ( sourceItem . RelativePhysicalPath ) ;
73+ RazorSourceGeneratorEventSource . Log . GenerateDeclarationCodeStart ( sourceItem . FilePath ) ;
7774
7875 var projectEngine = GetDeclarationProjectEngine ( sourceItem , importFiles , razorSourceGeneratorOptions ) ;
7976
8077 var codeGen = projectEngine . Process ( sourceItem ) ;
8178
8279 var result = codeGen . GetCSharpDocument ( ) . GeneratedCode ;
8380
84- RazorSourceGeneratorEventSource . Log . GenerateDeclarationCodeStop ( sourceItem . RelativePhysicalPath ) ;
81+ RazorSourceGeneratorEventSource . Log . GenerateDeclarationCodeStop ( sourceItem . FilePath ) ;
8582
86- return ( result , sourceItem . RelativePhysicalPath ) ;
83+ return result ;
8784 } ) ;
8885
8986 var generatedDeclarationSyntaxTrees = generatedDeclarationCode
9087 . Combine ( parseOptions )
91- . Select ( static ( pair , ct ) =>
88+ . Select ( static ( pair , _ ) =>
9289 {
93- var ( ( generatedDeclarationCode , filePath ) , parseOptions ) = pair ;
94- return CSharpSyntaxTree . ParseText ( generatedDeclarationCode , ( CSharpParseOptions ) parseOptions , filePath , cancellationToken : ct ) ;
90+ var ( generatedDeclarationCode , parseOptions ) = pair ;
91+ return CSharpSyntaxTree . ParseText ( generatedDeclarationCode , ( CSharpParseOptions ) parseOptions ) ;
9592 } ) ;
9693
97- var tagHelpersFromComponents = generatedDeclarationSyntaxTrees
94+ var tagHelpersFromCompilation = compilation
9895 . Combine ( generatedDeclarationSyntaxTrees . Collect ( ) )
99- . Combine ( compilation )
10096 . Combine ( razorSourceGeneratorOptions )
101- . SelectMany ( static ( pair , ct ) =>
97+ . Select ( static ( pair , _ ) =>
10298 {
99+ RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromCompilationStart ( ) ;
103100
104- var ( ( ( generatedDeclarationSyntaxTree , allGeneratedDeclarationSyntaxTrees ) , compilation ) , razorSourceGeneratorOptions ) = pair ;
105- RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromComponentStart ( generatedDeclarationSyntaxTree . FilePath ) ;
101+ var ( ( compilation , generatedDeclarationSyntaxTrees ) , razorSourceGeneratorOptions ) = pair ;
106102
107103 var tagHelperFeature = new StaticCompilationTagHelperFeature ( ) ;
108104 var discoveryProjectEngine = GetDiscoveryProjectEngine ( compilation . References . ToImmutableArray ( ) , tagHelperFeature ) ;
109105
110- var compilationWithDeclarations = compilation . AddSyntaxTrees ( allGeneratedDeclarationSyntaxTrees ) ;
111-
112- // try and find the specific root class this component is declaring, falling back to the assembly if for any reason the code is not in the shape we expect
113- ISymbol targetSymbol = compilationWithDeclarations . Assembly ;
114- var root = generatedDeclarationSyntaxTree . GetRoot ( ct ) ;
115- if ( root is CompilationUnitSyntax { Members : [ NamespaceDeclarationSyntax { Members : [ ClassDeclarationSyntax classSyntax , ..] } , ..] } )
116- {
117- var declaredClass = compilationWithDeclarations . GetSemanticModel ( generatedDeclarationSyntaxTree ) . GetDeclaredSymbol ( classSyntax , ct ) ;
118- Debug . Assert ( declaredClass is null || declaredClass is { AllInterfaces : [ { Name : "IComponent" } , ..] } ) ;
119- targetSymbol = declaredClass ?? targetSymbol ;
120- }
106+ var compilationWithDeclarations = compilation . AddSyntaxTrees ( generatedDeclarationSyntaxTrees ) ;
121107
122108 tagHelperFeature . Compilation = compilationWithDeclarations ;
123- tagHelperFeature . TargetSymbol = targetSymbol ;
109+ tagHelperFeature . TargetSymbol = compilationWithDeclarations . Assembly ;
124110
125- var result = tagHelperFeature . GetDescriptors ( ) ;
126- RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromComponentStop ( generatedDeclarationSyntaxTree . FilePath ) ;
111+ var result = ( IList < TagHelperDescriptor > ) tagHelperFeature . GetDescriptors ( ) ;
112+ RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromCompilationStop ( ) ;
127113 return result ;
128- } ) ;
129-
130- var tagHelpersFromCompilation = compilation
131- . Combine ( razorSourceGeneratorOptions )
132- . Select ( static ( pair , _ ) =>
114+ } )
115+ . WithLambdaComparer ( static ( a , b ) =>
133116 {
134- RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromCompilationStart ( ) ;
135-
136- var ( compilation , razorSourceGeneratorOptions ) = pair ;
137-
138- var tagHelperFeature = new StaticCompilationTagHelperFeature ( ) ;
139- var discoveryProjectEngine = GetDiscoveryProjectEngine ( compilation . References . ToImmutableArray ( ) , tagHelperFeature ) ;
117+ if ( a . Count != b . Count )
118+ {
119+ return false ;
120+ }
140121
141- tagHelperFeature . Compilation = compilation ;
142- tagHelperFeature . TargetSymbol = compilation . Assembly ;
122+ for ( var i = 0 ; i < a . Count ; i ++ )
123+ {
124+ if ( ! a [ i ] . Equals ( b [ i ] ) )
125+ {
126+ return false ;
127+ }
128+ }
143129
144- var result = tagHelperFeature . GetDescriptors ( ) ;
145- RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromCompilationStop ( ) ;
146- return result ;
147- } ) ;
130+ return true ;
131+ } , getHashCode : static a => a . Count ) ;
148132
149133 var tagHelpersFromReferences = compilation
150134 . Combine ( razorSourceGeneratorOptions )
@@ -187,7 +171,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
187171 var tagHelperFeature = new StaticCompilationTagHelperFeature ( ) ;
188172 var discoveryProjectEngine = GetDiscoveryProjectEngine ( compilation . References . ToImmutableArray ( ) , tagHelperFeature ) ;
189173
190- using var pool = ArrayBuilderPool < TagHelperDescriptor > . GetPooledObject ( out var descriptors ) ;
174+ List < TagHelperDescriptor > descriptors = new ( ) ;
191175 tagHelperFeature . Compilation = compilation ;
192176 foreach ( var reference in compilation . References )
193177 {
@@ -199,84 +183,47 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
199183 }
200184
201185 RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromReferencesStop ( ) ;
202- return descriptors . ToImmutable ( ) ;
186+ return ( ICollection < TagHelperDescriptor > ) descriptors ;
203187 } ) ;
204188
205- var allTagHelpers = tagHelpersFromComponents . Collect ( )
206- . Combine ( tagHelpersFromCompilation )
189+ var allTagHelpers = tagHelpersFromCompilation
207190 . Combine ( tagHelpersFromReferences )
208191 . Select ( static ( pair , _ ) =>
209192 {
210- var ( ( tagHelpersFromComponents , tagHelpersFromCompilation ) , tagHelpersFromReferences ) = pair ;
211- var count = tagHelpersFromCompilation . Length + tagHelpersFromReferences . Length + tagHelpersFromComponents . Length ;
193+ var ( tagHelpersFromCompilation , tagHelpersFromReferences ) = pair ;
194+ var count = tagHelpersFromCompilation . Count + tagHelpersFromReferences . Count ;
212195 if ( count == 0 )
213196 {
214- return ImmutableArray < TagHelperDescriptor > . Empty ;
197+ return Array . Empty < TagHelperDescriptor > ( ) ;
215198 }
216199
217- using var pool = ArrayBuilderPool < TagHelperDescriptor > . GetPooledObject ( out var allTagHelpers ) ;
218- allTagHelpers . AddRange ( tagHelpersFromCompilation ) ;
219- allTagHelpers . AddRange ( tagHelpersFromReferences ) ;
220- allTagHelpers . AddRange ( tagHelpersFromComponents ) ;
200+ var allTagHelpers = new TagHelperDescriptor [ count ] ;
201+ tagHelpersFromCompilation . CopyTo ( allTagHelpers , 0 ) ;
202+ tagHelpersFromReferences . CopyTo ( allTagHelpers , tagHelpersFromCompilation . Count ) ;
221203
222- return allTagHelpers . ToImmutable ( ) ;
204+ return allTagHelpers ;
223205 } ) ;
224206
225207 var generatedOutput = sourceItems
226208 . Combine ( importFiles . Collect ( ) )
227- . WithLambdaComparer ( ( old , @new ) => old . Left . Equals ( @new . Left ) && old . Right . SequenceEqual ( @new . Right ) , ( a ) => a . GetHashCode ( ) )
209+ . Combine ( allTagHelpers )
228210 . Combine ( razorSourceGeneratorOptions )
229211 . Select ( static ( pair , _ ) =>
230212 {
231- var ( ( sourceItem , imports ) , razorSourceGeneratorOptions ) = pair ;
232-
233- RazorSourceGeneratorEventSource . Log . ParseRazorDocumentStart ( sourceItem . RelativePhysicalPath ) ;
234-
235- var projectEngine = GetGenerationProjectEngine ( sourceItem , imports , razorSourceGeneratorOptions ) ;
236-
237- var document = projectEngine . ProcessInitialParse ( sourceItem ) ;
238-
239- RazorSourceGeneratorEventSource . Log . ParseRazorDocumentStop ( sourceItem . RelativePhysicalPath ) ;
240- return ( projectEngine , sourceItem . RelativePhysicalPath , document ) ;
241- } )
242-
243- // Add the tag helpers in, but ignore if they've changed or not, only reprocessing the actual document changed
244- . Combine ( allTagHelpers )
245- . WithLambdaComparer ( ( old , @new ) => old . Left . Equals ( @new . Left ) , ( item ) => item . GetHashCode ( ) )
246- . Select ( ( pair , _ ) =>
247- {
248- var ( ( projectEngine , filePath , codeDocument ) , allTagHelpers ) = pair ;
249- RazorSourceGeneratorEventSource . Log . RewriteTagHelpersStart ( filePath ) ;
213+ var ( ( ( sourceItem , imports ) , allTagHelpers ) , razorSourceGeneratorOptions ) = pair ;
250214
251- codeDocument = projectEngine . ProcessTagHelpers ( codeDocument , allTagHelpers , checkForIdempotency : false ) ;
215+ RazorSourceGeneratorEventSource . Log . RazorCodeGenerateStart ( sourceItem . FilePath ) ;
252216
253- RazorSourceGeneratorEventSource . Log . RewriteTagHelpersStop ( filePath ) ;
254- return ( projectEngine , filePath , codeDocument ) ;
255- } )
256-
257- // next we do a second parse, along with the helpers, but check for idempotency. If the tag helpers used on the previous parse match, the compiler can skip re-computing them
258- . Combine ( allTagHelpers )
259- . Select ( ( pair , _ ) =>
260- {
217+ // Add a generated suffix so tools, such as coverlet, consider the file to be generated
218+ var hintName = GetIdentifierFromPath ( sourceItem . RelativePhysicalPath ) + ".g.cs" ;
261219
262- var ( ( projectEngine , filePath , document ) , allTagHelpers ) = pair ;
263- RazorSourceGeneratorEventSource . Log . CheckAndRewriteTagHelpersStart ( filePath ) ;
220+ var projectEngine = GetGenerationProjectEngine ( allTagHelpers , sourceItem , imports , razorSourceGeneratorOptions ) ;
264221
265- document = projectEngine . ProcessTagHelpers ( document , allTagHelpers , checkForIdempotency : true ) ;
222+ var codeDocument = projectEngine . Process ( sourceItem ) ;
223+ var csharpDocument = codeDocument . GetCSharpDocument ( ) ;
266224
267- RazorSourceGeneratorEventSource . Log . CheckAndRewriteTagHelpersStop ( filePath ) ;
268- return ( projectEngine , filePath , document ) ;
269- } )
270-
271- . Select ( ( pair , _ ) =>
272- {
273- var ( projectEngine , filePath , document ) = pair ;
274- RazorSourceGeneratorEventSource . Log . RazorCodeGenerateStart ( filePath ) ;
275- document = projectEngine . ProcessRemaining ( document ) ;
276- var csharpDocument = document . CodeDocument . GetCSharpDocument ( ) ;
277-
278- RazorSourceGeneratorEventSource . Log . RazorCodeGenerateStop ( filePath ) ;
279- return ( filePath , csharpDocument ) ;
225+ RazorSourceGeneratorEventSource . Log . RazorCodeGenerateStop ( sourceItem . FilePath ) ;
226+ return ( hintName , csharpDocument ) ;
280227 } )
281228 . WithLambdaComparer ( static ( a , b ) =>
282229 {
@@ -291,11 +238,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
291238
292239 context . RegisterSourceOutput ( generatedOutput , static ( context , pair ) =>
293240 {
294- var ( filePath , csharpDocument ) = pair ;
295-
296- // Add a generated suffix so tools, such as coverlet, consider the file to be generated
297- var hintName = GetIdentifierFromPath ( filePath ) + ".g.cs" ;
298-
241+ var ( hintName , csharpDocument ) = pair ;
299242 RazorSourceGeneratorEventSource . Log . AddSyntaxTrees ( hintName ) ;
300243 for ( var i = 0 ; i < csharpDocument . Diagnostics . Count ; i ++ )
301244 {
0 commit comments