Repository navigation
Consume split Razor declarations through pre-compilation source output - #84670
Conversation
Emit the resolution-independent declaration half of a splittable Razor component via RegisterPreCompilationSourceOutput so it lands in the compilation that tag-helper discovery reads. Discovery runs over the real compilation instead of a separate declaration compilation parsed from generated text, which is the step that unlocks reusing the standard compilation's tag helpers. - A component the split can partition contributes its decl through the pre-compilation output; that decl is visible to tag-helper discovery and is compiled into the output as the decl partial alongside the impl partial. - A component the split cannot partition has no main-run decl, so the separate declaration engine produces a discovery-only decl for it. Fast discovery covers the standard compilation (split decls plus user types); slow discovery runs only when something falls back, augmenting the compilation with the fallback decl trees and keeping just the fallback types. The two are merged, with fallback types excluded from fast discovery so a type that is also a compilation partial isn't discovered twice or with an incomplete partial-only descriptor. - The decl half suppresses its #pragma checksum so a markup-only edit leaves the decl SourceText byte-identical: discovery stays cached and the decl stays out of the pre-compilation compilation delta. The impl half keeps its checksum for the debugger. - Decl diagnostics flow through the implementation-time output, since the pre-compilation output runs before the compilation exists. Tests match generated sources as a set rather than by position (decls and impls arrive through separate outputs) and follow the renamed incremental steps (DeclSources, FastTagHelpers). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c45f67d5-6fe0-4f6b-8c68-c268dc7c0621
…eates Generate-type-in-a-new-file copies the triggering document's file banner into the new file. Triggered from a Razor component's split declaration document -- whose first line is "// <auto-generated/>" because the decl suppresses its #pragma checksum -- that puts the auto-generated banner on the user's new .cs file, which is authored code, not generated. The delegated C# code action resolver drops a leading auto-generated comment from files the action creates, keeping authored files free of the marker while leaving the generated documents themselves untouched. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c45f67d5-6fe0-4f6b-8c68-c268dc7c0621
A component the markup split can't partition -- one with a header/arity directive (@inherits/@implements/@typeparam) or class-body markup it can't route -- has its tag-helper descriptor produced by the separate declaration engine rather than read from the pre-compilation compilation. That compilation therefore omits the fallback component's type, so a split component that references it in C# (e.g. [Parameter] public Widget Child) binds to an error type and records an unqualified name, which breaks consumers with CS0246 when they don't import the fallback's namespace. To make the type resolve, the split phase emits a bodiless type shell for such a component: the namespace, class name, modifiers, and type-parameter names only -- no base type, interfaces, members, or constraints. Routed through pre-compilation output, it lets the fallback type (and its nested types, which qualify from the resolved outer type) resolve, so references record a fully-qualified name. Carrying no base, the shell is not a component, so tag-helper discovery ignores it and the declaration engine owns its complete descriptor; as a member-less partial it rejoins the emitted impl cleanly. A non-null FallbackComponentTypeName on the document node routes a component to the declaration engine. It is a separate signal from the shell because an unsplit component with a primary class also produces a (shell) declaration, so a declaration's presence does not by itself distinguish a split component from a fallback one. A component with no primary class or a suppressed body carries the type name without a shell -- it has no distinct type to declare. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c45f67d5-6fe0-4f6b-8c68-c268dc7c0621
A fallback component emits a bodiless type-shell declaration document, so each component code-generation integration test that exercises one gains a declaration baseline (.decl.codegen.cs and .decl.ir.txt). The impl baselines are unchanged; these files are produced via GenerateBaselines.ShouldGenerate. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c45f67d5-6fe0-4f6b-8c68-c268dc7c0621
… half A fallback component emits a bodiless "type shell" declaration document so its type still resolves in the pre-compilation compilation. That shell is a non-null RazorCSharpDocument that carries no members or using directives, so tooling which treats any non-null declaration document as the component's full declaration surface is misled by it. Mark the shell with RazorCSharpDocument.IsStubDocument, threaded from the split phase (DocumentIntermediateNode.IsStubDeclaration) through declaration lowering. Diagnostic translation treats a stub as absent: unused-using (IDE0005) diagnostics for a fallback component now come from the implementation document unfiltered, instead of being filtered against the shell's empty using set -- which dropped every genuinely-unused using. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c45f67d5-6fe0-4f6b-8c68-c268dc7c0621
The decl/impl split lowers a fallback component to a bodiless type shell in the pre-compilation compilation, so a split component whose [Parameter] type is a delegate nested in that fallback binds to an error type during discovery. @bind-Value then lowers as an EventCallback and the consumer fails with CS1503. Capture the scenario as a skipped test alongside the other @Bind coverage so the gap stays discoverable and the eventual fix has a ready regression guard. Tracked by dotnet#84646. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c45f67d5-6fe0-4f6b-8c68-c268dc7c0621
|
Azure Pipelines: Successfully started running 2 pipeline(s). There may be pipelines that require an authorized user to comment /azp run to run. |
|
Azure Pipelines: Successfully started running 2 pipeline(s). There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Wires Razor component declaration halves into the source generator’s pre-compilation output (so tag-helper discovery runs over the real compilation), adds a stub (“type shell”) decl document for fallback components so their types resolve during pre-compilation, and updates cohost diagnostics/code actions plus generator tests/baselines accordingly.
Changes:
- Emit split component decl sources via
RegisterPreCompilationSourceOutputand split tag-helper discovery into fast/slow paths (slow only for fallback components). - Introduce fallback component stub decl documents (
RazorCSharpDocument.IsStubDocument) and adjust diagnostics translation/filtering behavior accordingly. - Update cohost C# code action resolution to strip the generated banner from newly-created authored
.csfiles; refresh/extend SG and integration test baselines for decl outputs.
Reviewed changes
Copilot reviewed 89 out of 89 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostDocumentPullDiagnosticsTest.cs | Adds regression coverage for unused-usings on fallback components where the decl is a stub. |
| src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Diagnostics/RazorTranslateDiagnosticsService.cs | Treats stub decl documents as “absent” to avoid dropping real impl diagnostics (notably unused-usings). |
| src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/CSharp/CSharpCodeActionResolver.cs | Strips // <auto-generated/> banner from files created by delegated Roslyn code actions. |
| src/Razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.UnitTests/TestFiles/RazorSourceGeneratorComponentTests/Inject/Shared/Component1_razor.decl.g.cs | New decl baseline output for a component (decl emitted separately from impl). |
| src/Razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.UnitTests/RazorSourceGeneratorTestsBase.cs | Makes generated source verification order-independent; relaxes checksum trimming to support decl outputs without checksum. |
| src/Razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.UnitTests/RazorSourceGeneratorTests.cs | Updates incremental-step tracking names/expectations for fast discovery and decl pre-comp output. |
| src/Razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.UnitTests/RazorSourceGeneratorTagHelperTests.cs | Adjusts expected generated source counts when fallback components now produce stub decl + impl. |
| src/Razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.UnitTests/RazorSourceGeneratorComponentTests.cs | Updates expected counts and adds a skipped regression test documenting a known fallback nested-delegate limitation. |
| src/Razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.Helpers.cs | Adds helper to strip generic arity from descriptor type names for fallback matching. |
| src/Razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs | Rewires decl emission via pre-compilation output; introduces fast/slow tag-helper discovery and fallback filtering. |
| src/Razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocumentWriter.cs | Threads a new isStubDocument flag into RazorCSharpDocument construction. |
| src/Razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs | Adds IsStubDocument metadata to distinguish stub decl shells from real decl halves. |
| src/Razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Intermediate/DocumentIntermediateNode.cs | Extends IR to carry fallback component type name and clarifies decl node semantics (full decl vs stub shell). |
| src/Razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorMarkupSplitPhase.cs | Routes unsplittable components to fallback discovery and emits a stub decl shell for type resolution. |
| src/Razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorDeclCSharpLoweringPhase.cs | Marks fallback decl outputs as stub documents for downstream tooling decisions. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/RenderMode_With_TypeInference/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/RenderMode_With_TypeInference/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/RenderMode_Directive_WithTypeParam/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/RenderMode_Directive_WithTypeParam/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/RenderMode_Directive_WithTypeParam_Razor9/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/RenderMode_Directive_WithTypeParam_Razor9/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/RenderMode_Directive_WithTypeParam_First/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/RenderMode_Directive_WithTypeParam_First/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/InjectDirective/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/InjectDirective/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/InheritsDirective/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/InheritsDirective/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/InheritsDirective_NullableReferenceType/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/InheritsDirective_NullableReferenceType/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/InheritsDirective_NullableReferenceType_NullableDisabled/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/InheritsDirective_NullableReferenceType_NullableDisabled/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentTypeUsageWithInference/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentTypeUsageWithInference/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentTypeUsageWithGenericType/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentTypeUsageWithGenericType/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentTypeUsageWhitespace/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentTypeUsageWhitespace/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentTypeUsage/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentTypeUsage/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentTypeParamUsageWithImplicitExpression2/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentTypeParamUsageWithImplicitExpression2/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentTypeParamUsageWithImplicitExpression/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentTypeParamUsageWithImplicitExpression/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentMultipleTypeParamUsage/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentMultipleTypeParamUsage/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithAfter_Action/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithAfter_Action/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentBindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponentBindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeInference/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeInference/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeExplicit/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeExplicit/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/FormName_Component_Generic/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/FormName_Component_Generic/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/FormName_Component_Generic_RazorLangVersion7/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/FormName_Component_Generic_RazorLangVersion7/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameterValueTupleGloballyQualifiedTypes/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameterValueTupleGloballyQualifiedTypes/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameterValueTuple/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameterValueTuple/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameterValueTuple_ExplicitGenericArguments/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameterValueTuple_ExplicitGenericArguments/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameters/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameters/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameters_WithSemicolon/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameters_WithSemicolon/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameters_Interconnected/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameters_Interconnected/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameterArray/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithTypeParameterArray/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithConstrainedTypeParameters/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithConstrainedTypeParameters/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithConstrainedTypeParameters_WithSemicolon/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/ComponentWithConstrainedTypeParameters_WithSemicolon/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/CanProduceLinePragmasForComponentWithRenderFragment_02/TestComponent.decl.ir.txt | New decl IR baseline for stub decl output shape. |
| src/Razor/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentCodeGenerationTest/CanProduceLinePragmasForComponentWithRenderFragment_02/TestComponent.decl.codegen.cs | New decl codegen baseline for stub decl output shape. |
The four-line comment between the test signature and the `=>` arrow was indented one column too far, which the analyzer-enforced IDE0055 formatting leg rejects even though a plain Debug build does not run it. Re-indent it to the arrow continuation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c45f67d5-6fe0-4f6b-8c68-c268dc7c0621
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 89 out of 89 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (3)
src/Razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorMarkupSplitPhase.cs:56
- RouteToFallbackDiscovery assumes primaryClass is non-null, but this method calls it even when FindPrimaryClass()/FindPrimaryMethod()/FindPrimaryNamespace() returned null. That will hit Debug.Assert and then throw NullReferenceException when computing FallbackComponentTypeName (primaryClass.Name) in release builds. Consider preserving the prior behavior (return codeDocument) when primaryClass is null, and only routing to fallback discovery when a primary class exists.
src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/CSharp/CSharpCodeActionResolver.cs:148 - TryRemoveLeadingAutoGeneratedComment won’t strip the banner if the inserted text starts with a UTF-8 BOM (\uFEFF). The generated decl sources in this PR start with "// ", and Roslyn’s new-file text may include the BOM too, so the StartsWith("//") check can fail and the banner won’t be removed.
src/Razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorMarkupSplitPhase.cs:113 - This comment states that the type shell makes nested types resolve, but the shell only declares the outer partial class. Nested types declared in the fallback component’s Razor code are not present in the pre-compilation compilation, so references like Widget.MyHandler still bind as error types (see the skipped test added in this PR). Suggest adjusting the comment to avoid claiming nested-type resolution.
| // document's file banner into the new file. When the trigger is a Razor component's generated | ||
| // C#, that banner is "// <auto-generated/>" -- correct for the generated document, but it must | ||
| // not be written onto the user's authored file, so it is stripped below. | ||
| var createdFileUris = new HashSet<DocumentUri>(); |
| return codeAction; | ||
| } | ||
|
|
||
| // Removes a leading "// <auto-generated/>" banner that Roslyn copied from a Razor component's |
There was a problem hiding this comment.
It's interesting that this started breaking now, but thanks for fixing regardless :)
There was a problem hiding this comment.
The decl half now suppresses its #pragma checksum which leaves // <auto-generated/> as the literal first line of the decl document, which lead to the need to strip it.
Three follow-up fixes in the component split and cohost code-action paths: - The markup split routes a component with no classified primary class to fallback discovery, which dereferences the class name to build the discovery key; with Debug.Assert compiled out (Release) that is a NullReferenceException. Return the document unchanged when there is no primary class -- there is no component type to discover or to split. - The delegated code-action banner strip matches "//" after TrimStart(), but TrimStart() does not treat a leading UTF-8 BOM (U+FEFF) as whitespace, so a BOM-prefixed generated banner would be left on the newly created file. Strip a leading BOM before the check. - Use a pooled HashSet for the created-file URI set instead of allocating one. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c45f67d5-6fe0-4f6b-8c68-c268dc7c0621
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 89 out of 89 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (4)
src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/CSharp/CSharpCodeActionResolver.cs:139
- RemoveGeneratedCodeBanner currently rewrites NewText for every edit in a newly-created file, regardless of where the edit applies. If Roslyn ever returns multiple edits for a create-file operation, this can end up stripping an "" comment that is not actually the file banner (i.e., not inserted at position 0,0). Consider restricting this to edits whose range starts at the beginning of the document (and ideally only insertion edits at 0,0).
src/Razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorMarkupSplitPhase.cs:123 - The comment on BuildStubDeclDocument claims the shell makes nested types resolve, but the stub decl intentionally does not include nested type declarations. For nested types declared only in the fallback component’s implementation, they will still be absent from the pre-compilation compilation. The comment should be adjusted to avoid implying nested types are covered by the shell.
src/Razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.UnitTests/RazorSourceGeneratorTestsBase.cs:518 - VerifyPageOutput’s set-based matching uses CollapseWhitespace, but AssertEx.AssertEqualToleratingWhitespaceDifferences uses a different normalization (NormalizeWhitespace trims each line, drops empty lines, and adds indentation based on braces). This can prevent a true match from being found when ordering differs, and then the fallback positional assertion compares against the wrong GeneratedSourceResult. The normalization used for matching should mirror AssertEx.NormalizeWhitespace semantics.
src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/CSharp/CSharpCodeActionResolver.cs:149 - TryRemoveLeadingAutoGeneratedComment trims all leading whitespace before checking for "// <auto-generated...". That’s inconsistent with the comment (“banner at the very start”) and can make the check succeed even when the inserted text doesn’t start with "//". If the intent is just to handle a leading BOM, consider stripping only U+FEFF and otherwise requiring "//" at the start.
Builds on the decl/impl split now in
features/sonic(#84577, #84605).What this does
Wires the resolution-independent declaration half of a splittable Razor component through
RegisterPreCompilationSourceOutput, so tag-helper discovery runs over the real compilation instead of a separate declaration compilation parsed from generated text. This is the step that unlocks reusing the standard compilation's tag helpers.Components the markup split can't partition (a header/arity directive like
@inherits/@implements/@typeparam, or class-body markup it can't route) still go through the separate declaration engine. To keep their type resolvable in the pre-compilation compilation — so a split component that references one in C# (e.g.[Parameter] public Widget Child) doesn't bind to an error type and fail consumers with CS0246 — the split phase emits a bodiless type shell for them.Commits
#pragma checksumsuppression so markup-only edits keep discovery cached, set-based test matching.// <auto-generated/>banner (from the decl's suppressed-checksum first line) onto authored.csfiles..decl.codegen.cs/.decl.ir.txtbaselines.RazorCSharpDocument.IsStubDocument, so tooling (diagnostic translation) treats the member-less shell as absent; fixes dropped IDE0005 unused-usings for fallback components.PROTOTYPE(sonic)so it can't reachmainunfixed.Testing
net10.0).Known follow-ups
Microsoft Reviewers: Open in CodeFlow