Commit b94546c
Make C# back-compat aware of ApiCompat baseline files (#11048)
## Problem
The backward-compatibility system uses `LastContractView` to keep
generated APIs source-compatible with the previous version: it
resurrects removed public members and preserves a property's previous
type. But when a breaking change has **already been accepted** in an
[ApiCompat](https://github.com/dotnet/sdk/tree/main/src/Compatibility)
baseline (suppression) file — conventionally
`eng/apicompatbaselines/<AssemblyName>.txt` in the Azure SDK — that
back-compat behavior fights the accepted decision: it re-introduces
intentionally-removed API and can reference types that no longer exist.
Example baseline entries:
```
TypesMustExist : Type 'Azure.AI.Projects.Agents.ProjectsAgentProtocol' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Azure.AI.Projects.Agents.ProtocolVersionRecord Azure.AI.Projects.Agents.ProjectsAgentsModelFactory.ProtocolVersionRecord(Azure.AI.Projects.Agents.ProjectsAgentProtocol, System.String)' does not exist in the implementation but it does exist in the contract.
```
## Fix
- Add `ApiCompatBaseline` (`Microsoft.TypeSpec.Generator.SourceInput`):
a tolerant parser for ApiCompat baseline files that understands
`TypesMustExist` and `MembersMustExist` suppressions. Member matching
uses declaring-type full name + member name + parameter count (arity),
avoiding brittle parameter-type string comparisons. Type suppression
implies all of its members are suppressed.
- Discover the baseline file by walking up from the project directory to
`eng/apicompatbaselines/<PrimaryNamespace>.txt`
(`GeneratedCodeWorkspace.LoadApiCompatBaseline`), expose the parsed
baseline on `SourceInputModel`, and wire loading into `CSharpGen`.
- **Skip resurrected members** in the model factory back-compat path
(`ModelFactoryProvider.BuildMethodsForBackCompatibility`): a removed
factory method whose removal is accepted in the baseline is not
regenerated.
- **Allow property type changes** in `ModelProvider.BuildProperties`:
the generator normally reverts a property to its previous
(last-contract) type to avoid a breaking change. When that previous type
— or a type nested within it (e.g. a collection element type) — is an
accepted baseline removal, preserving it would reference a now-deleted
type, so the current (spec) type is kept instead. Added
`ApiCompatBaseline.ReferencesSuppressedType` (recurses into generic
arguments) and a `BaselineAcceptedRemovalSkipped` change category.
The remaining back-compat consumers (`ModelProvider` constructors, the
enum providers, `ClientProvider`, and `RestClientProvider`) can be made
baseline-aware the same way as a follow-up; this is documented in
`docs/backward-compatibility.md`.
## Tests
- `ApiCompatBaselineTests` — parser coverage (types, methods,
constructors, property accessors, generic-arg arity, unknown/malformed
lines) and `ReferencesSuppressedType` (direct + nested generic
argument).
-
`ModelFactoryProviderTests.BackCompatibility_SuppressedByApiCompatBaselineNotRegenerated`
— a baselined factory method is **not** regenerated.
-
`ModelProviderTests.BackCompat_PropertyTypeChangeAllowedWhenPreviousTypeSuppressed`
— a property whose previous type is a baseline-accepted removal takes
its current spec type.
- Full `Microsoft.TypeSpec.Generator.Tests` suite passes (1552 tests).
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent f8f1a51 commit b94546c
19 files changed
Lines changed: 633 additions & 9 deletions
File tree
- packages/http-client-csharp/generator
- Microsoft.TypeSpec.Generator
- src
- EmitterRpc
- PostProcessing
- Providers
- SourceInput
- test
- Providers
- ModelFactories
- TestData/ModelFactoryProviderTests
- ModelProviders
- TestData/ModelProviderTests
- SourceInput
- TestData/ApiCompatBaselineTests
- TestHelpers
- common
- docs
Lines changed: 2 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
62 | | - | |
| 62 | + | |
| 63 | + | |
63 | 64 | | |
64 | 65 | | |
65 | 66 | | |
| |||
Lines changed: 3 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
45 | 48 | | |
46 | 49 | | |
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
181 | 181 | | |
182 | 182 | | |
183 | 183 | | |
| 184 | + | |
184 | 185 | | |
185 | 186 | | |
186 | 187 | | |
| |||
Lines changed: 27 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
| |||
364 | 365 | | |
365 | 366 | | |
366 | 367 | | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
367 | 394 | | |
368 | 395 | | |
369 | 396 | | |
| |||
Lines changed: 13 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
116 | 116 | | |
117 | 117 | | |
118 | 118 | | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
119 | 132 | | |
120 | 133 | | |
121 | 134 | | |
| |||
Lines changed: 16 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
620 | 620 | | |
621 | 621 | | |
622 | 622 | | |
623 | | - | |
624 | | - | |
625 | | - | |
626 | | - | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
627 | 639 | | |
628 | 640 | | |
629 | 641 | | |
| |||
0 commit comments