Skip to content

Commit a3c6a1d

Browse files
committed
Merge remote-tracking branch 'upstream/release/dev17.7' into merges/release/dev17.7-to-main
* upstream/release/dev17.7: Update baseline. [17.6] Revert "Perf/generator (#8212)" (#8742)
2 parents 11cad1b + 379929e commit a3c6a1d

22 files changed

+660
-547
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: 51 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,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

Comments
 (0)