| File: Language\Intermediate\DocumentIntermediateNode.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. #nullable disable using System; using Microsoft.AspNetCore.Razor.Language.CodeGeneration; namespace Microsoft.AspNetCore.Razor.Language.Intermediate; public sealed class DocumentIntermediateNode : IntermediateNode { public override IntermediateNodeCollection Children { get => field ??= []; } public string DocumentKind { get; set; } /// <summary> /// For a component document, the markup-free decl subtree that <see cref="DefaultRazorMarkupSplitPhase"/> /// captures for <see cref="DefaultRazorDeclCSharpLoweringPhase"/> to lower into the decl C# document /// before tag-helper discovery: the full declaration surface when the component splits completely, or /// a bodiless type shell when it can't (so its type still resolves in the pre-compilation /// compilation). Null for any other document -- a non-component, or a component with a suppressed /// primary body or no primary class. /// </summary> internal DocumentIntermediateNode DeclDocumentNode { get; set; } /// <summary> /// For a fallback component (one that could not be split), the full discoverable decl subtree -- /// the same declaration surface <see cref="DefaultRazorMarkupSplitPhase"/> builds for a split /// component, but retained here rather than emitted to pre-compilation. The source generator lowers /// it and feeds its syntax tree straight into slow discovery, so the fallback component's descriptor /// is produced from the already-parsed document instead of re-parsing the source through a separate /// declaration engine. Distinct from <see cref="DeclDocumentNode"/>, which for a fallback is the /// bodiless type shell emitted to pre-compilation for C# type resolution. Null when the component /// split completely, or for a fallback with no render method or namespace to build a decl from. /// </summary> internal DocumentIntermediateNode FallbackDiscoveryDeclDocumentNode { get; set; } /// <summary> /// The namespace-qualified type name of a component document that could not be split completely, so its /// tag-helper descriptor must be produced by the separate declaration engine (the fallback discovery /// path) rather than read from the pre-compilation compilation; <see langword="null"/> for a component /// that split completely or for a non-component. Set by <see cref="DefaultRazorMarkupSplitPhase"/>. A /// non-null value both marks the document for fallback discovery and carries the name the source /// generator matches to route its descriptor through slow discovery over the augmented compilation /// instead of fast discovery, without re-deriving the name from the generated code. Independent of /// <see cref="DeclDocumentNode"/>: a fallback component with a primary class also emits a type-shell /// decl for resolution. /// </summary> internal string FallbackComponentTypeName { get; set; } public RazorCodeGenerationOptions Options { get; set; } public CodeTarget Target { get; set; } public override void Accept(IntermediateNodeVisitor visitor) { if (visitor == null) { throw new ArgumentNullException(nameof(visitor)); } visitor.VisitDocument(this); } public override void FormatNode(IntermediateNodeFormatter formatter) { formatter.WriteContent(DocumentKind); formatter.WriteProperty(nameof(DocumentKind), DocumentKind); } protected override IntermediateNode CloneNode() { // The declaration subtree is already lowered and inert during replay, so it is shared by reference. var clone = new DocumentIntermediateNode { DocumentKind = DocumentKind, DeclDocumentNode = DeclDocumentNode, FallbackDiscoveryDeclDocumentNode = FallbackDiscoveryDeclDocumentNode, FallbackComponentTypeName = FallbackComponentTypeName, Options = Options, Target = Target, }; return clone; } }