Skip to content

Restore removed extensible enum members via back compat - #11502

Draft
jorgerangel-msft with Copilot wants to merge 7 commits into
mainfrom
copilot/investigate-extensible-enums
Draft

Restore removed extensible enum members via back compat#11502
jorgerangel-msft with Copilot wants to merge 7 commits into
mainfrom
copilot/investigate-extensible-enums

Conversation

Copilot AI commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Extensible enums that dropped members between versions produced a source-breaking change for consumers. Unlike fixed string enums (whose wire value can't be recovered), extensible enum members are backed by a private const <Member>Value field whose value is recoverable from the last contract — including compiled-assembly metadata — so removed members can be re-added, mirroring the existing integer fixed-enum behavior.

Changes

  • NamedTypeSymbolProvider.GetFieldInitializer — recover the constant value of any const field (previously only enum members), so extensible-enum <Member>Value wire values load from the last contract.
  • ExtensibleEnumProvider.BuildEnumValuesForBackCompatibility (new override) — re-add members present in the last contract but absent from the current spec, restoring the wire value from the const field. Skips members already present, supplied by custom code, or whose removal is accepted in the ApiCompat baseline; restored members are appended after current spec members.
  • TypeProvider.ProcessTypeForBackCompatibility — for extensible enums, rebuild fields (preserving the _value backing field) and properties from the updated members, reusing already-visited property instances and running only restored properties through the visitors.
  • LibraryVisitor.VisitProperty — widened protectedprotected internal (consistent with VisitField/VisitConstructor) so restored properties can be visited; overrides updated.
  • Tests / docs — back-compat tests for the re-add and baseline-accepted-removal cases with last-contract struct fixtures, plus a new "Extensible Enum Members" section in backward-compatibility.md.

Behavior

Given a last contract that still declares a member the current spec removed:

public readonly partial struct OperationStatusType {
    private const string RecoverValue = "Recover";      // recovered from last-contract metadata
    public static OperationStatusType Recover { get; }  // re-added property
}

the member is restored (property + const field); serialization is unaffected since it round-trips through _value. Enums with no removed members are unchanged.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
1 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@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 30, 2026
Copilot AI changed the title [WIP] Investigate if extensible enums members can be restored via back compat Restore removed extensible enum members via back compat Jul 30, 2026
Copilot AI requested a review from jorgerangel-msft July 30, 2026 22:38
@pkg-pr-new

pkg-pr-new Bot commented Jul 30, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 505fa57

Comment thread packages/http-client-csharp/generator/docs/backward-compatibility.md Outdated
Comment thread packages/http-client-csharp/generator/docs/backward-compatibility.md Outdated
Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

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

@copilot I'd like to see some unit tests where custom code is used in combination with there being a last contract. In addition, we have some spell check failures. We should address those by simply changing / removing the word(s) causing the issues

Comment thread packages/http-client-csharp/generator/docs/backward-compatibility.md Outdated
…ests

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

Copilot AI commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

@copilot I'd like to see some unit tests where custom code is used in combination with there being a last contract. In addition, we have some spell check failures. We should address those by simply ch...

Both addressed in 0ae951a:

  • Added custom-code + last-contract tests: BackCompat_ExtensibleEnumRemovedValueNotReaddedWhenProvidedByCustomCode (a removed member owned by custom code is not re-added) and BackCompat_ExtensibleEnumCustomCodeMemberPreservedWhileOtherMemberRestored (a custom-owned surviving member is left to custom code while a different removed member is still restored from the last contract). Both use (Custom)/(Last) TestData fixtures.
  • Fixed the spell-check failures by renaming readddedMembersrestoredMembers in ExtensibleEnumProvider; cspell now passes on the changed files.

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 enhances the C# HTTP client generator’s back-compat behavior for extensible (string-backed) enums by restoring members that were removed from the current spec but still exist in the last shipped contract, recovering their original wire values from <Member>Value const fields (including from compiled assembly metadata).

Changes:

  • Expand constant-value recovery in NamedTypeSymbolProvider so extensible-enum <Member>Value fields can be read from the last contract.
  • Add extensible-enum-specific back-compat logic to re-add removed members (while honoring custom code and ApiCompat baselines).
  • Update back-compat processing, visitor access, tests/fixtures, and documentation to support and validate the new behavior.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/NamedTypeSymbolProviders/NamedTypeSymbolProviderTests.cs Adds tests validating const-field initializer recovery and non-const behavior.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/EnumProviders/TestData/EnumProviderTests/BackCompat_ExtensibleEnumRemovedValueReadded/MockInputEnum.cs Adds last-contract fixture for re-adding an extensible enum member.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/EnumProviders/TestData/EnumProviderTests/BackCompat_ExtensibleEnumRemovedValueReadded.cs Adds expected generated output for the “re-added extensible enum member” scenario.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/EnumProviders/TestData/EnumProviderTests/BackCompat_ExtensibleEnumRemovedValueNotReaddedWhenProvidedByCustomCode(Last)/MockInputEnum.cs Adds last-contract fixture for the “custom code provides removed member” scenario.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/EnumProviders/TestData/EnumProviderTests/BackCompat_ExtensibleEnumRemovedValueNotReaddedWhenProvidedByCustomCode(Custom)/MockInputEnum.cs Adds custom-code fixture to ensure generator doesn’t collide with custom-provided members.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/EnumProviders/TestData/EnumProviderTests/BackCompat_ExtensibleEnumRemovedValueNotReaddedWhenProvidedByCustomCode.cs Adds expected generated output for the “custom code prevents re-add” scenario.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/EnumProviders/TestData/EnumProviderTests/BackCompat_ExtensibleEnumRemovedValueNotReaddedWhenBaselineAccepts/MockInputEnum.cs Adds last-contract fixture for baseline-accepted removals.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/EnumProviders/TestData/EnumProviderTests/BackCompat_ExtensibleEnumRemovedValueNotReaddedWhenBaselineAccepts.xml Adds XML baseline suppression fixture for accepted member removals.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/EnumProviders/TestData/EnumProviderTests/BackCompat_ExtensibleEnumRemovedValueNotReaddedWhenBaselineAccepts.txt Adds text baseline fixture for accepted member removals.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/EnumProviders/TestData/EnumProviderTests/BackCompat_ExtensibleEnumRemovedValueNotReaddedWhenBaselineAccepts.cs Adds expected generated output ensuring accepted removals are not re-added.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/EnumProviders/TestData/EnumProviderTests/BackCompat_ExtensibleEnumCustomCodeMemberPreservedWhileOtherMemberRestored(Last)/MockInputEnum.cs Adds last-contract fixture for mixed custom-code + restored-member scenario.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/EnumProviders/TestData/EnumProviderTests/BackCompat_ExtensibleEnumCustomCodeMemberPreservedWhileOtherMemberRestored(Custom)/MockInputEnum.cs Adds custom-code fixture to ensure custom-owned member is not regenerated.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/EnumProviders/EnumProviderTests.cs Adds end-to-end tests covering re-add, baseline-accepted removal, and custom-code interactions.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/OutputLibraryVisitorTests.cs Updates test visitor override access modifier to match LibraryVisitor change.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/TypeProvider.cs Rebuilds extensible-enum fields/properties from updated enum values and re-visits only newly restored members.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/NamedTypeSymbolProvider.cs Broadens const-field initializer recovery beyond enum types.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ExtensibleEnumProvider.cs Implements extensible-enum back-compat member restoration and wire-value recovery from last-contract const fields.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/EnumProvider.cs Exposes custom member name set to derived providers for back-compat filtering.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/LibraryVisitor.cs Widens VisitProperty accessibility to allow back-compat-added properties to be visited.
packages/http-client-csharp/generator/docs/backward-compatibility.md Documents the new extensible-enum member restoration behavior and scenario.

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
@jorgerangel-msft
jorgerangel-msft force-pushed the copilot/investigate-extensible-enums branch from a5dff14 to 7710713 Compare July 31, 2026 21:53
@github-actions

Copy link
Copy Markdown
Contributor

No changes needing a change description found.

@jorgerangel-msft
jorgerangel-msft force-pushed the copilot/investigate-extensible-enums branch from 7710713 to 505fa57 Compare July 31, 2026 22:27
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.

Investigate if Extensible Enums Members Can Be Restored via Back Compat

3 participants