Skip to content

[C#] Emit Obsolete attributes for deprecated model properties - #12523

Merged
JoshLove-msft merged 12 commits into
mainfrom
copilot/emit-obsolete-attribute
Nov 12, 2026
Merged

JoshLove-msft merged 12 commits into
mainfrom
copilot/emit-obsolete-attribute

Conversation

Copilot AI commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Property-level #deprecated messages were dropped during generation, leaving consumers without compiler warnings.

  • Metadata: Carry the exact message from TypeSpec through the serialized model to property generation.
  • Emission: Generate [Obsolete(message)] on ordinary and renamed/customized models, reusing existing warning suppressions for generated references.
  • Customization: Preserve handwritten attributes without duplicates; leave non-deprecated properties unchanged.

For #deprecated "Use replacement instead.", emit:

[Obsolete("Use replacement instead.")]
public string Legacy { get; set; }

@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: JoshLove-msft <54595583+JoshLove-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 Nov 10, 2026
Copilot AI changed the title [WIP] Emit [Obsolete] attribute for properties marked with #deprecated [C#] Emit Obsolete attributes for deprecated model properties Nov 10, 2026
Copilot AI requested a review from JoshLove-msft November 10, 2026 00:19
@JoshLove-msft
JoshLove-msft marked this pull request as ready for review November 10, 2026 01:18
Copilot AI balanced review requested due to automatic review settings November 10, 2026 01:18

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

Deprecation handling leaves unsuppressed warnings in generated inheritance and property-access paths that break warnings-as-errors builds, and lacks compatibility guards for previously published properties.

3 open issues
What changed in this PR

This PR addresses #12522 by carrying property deprecation metadata through the C# emitter and generating [Obsolete(message)] attributes so SDK consumers receive compiler warnings.

Changes:

  • Preserve exact deprecation messages through serialization and property generation.
  • Cover ordinary and renamed models, handwritten attributes, and non-deprecated properties.
  • Update generated samples and suppress intentional deprecated-property references in tests.
File Description
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​tspCodeModel.json Records property deprecation messages.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​RenamedModelCustom.Serialization.cs Suppresses warnings around deprecated-property serialization.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​RenamedModelCustom.cs Adds the attribute and constructor warning suppressions.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​CurrentDetails.cs Emits an attribute with an escaped message.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​Sample-TypeSpec.tsp Adds deprecated-property sample declarations.
packages/​http-client-csharp/​generator/​TestProjects/​Local.Tests/​CustomizationTests.cs Checks emitted messages and unaffected properties.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​test/​Providers/​TypeProviderTests.cs Tests metadata, attributes, and customization handling.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​test/​Providers/​TestData/​TypeProviderTests/​DeprecatedPropertiesPreserveMessagesAndCustomizations/​Custom.cs Supplies a renamed model with a handwritten attribute.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​src/​Providers/​PropertyProvider.cs Adds deprecation attributes to generated properties.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.Input/​src/​InputTypes/​Serialization/​InputModelPropertyConverter.cs Deserializes property deprecation messages.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.Input/​src/​InputTypes/​InputModelProperty.cs Stores property deprecation metadata.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.ClientModel/​test/​ModelReaderWriterValidation/​TestProjects/​Sample_TypeSpec/​RenamedModelTests.cs Suppresses intentional deprecated-property usage in tests.
packages/​http-client-csharp/​emitter/​test/​Unit/​model-type.test.ts Tests absent, empty, and escaped deprecation messages.
packages/​http-client-csharp/​emitter/​src/​type/​input-type.ts Extends the property metadata interface.
packages/​http-client-csharp/​emitter/​src/​lib/​type-converter.ts Reads property deprecation from TypeSpec.

Review effort: Balanced

@pkg-pr-new

pkg-pr-new Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 2a1a28f

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 10, 2026 21:02
@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

Unsuppressed deprecation warnings in generated property forwarding, exploded queries, and paging helpers break warnings-as-errors builds, while lazy attribute filtering can discard unrelated attributes.

4 open issues
3 resolved since last review

Review effort: Balanced

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 10, 2026 22:27

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

Human review is needed because inherited-only overrides may lose base-property metadata, leaving obsolete-member warnings unsuppressed in paging access.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 11, 2026 20:49

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

Human assessment is needed because public API signature changes break source and binary compatibility for supported generator extensions, including runtime failures in previously compiled plugins.

No open issues 🎉

Review effort: Balanced

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 11, 2026 21:33

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

Human assessment is needed because replacing a public overload breaks compatibility with existing generator extensions, a critical concern omitted from the published review.

No open issues 🎉

Review effort: Balanced

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 11, 2026 22:13
@JoshLove-msft

Copy link
Copy Markdown
Contributor

Re: the review summary's note about a replaced public overload. Fixed in c8b9fc1. I restored the public ModelProviderSnippets.GetPropertyExpression(ModelProvider, ValueExpression, IReadOnlyList<string>, out PropertyProvider) overload that this PR had replaced. The new overload, which also returns the properties accessed along the path, is added alongside it. Existing generator extensions that call the original overload keep compiling and binding. I checked the diff against main, and no other public or protected members are removed.

--generated by Copilot

@JoshLove-msft

Copy link
Copy Markdown
Contributor

Re: the review summary's note about a replaced public overload. Fixed in c8b9fc1. I restored the public ModelProviderSnippets.GetPropertyExpression(ModelProvider, ValueExpression, IReadOnlyList<string>, out PropertyProvider) overload that this PR had replaced. The new overload, which also returns the properties accessed along the path, is added alongside it. Existing generator extensions that call the original overload keep compiling and binding. I checked the diff against main, and no other public or protected members are removed.

--generated by Copilot

We don't need to retain the public overload for backwards compatibililty. Revert this commit.

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

Human assessment is needed because the compatibility check can miss inherited public properties and introduce new consumer warnings when they are redeclared as deprecated.

No open issues 🎉

Review effort: Balanced

JoshLove-msft and others added 2 commits November 11, 2026 14:44
This reverts commit c8b9fc1. The original public overload does not need to be kept for backward compatibility.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 11, 2026 22:48
@JoshLove-msft

Copy link
Copy Markdown
Contributor

Reverted in f698371, so the restored GetPropertyExpression overload is gone.

Also fixed the issue in the latest review summary in 2a1a28f. The last-contract check only looked at properties declared directly on the model's last-contract type. Suppose a property was inherited from a base class in the last contract, such as InheritingModel.PreviouslyStable coming from StableModel, and is now redeclared on the derived model as deprecated. The check found no previous declaration and added [Obsolete], giving consumers who already used that stable property new warnings. The check now walks the last-contract base types and uses the nearest public declaration. PropertyDeprecationPreservesInheritedLastContract covers stable, obsolete, and new inherited cases, and the stable case fails without the fix.

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

🟡 Changes recommended

Replacing the public four-parameter GetPropertyExpression overload breaks existing source callers and compiled generator plugins; it should remain as a forwarding wrapper alongside the new overload.

1 open issue

Review effort: Balanced

@JoshLove-msft
JoshLove-msft added this pull request to the merge queue Nov 11, 2026
Merged via the queue into main with commit ccde4f5 Nov 12, 2026
31 checks passed
@JoshLove-msft
JoshLove-msft deleted the copilot/emit-obsolete-attribute branch November 12, 2026 00:48
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.

[C# generator] Emit [Obsolete] attribute for properties marked with #deprecated

5 participants