Skip to content

Commit a6a61fd

Browse files
authored
[17.6] Revert "Perf/generator (#8212)" (#8742)
* Revert "Perf/generator (#8212)" This reverts commit 4ab512e. * Add more tests
1 parent 37f2727 commit a6a61fd

22 files changed

+711
-601
lines changed

src/Compiler/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorTagHelperContextDiscoveryPhase.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ internal sealed class DefaultRazorTagHelperContextDiscoveryPhase : RazorEnginePh
1717
{
1818
protected override void ExecuteCore(RazorCodeDocument codeDocument)
1919
{
20-
var syntaxTree = codeDocument.GetPreTagHelperSyntaxTree() ?? codeDocument.GetSyntaxTree();
20+
var syntaxTree = codeDocument.GetSyntaxTree();
2121
ThrowForMissingDocumentDependency(syntaxTree);
2222

2323
var descriptors = codeDocument.GetTagHelpers();
@@ -69,6 +69,7 @@ protected override void ExecuteCore(RazorCodeDocument codeDocument)
6969

7070
var context = TagHelperDocumentContext.Create(tagHelperPrefix, descriptors);
7171
codeDocument.SetTagHelperContext(context);
72+
codeDocument.SetPreTagHelperSyntaxTree(syntaxTree);
7273
}
7374

7475
private static bool MatchesDirective(TagHelperDescriptor descriptor, string typePattern, string assemblyName)

src/Compiler/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorTagHelperRewritePhase.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,24 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
#nullable enable
44

5-
using System.Collections.Generic;
65
using Microsoft.AspNetCore.Razor.Language.Legacy;
76

87
namespace Microsoft.AspNetCore.Razor.Language;
98
internal sealed class DefaultRazorTagHelperRewritePhase : RazorEnginePhaseBase
109
{
1110
protected override void ExecuteCore(RazorCodeDocument codeDocument)
1211
{
13-
var syntaxTree = codeDocument.GetPreTagHelperSyntaxTree() ?? codeDocument.GetSyntaxTree();
14-
ThrowForMissingDocumentDependency(syntaxTree);
15-
12+
var syntaxTree = codeDocument.GetPreTagHelperSyntaxTree();
1613
var context = codeDocument.GetTagHelperContext();
17-
if (context?.TagHelpers.Count > 0)
18-
{
19-
var rewrittenSyntaxTree = TagHelperParseTreeRewriter.Rewrite(syntaxTree, context.Prefix, context.TagHelpers, out var usedHelpers);
20-
codeDocument.SetSyntaxTree(rewrittenSyntaxTree);
21-
codeDocument.SetReferencedTagHelpers(usedHelpers);
22-
}
23-
else
14+
if (syntaxTree is null || context.TagHelpers.Count == 0)
2415
{
25-
codeDocument.SetReferencedTagHelpers(new HashSet<TagHelperDescriptor>());
16+
// No descriptors, no-op.
17+
return;
2618
}
19+
20+
var rewrittenSyntaxTree = TagHelperParseTreeRewriter.Rewrite(syntaxTree, context.Prefix, context.TagHelpers, out var usedHelpers);
21+
22+
codeDocument.SetReferencedTagHelpers(usedHelpers);
23+
codeDocument.SetSyntaxTree(rewrittenSyntaxTree);
2724
}
2825
}

src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/Microsoft.NET.Sdk.Razor.SourceGenerators.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
</ItemGroup>
2020

2121
<ItemGroup>
22-
<ProjectReference Include="..\..\Shared\Microsoft.AspNetCore.Razor.Utilities.Shared\Microsoft.AspNetCore.Razor.Utilities.Shared.csproj" />
2322
<ProjectReference Include="..\Microsoft.AspNetCore.Mvc.Razor.Extensions\src\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj" />
2423
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Language\src\Microsoft.AspNetCore.Razor.Language.csproj" />
2524
<ProjectReference Include="..\Microsoft.CodeAnalysis.Razor\src\Microsoft.CodeAnalysis.Razor.csproj" />

src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.Helpers.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ private static RazorProjectEngine GetDiscoveryProjectEngine(
8383
return discoveryProjectEngine;
8484
}
8585

86-
private static SourceGeneratorProjectEngine GetGenerationProjectEngine(
86+
private static RazorProjectEngine GetGenerationProjectEngine(
87+
IReadOnlyList<TagHelperDescriptor> tagHelpers,
8788
SourceGeneratorProjectItem item,
8889
IEnumerable<SourceGeneratorProjectItem> imports,
8990
RazorSourceGenerationOptions razorSourceGeneratorOptions)
@@ -95,7 +96,7 @@ private static SourceGeneratorProjectEngine GetGenerationProjectEngine(
9596
fileSystem.Add(import);
9697
}
9798

98-
var projectEngine = (DefaultRazorProjectEngine)RazorProjectEngine.Create(razorSourceGeneratorOptions.Configuration, fileSystem, b =>
99+
var projectEngine = RazorProjectEngine.Create(razorSourceGeneratorOptions.Configuration, fileSystem, b =>
99100
{
100101
b.Features.Add(new DefaultTypeNameFeature());
101102
b.SetRootNamespace(razorSourceGeneratorOptions.RootNamespace);
@@ -106,13 +107,16 @@ private static SourceGeneratorProjectEngine GetGenerationProjectEngine(
106107
options.SupportLocalizedComponentNames = razorSourceGeneratorOptions.SupportLocalizedComponentNames;
107108
}));
108109

110+
b.Features.Add(new StaticTagHelperFeature { TagHelpers = tagHelpers });
111+
b.Features.Add(new DefaultTagHelperDescriptorProvider());
112+
109113
CompilerFeatures.Register(b);
110114
RazorExtensions.Register(b);
111115

112116
b.SetCSharpLanguageVersion(razorSourceGeneratorOptions.CSharpLanguageVersion);
113117
});
114118

115-
return new SourceGeneratorProjectEngine(projectEngine);
119+
return projectEngine;
116120
}
117121
}
118122
}

src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.cs

Lines changed: 52 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Collections.Generic;
56
using System.Collections.Immutable;
6-
using System.Diagnostics;
77
using System.IO;
88
using System.Linq;
99
using Microsoft.AspNetCore.Razor.Language;
10-
using Microsoft.AspNetCore.Razor.PooledObjects;
1110
using Microsoft.CodeAnalysis;
1211
using Microsoft.CodeAnalysis.CSharp;
13-
using Microsoft.CodeAnalysis.CSharp.Syntax;
1412

1513
namespace 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

Comments
 (0)