Skip to content

Restore missing last-contract buildable attributes on ModelReaderWriterContextDefinition - #11379

Merged
jorgerangel-msft merged 11 commits into
mainfrom
copilot/add-back-compat-attribute-processing
Jul 27, 2026
Merged

Restore missing last-contract buildable attributes on ModelReaderWriterContextDefinition#11379
jorgerangel-msft merged 11 commits into
mainfrom
copilot/add-back-compat-attribute-processing

Conversation

Copilot AI commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

ModelReaderWriterContextDefinition rebuilt its [ModelReaderWriterBuildable(...)] attributes purely from the current generation, so a type dropped from the spec silently lost its buildable entry — a source-breaking change for consumers that rely on the context to build that type. Attributes are now reconciled against the last contract.

Changes

  • ModelReaderWriterContextDefinition.BuildAttributes() — after collecting generated + customized entries, restore any ModelReaderWriterBuildableAttribute present on LastContractView that the current generation no longer produces.

    • Last-contract attributes are symbol-based (IsFrameworkType == false), so they're matched by Type.FullyQualifiedName rather than Type.FrameworkType.
    • De-duplication is by the target type's simple name across generated, customized, and last-contract entries; last-contract targets can render with an empty namespace (global::.Foo) when the referenced type isn't defined in that compilation.
    • Restored entries are keyed by type identity so they sort consistently with generated ones. IsBuildableAttribute already recognizes the restored attributes, so BuildAttributesForWrite does not re-emit them.
  • TestsLastContractBuildableAttributesAreRestoredWhenMissing (removed type restored, present type not duplicated) and BuildAttributesForBackCompatibilityDeduplicatesAcrossGeneratedCustomAndLastContractBuildableAttributes (dedupe across all three sources), plus supporting SampleContext.cs TestData.

Given a last contract that shipped RegularModel + RemovedModel but a generation that only produces RegularModel, the emitted context is:

[global::System.ClientModel.Primitives.ModelReaderWriterBuildableAttribute(typeof(global::Sample.Models.RegularModel))]
[global::System.ClientModel.Primitives.ModelReaderWriterBuildableAttribute(typeof(global::Sample.Models.RemovedModel))]
public partial class SampleContext : global::System.ClientModel.Primitives.ModelReaderWriterContext
{
}

@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 23, 2026
Copilot AI changed the title [WIP] Add back compat attribute processing for ModelReaderWriterContextDefinition Restore missing last-contract buildable attributes on ModelReaderWriterContextDefinition Jul 23, 2026
Copilot AI requested a review from jorgerangel-msft July 23, 2026 23:26

@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 add at least 1 more unit test that covers a case where there are attributes in custom code, back compat, and in the generated layer

@pkg-pr-new

pkg-pr-new Bot commented Jul 23, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 630e1e8

…te layers, validate via TestData

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

Copilot AI commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot add at least 1 more unit test that covers a case where there are attributes in custom code, back compat, and in the generated layer

Added BuildAttributesForBackCompatibilityIncludesGeneratedCustomAndRestoredLastContractBuildableAttributes, which covers generated (GeneratedModelA/GeneratedModelB), customized (CustomModel), and last-contract-only (RemovedModelA/RemovedModelB) buildable attributes together, validated against a TestData expected file.

@github-actions

Copy link
Copy Markdown
Contributor

No changes needing a change description found.

…om AddAttributeForType, expose GetClrMetadataName on CSharpType

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
…pe for key and emission

Use targetType (the constructed type from the last contract) for both the
dictionary key and the emitted TypeOf(...) expression, instead of
resolvedProvider.Type (the generic type definition). This ensures:

- typeof(Foo<string>) is emitted instead of typeof(Foo<T>)
- Foo<string> and Foo<int> are treated as distinct entries (not deduplicated)

Also refactor AddAttributeForType(TypeProvider) to accept an explicit key
so the suppression-handling path uses the targetType-derived key when called
from AddLastContractBuildableAttributes.

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
…ClrMetadataName property tests and ObsoleteCustomType suppression test

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
… use CanonicalView, add experimental/both-attributes tests

- Remove comment before AddLastContractBuildableAttributes call
- Remove comment before new attribute statement
- Remove redundant typeKey computation (identity already computed at line 129)
- Fix AddAttributeForType to always use typeProvider.CanonicalView.Attributes
- Fix LiteralExpression.Write() to handle byte, sbyte, short, ushort, uint, ulong
  (needed for CanonicalView.Attributes to work on BCL types with compiler-emitted attrs)
- Add LastContractBuildableAttributesForExperimentalCustomTypeHaveSuppression test
- Add LastContractBuildableAttributesForExperimentalAndObsoleteCustomTypeHaveSuppression test
  (verifies experimental takes precedence when both attrs are present)

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
… tests for uint/ulong/byte/sbyte/short/ushort

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
@jorgerangel-msft
jorgerangel-msft added this pull request to the merge queue Jul 27, 2026
Merged via the queue into main with commit 1f7b35c Jul 27, 2026
29 checks passed
@jorgerangel-msft
jorgerangel-msft deleted the copilot/add-back-compat-attribute-processing branch July 27, 2026 20:09
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.

Add Back Compat Attribute Processing for ModelReaderWriterContextDefinition

4 participants