зеркало из https://github.com/dotnet/razor.git
* Revert "Perf/generator (#8212)"
This reverts commit 4ab512e7f0
.
* Add more tests
This commit is contained in:
Родитель
37f2727000
Коммит
a6a61fdfa7
|
@ -17,7 +17,7 @@ internal sealed class DefaultRazorTagHelperContextDiscoveryPhase : RazorEnginePh
|
|||
{
|
||||
protected override void ExecuteCore(RazorCodeDocument codeDocument)
|
||||
{
|
||||
var syntaxTree = codeDocument.GetPreTagHelperSyntaxTree() ?? codeDocument.GetSyntaxTree();
|
||||
var syntaxTree = codeDocument.GetSyntaxTree();
|
||||
ThrowForMissingDocumentDependency(syntaxTree);
|
||||
|
||||
var descriptors = codeDocument.GetTagHelpers();
|
||||
|
@ -69,6 +69,7 @@ internal sealed class DefaultRazorTagHelperContextDiscoveryPhase : RazorEnginePh
|
|||
|
||||
var context = TagHelperDocumentContext.Create(tagHelperPrefix, descriptors);
|
||||
codeDocument.SetTagHelperContext(context);
|
||||
codeDocument.SetPreTagHelperSyntaxTree(syntaxTree);
|
||||
}
|
||||
|
||||
private static bool MatchesDirective(TagHelperDescriptor descriptor, string typePattern, string assemblyName)
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
#nullable enable
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language;
|
||||
|
@ -10,19 +9,17 @@ internal sealed class DefaultRazorTagHelperRewritePhase : RazorEnginePhaseBase
|
|||
{
|
||||
protected override void ExecuteCore(RazorCodeDocument codeDocument)
|
||||
{
|
||||
var syntaxTree = codeDocument.GetPreTagHelperSyntaxTree() ?? codeDocument.GetSyntaxTree();
|
||||
ThrowForMissingDocumentDependency(syntaxTree);
|
||||
|
||||
var syntaxTree = codeDocument.GetPreTagHelperSyntaxTree();
|
||||
var context = codeDocument.GetTagHelperContext();
|
||||
if (context?.TagHelpers.Count > 0)
|
||||
if (syntaxTree is null || context.TagHelpers.Count == 0)
|
||||
{
|
||||
var rewrittenSyntaxTree = TagHelperParseTreeRewriter.Rewrite(syntaxTree, context.Prefix, context.TagHelpers, out var usedHelpers);
|
||||
codeDocument.SetSyntaxTree(rewrittenSyntaxTree);
|
||||
codeDocument.SetReferencedTagHelpers(usedHelpers);
|
||||
}
|
||||
else
|
||||
{
|
||||
codeDocument.SetReferencedTagHelpers(new HashSet<TagHelperDescriptor>());
|
||||
// No descriptors, no-op.
|
||||
return;
|
||||
}
|
||||
|
||||
var rewrittenSyntaxTree = TagHelperParseTreeRewriter.Rewrite(syntaxTree, context.Prefix, context.TagHelpers, out var usedHelpers);
|
||||
|
||||
codeDocument.SetReferencedTagHelpers(usedHelpers);
|
||||
codeDocument.SetSyntaxTree(rewrittenSyntaxTree);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Shared\Microsoft.AspNetCore.Razor.Utilities.Shared\Microsoft.AspNetCore.Razor.Utilities.Shared.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Mvc.Razor.Extensions\src\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Language\src\Microsoft.AspNetCore.Razor.Language.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.CodeAnalysis.Razor\src\Microsoft.CodeAnalysis.Razor.csproj" />
|
||||
|
|
|
@ -83,7 +83,8 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
|
|||
return discoveryProjectEngine;
|
||||
}
|
||||
|
||||
private static SourceGeneratorProjectEngine GetGenerationProjectEngine(
|
||||
private static RazorProjectEngine GetGenerationProjectEngine(
|
||||
IReadOnlyList<TagHelperDescriptor> tagHelpers,
|
||||
SourceGeneratorProjectItem item,
|
||||
IEnumerable<SourceGeneratorProjectItem> imports,
|
||||
RazorSourceGenerationOptions razorSourceGeneratorOptions)
|
||||
|
@ -95,7 +96,7 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
|
|||
fileSystem.Add(import);
|
||||
}
|
||||
|
||||
var projectEngine = (DefaultRazorProjectEngine)RazorProjectEngine.Create(razorSourceGeneratorOptions.Configuration, fileSystem, b =>
|
||||
var projectEngine = RazorProjectEngine.Create(razorSourceGeneratorOptions.Configuration, fileSystem, b =>
|
||||
{
|
||||
b.Features.Add(new DefaultTypeNameFeature());
|
||||
b.SetRootNamespace(razorSourceGeneratorOptions.RootNamespace);
|
||||
|
@ -106,13 +107,16 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
|
|||
options.SupportLocalizedComponentNames = razorSourceGeneratorOptions.SupportLocalizedComponentNames;
|
||||
}));
|
||||
|
||||
b.Features.Add(new StaticTagHelperFeature { TagHelpers = tagHelpers });
|
||||
b.Features.Add(new DefaultTagHelperDescriptorProvider());
|
||||
|
||||
CompilerFeatures.Register(b);
|
||||
RazorExtensions.Register(b);
|
||||
|
||||
b.SetCSharpLanguageVersion(razorSourceGeneratorOptions.CSharpLanguageVersion);
|
||||
});
|
||||
|
||||
return new SourceGeneratorProjectEngine(projectEngine);
|
||||
return projectEngine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,13 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
|
||||
namespace Microsoft.NET.Sdk.Razor.SourceGenerators
|
||||
{
|
||||
|
@ -68,12 +66,11 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
|
|||
var generatedDeclarationCode = componentFiles
|
||||
.Combine(importFiles.Collect())
|
||||
.Combine(razorSourceGeneratorOptions)
|
||||
.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())
|
||||
.Select(static (pair, _) =>
|
||||
{
|
||||
|
||||
var ((sourceItem, importFiles), razorSourceGeneratorOptions) = pair;
|
||||
RazorSourceGeneratorEventSource.Log.GenerateDeclarationCodeStart(sourceItem.RelativePhysicalPath);
|
||||
RazorSourceGeneratorEventSource.Log.GenerateDeclarationCodeStart(sourceItem.FilePath);
|
||||
|
||||
var projectEngine = GetDeclarationProjectEngine(sourceItem, importFiles, razorSourceGeneratorOptions);
|
||||
|
||||
|
@ -81,69 +78,57 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
|
|||
|
||||
var result = codeGen.GetCSharpDocument().GeneratedCode;
|
||||
|
||||
RazorSourceGeneratorEventSource.Log.GenerateDeclarationCodeStop(sourceItem.RelativePhysicalPath);
|
||||
RazorSourceGeneratorEventSource.Log.GenerateDeclarationCodeStop(sourceItem.FilePath);
|
||||
|
||||
return (result, sourceItem.RelativePhysicalPath);
|
||||
return result;
|
||||
});
|
||||
|
||||
var generatedDeclarationSyntaxTrees = generatedDeclarationCode
|
||||
.Combine(parseOptions)
|
||||
.Select(static (pair, ct) =>
|
||||
.Select(static (pair, _) =>
|
||||
{
|
||||
var ((generatedDeclarationCode, filePath), parseOptions) = pair;
|
||||
return CSharpSyntaxTree.ParseText(generatedDeclarationCode, (CSharpParseOptions)parseOptions, filePath, cancellationToken: ct);
|
||||
});
|
||||
|
||||
var tagHelpersFromComponents = generatedDeclarationSyntaxTrees
|
||||
.Combine(compilation)
|
||||
.Combine(razorSourceGeneratorOptions)
|
||||
.SelectMany(static (pair, ct) =>
|
||||
{
|
||||
|
||||
var ((generatedDeclarationSyntaxTree, compilation), razorSourceGeneratorOptions) = pair;
|
||||
RazorSourceGeneratorEventSource.Log.DiscoverTagHelpersFromComponentStart(generatedDeclarationSyntaxTree.FilePath);
|
||||
|
||||
var tagHelperFeature = new StaticCompilationTagHelperFeature();
|
||||
var discoveryProjectEngine = GetDiscoveryProjectEngine(compilation.References.ToImmutableArray(), tagHelperFeature);
|
||||
|
||||
var compilationWithDeclarations = compilation.AddSyntaxTrees(generatedDeclarationSyntaxTree);
|
||||
|
||||
// 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
|
||||
ISymbol targetSymbol = compilationWithDeclarations.Assembly;
|
||||
var root = generatedDeclarationSyntaxTree.GetRoot(ct);
|
||||
if (root is CompilationUnitSyntax { Members: [NamespaceDeclarationSyntax { Members: [ClassDeclarationSyntax classSyntax, ..] }, ..] })
|
||||
{
|
||||
var declaredClass = compilationWithDeclarations.GetSemanticModel(generatedDeclarationSyntaxTree).GetDeclaredSymbol(classSyntax, ct);
|
||||
Debug.Assert(declaredClass is null || declaredClass is { AllInterfaces: [{ Name: "IComponent" }, ..] });
|
||||
targetSymbol = declaredClass ?? targetSymbol;
|
||||
}
|
||||
|
||||
tagHelperFeature.Compilation = compilationWithDeclarations;
|
||||
tagHelperFeature.TargetSymbol = targetSymbol;
|
||||
|
||||
var result = tagHelperFeature.GetDescriptors();
|
||||
RazorSourceGeneratorEventSource.Log.DiscoverTagHelpersFromComponentStop(generatedDeclarationSyntaxTree.FilePath);
|
||||
return result;
|
||||
var (generatedDeclarationCode, parseOptions) = pair;
|
||||
return CSharpSyntaxTree.ParseText(generatedDeclarationCode, (CSharpParseOptions)parseOptions);
|
||||
});
|
||||
|
||||
var tagHelpersFromCompilation = compilation
|
||||
.Combine(generatedDeclarationSyntaxTrees.Collect())
|
||||
.Combine(razorSourceGeneratorOptions)
|
||||
.Select(static (pair, _) =>
|
||||
{
|
||||
RazorSourceGeneratorEventSource.Log.DiscoverTagHelpersFromCompilationStart();
|
||||
|
||||
var (compilation, razorSourceGeneratorOptions) = pair;
|
||||
var ((compilation, generatedDeclarationSyntaxTrees), razorSourceGeneratorOptions) = pair;
|
||||
|
||||
var tagHelperFeature = new StaticCompilationTagHelperFeature();
|
||||
var discoveryProjectEngine = GetDiscoveryProjectEngine(compilation.References.ToImmutableArray(), tagHelperFeature);
|
||||
|
||||
tagHelperFeature.Compilation = compilation;
|
||||
tagHelperFeature.TargetSymbol = compilation.Assembly;
|
||||
var compilationWithDeclarations = compilation.AddSyntaxTrees(generatedDeclarationSyntaxTrees);
|
||||
|
||||
var result = tagHelperFeature.GetDescriptors();
|
||||
tagHelperFeature.Compilation = compilationWithDeclarations;
|
||||
tagHelperFeature.TargetSymbol = compilationWithDeclarations.Assembly;
|
||||
|
||||
var result = (IList<TagHelperDescriptor>)tagHelperFeature.GetDescriptors();
|
||||
RazorSourceGeneratorEventSource.Log.DiscoverTagHelpersFromCompilationStop();
|
||||
return result;
|
||||
});
|
||||
})
|
||||
.WithLambdaComparer(static (a, b) =>
|
||||
{
|
||||
if (a.Count != b.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < a.Count; i++)
|
||||
{
|
||||
if (!a[i].Equals(b[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}, getHashCode: static a => a.Count);
|
||||
|
||||
var tagHelpersFromReferences = compilation
|
||||
.Combine(razorSourceGeneratorOptions)
|
||||
|
@ -186,7 +171,7 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
|
|||
var tagHelperFeature = new StaticCompilationTagHelperFeature();
|
||||
var discoveryProjectEngine = GetDiscoveryProjectEngine(compilation.References.ToImmutableArray(), tagHelperFeature);
|
||||
|
||||
using var pool = ArrayBuilderPool<TagHelperDescriptor>.GetPooledObject(out var descriptors);
|
||||
List<TagHelperDescriptor> descriptors = new();
|
||||
tagHelperFeature.Compilation = compilation;
|
||||
foreach (var reference in compilation.References)
|
||||
{
|
||||
|
@ -198,84 +183,47 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
|
|||
}
|
||||
|
||||
RazorSourceGeneratorEventSource.Log.DiscoverTagHelpersFromReferencesStop();
|
||||
return descriptors.ToImmutable();
|
||||
return (ICollection<TagHelperDescriptor>)descriptors;
|
||||
});
|
||||
|
||||
var allTagHelpers = tagHelpersFromComponents.Collect()
|
||||
.Combine(tagHelpersFromCompilation)
|
||||
var allTagHelpers = tagHelpersFromCompilation
|
||||
.Combine(tagHelpersFromReferences)
|
||||
.Select(static (pair, _) =>
|
||||
{
|
||||
var ((tagHelpersFromComponents, tagHelpersFromCompilation), tagHelpersFromReferences) = pair;
|
||||
var count = tagHelpersFromCompilation.Length + tagHelpersFromReferences.Length + tagHelpersFromComponents.Length;
|
||||
var (tagHelpersFromCompilation, tagHelpersFromReferences) = pair;
|
||||
var count = tagHelpersFromCompilation.Count + tagHelpersFromReferences.Count;
|
||||
if (count == 0)
|
||||
{
|
||||
return ImmutableArray<TagHelperDescriptor>.Empty;
|
||||
return Array.Empty<TagHelperDescriptor>();
|
||||
}
|
||||
|
||||
using var pool = ArrayBuilderPool<TagHelperDescriptor>.GetPooledObject(out var allTagHelpers);
|
||||
allTagHelpers.AddRange(tagHelpersFromCompilation);
|
||||
allTagHelpers.AddRange(tagHelpersFromReferences);
|
||||
allTagHelpers.AddRange(tagHelpersFromComponents);
|
||||
var allTagHelpers = new TagHelperDescriptor[count];
|
||||
tagHelpersFromCompilation.CopyTo(allTagHelpers, 0);
|
||||
tagHelpersFromReferences.CopyTo(allTagHelpers, tagHelpersFromCompilation.Count);
|
||||
|
||||
return allTagHelpers.ToImmutable();
|
||||
return allTagHelpers;
|
||||
});
|
||||
|
||||
var generatedOutput = sourceItems
|
||||
.Combine(importFiles.Collect())
|
||||
.WithLambdaComparer((old, @new) => old.Left.Equals(@new.Left) && old.Right.SequenceEqual(@new.Right), (a) => a.GetHashCode())
|
||||
.Combine(allTagHelpers)
|
||||
.Combine(razorSourceGeneratorOptions)
|
||||
.Select(static (pair, _) =>
|
||||
{
|
||||
var ((sourceItem, imports), razorSourceGeneratorOptions) = pair;
|
||||
var (((sourceItem, imports), allTagHelpers), razorSourceGeneratorOptions) = pair;
|
||||
|
||||
RazorSourceGeneratorEventSource.Log.ParseRazorDocumentStart(sourceItem.RelativePhysicalPath);
|
||||
RazorSourceGeneratorEventSource.Log.RazorCodeGenerateStart(sourceItem.FilePath);
|
||||
|
||||
var projectEngine = GetGenerationProjectEngine(sourceItem, imports, razorSourceGeneratorOptions);
|
||||
// Add a generated suffix so tools, such as coverlet, consider the file to be generated
|
||||
var hintName = GetIdentifierFromPath(sourceItem.RelativePhysicalPath) + ".g.cs";
|
||||
|
||||
var document = projectEngine.ProcessInitialParse(sourceItem);
|
||||
var projectEngine = GetGenerationProjectEngine(allTagHelpers, sourceItem, imports, razorSourceGeneratorOptions);
|
||||
|
||||
RazorSourceGeneratorEventSource.Log.ParseRazorDocumentStop(sourceItem.RelativePhysicalPath);
|
||||
return (projectEngine, sourceItem.RelativePhysicalPath, document);
|
||||
})
|
||||
var codeDocument = projectEngine.Process(sourceItem);
|
||||
var csharpDocument = codeDocument.GetCSharpDocument();
|
||||
|
||||
// Add the tag helpers in, but ignore if they've changed or not, only reprocessing the actual document changed
|
||||
.Combine(allTagHelpers)
|
||||
.WithLambdaComparer((old, @new) => old.Left.Equals(@new.Left), (item) => item.GetHashCode())
|
||||
.Select((pair, _) =>
|
||||
{
|
||||
var ((projectEngine, filePath, codeDocument), allTagHelpers) = pair;
|
||||
RazorSourceGeneratorEventSource.Log.RewriteTagHelpersStart(filePath);
|
||||
|
||||
codeDocument = projectEngine.ProcessTagHelpers(codeDocument, allTagHelpers, checkForIdempotency: false);
|
||||
|
||||
RazorSourceGeneratorEventSource.Log.RewriteTagHelpersStop(filePath);
|
||||
return (projectEngine, filePath, codeDocument);
|
||||
})
|
||||
|
||||
// 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
|
||||
.Combine(allTagHelpers)
|
||||
.Select((pair, _) =>
|
||||
{
|
||||
|
||||
var ((projectEngine, filePath, document), allTagHelpers) = pair;
|
||||
RazorSourceGeneratorEventSource.Log.CheckAndRewriteTagHelpersStart(filePath);
|
||||
|
||||
document = projectEngine.ProcessTagHelpers(document, allTagHelpers, checkForIdempotency: true);
|
||||
|
||||
RazorSourceGeneratorEventSource.Log.CheckAndRewriteTagHelpersStop(filePath);
|
||||
return (projectEngine, filePath, document);
|
||||
})
|
||||
|
||||
.Select((pair, _) =>
|
||||
{
|
||||
var (projectEngine, filePath, document) = pair;
|
||||
RazorSourceGeneratorEventSource.Log.RazorCodeGenerateStart(filePath);
|
||||
document = projectEngine.ProcessRemaining(document);
|
||||
var csharpDocument = document.CodeDocument.GetCSharpDocument();
|
||||
|
||||
RazorSourceGeneratorEventSource.Log.RazorCodeGenerateStop(filePath);
|
||||
return (filePath, csharpDocument);
|
||||
RazorSourceGeneratorEventSource.Log.RazorCodeGenerateStop(sourceItem.FilePath);
|
||||
return (hintName, csharpDocument);
|
||||
})
|
||||
.WithLambdaComparer(static (a, b) =>
|
||||
{
|
||||
|
@ -290,11 +238,7 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
|
|||
|
||||
context.RegisterSourceOutput(generatedOutput, static (context, pair) =>
|
||||
{
|
||||
var (filePath, csharpDocument) = pair;
|
||||
|
||||
// Add a generated suffix so tools, such as coverlet, consider the file to be generated
|
||||
var hintName = GetIdentifierFromPath(filePath) + ".g.cs";
|
||||
|
||||
var (hintName, csharpDocument) = pair;
|
||||
RazorSourceGeneratorEventSource.Log.AddSyntaxTrees(hintName);
|
||||
for (var i = 0; i < csharpDocument.Diagnostics.Count; i++)
|
||||
{
|
||||
|
|
|
@ -59,37 +59,5 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
|
|||
private const int GenerateDeclarationSyntaxTreeStopId = 14;
|
||||
[Event(GenerateDeclarationSyntaxTreeStopId, Level = EventLevel.Informational)]
|
||||
public void GenerateDeclarationSyntaxTreeStop() => WriteEvent(GenerateDeclarationSyntaxTreeStopId);
|
||||
|
||||
private const int DiscoverTagHelpersFromComponentStartId = 15;
|
||||
[Event(DiscoverTagHelpersFromComponentStartId, Level = EventLevel.Informational)]
|
||||
public void DiscoverTagHelpersFromComponentStart(string filePath) => WriteEvent(DiscoverTagHelpersFromComponentStartId, filePath);
|
||||
|
||||
private const int DiscoverTagHelpersFromComponentStopId = 16;
|
||||
[Event(DiscoverTagHelpersFromComponentStopId, Level = EventLevel.Informational)]
|
||||
public void DiscoverTagHelpersFromComponentStop(string filePath) => WriteEvent(DiscoverTagHelpersFromComponentStopId, filePath);
|
||||
|
||||
private const int ParseRazorDocumentStartId = 17;
|
||||
[Event(ParseRazorDocumentStartId, Level = EventLevel.Informational)]
|
||||
public void ParseRazorDocumentStart(string file) => WriteEvent(ParseRazorDocumentStartId, file);
|
||||
|
||||
private const int ParseRazorDocumentStopId = 18;
|
||||
[Event(ParseRazorDocumentStopId, Level = EventLevel.Informational)]
|
||||
public void ParseRazorDocumentStop(string file) => WriteEvent(ParseRazorDocumentStopId, file);
|
||||
|
||||
private const int RewriteTagHelpersStartId = 19;
|
||||
[Event(RewriteTagHelpersStartId, Level = EventLevel.Informational)]
|
||||
public void RewriteTagHelpersStart(string file) => WriteEvent(RewriteTagHelpersStartId, file);
|
||||
|
||||
private const int RewriteTagHelpersStopId = 20;
|
||||
[Event(RewriteTagHelpersStopId, Level = EventLevel.Informational)]
|
||||
public void RewriteTagHelpersStop(string file) => WriteEvent(RewriteTagHelpersStopId, file);
|
||||
|
||||
private const int CheckAndRewriteTagHelpersStartId = 21;
|
||||
[Event(CheckAndRewriteTagHelpersStartId, Level = EventLevel.Informational)]
|
||||
public void CheckAndRewriteTagHelpersStart(string file) => WriteEvent(CheckAndRewriteTagHelpersStartId, file);
|
||||
|
||||
private const int CheckAndRewriteTagHelpersStopId = 22;
|
||||
[Event(CheckAndRewriteTagHelpersStopId, Level = EventLevel.Informational)]
|
||||
public void CheckAndRewriteTagHelpersStop(string file) => WriteEvent(CheckAndRewriteTagHelpersStopId, file);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.NET.Sdk.Razor.SourceGenerators;
|
||||
|
||||
internal class SourceGeneratorProjectEngine : DefaultRazorProjectEngine
|
||||
{
|
||||
private readonly int discoveryPhaseIndex = -1;
|
||||
|
||||
private readonly int rewritePhaseIndex = -1;
|
||||
|
||||
public SourceGeneratorProjectEngine(DefaultRazorProjectEngine projectEngine)
|
||||
: base(projectEngine.Configuration, projectEngine.Engine, projectEngine.FileSystem, projectEngine.ProjectFeatures)
|
||||
{
|
||||
for (int i = 0; i < Engine.Phases.Count; i++)
|
||||
{
|
||||
if (Engine.Phases[i] is DefaultRazorTagHelperContextDiscoveryPhase)
|
||||
{
|
||||
discoveryPhaseIndex = i;
|
||||
}
|
||||
else if (Engine.Phases[i] is DefaultRazorTagHelperRewritePhase)
|
||||
{
|
||||
rewritePhaseIndex = i;
|
||||
}
|
||||
else if (discoveryPhaseIndex >= 0 && rewritePhaseIndex >= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Debug.Assert(discoveryPhaseIndex >= 0);
|
||||
Debug.Assert(rewritePhaseIndex >= 0);
|
||||
}
|
||||
|
||||
public SourceGeneratorRazorCodeDocument ProcessInitialParse(RazorProjectItem projectItem)
|
||||
{
|
||||
var codeDocument = CreateCodeDocumentCore(projectItem);
|
||||
ProcessPartial(codeDocument, 0, discoveryPhaseIndex);
|
||||
|
||||
// record the syntax tree, before the tag helper re-writing occurs
|
||||
codeDocument.SetPreTagHelperSyntaxTree(codeDocument.GetSyntaxTree());
|
||||
return new SourceGeneratorRazorCodeDocument(codeDocument);
|
||||
}
|
||||
|
||||
public SourceGeneratorRazorCodeDocument ProcessTagHelpers(SourceGeneratorRazorCodeDocument sgDocument, IReadOnlyList<TagHelperDescriptor> tagHelpers, bool checkForIdempotency)
|
||||
{
|
||||
Debug.Assert(sgDocument.CodeDocument.GetPreTagHelperSyntaxTree() is not null);
|
||||
|
||||
int startIndex = discoveryPhaseIndex;
|
||||
var codeDocument = sgDocument.CodeDocument;
|
||||
var previousTagHelpers = codeDocument.GetTagHelpers();
|
||||
if (checkForIdempotency && previousTagHelpers is not null)
|
||||
{
|
||||
// compare the tag helpers with the ones the document last used
|
||||
if (Enumerable.SequenceEqual(tagHelpers, previousTagHelpers))
|
||||
{
|
||||
// tag helpers are the same, nothing to do!
|
||||
return sgDocument;
|
||||
}
|
||||
else
|
||||
{
|
||||
// tag helpers have changed, figure out if we need to re-write
|
||||
var oldContextHelpers = codeDocument.GetTagHelperContext().TagHelpers;
|
||||
|
||||
// re-run the scope check to figure out which tag helpers this document can see
|
||||
codeDocument.SetTagHelpers(tagHelpers);
|
||||
Engine.Phases[discoveryPhaseIndex].Execute(codeDocument);
|
||||
|
||||
// Check if any new tag helpers were added or ones we previously used were removed
|
||||
var newContextHelpers = codeDocument.GetTagHelperContext().TagHelpers;
|
||||
var added = newContextHelpers.Except(oldContextHelpers);
|
||||
var referencedByRemoved = codeDocument.GetReferencedTagHelpers().Except(newContextHelpers);
|
||||
if (!added.Any() && !referencedByRemoved.Any())
|
||||
{
|
||||
// Either nothing new, or any that got removed weren't used by this document anyway
|
||||
return sgDocument;
|
||||
}
|
||||
|
||||
// We need to re-write the document, but can skip the scoping as we just performed it
|
||||
startIndex = rewritePhaseIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
codeDocument.SetTagHelpers(tagHelpers);
|
||||
}
|
||||
|
||||
ProcessPartial(codeDocument, startIndex, rewritePhaseIndex + 1);
|
||||
return new SourceGeneratorRazorCodeDocument(codeDocument);
|
||||
}
|
||||
|
||||
public SourceGeneratorRazorCodeDocument ProcessRemaining(SourceGeneratorRazorCodeDocument sgDocument)
|
||||
{
|
||||
var codeDocument = sgDocument.CodeDocument;
|
||||
Debug.Assert(codeDocument.GetReferencedTagHelpers() is not null);
|
||||
|
||||
ProcessPartial(sgDocument.CodeDocument, rewritePhaseIndex, Engine.Phases.Count);
|
||||
return new SourceGeneratorRazorCodeDocument(codeDocument);
|
||||
}
|
||||
|
||||
private void ProcessPartial(RazorCodeDocument codeDocument, int startIndex, int endIndex)
|
||||
{
|
||||
Debug.Assert(startIndex >= 0 && startIndex <= endIndex && endIndex <= Engine.Phases.Count);
|
||||
for (var i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
Engine.Phases[i].Execute(codeDocument);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.NET.Sdk.Razor.SourceGenerators;
|
||||
|
||||
/// <summary>
|
||||
/// A wrapper for <see cref="RazorCodeDocument"/>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The razor compiler modifies the <see cref="RazorCodeDocument"/> in place during the various phases,
|
||||
/// meaning object identity is maintained even when the contents have changed.
|
||||
///
|
||||
/// We need to be able to identify from the source generator if a given code document was modified or
|
||||
/// returned unchanged. Rather than implementing deep equality on the <see cref="RazorCodeDocument"/>
|
||||
/// which can get expensive when the <see cref="ItemCollection"/> is large, we instead use a wrapper class.
|
||||
/// If the underlying document is unchanged we return the original wrapper class. If the underlying
|
||||
/// document is changed, we return a new instance of the wrapper.
|
||||
/// </remarks>
|
||||
internal class SourceGeneratorRazorCodeDocument
|
||||
{
|
||||
public RazorCodeDocument CodeDocument { get; }
|
||||
|
||||
public SourceGeneratorRazorCodeDocument(RazorCodeDocument razorCodeDocument)
|
||||
{
|
||||
this.CodeDocument = razorCodeDocument;
|
||||
}
|
||||
}
|
|
@ -2,10 +2,8 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.PooledObjects;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
|
||||
|
@ -13,16 +11,18 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
|
|||
{
|
||||
internal sealed class StaticCompilationTagHelperFeature : RazorEngineFeatureBase, ITagHelperFeature
|
||||
{
|
||||
private static readonly List<TagHelperDescriptor> EmptyList = new();
|
||||
|
||||
private ITagHelperDescriptorProvider[]? _providers;
|
||||
|
||||
public ImmutableArray<TagHelperDescriptor> GetDescriptors()
|
||||
public List<TagHelperDescriptor> GetDescriptors()
|
||||
{
|
||||
if (Compilation is null)
|
||||
{
|
||||
return ImmutableArray<TagHelperDescriptor>.Empty;
|
||||
return EmptyList;
|
||||
}
|
||||
|
||||
using var pool = ArrayBuilderPool<TagHelperDescriptor>.GetPooledObject(out var results);
|
||||
var results = new List<TagHelperDescriptor>();
|
||||
var context = TagHelperDescriptorProviderContext.Create(results);
|
||||
context.SetCompilation(Compilation);
|
||||
if (TargetSymbol is not null)
|
||||
|
@ -35,7 +35,7 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
|
|||
_providers[i].Execute(context);
|
||||
}
|
||||
|
||||
return results.ToImmutable();
|
||||
return results;
|
||||
}
|
||||
|
||||
IReadOnlyList<TagHelperDescriptor> ITagHelperFeature.GetDescriptors() => GetDescriptors();
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.NET.Sdk.Razor.SourceGenerators
|
||||
{
|
||||
internal sealed class StaticTagHelperFeature : RazorEngineFeatureBase, ITagHelperFeature
|
||||
{
|
||||
public IReadOnlyList<TagHelperDescriptor> TagHelpers { get; set; }
|
||||
|
||||
public IReadOnlyList<TagHelperDescriptor> GetDescriptors() => TagHelpers;
|
||||
|
||||
public StaticTagHelperFeature()
|
||||
{
|
||||
TagHelpers = new List<TagHelperDescriptor>();
|
||||
}
|
||||
|
||||
public StaticTagHelperFeature(IEnumerable<TagHelperDescriptor> tagHelpers)
|
||||
{
|
||||
TagHelpers = new List<TagHelperDescriptor>(tagHelpers);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Test.Common;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.NET.Sdk.Razor.SourceGenerators;
|
||||
|
||||
public sealed class RazorSourceGeneratorComponentTests : RazorSourceGeneratorTestsBase
|
||||
{
|
||||
[Fact, WorkItem("https://github.com/dotnet/razor/issues/8718")]
|
||||
public async Task PartialClass()
|
||||
{
|
||||
// Arrange
|
||||
var project = CreateTestProject(new()
|
||||
{
|
||||
["Views/Home/Index.cshtml"] = """
|
||||
@(await Html.RenderComponentAsync<MyApp.Shared.Component1>(RenderMode.Static))
|
||||
""",
|
||||
["Shared/Component1.razor"] = """
|
||||
<Component2 Param="42" />
|
||||
""",
|
||||
["Shared/Component2.razor"] = """
|
||||
@inherits ComponentBase
|
||||
|
||||
Value: @(Param + 1)
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public int Param { get; set; }
|
||||
}
|
||||
"""
|
||||
}, new()
|
||||
{
|
||||
["Component2.razor.cs"] = """
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace MyApp.Shared;
|
||||
|
||||
public partial class Component2 : ComponentBase { }
|
||||
"""
|
||||
});
|
||||
var compilation = await project.GetCompilationAsync();
|
||||
var driver = await GetDriverAsync(project, options =>
|
||||
{
|
||||
options.TestGlobalOptions["build_property.RazorLangVersion"] = "7.0";
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = RunGenerator(compilation!, ref driver, out compilation);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Diagnostics);
|
||||
Assert.Equal(3, result.GeneratedSources.Length);
|
||||
await VerifyRazorPageMatchesBaselineAsync(compilation, "Views_Home_Index");
|
||||
}
|
||||
|
||||
[Fact, WorkItem("https://github.com/dotnet/razor/issues/8718")]
|
||||
public async Task PartialClass_NoBaseInCSharp()
|
||||
{
|
||||
// Arrange
|
||||
var project = CreateTestProject(new()
|
||||
{
|
||||
["Views/Home/Index.cshtml"] = """
|
||||
@(await Html.RenderComponentAsync<MyApp.Shared.Component1>(RenderMode.Static))
|
||||
""",
|
||||
["Shared/Component1.razor"] = """
|
||||
<Component2 Param="42" />
|
||||
""",
|
||||
["Shared/Component2.razor"] = """
|
||||
@inherits ComponentBase
|
||||
|
||||
Value: @(Param + 1)
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public int Param { get; set; }
|
||||
}
|
||||
"""
|
||||
}, new()
|
||||
{
|
||||
["Component2.razor.cs"] = """
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace MyApp.Shared;
|
||||
|
||||
public partial class Component2 { }
|
||||
"""
|
||||
});
|
||||
var compilation = await project.GetCompilationAsync();
|
||||
var driver = await GetDriverAsync(project, options =>
|
||||
{
|
||||
options.TestGlobalOptions["build_property.RazorLangVersion"] = "7.0";
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = RunGenerator(compilation!, ref driver, out compilation);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Diagnostics);
|
||||
Assert.Equal(3, result.GeneratedSources.Length);
|
||||
await VerifyRazorPageMatchesBaselineAsync(compilation, "Views_Home_Index");
|
||||
}
|
||||
|
||||
[Fact, WorkItem("https://github.com/dotnet/razor/issues/8718")]
|
||||
public async Task ComponentInheritsFromComponent()
|
||||
{
|
||||
// Arrange
|
||||
var project = CreateTestProject(new()
|
||||
{
|
||||
["Views/Home/Index.cshtml"] = """
|
||||
@(await Html.RenderComponentAsync<MyApp.Shared.Component1>(RenderMode.Static))
|
||||
""",
|
||||
["Shared/Component1.razor"] = """
|
||||
Hello from Component1
|
||||
<DerivedComponent />
|
||||
""",
|
||||
["Shared/BaseComponent.razor"] = """
|
||||
Hello from Base
|
||||
""",
|
||||
["Shared/DerivedComponent.razor"] = """
|
||||
@inherits BaseComponent
|
||||
Hello from Derived
|
||||
"""
|
||||
});
|
||||
var compilation = await project.GetCompilationAsync();
|
||||
var driver = await GetDriverAsync(project, options =>
|
||||
{
|
||||
options.TestGlobalOptions["build_property.RazorLangVersion"] = "7.0";
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = RunGenerator(compilation!, ref driver, out compilation);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Diagnostics);
|
||||
Assert.Equal(4, result.GeneratedSources.Length);
|
||||
await VerifyRazorPageMatchesBaselineAsync(compilation, "Views_Home_Index");
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Test.Common;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.NET.Sdk.Razor.SourceGenerators;
|
||||
|
@ -88,4 +89,107 @@ public sealed class RazorSourceGeneratorTagHelperTests : RazorSourceGeneratorTes
|
|||
result.VerifyOutputsMatchBaseline();
|
||||
await VerifyRazorPageMatchesBaselineAsync(compilation, "Views_Home_Index");
|
||||
}
|
||||
|
||||
[Fact, WorkItem("https://github.com/dotnet/razor/issues/8718")]
|
||||
public async Task ComponentAndTagHelper()
|
||||
{
|
||||
// Arrange
|
||||
var project = CreateTestProject(new()
|
||||
{
|
||||
["Views/Home/Index.cshtml"] = """
|
||||
@addTagHelper *, TestProject
|
||||
|
||||
<email mail="example">custom tag helper</email>
|
||||
""",
|
||||
["Shared/EmailTagHelper.razor"] = """
|
||||
@inherits ComponentAndTagHelper
|
||||
@code {
|
||||
public string? Mail { get; set; }
|
||||
}
|
||||
""",
|
||||
}, new()
|
||||
{
|
||||
["EmailTagHelper.cs"] = """
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
namespace MyApp.Shared;
|
||||
|
||||
public abstract class ComponentAndTagHelper : TagHelper
|
||||
{
|
||||
protected abstract void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder);
|
||||
}
|
||||
|
||||
public partial class EmailTagHelper : ComponentAndTagHelper
|
||||
{
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
output.TagName = "a";
|
||||
output.Attributes.SetAttribute("href", $"mailto:{Mail}");
|
||||
}
|
||||
}
|
||||
"""
|
||||
});
|
||||
var compilation = await project.GetCompilationAsync();
|
||||
var driver = await GetDriverAsync(project);
|
||||
|
||||
// Act
|
||||
var result = RunGenerator(compilation!, ref driver, out compilation);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Diagnostics);
|
||||
Assert.Equal(2, result.GeneratedSources.Length);
|
||||
await VerifyRazorPageMatchesBaselineAsync(compilation, "Views_Home_Index");
|
||||
}
|
||||
|
||||
[Fact, WorkItem("https://github.com/dotnet/razor/issues/8718")]
|
||||
public async Task ComponentAndTagHelper_HtmlTargetElement()
|
||||
{
|
||||
// Arrange
|
||||
var project = CreateTestProject(new()
|
||||
{
|
||||
["Views/Home/Index.cshtml"] = """
|
||||
@addTagHelper *, TestProject
|
||||
|
||||
<email mail="example1">inside email</email>
|
||||
<mail mail="example2">inside mail</mail>
|
||||
""",
|
||||
["Shared/EmailTagHelper.razor"] = """
|
||||
@using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
@attribute [HtmlTargetElement("mail")]
|
||||
@inherits ComponentAndTagHelper
|
||||
@code {
|
||||
public string? Mail { get; set; }
|
||||
}
|
||||
""",
|
||||
}, new()
|
||||
{
|
||||
["EmailTagHelper.cs"] = """
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
namespace MyApp.Shared;
|
||||
|
||||
public abstract class ComponentAndTagHelper : TagHelper
|
||||
{
|
||||
protected abstract void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder);
|
||||
}
|
||||
|
||||
public partial class EmailTagHelper : ComponentAndTagHelper
|
||||
{
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
output.TagName = "a";
|
||||
output.Attributes.SetAttribute("href", $"mailto:{Mail}");
|
||||
}
|
||||
}
|
||||
"""
|
||||
});
|
||||
var compilation = await project.GetCompilationAsync();
|
||||
var driver = await GetDriverAsync(project);
|
||||
|
||||
// Act
|
||||
var result = RunGenerator(compilation!, ref driver, out compilation);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Diagnostics);
|
||||
Assert.Equal(2, result.GeneratedSources.Length);
|
||||
await VerifyRazorPageMatchesBaselineAsync(compilation, "Views_Home_Index");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ using System;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Test.Common;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
@ -60,6 +61,42 @@ namespace MyApp.Pages
|
|||
Assert.Single(result.GeneratedSources);
|
||||
}
|
||||
|
||||
[Fact, WorkItem("https://github.com/dotnet/razor/issues/8610")]
|
||||
public async Task SourceGenerator_RazorFiles_UsingAlias_NestedClass()
|
||||
{
|
||||
// Arrange
|
||||
var project = CreateTestProject(new()
|
||||
{
|
||||
["Pages/Index.razor"] = """
|
||||
@code {
|
||||
public class MyModel { }
|
||||
}
|
||||
""",
|
||||
["Shared/MyComponent.razor"] = """
|
||||
@using MyAlias = Pages.Index.MyModel;
|
||||
|
||||
<MyComponent Data="@Data" />
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public MyAlias? Data { get; set; }
|
||||
}
|
||||
""",
|
||||
});
|
||||
var compilation = await project.GetCompilationAsync();
|
||||
var driver = await GetDriverAsync(project, options =>
|
||||
{
|
||||
options.TestGlobalOptions["build_property.RazorLangVersion"] = "7.0";
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = RunGenerator(compilation!, ref driver);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Diagnostics);
|
||||
Assert.Equal(2, result.GeneratedSources.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SourceGeneratorEvents_RazorFiles_Works()
|
||||
{
|
||||
|
@ -127,41 +164,74 @@ namespace MyApp.Pages
|
|||
|
||||
Assert.Collection(eventListener.Events,
|
||||
e => Assert.Equal("ComputeRazorSourceGeneratorOptions", e.EventName),
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("GenerateDeclarationCodeStart", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("GenerateDeclarationCodeStop", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("GenerateDeclarationCodeStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("GenerateDeclarationCodeStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStart", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStop", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStop", "Pages/Counter.razor"),
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("GenerateDeclarationCodeStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Index.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("GenerateDeclarationCodeStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Index.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("GenerateDeclarationCodeStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("GenerateDeclarationCodeStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromReferencesStart", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromReferencesStop", e.EventName),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStart", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStop", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Index_razor.g.cs"),
|
||||
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Counter_razor.g.cs")
|
||||
);
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Index.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Index.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("AddSyntaxTrees", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("Pages_Index_razor.g.cs", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("AddSyntaxTrees", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("Pages_Counter_razor.g.cs", file);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IncrementalCompilation_DoesNotReExecuteSteps_WhenRazorFilesAreUnchanged()
|
||||
public async Task IncrementalCompilation_DoesNotReexecuteSteps_WhenRazorFilesAreUnchanged()
|
||||
{
|
||||
// Arrange
|
||||
using var eventListener = new RazorEventListener();
|
||||
|
@ -343,18 +413,36 @@ namespace MyApp.Pages
|
|||
Assert.Equal(2, result.GeneratedSources.Length);
|
||||
|
||||
Assert.Collection(eventListener.Events,
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("GenerateDeclarationCodeStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("GenerateDeclarationCodeStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Counter_razor.g.cs")
|
||||
);
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("GenerateDeclarationCodeStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("GenerateDeclarationCodeStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("AddSyntaxTrees", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("Pages_Counter_razor.g.cs", file);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -447,13 +535,8 @@ public class Person
|
|||
Assert.Equal(2, result.GeneratedSources.Length);
|
||||
|
||||
Assert.Collection(eventListener.Events,
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStart", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStop", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStop", "Pages/Counter.razor"),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName)
|
||||
);
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -551,8 +634,6 @@ public class Person
|
|||
}", Encoding.UTF8)).Project;
|
||||
compilation = await project.GetCompilationAsync();
|
||||
|
||||
eventListener.Events.Clear();
|
||||
|
||||
result = RunGenerator(compilation!, ref driver, expectedDiagnostics)
|
||||
.VerifyOutputsMatch(result);
|
||||
|
||||
|
@ -560,13 +641,8 @@ public class Person
|
|||
Assert.Equal(2, result.GeneratedSources.Length);
|
||||
|
||||
Assert.Collection(eventListener.Events,
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStart", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStop", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStop", "Pages/Counter.razor"),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName)
|
||||
);
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -711,20 +787,38 @@ __builder.AddContent(3, count);
|
|||
Assert.Equal(2, result.GeneratedSources.Length);
|
||||
|
||||
Assert.Collection(eventListener.Events,
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("GenerateDeclarationCodeStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("GenerateDeclarationCodeStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Counter_razor.g.cs")
|
||||
);
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("GenerateDeclarationCodeStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("GenerateDeclarationCodeStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("AddSyntaxTrees", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("Pages_Counter_razor.g.cs", file);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -873,24 +967,50 @@ __builder.AddContent(3, count);
|
|||
Assert.Equal(2, result.GeneratedSources.Length);
|
||||
|
||||
Assert.Collection(eventListener.Events,
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("GenerateDeclarationCodeStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("GenerateDeclarationCodeStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStart", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStop", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Counter_razor.g.cs")
|
||||
);
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("GenerateDeclarationCodeStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("GenerateDeclarationCodeStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Index.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Index.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("AddSyntaxTrees", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("Pages_Counter_razor.g.cs", file);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -1021,24 +1141,40 @@ using SurveyPromptRootNamspace;
|
|||
Assert.Equal(2, result.GeneratedSources.Length);
|
||||
|
||||
Assert.Collection(eventListener.Events,
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStart", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStop", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("DiscoverTagHelpersFromComponentStop", "Pages/Counter.razor"),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromReferencesStart", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromReferencesStop", e.EventName),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStart", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStop", "Pages/Index.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStart", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStop", "Pages/Counter.razor"),
|
||||
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Index_razor.g.cs")
|
||||
);
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Index.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Index.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Counter.razor", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("AddSyntaxTrees", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("Pages_Index_razor.g.cs", file);
|
||||
});
|
||||
|
||||
// Verify caching
|
||||
eventListener.Events.Clear();
|
||||
|
@ -1190,29 +1326,46 @@ namespace AspNetCoreGeneratedDocument
|
|||
|
||||
Assert.Collection(eventListener.Events,
|
||||
e => Assert.Equal("ComputeRazorSourceGeneratorOptions", e.EventName),
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Index.cshtml"),
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Index.cshtml"),
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStart", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStop", "Views/Shared/_Layout.cshtml"),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromReferencesStart", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromReferencesStop", e.EventName),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Index.cshtml"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Index.cshtml"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStart", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStop", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Index.cshtml"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Index.cshtml"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStart", "Pages/Index.cshtml"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStop", "Pages/Index.cshtml"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStart", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStop", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Index_cshtml.g.cs"),
|
||||
e => e.AssertSingleItem("AddSyntaxTrees", "Views_Shared__Layout_cshtml.g.cs")
|
||||
);
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Index.cshtml", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Index.cshtml", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Views/Shared/_Layout.cshtml", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Views/Shared/_Layout.cshtml", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("AddSyntaxTrees", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("Pages_Index_cshtml.g.cs", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("AddSyntaxTrees", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("Views_Shared__Layout_cshtml.g.cs", file);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -1404,16 +1557,24 @@ namespace AspNetCoreGeneratedDocument
|
|||
Assert.Equal(2, result.GeneratedSources.Length);
|
||||
|
||||
Assert.Collection(eventListener.Events,
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStart", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("ParseRazorDocumentStop", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStart", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("RewriteTagHelpersStop", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStart", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStop", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("AddSyntaxTrees", "Views_Shared__Layout_cshtml.g.cs")
|
||||
);
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Views/Shared/_Layout.cshtml", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Views/Shared/_Layout.cshtml", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("AddSyntaxTrees", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("Views_Shared__Layout_cshtml.g.cs", file);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -1572,8 +1733,8 @@ public class Person
|
|||
|
||||
Assert.Collection(eventListener.Events,
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName)
|
||||
);
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName));
|
||||
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -1723,92 +1884,7 @@ public class HeaderTagHelper : TagHelper
|
|||
}", Encoding.UTF8)).Project;
|
||||
compilation = await project.GetCompilationAsync();
|
||||
|
||||
result = RunGenerator(compilation!, ref driver)
|
||||
.VerifyOutputsMatch(result, (0, @"
|
||||
#pragma checksum ""Pages/Index.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""5d59ecd7b7cf7355d7f60234988be34b81a8b614""
|
||||
// <auto-generated/>
|
||||
#pragma warning disable 1591
|
||||
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Pages_Index), @""mvc.1.0.view"", @""/Pages/Index.cshtml"")]
|
||||
namespace AspNetCoreGeneratedDocument
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
[global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Pages/Index.cshtml"")]
|
||||
[global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
|
||||
#nullable restore
|
||||
internal sealed class Pages_Index : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
|
||||
#nullable disable
|
||||
{
|
||||
#line hidden
|
||||
#pragma warning disable 0649
|
||||
private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext __tagHelperExecutionContext;
|
||||
#pragma warning restore 0649
|
||||
private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner __tagHelperRunner = new global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner();
|
||||
#pragma warning disable 0169
|
||||
private string __tagHelperStringValueBuffer;
|
||||
#pragma warning restore 0169
|
||||
private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager __backed__tagHelperScopeManager = null;
|
||||
private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager __tagHelperScopeManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if (__backed__tagHelperScopeManager == null)
|
||||
{
|
||||
__backed__tagHelperScopeManager = new global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager(StartTagHelperWritingScope, EndTagHelperWritingScope);
|
||||
}
|
||||
return __backed__tagHelperScopeManager;
|
||||
}
|
||||
}
|
||||
private global::MyApp.HeaderTagHelper __MyApp_HeaderTagHelper;
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
WriteLiteral(""\r\n"");
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin(""h2"", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.StartTagAndEndTag, ""5d59ecd7b7cf7355d7f60234988be34b81a8b6142529"", async() => {
|
||||
WriteLiteral(""Hello world"");
|
||||
}
|
||||
);
|
||||
__MyApp_HeaderTagHelper = CreateTagHelper<global::MyApp.HeaderTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__MyApp_HeaderTagHelper);
|
||||
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
||||
if (!__tagHelperExecutionContext.Output.IsContentModified)
|
||||
{
|
||||
await __tagHelperExecutionContext.SetOutputContentAsync();
|
||||
}
|
||||
Write(__tagHelperExecutionContext.Output);
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
#nullable restore
|
||||
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
|
||||
#nullable disable
|
||||
#nullable restore
|
||||
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
|
||||
#nullable disable
|
||||
#nullable restore
|
||||
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
|
||||
#nullable disable
|
||||
#nullable restore
|
||||
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
|
||||
#nullable disable
|
||||
#nullable restore
|
||||
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
|
||||
#nullable disable
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
"));
|
||||
result = RunGenerator(compilation!, ref driver);
|
||||
|
||||
Assert.Empty(result.Diagnostics);
|
||||
Assert.Equal(2, result.GeneratedSources.Length);
|
||||
|
@ -1816,14 +1892,36 @@ namespace AspNetCoreGeneratedDocument
|
|||
Assert.Collection(eventListener.Events,
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
|
||||
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Index.cshtml"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Index.cshtml"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Views/Shared/_Layout.cshtml"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStart", "Pages/Index.cshtml"),
|
||||
e => e.AssertSingleItem("RazorCodeGenerateStop", "Pages/Index.cshtml"),
|
||||
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Index_cshtml.g.cs")
|
||||
);
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Index.cshtml", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Pages/Index.cshtml", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStart", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Views/Shared/_Layout.cshtml", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("RazorCodeGenerateStop", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("/Views/Shared/_Layout.cshtml", file);
|
||||
},
|
||||
e =>
|
||||
{
|
||||
Assert.Equal("AddSyntaxTrees", e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal("Pages_Index_cshtml.g.cs", file);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -2490,60 +2588,5 @@ namespace MyApp
|
|||
|
||||
Assert.Empty(result.GeneratedSources);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SourceGenerator_Class_Inside_CodeBlock()
|
||||
{
|
||||
var project = CreateTestProject(new()
|
||||
{
|
||||
["Component.Razor"] =
|
||||
"""
|
||||
<h1>Hello world</h1>
|
||||
|
||||
@code
|
||||
{
|
||||
public class X {}
|
||||
}
|
||||
"""});
|
||||
|
||||
var compilation = await project.GetCompilationAsync();
|
||||
var driver = await GetDriverAsync(project);
|
||||
|
||||
var result = RunGenerator(compilation!, ref driver).VerifyPageOutput(
|
||||
@"#pragma checksum ""Component.Razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""20b14071a74e1fd554d7b3dff6ff41722270ebee""
|
||||
// <auto-generated/>
|
||||
#pragma warning disable 1591
|
||||
namespace MyApp
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
public partial class Component : global::Microsoft.AspNetCore.Components.ComponentBase
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
|
||||
{
|
||||
__builder.AddMarkupContent(0, ""<h1>Hello world</h1>"");
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
#nullable restore
|
||||
#line 4 ""Component.Razor""
|
||||
|
||||
public class X {}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#nullable disable
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
");
|
||||
|
||||
Assert.Empty(result.Diagnostics);
|
||||
Assert.Single(result.GeneratedSources);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,10 @@ using System.Text.Encodings.Web;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
@ -43,9 +45,9 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators;
|
|||
[Collection(nameof(RazorSourceGenerator))]
|
||||
public abstract class RazorSourceGeneratorTestsBase
|
||||
{
|
||||
protected static async ValueTask<GeneratorDriver> GetDriverAsync(Project project)
|
||||
protected static async ValueTask<GeneratorDriver> GetDriverAsync(Project project, Action<TestAnalyzerConfigOptionsProvider>? configureGlobalOptions = null)
|
||||
{
|
||||
var (driver, _) = await GetDriverWithAdditionalTextAsync(project);
|
||||
var (driver, _) = await GetDriverWithAdditionalTextAsync(project, configureGlobalOptions);
|
||||
return driver;
|
||||
}
|
||||
|
||||
|
@ -134,12 +136,27 @@ public abstract class RazorSourceGeneratorTestsBase
|
|||
|
||||
// Create ViewContext.
|
||||
var appBuilder = WebApplication.CreateBuilder();
|
||||
appBuilder.Services.AddMvc().AddApplicationPart(assembly);
|
||||
appBuilder.Services.AddMvc().ConfigureApplicationPartManager(manager =>
|
||||
{
|
||||
var partFactory = new ConsolidatedAssemblyApplicationPartFactory();
|
||||
foreach (var applicationPart in partFactory.GetApplicationParts(assembly))
|
||||
{
|
||||
manager.ApplicationParts.Add(applicationPart);
|
||||
}
|
||||
});
|
||||
var app = appBuilder.Build();
|
||||
var httpContext = new DefaultHttpContext
|
||||
{
|
||||
RequestServices = app.Services
|
||||
};
|
||||
var requestFeature = new HttpRequestFeature
|
||||
{
|
||||
Method = HttpMethods.Get,
|
||||
Protocol = HttpProtocol.Http2,
|
||||
Scheme = "http"
|
||||
};
|
||||
requestFeature.Headers.Host = "localhost";
|
||||
httpContext.Features.Set<IHttpRequestFeature>(requestFeature);
|
||||
var actionContext = new ActionContext(
|
||||
httpContext,
|
||||
new AspNetCore.Routing.RouteData(),
|
||||
|
@ -158,7 +175,10 @@ public abstract class RazorSourceGeneratorTestsBase
|
|||
page.HtmlEncoder = HtmlEncoder.Default;
|
||||
|
||||
// Render the page.
|
||||
await page.ExecuteAsync();
|
||||
var view = ActivatorUtilities.CreateInstance<RazorView>(app.Services,
|
||||
/* IReadOnlyList<IRazorPage> viewStartPages */ Array.Empty<IRazorPage>(),
|
||||
/* IRazorPage razorPage */ page);
|
||||
await view.RenderAsync(viewContext);
|
||||
|
||||
assemblyLoadContext.Unload();
|
||||
|
||||
|
@ -469,11 +489,4 @@ internal static class Extensions
|
|||
Assert.StartsWith("#pragma", trimmed);
|
||||
return trimmed.Substring(trimmed.IndexOf('\n') + 1);
|
||||
}
|
||||
|
||||
public static void AssertSingleItem(this RazorEventListener.RazorEvent e, string expectedEventName, string expectedFileName)
|
||||
{
|
||||
Assert.Equal(expectedEventName, e.EventName);
|
||||
var file = Assert.Single(e.Payload);
|
||||
Assert.Equal(expectedFileName, file);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Hello from Component1
|
||||
Hello from Derived
|
|
@ -0,0 +1,2 @@
|
|||
Hello from Component1
|
||||
Hello from Derived
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
Value: 43
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
Value: 43
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
Value: 43
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
Value: 43
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
<a href="mailto:example">custom tag helper</a>
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
<email mail="example1">inside email</email>
|
||||
<a href="mailto:example2">inside mail</a>
|
Загрузка…
Ссылка в новой задаче