Skip to content

[http-client-csharp] Emit Obsolete attributes for deprecated APIs - #12394

Merged
JoshLove-msft merged 12 commits into
microsoft:mainfrom
JoshLove-msft:joshlove-msft-csharp-deprecation-attributes
Oct 26, 2026
Merged

JoshLove-msft merged 12 commits into
microsoft:mainfrom
JoshLove-msft:joshlove-msft-csharp-deprecation-attributes

Conversation

@JoshLove-msft

Copy link
Copy Markdown
Contributor

Fixes #12392.

Changes

  • Emit warning-only Obsolete attributes from TypeSpec #deprecated metadata on models, fixed/extensible enums, and synchronous/asynchronous protocol and convenience methods. Preserve messages, including empty strings and C# escaping.
  • Preserve the last released GA contract: existing APIs that were not obsolete do not gain the attribute. Apply the same rule after parameter reordering and to compatibility overloads. New APIs and previously experimental APIs can be marked obsolete; already obsolete APIs use the current message.
  • Respect customization-supplied attributes without duplicating them on partial implementations.
  • Suppress obsolete-reference diagnostics within generated implementation code while retaining consumer warnings.
  • Add metadata, provider, output-baseline, customization, compatibility, and generated-library coverage; regenerate the sample and all Spector libraries.

Validation

  • Package build and API extraction passed; the generator solution, including generated libraries, builds with warnings as errors.
  • Core generator: 2,967 passed; client generator: 2,620 passed; input: 307 passed; generated local libraries: 738 passed.
  • Emitter: 396 passed, 2 skipped (serial run to avoid an existing five-second test timeout under concurrent builds).
  • Repository/package formatting, emitter type-aware oxlint, and Cop checks passed. The package's existing ESLint script references an unavailable tool, so linting used the repository's configured oxlint instead.
  • A separate consumer build reported the expected CS0618 diagnostics for the model, both enum forms, and the operation.

Windows validation used temporary drive mappings to avoid existing long-path limitations. Regeneration reported restore/artifact-path warnings for some long Spector paths; the subsequent shortened-path solution build succeeded.

Preserve non-obsolete GA contracts and compatibility overloads while exposing TypeSpec deprecation messages on new APIs.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 23, 2026 20:25
@microsoft-github-policy-service microsoft-github-policy-service Bot added emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp auto-merge Automatically merge the pull request after all requirements pass labels Oct 23, 2026

@microsoft-github-policy-service microsoft-github-policy-service Bot 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.

Approved automatically for a Dependabot update.

@pkg-pr-new

pkg-pr-new Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 3ce1ba0

@github-actions

Copy link
Copy Markdown
Contributor

No changes needing a change description found.

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.

🟡 Changes recommended

Shared partial-method handling duplicates customization-supplied obsolete attributes, causing generated-library compilation errors.

1 open issue
What changed in this PR

Adds native C# deprecation warnings from TypeSpec #deprecated metadata, addressing #12392 while preserving published API compatibility.

Changes:

  • Emit warning-only Obsolete attributes on models, enums, and operation methods.
  • Handle published contracts, customization attributes, and generated-code warning suppression.
  • Add metadata, provider, baseline, and generated-library coverage, plus documentation.
File Description
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​SampleTypeSpecModelFactory.cs Adds factories for deprecation samples with warning suppression.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​SampleTypeSpecClient.cs Exposes the deprecation sample subclient.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​SampleTypeSpecContext.cs Registers sample models and suppresses obsolete-reference warnings.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​LegacyExtensibleChoice.cs Demonstrates a deprecated extensible enum.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​LegacyDetails.Serialization.cs Adds serialization for the deprecated model.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​LegacyDetails.cs Demonstrates an escaped deprecation message.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​LegacyChoice.Serialization.cs Suppresses warnings in deprecated enum serialization.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​LegacyChoice.cs Demonstrates a deprecated fixed enum.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​CurrentDetails.Serialization.cs Handles deprecated references during serialization.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​CurrentDetails.cs Demonstrates inheritance and collections involving deprecated types.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​DeprecationSamples.RestClient.cs Adds request builders for sample operations.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​DeprecationSamples.cs Demonstrates deprecated protocol and convenience methods.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​Sample-TypeSpec.tsp Defines deprecation sample types and operations.
packages/​http-client-csharp/​generator/​TestProjects/​Local.Tests/​CustomizationTests.cs Verifies generated attributes and warning-only messages.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​test/​Writers/​TypeProviderWriterTests.cs Adds escaped-message output coverage.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​test/​Writers/​TestData/​TypeProviderWriterTests/​WriteDeprecatedEnumWithEscapedMessage.cs Records the expected escaped attribute output.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​test/​Providers/​TypeProviderTests.cs Tests attributes, customization, and contract preservation.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​test/​Providers/​TestData/​TypeProviderTests/​DeprecationPreservesLastContract/​Types.cs Supplies published type-contract fixtures.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​test/​Providers/​TestData/​TypeProviderTests/​DeprecationPreservesBackCompatOverloads/​LegacyClient.cs Supplies compatibility-overload contract fixtures.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​test/​Providers/​TestData/​TypeProviderTests/​DeprecatedCustomModelKeepsExistingAttribute/​Legacy.cs Supplies custom obsolete type declarations.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​test/​common/​InputFactory.cs Supports deprecation metadata in test inputs.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​src/​Utilities/​BackCompatHelper.cs Preserves obsolete status on compatibility overloads.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​src/​Shared/​ExperimentalApiHelpers.cs Extends reference suppression to obsolete APIs.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​src/​Shared/​DeprecationApiHelpers.cs Centralizes obsolete attributes and warning suppressions.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​src/​Providers/​TypeProvider.cs Emits type attributes and preserves published method status.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​src/​Providers/​NamedTypeSymbolProvider.cs Reads obsolete metadata from method symbols.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​src/​Providers/​EnumProvider.cs Uses shared deprecation metadata initialization.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.ClientModel/​test/​Providers/​TestData/​ScmMethodProviderCollectionTests/​DeprecationPreservesLastContractMethods/​TestClient.cs Supplies published client-method fixtures.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.ClientModel/​test/​Providers/​TestData/​ScmMethodProviderCollectionTests/​DeprecatedCustomizedPartialMethodsKeepExistingAttributes/​TestClient.cs Supplies custom obsolete partial-method declarations.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.ClientModel/​test/​Providers/​ScmMethodProviderCollectionTests.cs Tests client-method deprecation and customization behavior.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.ClientModel/​src/​Providers/​ScmMethodProviderCollection.cs Applies operation attributes and dependency suppressions.
packages/​http-client-csharp/​emitter/​test/​Unit/​operation-converter.test.ts Tests operation metadata propagation and serialization.
packages/​http-client-csharp/​emitter/​test/​Unit/​model-type.test.ts Tests model and enum metadata propagation.
packages/​http-client-csharp/​docs/​emitter.md Documents deprecation and compatibility behavior.

Review effort: Balanced

Keep customization-owned Obsolete attributes on the defining declaration in the shared partial-signature builder, covering non-client methods as well as operation methods.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 23, 2026 21:21

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.

🟡 Changes recommended

Combined experimental/deprecated models can leave build warnings unsuppressed, and compatibility overloads can lose existing deprecation warnings.

1 open issue
1 previously missed issue

In code that hasn't changed since last review

Medium severity Preserve Obsolete message when restoring GA overloads

packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.ClientModel/​src/​Providers/​ScmMethodProviderCollection.cs:1166

If the GA contract contains obsolete Read(int value) and non-obsolete Read(int value, bool added = false), this early filtering removes the current deprecation message, so BackCompatHelper.cs:534–543 strips Obsolete from the restored one-parameter overload. Defer GA filtering to the existing post-overload pass in TypeProvider.cs:1254–1263 so the stable signature stays unchanged while the already-obsolete overload retains the current message.

1 resolved since last review

Review effort: Balanced

Suppress all experimental and obsolete diagnostics on generated model registrations. Defer GA method filtering until after compatibility overload restoration so previously obsolete overloads retain the current message.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 23, 2026 22:13
@JoshLove-msft

Copy link
Copy Markdown
Contributor Author

Fixed the mixed GA-overload case from the latest review in fb5bf95 as well. Deprecation metadata is now retained until compatibility overloads are restored, then the existing final GA pass removes it only from signatures that were previously non-obsolete. An already-obsolete restored overload keeps the current message, while the stable overload remains non-obsolete. Added a sync/async regression covering the mixed contract.

--generated by Copilot

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.

🔵 Needs a closer look

The interacting changes to published-contract preservation, partial-method attributes, and diagnostic suppression warrant final human review despite the extensive regression coverage.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

Keep custom Experimental and Obsolete attributes on partial declarations through the shared signature builder. Cover non-client block- and expression-bodied methods, and remove the requested emitter documentation changes.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 24, 2026 02:11

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.

🔵 Needs a closer look

Released-contract compatibility remains unresolved, and the interactions between attribute caching, visitors, and warning suppression warrant final human review.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Refresh obsolete metadata after identity changes

packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​src/​Providers/​TypeProvider.cs:775

If a visitor renames or moves a deprecated type to an existing, non-obsolete GA identity after Attributes has been read, the cached Obsolete attribute survives and introduces consumer warnings on that stable API. ResetMembersBasedOnIdentityChange refreshes LastContractView but leaves _attributes intact (TypeProvider.cs:986–1013). Re-evaluate generated deprecation metadata against the final identity without discarding visitor-supplied attributes, and add a regression that reads attributes before renaming.

Review effort: Balanced

Re-evaluate generated obsolete metadata after visitor renames and namespace changes while preserving visitor-added attributes and explicit removals. Prevent stale attribute snapshots from restoring obsolete warnings on non-obsolete GA types.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 24, 2026 03:11
@JoshLove-msft

Copy link
Copy Markdown
Contributor Author

Fixed the cached-attribute identity issue from the latest review in 96f0a6e. Generated deprecation metadata is now re-evaluated after type updates against the final identity and released contract. Visitor-added attributes, explicit removals, and replacement Obsolete messages are preserved; applying a stale pre-rename attribute list cannot reintroduce a generated warning on a non-obsolete GA type.

Added rename/namespace-change regressions for models and both enum forms, transitions to and from GA identities, customization precedence, visitor overrides, stale attribute snapshots, and final generated output.

--generated by Copilot

Remove mutable type-map keys before name or namespace updates and reinsert owned mappings afterward. Refresh serialization caches so renamed enum helpers retain warning suppressions and final identities.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 24, 2026 06:02

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.

🔵 Needs a closer look

An unresolved provider-mapping collision and coupled compatibility, customization, and diagnostic changes require correction and final human review.

1 open issue
1 resolved since last review

Review effort: Balanced

Resolve name and namespace together so provider reindexing never overwrites an unrelated intermediate identity. Cover models and both enum forms with retained warning lookup.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 24, 2026 06:55

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.

🔵 Needs a closer look

Interactions among published API compatibility, partial customization, diagnostic suppression, and provider identity updates warrant final human review.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@timotheeguerin Timothee Guerin (timotheeguerin) removed the auto-merge Automatically merge the pull request after all requirements pass label Oct 26, 2026
Remove the combined-model suppression test and its unused fixture and baseline as requested. Reuse IsObsoleteAttribute in the context check per review feedback.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 26, 2026 19:28

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.

🔵 Needs a closer look

Interactions among released-contract preservation, partial-method customization, type-identity caches, and diagnostic suppressions warrant final human review despite extensive regression coverage.

No open issues 🎉

Review effort: Balanced

Group generated attribute updates under the existing inclusion branches and use consistent conditional attribute collection syntax.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 26, 2026 20:08

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.

🔵 Needs a closer look

Cross-cutting compatibility and identity-cache changes warrant human review, with an unresolved visitor-attribute preservation issue.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Preserve explicit visitor-added Obsolete attributes

packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​src/​Providers/​TypeProvider.cs:1292

When a visitor explicitly adds [Obsolete] to a method that was not obsolete in the last released contract, this filter removes it—even if the operation has no #deprecated metadata. Visitors run before compatibility processing (CSharpGen.cs:80–92), so the intended consumer warning disappears. Track generator-owned method deprecation attributes and restrict this removal to those, preserving explicit visitor overrides.

Review effort: Balanced

Track generated Obsolete attribute instances before library visitors run, and limit GA compatibility filtering to those instances. Keep explicit visitor attributes on methods and restored compatibility overloads.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 26, 2026 21:09
@JoshLove-msft

Copy link
Copy Markdown
Contributor Author

Fixed the visitor-owned method attribute finding from the latest review in 3ce1ba0. The compatibility pass now tracks the original generated Obsolete instances before library visitors run and removes only those for previously non-obsolete GA signatures. Explicit visitor additions and replacements, including custom diagnostic IDs, remain intact. Restored compatibility overloads also preserve explicit visitor overrides rather than applying the automatic-metadata rule to them.

Added failing-before-fix regressions through the real library visitor path with and without TypeSpec deprecation metadata, generic method/compatibility-overload coverage, and a control showing the generated attribute is still removed when a visitor adds its own. Existing generated-only GA and mixed-overload regressions remain passing.

--generated by Copilot

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.

🔵 Needs a closer look

Shared type-identity, customization, and released-contract changes warrant human confirmation of downstream generated-code behavior.

No open issues 🎉

Review effort: Balanced

@JoshLove-msft
JoshLove-msft added this pull request to the merge queue Oct 26, 2026
Merged via the queue into microsoft:main with commit ea154bb Oct 26, 2026
30 checks passed
@JoshLove-msft
JoshLove-msft deleted the joshlove-msft-csharp-deprecation-attributes branch October 26, 2026 23:57
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.

[http-client-csharp] Generate Obsolete attributes from TypeSpec deprecation metadata

5 participants