Repository navigation
Add the documentation directive to the Razor compiler - #85723
Conversation
|
Azure Pipelines: 2 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
ba393cd to
c7b6169
Compare
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
No concrete defect was found, but the new parser recovery and code-generation behavior warrants final maintainer review.
Review effort: Balanced
Findings: None
What changed in this PR
Adds Razor 12’s @documentation directive, allowing generated component and view classes to receive source-mapped XML documentation safely.
Changes:
- Implements versioned parsing, lowering, code generation, diagnostics, recovery, and import/duplicate handling.
- Adds extensive component, view, source-mapping, compatibility, and cohost diagnostic coverage.
- Documents directive behavior and the RZ1048 warning wave.
| File group | Description |
|---|---|
docs/razor/documentation-directive.md |
Documents directive behavior and recovery. |
docs/razor/warning-levels.md |
Documents the RZ1048 warning wave. |
DocumentationDirectiveCodeGenerationTest.cs |
Component baseline tests. |
DocumentationDirectiveCodeGenerationTest_Legacy.cs |
Legacy-view baseline tests. |
DocumentationDirectiveCompatibilityTest.cs |
Version compatibility tests. |
DocumentationDirectiveIntegrationTest.cs |
Comprehensive compiler behavior tests. |
DocumentationDirectiveCodeGenerationTest/** (89 files) |
Component syntax, IR, generated-code, mapping, and diagnostic baselines. |
DocumentationDirectiveCodeGenerationTest_Legacy/** (70 files) |
Legacy-view inputs and expected baselines. |
DefaultRazorIntermediateNodeLoweringPhase.cs |
Lowers documentation syntax to IR. |
DefaultRazorMarkupSplitPhase.cs |
Retains documentation on declaration partials. |
DocumentationDirective.cs |
Defines and registers the directive. |
DocumentationDirectivePass.cs |
Attaches the first local block to the class. |
DocumentationIntermediateNode.cs |
Safely emits source-mapped XML documentation. |
CSharpCodeParser.cs |
Parses XML bodies and implements recovery. |
ClassifiedSpanVisitor.cs |
Classifies the new syntax node. |
TagHelperBlockRewriter.cs |
Avoids rewriting documentation bodies. |
RazorDiagnosticFactory.cs |
Defines RZ1047–RZ1049. |
RazorProjectEngine.cs |
Enables the feature for Razor 12+. |
Resources.resx |
Adds directive and diagnostic text. |
Syntax.xml |
Defines the documentation syntax node. |
SyntaxKind.cs |
Adds its syntax kind. |
SyntaxSerializer.cs |
Serializes the node in syntax baselines. |
Syntax.xml.*.Generated.cs (3 files) |
Regenerates syntax nodes, factories, and visitors. |
CohostDocumentPullDiagnosticsTest.cs (3 projects) |
Verifies endpoint diagnostics across cohost clients. |
RazorBaselineIntegrationTestBase.cs |
Adds syntax-tree baseline assertions. |
Specific directive syntax nodes share the same descriptor contract. Put it on their base so serializers and consumers can use it without passing the descriptor separately.
Components and views need a source-mapped way to document their generated class. Keep the XML file-local, let C# validate it, and prevent malformed documentation from escaping into generated code.
These two examples show the entire compiler feature from Razor syntax to generated C#. Keeping their source and baselines together gives reviewers a small starting point before the rest of the test matrix.
The directive needs to recover without swallowing later markup or replacing the first local block. Cover version boundaries, diagnostics and malformed input through the compiler and editor endpoints. The remaining baseline files follow in the next commit.
The integration scenarios need checked-in syntax, IR, generated C# and mapping expectations. Keeping those outputs separate makes the test inputs and generated results easier to review.
c7b6169 to
21e0428
Compare
| @documentation {<summary> | ||
| } | ||
| @code { public int Example => 1; } | ||
| </summary> Extra information.} |
There was a problem hiding this comment.
I see you fixed this example to not emit any errors, but other punctuation seems to be still broken. For example, replacing the period with an exclamation mark fails with (4,1): error RZ9981: Unexpected closing tag 'summary' with no matching start tag.
@documentation {<summary>
}
@code { public int Example => 1; }
</summary> Extra information!}
<p>After</p>Consider adding a test for that too.
There was a problem hiding this comment.
Great catch! Thank you. Anything that the parser produces a separate token for, and not part of the Text token, would fail and we get bad error recovery.
There was a problem hiding this comment.
Okay, in order to fix this and not introduce the need to parse XML when recovering from failing to parse XML, I decided to just go with a more relaxed recovery rule. Essentially the documentation parsing might go all the way to EOF, and then recovery will pick a close brace. This is a little extreme, but feels much more pragmatic to me than trying to solve the worlds problems for a document that is ultimately invalid.
Trust XML-selected closing braces and only use Razor recovery at EOF. This keeps trailing punctuation and code examples in the documentation. Remove the unused completeness hint and cover !, ?, other tokenised punctuation, and the accepted malformed-XML recovery cases.
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The parser, lowering, safe emission, mappings, compatibility behavior, and diagnostics are consistently implemented and extensively tested.
Review effort: Balanced
Findings: None
Resolved since last review (1)
Classify `@documentation` through the existing workspace pipeline so the directive and its XML body get consistent semantic tokens in both editors. Includes the shared tests and their checked-in baselines, without folding, completion or formatting changes. Builds on #85723. This is the classification layer of #85414. Ran the full `CohostSemanticTokensRangeEndpointTest` class with analysers enabled and baseline generation disabled: **96/96 passed in VS Code (`net10.0`) and 96/96 in VS (`net472`)**. Each host exercised all 20 new documentation baseline variants (five layouts, both file kinds and background on/off), plus all 12 existing render-mode cases. ###### Microsoft Reviewers: [Open in CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/dotnet/roslyn/pull/85724)

Adds
@documentationin Razor 12 so components and views can document their generated class without losing source mappings. The XML stays file-local and C# validates it. The first local directive wins, imports cannot suppress it, and bodies containing an unsafe*/aren't emitted. Includes the RZ1047/RZ1048/RZ1049 diagnostics and recovery, declaration-splitting and mapping coverage.Depends on #85721 (
davidwengier/razor-xml-parsing). Part of #85414; editor classification, folding, completion, formatting and quick fixes follow separately.Review order (five commits): shared directive descriptors; compiler implementation; two baseline-backed examples; remaining test sources and inputs; remaining expected baselines. The fourth commit builds but deliberately lacks the remaining baseline files until the fifth.
Validation: 4,514 compiler tests, 25 VS Code document-diagnostic tests and 47 Visual Studio document-diagnostic tests passed, with analysers enabled and baseline generation off. Both compiler target frameworks and all three affected test projects build. The preparatory slice passed 587 existing syntax/directive checks, and both basic examples passed before adding the rest of the matrix.
Microsoft Reviewers: Open in CodeFlow