Handle custom external model bases - #11183
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
commit: |
|
No changes needing a change description found. |
Use the system object model provider's base model chain for inheritance and expose customization-only properties through a TypeProvider hook instead of storing inherited properties separately. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Populate synthetic system object input models with referenced type properties so existing ModelProvider inheritance handles inherited property filtering. Skip constructor forwarding for synthetic custom-base providers so external constructor surfaces are not generated into derived models. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cover canonical generated duplicate removal when a custom system object base exposes the same wire path through a differently named property. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Stop storing a base model provider on SystemObjectModelProvider. Seed the CSharpTypeMap for external base types and let the existing BaseType/BuildBaseModelProvider path resolve inheritance normally. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the ModelProvider-local custom base helper and centralize synthetic SystemObjectModelProvider creation in TypeFactory. ModelProvider now only asks TypeFactory to create/register a model provider for a custom external base, then uses the existing BaseType/CSharpTypeMap lookup path for inheritance. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The root cause is fixed in microsoft/typespec#11183, so this SDK PR should not carry generator changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This reverts commit 6f3c763.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR refines how the C# generator models and serializes types that derive from custom/external base classes, removing reliance on a synthetic base-provider path and instead using existing type metadata and hierarchy-aware detection (especially for MRW XML serialization). It also adds test coverage around external base chains and canonical wire-path deduplication.
Changes:
- Extend model/provider plumbing to better represent external/custom base type chains (base type + constructor-parameter propagation behavior).
- Improve MRW serialization override decisions (JSON root return type discovery; XML override detection with signature/accessibility/overridability checks).
- Add tests + test data for external base behaviors and canonical duplicate wire-path filtering.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/SystemObjectModelProviderTests.cs | Adds coverage for representing an external base chain via type metadata without duplicating inherited properties. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/TestData/ModelCustomizationTests/CanFilterCanonicalDuplicateWirePathFromSystemObjectModelProviderBase/MockInputModel.cs | Adds test customization source defining a framework-like base (ResourceData) and a derived partial model. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/ModelCustomizationTests.cs | Adds test ensuring canonical duplicate wire-path properties are filtered when a system/custom base already maps that wire path. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Writers/CodeWriter.cs | Adds sealed emission support for method/property signatures. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/TypeProvider.cs | Enhances customized-member filtering to consider canonical duplicate wire paths (not just names). |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/SystemObjectModelProvider.cs | Adds base-type propagation and derived-constructor parameter behavior control for wrapped system types. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/NamedTypeSymbolProvider.cs | Adds interface list materialization and propagates sealed into method signature modifiers. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelProvider.cs | Gates base-constructor parameter propagation based on the base provider’s preference. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Primitives/MethodSignatureModifiers.cs | Adds Sealed to the modifier bitflags. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/MrwSerializationTypeDefinitions/XmlSerializationCustomizationTests.cs | Adds extensive XML override-detection tests across multiple base scenarios. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/XmlSerializationCustomizationTests/XmlModelWriteCoreOverridesGeneratedBaseWithCustomReplacement/BaseModel.cs | Adds test data for a generated base with a compatible virtual XML core method. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/XmlSerializationCustomizationTests/XmlModelWriteCoreDoesNotOverrideProtectedCustomExternalBase/MockInputModel.cs | Adds test data for a protected XML base method that must not be overridden by an internal method. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/XmlSerializationCustomizationTests/XmlModelWriteCoreDoesNotOverrideJsonOnlyCustomBase/MockInputModel.cs | Adds test data for a JSON-only base to ensure XML methods are not overridden incorrectly. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/XmlSerializationCustomizationTests/XmlModelWriteCoreDoesNotOverrideGeneratedBaseWithSealedCustomMethod/BaseModel.cs | Adds test data ensuring a sealed override in a customized base prevents derived overrides. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/XmlSerializationCustomizationTests/XmlModelWriteCoreDoesNotOverrideGeneratedBaseWithProtectedCustomMethod/BaseModel.cs | Adds test data ensuring protected custom methods don’t trigger internal overrides. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/XmlSerializationCustomizationTests/XmlModelWriteCoreDoesNotOverrideGeneratedBaseWithNonVirtualCustomMethod/BaseModel.cs | Adds test data ensuring non-virtual methods don’t trigger overrides. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/MrwSerializationTypeDefinitions/SystemObjectModelSerializationTests.cs | Adjusts system-base MRW tests to explicitly model interface implementation via a specialized provider. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/MrwSerializationTypeDefinition.Xml.cs | Reworks XML override detection to be XML-specific and hierarchy-aware. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/MrwSerializationTypeDefinition.cs | Improves MRW override decisions and root-type discovery for models with custom/external bases. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 81a9ead3-77ac-498f-ae8f-d9f4e69ce052
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 81a9ead3-77ac-498f-ae8f-d9f4e69ce052
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 81a9ead3-77ac-498f-ae8f-d9f4e69ce052
jorgerangel-msft
left a comment
There was a problem hiding this comment.
Can you share the regen preview please?
- Fix WriteProperty emitting 'protected private' instead of 'private protected' - Replace null-forgiving BaseType access with an explicit null check - Rename TryGet* helpers that return nullable to Get* - Narrow ShouldUseFullConstructorInDerivedTypes to private protected - Reuse TestTypeProvider for the inherited-interface test Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 81a9ead3-77ac-498f-ae8f-d9f4e69ce052
… those methods A hand-authored base class was unconditionally used as the return type of the generated JsonModelCreateCore/PersistableModelCreateCore methods. When such a base does not take part in MRW serialization (for example Azure.AI.VoiceLive's VoiceProvider, a plain abstract grouping class), the generated base declared a wider return type than its derived overrides. That produces covariant returns, which fail to compile on netstandard2.0 with CS8830, and changes the signature of protected virtual members that are part of the shipped public API. Defer to the custom base only when it actually declares the *Core creation methods, in which case the signatures must match for the override to be valid. This also removes two unreachable fallbacks and the now unused GetRootBaseType/IsFrameworkRootType helpers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 38fbad13-07b0-42dd-ae90-b5243c7b1d85
@typespec/http-client-csharp is excluded from the pnpm workspace, so chronus rejects change entries that reference it. The emitter package does not use chronus for changelogs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 38fbad13-07b0-42dd-ae90-b5243c7b1d85
|
You can try these changes here
|
A custom base was previously matched on method name alone, so a base whose JsonModelWriteCore is non-virtual, sealed, not protected, or declared with a different signature still caused the generated method to be emitted as `override`, producing CS0506/CS0115/CS0507. Mirror the validation the XML path performs: exact signature, protected accessibility, and overridability. Also fix InterfaceTests order dependency by initializing the mock generator in [SetUp] so the tests pass in isolation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 38fbad13-07b0-42dd-ae90-b5243c7b1d85
latest regen: Azure/azure-sdk-for-net#61461 |
GetCustomMrwBaseRootType delegated to GetCustomBaseMethodReturnType, which in turn delegated to GetMethodReturnTypeInHierarchy; each had exactly one caller. Inline the chain into a single method. Also restore the ShouldSkipDerivedSerializationMethodOverrides doc comment, which was left attached to GetCustomSerializationBaseType. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 38fbad13-07b0-42dd-ae90-b5243c7b1d85
Summary
SystemObjectModelProviderso generated models can inherit from resolved framework or referenced C# types without emitting the external model itself.XmlModelWriteCoreonly overrides a compatible, accessible, overridable base method:Validation
npm run buildnpm run formatnpm run copdotnet test ./generator/Microsoft.TypeSpec.Generator/test/Microsoft.TypeSpec.Generator.Tests.csproj --no-restoredotnet test ./generator/Microsoft.TypeSpec.Generator.ClientModel/test/Microsoft.TypeSpec.Generator.ClientModel.Tests.csproj --no-restore