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,82 +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
98- . Combine ( compilation )
94+ var tagHelpersFromCompilation = compilation
95+ . Combine ( generatedDeclarationSyntaxTrees . Collect ( ) )
9996 . Combine ( razorSourceGeneratorOptions )
100- . SelectMany ( static ( pair , ct ) =>
97+ . Select ( static ( pair , _ ) =>
10198 {
99+ RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromCompilationStart ( ) ;
102100
103- var ( ( generatedDeclarationSyntaxTree , compilation ) , razorSourceGeneratorOptions ) = pair ;
104- RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromComponentStart ( generatedDeclarationSyntaxTree . FilePath ) ;
101+ var ( ( compilation , generatedDeclarationSyntaxTrees ) , razorSourceGeneratorOptions ) = pair ;
105102
106103 var tagHelperFeature = new StaticCompilationTagHelperFeature ( ) ;
107104 var discoveryProjectEngine = GetDiscoveryProjectEngine ( compilation . References . ToImmutableArray ( ) , tagHelperFeature ) ;
108105
109- var compilationWithDeclarations = compilation . AddSyntaxTrees ( generatedDeclarationSyntaxTree ) ;
110-
111- // 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
112- ISymbol targetSymbol = compilationWithDeclarations . Assembly ;
113- var root = generatedDeclarationSyntaxTree . GetRoot ( ct ) ;
114- if ( root is CompilationUnitSyntax { Members : [ NamespaceDeclarationSyntax { Members : [ ClassDeclarationSyntax classSyntax , ..] } , ..] } )
115- {
116- var declaredClass = compilationWithDeclarations . GetSemanticModel ( generatedDeclarationSyntaxTree ) . GetDeclaredSymbol ( classSyntax , ct ) ;
117- Debug . Assert ( declaredClass is null || declaredClass is { AllInterfaces : [ { Name : "IComponent" } , ..] } ) ;
118- targetSymbol = declaredClass ?? targetSymbol ;
119- }
106+ var compilationWithDeclarations = compilation . AddSyntaxTrees ( generatedDeclarationSyntaxTrees ) ;
120107
121108 tagHelperFeature . Compilation = compilationWithDeclarations ;
122- tagHelperFeature . TargetSymbol = targetSymbol ;
109+ tagHelperFeature . TargetSymbol = compilationWithDeclarations . Assembly ;
123110
124- var result = tagHelperFeature . GetDescriptors ( ) ;
125- RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromComponentStop ( generatedDeclarationSyntaxTree . FilePath ) ;
111+ var result = ( IList < TagHelperDescriptor > ) tagHelperFeature . GetDescriptors ( ) ;
112+ RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromCompilationStop ( ) ;
126113 return result ;
127- } ) ;
128-
129- var tagHelpersFromCompilation = compilation
130- . Combine ( razorSourceGeneratorOptions )
131- . Select ( static ( pair , _ ) =>
114+ } )
115+ . WithLambdaComparer ( static ( a , b ) =>
132116 {
133- RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromCompilationStart ( ) ;
134-
135- var ( compilation , razorSourceGeneratorOptions ) = pair ;
136-
137- var tagHelperFeature = new StaticCompilationTagHelperFeature ( ) ;
138- var discoveryProjectEngine = GetDiscoveryProjectEngine ( compilation . References . ToImmutableArray ( ) , tagHelperFeature ) ;
117+ if ( a . Count != b . Count )
118+ {
119+ return false ;
120+ }
139121
140- tagHelperFeature . Compilation = compilation ;
141- 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+ }
142129
143- var result = tagHelperFeature . GetDescriptors ( ) ;
144- RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromCompilationStop ( ) ;
145- return result ;
146- } ) ;
130+ return true ;
131+ } , getHashCode : static a => a . Count ) ;
147132
148133 var tagHelpersFromReferences = compilation
149134 . Combine ( razorSourceGeneratorOptions )
@@ -186,7 +171,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
186171 var tagHelperFeature = new StaticCompilationTagHelperFeature ( ) ;
187172 var discoveryProjectEngine = GetDiscoveryProjectEngine ( compilation . References . ToImmutableArray ( ) , tagHelperFeature ) ;
188173
189- using var pool = ArrayBuilderPool < TagHelperDescriptor > . GetPooledObject ( out var descriptors ) ;
174+ List < TagHelperDescriptor > descriptors = new ( ) ;
190175 tagHelperFeature . Compilation = compilation ;
191176 foreach ( var reference in compilation . References )
192177 {
@@ -198,84 +183,47 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
198183 }
199184
200185 RazorSourceGeneratorEventSource . Log . DiscoverTagHelpersFromReferencesStop ( ) ;
201- return descriptors . ToImmutable ( ) ;
186+ return ( ICollection < TagHelperDescriptor > ) descriptors ;
202187 } ) ;
203188
204- var allTagHelpers = tagHelpersFromComponents . Collect ( )
205- . Combine ( tagHelpersFromCompilation )
189+ var allTagHelpers = tagHelpersFromCompilation
206190 . Combine ( tagHelpersFromReferences )
207191 . Select ( static ( pair , _ ) =>
208192 {
209- var ( ( tagHelpersFromComponents , tagHelpersFromCompilation ) , tagHelpersFromReferences ) = pair ;
210- var count = tagHelpersFromCompilation . Length + tagHelpersFromReferences . Length + tagHelpersFromComponents . Length ;
193+ var ( tagHelpersFromCompilation , tagHelpersFromReferences ) = pair ;
194+ var count = tagHelpersFromCompilation . Count + tagHelpersFromReferences . Count ;
211195 if ( count == 0 )
212196 {
213- return ImmutableArray < TagHelperDescriptor > . Empty ;
197+ return Array . Empty < TagHelperDescriptor > ( ) ;
214198 }
215199
216- using var pool = ArrayBuilderPool < TagHelperDescriptor > . GetPooledObject ( out var allTagHelpers ) ;
217- allTagHelpers . AddRange ( tagHelpersFromCompilation ) ;
218- allTagHelpers . AddRange ( tagHelpersFromReferences ) ;
219- allTagHelpers . AddRange ( tagHelpersFromComponents ) ;
200+ var allTagHelpers = new TagHelperDescriptor [ count ] ;
201+ tagHelpersFromCompilation . CopyTo ( allTagHelpers , 0 ) ;
202+ tagHelpersFromReferences . CopyTo ( allTagHelpers , tagHelpersFromCompilation . Count ) ;
220203
221- return allTagHelpers . ToImmutable ( ) ;
204+ return allTagHelpers ;
222205 } ) ;
223206
224207 var generatedOutput = sourceItems
225208 . Combine ( importFiles . Collect ( ) )
226- . WithLambdaComparer ( ( old , @new ) => old . Left . Equals ( @new . Left ) && old . Right . SequenceEqual ( @new . Right ) , ( a ) => a . GetHashCode ( ) )
209+ . Combine ( allTagHelpers )
227210 . Combine ( razorSourceGeneratorOptions )
228211 . Select ( static ( pair , _ ) =>
229212 {
230- var ( ( sourceItem , imports ) , razorSourceGeneratorOptions ) = pair ;
231-
232- RazorSourceGeneratorEventSource . Log . ParseRazorDocumentStart ( sourceItem . RelativePhysicalPath ) ;
233-
234- var projectEngine = GetGenerationProjectEngine ( sourceItem , imports , razorSourceGeneratorOptions ) ;
235-
236- var document = projectEngine . ProcessInitialParse ( sourceItem ) ;
237-
238- RazorSourceGeneratorEventSource . Log . ParseRazorDocumentStop ( sourceItem . RelativePhysicalPath ) ;
239- return ( projectEngine , sourceItem . RelativePhysicalPath , document ) ;
240- } )
241-
242- // Add the tag helpers in, but ignore if they've changed or not, only reprocessing the actual document changed
243- . Combine ( allTagHelpers )
244- . WithLambdaComparer ( ( old , @new ) => old . Left . Equals ( @new . Left ) , ( item ) => item . GetHashCode ( ) )
245- . Select ( ( pair , _ ) =>
246- {
247- var ( ( projectEngine , filePath , codeDocument ) , allTagHelpers ) = pair ;
248- RazorSourceGeneratorEventSource . Log . RewriteTagHelpersStart ( filePath ) ;
213+ var ( ( ( sourceItem , imports ) , allTagHelpers ) , razorSourceGeneratorOptions ) = pair ;
249214
250- codeDocument = projectEngine . ProcessTagHelpers ( codeDocument , allTagHelpers , checkForIdempotency : false ) ;
215+ RazorSourceGeneratorEventSource . Log . RazorCodeGenerateStart ( sourceItem . FilePath ) ;
251216
252- RazorSourceGeneratorEventSource . Log . RewriteTagHelpersStop ( filePath ) ;
253- return ( projectEngine , filePath , codeDocument ) ;
254- } )
255-
256- // 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
257- . Combine ( allTagHelpers )
258- . Select ( ( pair , _ ) =>
259- {
217+ // Add a generated suffix so tools, such as coverlet, consider the file to be generated
218+ var hintName = GetIdentifierFromPath ( sourceItem . RelativePhysicalPath ) + ".g.cs" ;
260219
261- var ( ( projectEngine , filePath , document ) , allTagHelpers ) = pair ;
262- RazorSourceGeneratorEventSource . Log . CheckAndRewriteTagHelpersStart ( filePath ) ;
220+ var projectEngine = GetGenerationProjectEngine ( allTagHelpers , sourceItem , imports , razorSourceGeneratorOptions ) ;
263221
264- document = projectEngine . ProcessTagHelpers ( document , allTagHelpers , checkForIdempotency : true ) ;
222+ var codeDocument = projectEngine . Process ( sourceItem ) ;
223+ var csharpDocument = codeDocument . GetCSharpDocument ( ) ;
265224
266- RazorSourceGeneratorEventSource . Log . CheckAndRewriteTagHelpersStop ( filePath ) ;
267- return ( projectEngine , filePath , document ) ;
268- } )
269-
270- . Select ( ( pair , _ ) =>
271- {
272- var ( projectEngine , filePath , document ) = pair ;
273- RazorSourceGeneratorEventSource . Log . RazorCodeGenerateStart ( filePath ) ;
274- document = projectEngine . ProcessRemaining ( document ) ;
275- var csharpDocument = document . CodeDocument . GetCSharpDocument ( ) ;
276-
277- RazorSourceGeneratorEventSource . Log . RazorCodeGenerateStop ( filePath ) ;
278- return ( filePath , csharpDocument ) ;
225+ RazorSourceGeneratorEventSource . Log . RazorCodeGenerateStop ( sourceItem . FilePath ) ;
226+ return ( hintName , csharpDocument ) ;
279227 } )
280228 . WithLambdaComparer ( static ( a , b ) =>
281229 {
@@ -290,11 +238,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
290238
291239 context . RegisterSourceOutput ( generatedOutput , static ( context , pair ) =>
292240 {
293- var ( filePath , csharpDocument ) = pair ;
294-
295- // Add a generated suffix so tools, such as coverlet, consider the file to be generated
296- var hintName = GetIdentifierFromPath ( filePath ) + ".g.cs" ;
297-
241+ var ( hintName , csharpDocument ) = pair ;
298242 RazorSourceGeneratorEventSource . Log . AddSyntaxTrees ( hintName ) ;
299243 for ( var i = 0 ; i < csharpDocument . Diagnostics . Count ; i ++ )
300244 {
0 commit comments