Skip to content

Handle custom external model bases - #11183

Merged
live1206 merged 32 commits into
microsoft:mainfrom
live1206:fix/system-object-custom-base-mrw
Jul 29, 2026
Merged

Handle custom external model bases#11183
live1206 merged 32 commits into
microsoft:mainfrom
live1206:fix/system-object-custom-base-mrw

Conversation

@live1206

@live1206 live1206 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Represent external model mappings with SystemObjectModelProvider so generated models can inherit from resolved framework or referenced C# types without emitting the external model itself.
  • Preserve model inheritance behavior across custom/external bases:
    • propagate the resolved base type and interface metadata, including generic interface arguments;
    • avoid regenerating members owned by the external type;
    • control whether external-base constructor parameters flow into derived constructors.
  • Improve model reader/writer serialization for custom and external base hierarchies:
    • centralize MRW interface detection, provider resolution, hierarchy traversal, and overridability checks in shared internal helpers;
    • resolve mapped and referenced type providers when method metadata is available;
    • conservatively avoid overrides when an external type cannot be resolved.
  • Tighten XML serialization override detection so XmlModelWriteCore only overrides a compatible, accessible, overridable base method:
    • retain XML-specific signature and internal-only accessibility validation;
    • account for customized generated bases and method replacement;
    • reject JSON-only, wrong-signature, non-virtual, protected/public, sealed, and shadowed ancestor methods.
  • Keep MRW create-core return types rooted at the meaningful custom base type and only participate in override chains supported by that base.
  • Keep management-plane wire-path deduplication out of MTG; downstream generators remain responsible for management-specific attributes and behavior.

Validation

  • npm run build
  • npm run format
  • npm run cop
  • dotnet test ./generator/Microsoft.TypeSpec.Generator/test/Microsoft.TypeSpec.Generator.Tests.csproj --no-restore
  • dotnet test ./generator/Microsoft.TypeSpec.Generator.ClientModel/test/Microsoft.TypeSpec.Generator.ClientModel.Tests.csproj --no-restore
  • Azure SDK for .NET management generator validation: no regeneration diff.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@microsoft-github-policy-service microsoft-github-policy-service Bot added the emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp label Jul 7, 2026
@pkg-pr-new

pkg-pr-new Bot commented Jul 7, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/http-client-csharp@11183

commit: 0ba934f

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

No changes needing a change description found.

live1206 and others added 6 commits July 7, 2026 06:54
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>
live1206 added a commit to live1206/azure-sdk-for-net that referenced this pull request Jul 7, 2026
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>
live1206 and others added 11 commits July 7, 2026 09:44
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>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@live1206
live1206 marked this pull request as ready for review July 8, 2026 07:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

live1206 and others added 2 commits July 10, 2026 01:25
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
live1206 added 3 commits July 27, 2026 07:40
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 jorgerangel-msft left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you share the regen preview please?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.

live1206 and others added 2 commits July 28, 2026 02:49
- 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
live1206 and others added 2 commits July 28, 2026 07:09
… 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
@azure-sdk-automation

Copy link
Copy Markdown

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

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
@live1206

Copy link
Copy Markdown
Contributor Author

Can you share the regen preview please?

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
@live1206
live1206 enabled auto-merge July 29, 2026 02:00
@live1206
live1206 added this pull request to the merge queue Jul 29, 2026
Merged via the queue into microsoft:main with commit d320a53 Jul 29, 2026
29 checks passed
@live1206
live1206 deleted the fix/system-object-custom-base-mrw branch July 29, 2026 02:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants