Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ public void Execute_CombinesErrorsOnRewritingErrors()
codeDocument = projectEngine.ExecutePhase<DefaultRazorTagHelperRewritePhase>(codeDocument);

// Assert
var outputTree = codeDocument.GetSyntaxTree();
var outputTree = codeDocument.GetTagHelperRewrittenSyntaxTree();
Assert.Empty(originalTree.Diagnostics);
Assert.NotSame(erroredOriginalTree, outputTree);
Assert.Equal<RazorDiagnostic>([initialError, expectedRewritingError], outputTree.Diagnostics);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ internal class DefaultRazorIntermediateNodeLoweringPhase : RazorEnginePhaseBase,
{
protected override RazorCodeDocument ExecuteCore(RazorCodeDocument codeDocument, CancellationToken cancellationToken)
{
var syntaxTree = codeDocument.GetPreTagHelperSyntaxTree() ?? codeDocument.GetSyntaxTree();
// The canonical syntax tree is established by DefaultRazorTagHelperContextDiscoveryPhase,
// which always runs before this phase in the pipeline.
var syntaxTree = codeDocument.GetSyntaxTree();
ThrowForMissingDocumentDependency(syntaxTree);

var documentNode = new DocumentIntermediateNode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ internal sealed partial class DefaultRazorTagHelperContextDiscoveryPhase : Razor
{
protected override RazorCodeDocument ExecuteCore(RazorCodeDocument codeDocument, CancellationToken cancellationToken)
{
var syntaxTree = codeDocument.GetPreTagHelperSyntaxTree() ?? codeDocument.GetSyntaxTree();
// The canonical syntax tree is established by DefaultRazorParsingPhase (which runs before this phase).
var syntaxTree = codeDocument.GetSyntaxTree();
ThrowForMissingDocumentDependency(syntaxTree);

if (!codeDocument.TryGetTagHelpers(out var tagHelpers))
Expand Down Expand Up @@ -56,7 +57,6 @@ protected override RazorCodeDocument ExecuteCore(RazorCodeDocument codeDocument,
var context = TagHelperDocumentContext.GetOrCreate(tagHelperPrefix, visitor.GetResults());
return codeDocument
.WithTagHelperContext(context)
.WithPreTagHelperSyntaxTree(syntaxTree)
.WithDirectiveTagHelperContributions(directiveContributions);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,28 @@ internal sealed class DefaultRazorTagHelperRewritePhase : RazorEnginePhaseBase
{
protected override RazorCodeDocument ExecuteCore(RazorCodeDocument codeDocument, CancellationToken cancellationToken)
{
if (!codeDocument.TryGetPreTagHelperSyntaxTree(out var syntaxTree) ||
!codeDocument.TryGetTagHelperContext(out var context) ||
context.TagHelpers is [])
if (!codeDocument.TryGetSyntaxTree(out var syntaxTree))
{
// No descriptors, so no need to see if any are used. Without setting this though,
// we trigger an Assert in the ProcessRemaining method in the source generator.
return codeDocument.WithReferencedTagHelpers([]);
}

if (!codeDocument.TryGetTagHelperContext(out var context) ||
context.TagHelpers is [])
{
// No tag helpers to rewrite. The rewritten tree is the same as the canonical tree.
// Tooling in the workspaces layer always expects GetRequiredTagHelperRewrittenSyntaxTree()
// to return a non-null value after the full pipeline has run.
return codeDocument
.WithReferencedTagHelpers([])
.WithTagHelperRewrittenSyntaxTree(syntaxTree);
}

var binder = context.GetBinder();
using var usedHelpers = new TagHelperCollection.Builder();
var rewrittenSyntaxTree = TagHelperParseTreeRewriter.Rewrite(syntaxTree, binder, usedHelpers, cancellationToken);

return codeDocument
.WithReferencedTagHelpers(usedHelpers.ToCollection())
.WithSyntaxTree(rewrittenSyntaxTree);
.WithTagHelperRewrittenSyntaxTree(rewrittenSyntaxTree);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,17 @@ protected override RazorCodeDocument ExecuteCore(RazorCodeDocument codeDocument,
}

var tagHelperContext = codeDocument.GetTagHelperContext();
var syntaxTree = codeDocument.GetPreTagHelperSyntaxTree() ?? codeDocument.GetSyntaxTree();
var parserOptions = syntaxTree?.Options;

// This phase works with IR nodes only -- no syntax tree access needed.
// RazorCodeDocument.ParserOptions is a non-nullable property initialized by Create(),
// so it is always available here.
var parserOptions = codeDocument.ParserOptions;

// Choose resolver based on file kind and language version. Component features
// (MarkupElementIntermediateNode, RZ10012 diagnostics) require Version_3_0+ because
// the ComponentDocumentClassifierPass is only registered at that version.
_resolver = (codeDocument.FileKind.IsComponent() || codeDocument.FileKind.IsComponentImport())
&& parserOptions?.LanguageVersion >= RazorLanguageVersion.Version_3_0
&& parserOptions.LanguageVersion >= RazorLanguageVersion.Version_3_0
? new ComponentTagHelperResolver()
: new LegacyTagHelperResolver();

Expand All @@ -65,7 +68,7 @@ protected override RazorCodeDocument ExecuteCore(RazorCodeDocument codeDocument,

using var usedHelpers = new TagHelperCollection.Builder();
var sourceDocument = codeDocument.Source;
var context = new ResolutionContext(sourceDocument, parserOptions, documentNode);
var context = new ResolutionContext(sourceDocument, documentNode);
ResolveElements(documentNode, binder, prefix, usedHelpers, in context);

// Add tag helper descriptor validation diagnostics (e.g. RZ3003).
Expand All @@ -90,13 +93,11 @@ protected override RazorCodeDocument ExecuteCore(RazorCodeDocument codeDocument,
private readonly struct ResolutionContext
{
public readonly RazorSourceDocument SourceDocument;
public readonly RazorParserOptions ParserOptions;
public readonly DocumentIntermediateNode DocumentNode;

public ResolutionContext(RazorSourceDocument sourceDocument, RazorParserOptions parserOptions, DocumentIntermediateNode documentNode)
public ResolutionContext(RazorSourceDocument sourceDocument, DocumentIntermediateNode documentNode)
{
SourceDocument = sourceDocument;
ParserOptions = parserOptions;
DocumentNode = documentNode;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,14 @@ public sealed partial class RazorCodeDocument

private readonly TagHelperCollection? _tagHelpers;
private readonly TagHelperCollection? _referencedTagHelpers;
private readonly RazorSyntaxTree? _preTagHelperSyntaxTree;
// The canonical syntax tree produced by parsing and syntax-tree passes, before tag helper rewriting.
// Established by DefaultRazorTagHelperContextDiscoveryPhase (which reads it from _tagHelperRewrittenSyntaxTree
// on the first run). Once set, this field is stable throughout the rest of the pipeline.
private readonly RazorSyntaxTree? _syntaxTree;
// The working syntax tree: initially set by DefaultRazorParsingPhase (same value as _syntaxTree),
// updated by DefaultRazorSyntaxTreePhase, and finally replaced with the tag-helper-rewritten tree
// by DefaultRazorTagHelperRewritePhase.
private readonly RazorSyntaxTree? _tagHelperRewrittenSyntaxTree;
private readonly ImmutableArray<RazorSyntaxTree> _importSyntaxTrees;
private readonly TagHelperDocumentContext? _tagHelperContext;
private readonly DocumentIntermediateNode? _documentNode;
Expand All @@ -38,8 +44,8 @@ private RazorCodeDocument(
RazorCodeGenerationOptions codeGenerationOptions,
TagHelperCollection? tagHelpers,
TagHelperCollection? referencedTagHelpers,
RazorSyntaxTree? preTagHelperSyntaxTree,
RazorSyntaxTree? syntaxTree,
RazorSyntaxTree? tagHelperRewrittenSyntaxTree,
ImmutableArray<RazorSyntaxTree> importSyntaxTrees,
TagHelperDocumentContext? tagHelperContext,
DocumentIntermediateNode? documentNode,
Expand All @@ -54,8 +60,8 @@ private RazorCodeDocument(

_tagHelpers = tagHelpers;
_referencedTagHelpers = referencedTagHelpers;
_preTagHelperSyntaxTree = preTagHelperSyntaxTree;
_syntaxTree = syntaxTree;
_tagHelperRewrittenSyntaxTree = tagHelperRewrittenSyntaxTree;
_importSyntaxTrees = importSyntaxTrees;
_tagHelperContext = tagHelperContext;
_documentNode = documentNode;
Expand Down Expand Up @@ -84,8 +90,8 @@ public static RazorCodeDocument Create(
codeGenerationOptions ?? RazorCodeGenerationOptions.Default,
tagHelpers: null,
referencedTagHelpers: null,
preTagHelperSyntaxTree: null,
syntaxTree: null,
tagHelperRewrittenSyntaxTree: null,
importSyntaxTrees: default,
tagHelperContext: null,
documentNode: null,
Expand All @@ -111,7 +117,7 @@ internal RazorCodeDocument WithTagHelpers(TagHelperCollection? value)
{
return this;
}
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, value, _referencedTagHelpers, _preTagHelperSyntaxTree, _syntaxTree, _importSyntaxTrees, _tagHelperContext, _documentNode, _csharpDocument, _directiveTagHelperContributions);
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, value, _referencedTagHelpers, _syntaxTree, _tagHelperRewrittenSyntaxTree, _importSyntaxTrees, _tagHelperContext, _documentNode, _csharpDocument, _directiveTagHelperContributions);
}

internal bool TryGetReferencedTagHelpers([NotNullWhen(true)] out TagHelperCollection? result)
Expand All @@ -132,50 +138,51 @@ internal RazorCodeDocument WithReferencedTagHelpers(TagHelperCollection value)
{
return this;
}
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, value, _preTagHelperSyntaxTree, _syntaxTree, _importSyntaxTrees, _tagHelperContext, _documentNode, _csharpDocument, _directiveTagHelperContributions);
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, value, _syntaxTree, _tagHelperRewrittenSyntaxTree, _importSyntaxTrees, _tagHelperContext, _documentNode, _csharpDocument, _directiveTagHelperContributions);
}

internal bool TryGetPreTagHelperSyntaxTree([NotNullWhen(true)] out RazorSyntaxTree? result)
internal bool TryGetSyntaxTree([NotNullWhen(true)] out RazorSyntaxTree? result)
{
result = _preTagHelperSyntaxTree;
result = _syntaxTree;
return result is not null;
}

internal RazorSyntaxTree? GetPreTagHelperSyntaxTree()
=> _preTagHelperSyntaxTree;
internal RazorSyntaxTree? GetSyntaxTree()
=> _syntaxTree;

internal RazorSyntaxTree GetRequiredPreTagHelperSyntaxTree()
=> _preTagHelperSyntaxTree.AssumeNotNull();
internal RazorSyntaxTree GetRequiredSyntaxTree()
=> _syntaxTree.AssumeNotNull();

internal RazorCodeDocument WithPreTagHelperSyntaxTree(RazorSyntaxTree? value)
internal RazorCodeDocument WithSyntaxTree(RazorSyntaxTree value)
{
if (ReferenceEquals(value, _preTagHelperSyntaxTree))
Debug.Assert(value is not null);
if (ReferenceEquals(value, _syntaxTree))
{
return this;
}
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, value, _syntaxTree, _importSyntaxTrees, _tagHelperContext, _documentNode, _csharpDocument, _directiveTagHelperContributions);
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, value, _tagHelperRewrittenSyntaxTree, _importSyntaxTrees, _tagHelperContext, _documentNode, _csharpDocument, _directiveTagHelperContributions);
}

internal bool TryGetSyntaxTree([NotNullWhen(true)] out RazorSyntaxTree? result)
internal bool TryGetTagHelperRewrittenSyntaxTree([NotNullWhen(true)] out RazorSyntaxTree? result)
{
result = _syntaxTree;
result = _tagHelperRewrittenSyntaxTree;
return result is not null;
}

internal RazorSyntaxTree? GetSyntaxTree()
=> _syntaxTree;
internal RazorSyntaxTree? GetTagHelperRewrittenSyntaxTree()
=> _tagHelperRewrittenSyntaxTree;

internal RazorSyntaxTree GetRequiredSyntaxTree()
=> _syntaxTree.AssumeNotNull();
internal RazorSyntaxTree GetRequiredTagHelperRewrittenSyntaxTree()
=> _tagHelperRewrittenSyntaxTree.AssumeNotNull();

internal RazorCodeDocument WithSyntaxTree(RazorSyntaxTree value)
internal RazorCodeDocument WithTagHelperRewrittenSyntaxTree(RazorSyntaxTree value)
{
Debug.Assert(value is not null);
if (ReferenceEquals(value, _syntaxTree))
if (ReferenceEquals(value, _tagHelperRewrittenSyntaxTree))
{
return this;
}
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, _preTagHelperSyntaxTree, value, _importSyntaxTrees, _tagHelperContext, _documentNode, _csharpDocument, _directiveTagHelperContributions);
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, _syntaxTree, value, _importSyntaxTrees, _tagHelperContext, _documentNode, _csharpDocument, _directiveTagHelperContributions);
}

internal bool TryGetImportSyntaxTrees(out ImmutableArray<RazorSyntaxTree> result)
Expand All @@ -202,7 +209,7 @@ internal RazorCodeDocument WithImportSyntaxTrees(ImmutableArray<RazorSyntaxTree>
{
return this;
}
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, _preTagHelperSyntaxTree, _syntaxTree, value, _tagHelperContext, _documentNode, _csharpDocument, _directiveTagHelperContributions);
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, _syntaxTree, _tagHelperRewrittenSyntaxTree, value, _tagHelperContext, _documentNode, _csharpDocument, _directiveTagHelperContributions);
}

internal bool TryGetTagHelperContext([NotNullWhen(true)] out TagHelperDocumentContext? result)
Expand All @@ -225,7 +232,7 @@ internal RazorCodeDocument WithTagHelperContext(TagHelperDocumentContext value)
{
return this;
}
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, _preTagHelperSyntaxTree, _syntaxTree, _importSyntaxTrees, value, _documentNode, _csharpDocument, _directiveTagHelperContributions);
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, _syntaxTree, _tagHelperRewrittenSyntaxTree, _importSyntaxTrees, value, _documentNode, _csharpDocument, _directiveTagHelperContributions);
}

internal bool TryGetDocumentNode([NotNullWhen(true)] out DocumentIntermediateNode? result)
Expand All @@ -247,7 +254,7 @@ internal RazorCodeDocument WithDocumentNode(DocumentIntermediateNode value)
{
return this;
}
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, _preTagHelperSyntaxTree, _syntaxTree, _importSyntaxTrees, _tagHelperContext, value, _csharpDocument, _directiveTagHelperContributions);
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, _syntaxTree, _tagHelperRewrittenSyntaxTree, _importSyntaxTrees, _tagHelperContext, value, _csharpDocument, _directiveTagHelperContributions);
}

internal bool TryGetCSharpDocument([NotNullWhen(true)] out RazorCSharpDocument? result)
Expand All @@ -269,7 +276,7 @@ internal RazorCodeDocument WithCSharpDocument(RazorCSharpDocument value)
{
return this;
}
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, _preTagHelperSyntaxTree, _syntaxTree, _importSyntaxTrees, _tagHelperContext, _documentNode, value, _directiveTagHelperContributions);
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, _syntaxTree, _tagHelperRewrittenSyntaxTree, _importSyntaxTrees, _tagHelperContext, _documentNode, value, _directiveTagHelperContributions);
}

internal ImmutableArray<DirectiveTagHelperContribution> GetDirectiveTagHelperContributions()
Expand All @@ -282,7 +289,7 @@ internal RazorCodeDocument WithDirectiveTagHelperContributions(ImmutableArray<Di
return this;
}

return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, _preTagHelperSyntaxTree, _syntaxTree, _importSyntaxTrees, _tagHelperContext, _documentNode, _csharpDocument, value);
return new RazorCodeDocument(Source, Imports, ParserOptions, CodeGenerationOptions, _tagHelpers, _referencedTagHelpers, _syntaxTree, _tagHelperRewrittenSyntaxTree, _importSyntaxTrees, _tagHelperContext, _documentNode, _csharpDocument, value);
}

// In general documents will have a relative path (relative to the project root).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public static RazorHtmlDocument GetHtmlDocument(RazorCodeDocument codeDocument)
using var codeWriter = new CodeWriter(options);

var htmlWriter = new RazorHtmlWriter(source, codeWriter);
var syntaxTree = codeDocument.GetRequiredSyntaxTree();
var syntaxTree = codeDocument.GetRequiredTagHelperRewrittenSyntaxTree();

htmlWriter.Visit(syntaxTree);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ public SourceGeneratorRazorCodeDocument ProcessInitialParse(RazorProjectItem pro

codeDocument = ExecutePhases(Phases[.._discoveryPhaseIndex], codeDocument, cancellationToken);

// record the syntax tree, before the tag helper re-writing occurs
codeDocument = codeDocument.WithPreTagHelperSyntaxTree(codeDocument.GetSyntaxTree());
// By this point, DefaultRazorParsingPhase has set the canonical syntax tree (_syntaxTree)
// so that discovery and subsequent phases can read it via GetSyntaxTree().
return new SourceGeneratorRazorCodeDocument(codeDocument);
}

Expand All @@ -69,7 +69,7 @@ public SourceGeneratorRazorCodeDocument ProcessTagHelpers(
bool checkForIdempotency,
CancellationToken cancellationToken)
{
Debug.Assert(sgDocument.CodeDocument.GetPreTagHelperSyntaxTree() is not null);
Debug.Assert(sgDocument.CodeDocument.GetSyntaxTree() is not null);

int startIndex = _discoveryPhaseIndex;
var codeDocument = sgDocument.CodeDocument;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public Task<ImmutableArray<RazorVSInternalCodeAction>> ProvideAsync(RazorCodeAct
return SpecializedTasks.EmptyImmutableArray<RazorVSInternalCodeAction>();
}

if (!context.CodeDocument.TryGetSyntaxTree(out var syntaxTree))
if (!context.CodeDocument.TryGetTagHelperRewrittenSyntaxTree(out var syntaxTree))
{
return SpecializedTasks.EmptyImmutableArray<RazorVSInternalCodeAction>();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ internal class ExtractToComponentCodeActionResolver(
builder.AppendLine();
}

var syntaxTree = componentDocument.GetRequiredSyntaxTree();
var syntaxTree = componentDocument.GetRequiredTagHelperRewrittenSyntaxTree();

// Right now this includes all the usings in the original document.
// https://github.com/dotnet/razor/issues/11025 tracks reducing to only the required set.
Expand Down
Loading
Loading