| File: Language\DefaultRazorDeclCSharpLoweringPhase.cs | Web Access |
| Project: src\roslyn\src\Razor\src\Compiler\Microsoft.CodeAnalysis.Razor.Compiler\src\Microsoft.CodeAnalysis.Razor.Compiler.csproj (Microsoft.CodeAnalysis.Razor.Compiler) |
// 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; namespace Microsoft.AspNetCore.Razor.Language; /// <summary> /// Lowers the markup-free decl subtree that <see cref="DefaultRazorMarkupSplitPhase"/> stashed on the /// document node into the "decl" C# document -- the component's public API surface -- and stashes it via /// <c>WithDeclCSharpDocument</c>. Running before tag-helper discovery freezes the decl text ahead of /// resolution, which is what lets the source generator feed it into the input compilation instead of /// running a second declaration compilation. The matching "impl" half is produced by /// <see cref="DefaultRazorCSharpLoweringPhase"/>; both are emitted as <c>partial</c> so they rejoin at /// compile time. For anything the split phase left unsplit (a non-component, a suppressed primary body, /// or a fallback component) no decl subtree is stashed and this phase is a no-op; /// <see cref="DefaultRazorCSharpLoweringPhase"/> then produces the whole document as a single file. /// </summary> internal sealed class DefaultRazorDeclCSharpLoweringPhase : RazorEnginePhaseBase, IRazorCSharpLoweringPhase { protected override RazorCodeDocument ExecuteCore(RazorCodeDocument codeDocument, CancellationToken cancellationToken) { var documentNode = codeDocument.GetDocumentNode(); ThrowForMissingDocumentDependency(documentNode); if (documentNode.DeclDocumentNode is not { } declDocNode) { return codeDocument; } // The decl C# document is lowered before the tag-helper rewrite phase runs, so the code // document it back-references has no rewritten syntax tree. Tooling reads // GetRequiredTagHelperRewrittenSyntaxTree() off the decl document (e.g. diagnostic filtering // in the workspaces layer); the decl is markup-free, so its rewritten tree is just the // canonical syntax tree. Seed it here so that back-reference is complete without disturbing the // main document, which the real rewrite phase updates later. var declCodeDocument = codeDocument.GetTagHelperRewrittenSyntaxTree() is null ? codeDocument.WithTagHelperRewrittenSyntaxTree(codeDocument.GetRequiredSyntaxTree()) : codeDocument; // The decl writer suppresses diagnostic collection because every diagnostic on the decl tree is // also reachable from the impl tree the final lowering phase writes; letting both report would // surface every Razor-detected issue twice. // A non-null FallbackComponentTypeName marks the main document as a fallback, and a fallback's decl // (when it has one) is always the bodiless type shell rather than a real declaration surface, so it // flows to RazorCSharpDocument.IsStubDocument -- letting tooling tell a shell apart from a real // declaration half and fall back to the implementation document. var declDocument = RazorCSharpDocumentWriter.Write( declDocNode, declCodeDocument, reportDiagnostics: false, isDeclarationDocument: true, isStubDocument: documentNode.FallbackComponentTypeName is not null, cancellationToken: cancellationToken); return codeDocument.WithDeclCSharpDocument(declDocument); } }