-
Notifications
You must be signed in to change notification settings - Fork 375
Centralize C# type attribute back-compat merging in TypeProvider #11237
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Copilot
wants to merge
32
commits into
main
Choose a base branch
from
copilot/centralize-type-attribute-merging
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
08d2fc3
Initial plan
Copilot 6a86f1b
Centralize C# type attribute back-compat merging in TypeProvider
Copilot 83afc6f
Add unit test for BuildAttributesForBackCompatibility dedup
Copilot bbb6960
Remove redundant test constructor per review feedback
Copilot e5769db
Address review: revert canonical delegation, only add new back-compat…
Copilot 4f3265a
Refine back-compat attribute comment and skip work for public types
Copilot 921c0ec
Address review: parameterize BuildAttributesForBackCompatibility, dro…
Copilot ff61d50
Address review: remove comment, use TestData for generated-code asser…
Copilot 0511c9c
Merge remote-tracking branch 'origin/main' into copilot/centralize-ty…
Copilot f74deb3
Restore attributes unless known non-restorable; MRW skips buildable
Copilot 2d19520
Address review: virtual predicate for back-compat attrs, add Obsolete…
Copilot 64f6b16
Address review: remove virtual predicate, centralize back-compat attr…
Copilot 523bc67
Remove new protected overload; MRW override post-filters buildable attrs
Copilot 55a499b
Address review: hashset-based buildable filter, Serializable/json ign…
Copilot fe31576
test: drive attribute back-compat tests through ProcessTypeForBackCom…
Copilot 705fde4
test: drive MRW back-compat test through ProcessTypeForBackCompatibility
Copilot a386cef
feat: shared Scm back-compat attribute helper; MRW serialization skip…
Copilot 7c1fb8d
refactor: accept IReadOnlySet in shared back-compat attribute helper
Copilot 6e4b68b
refactor: move back-compat attribute fields to top; filter MRW proxy …
Copilot 79feacf
Skip restoring any CodeGen-prefixed attribute in back-compat merge
Copilot cadf5bf
Make CodeGenAttributePrefix internal; check hashset first with case-i…
Copilot da7bb35
test: cover skipping all CodeGen-prefixed attributes in back-compat m…
Copilot 8402982
fix: ScmModelProvider skips restoring PersistableModelProxy in back-c…
Copilot 177c99a
test: move ScmModelProvider back-compat test into ScmModelProviderTes…
Copilot 9a5f87c
Skip restoring DefaultMember attribute in back-compat merge; add unit…
Copilot 3a316e3
Merge remote-tracking branch 'origin/main' into copilot/centralize-ty…
Copilot b8f7634
fix(csharp): prevent emitter crash when restoring last-contract attri…
Copilot d101de6
refactor(csharp): narrow back-compat attribute render catch to specif…
Copilot edc3ee3
fix(csharp): restrict back-compat attribute restoration to public/pro…
Copilot 4a9b6cc
refactor(csharp): catch any exception when rendering back-compat attr…
Copilot 7f8188f
test/refactor(csharp): dedup back-compat test; lazy owned-attrs param…
Copilot 68a9a9b
Pass lazy attribute-ignore set directly to FilterRestoredAttributes
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
...tor/Microsoft.TypeSpec.Generator.ClientModel/src/Utilities/ScmBackCompatibilityHelpers.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
| using Microsoft.TypeSpec.Generator.Statements; | ||
|
|
||
| namespace Microsoft.TypeSpec.Generator.ClientModel.Utilities | ||
| { | ||
| internal static class ScmBackCompatibilityHelpers | ||
| { | ||
|
jorgerangel-msft marked this conversation as resolved.
|
||
| /// <summary> | ||
| /// Drops any generator-owned attributes that were newly restored from the last contract. | ||
| /// <paramref name="restoredAttributes"/> is the result of the base | ||
| /// <c>BuildAttributesForBackCompatibility</c> call; any attribute whose type name is in | ||
| /// <paramref name="generatorOwnedAttributeNames"/> and was not already present in | ||
| /// <paramref name="originalAttributes"/> is removed, since generation recomputes it. | ||
| /// <paramref name="generatorOwnedAttributeNames"/> is only evaluated when there is restored | ||
| /// content to filter, so callers can pass a lazily-initialized set without paying for it when | ||
| /// nothing was restored. | ||
| /// </summary> | ||
| public static IReadOnlyList<AttributeStatement> FilterRestoredAttributes( | ||
| IReadOnlyList<AttributeStatement> originalAttributes, | ||
| IReadOnlyList<AttributeStatement> restoredAttributes, | ||
| Lazy<HashSet<string>> generatorOwnedAttributeNames) | ||
| { | ||
| // The base returns the original list unchanged when nothing was restored. | ||
| if (ReferenceEquals(restoredAttributes, originalAttributes)) | ||
| { | ||
| return restoredAttributes; | ||
| } | ||
|
|
||
| var ownedNames = generatorOwnedAttributeNames.Value; | ||
|
|
||
| var originalDisplayStrings = new HashSet<string>(StringComparer.Ordinal); | ||
| foreach (var attribute in originalAttributes) | ||
| { | ||
| originalDisplayStrings.Add(attribute.ToDisplayString()); | ||
| } | ||
|
|
||
| var result = new List<AttributeStatement>(restoredAttributes.Count); | ||
| foreach (var attribute in restoredAttributes) | ||
| { | ||
| if (ownedNames.Contains(attribute.Type.Name) | ||
| && !originalDisplayStrings.Contains(attribute.ToDisplayString())) | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| result.Add(attribute); | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
...extDefinitionTests/BuildAttributesForBackCompatibilityDoesNotRestoreBuildableAttribute.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // <auto-generated/> | ||
|
|
||
| #nullable disable | ||
|
|
||
| using System.ClientModel.Primitives; | ||
| using System.ComponentModel; | ||
|
|
||
| namespace Sample | ||
| { | ||
| [global::System.ComponentModel.DescriptionAttribute("bc")] | ||
| public partial class SampleContext : global::System.ClientModel.Primitives.ModelReaderWriterContext | ||
| { | ||
| } | ||
| } |
11 changes: 11 additions & 0 deletions
11
...ests/BuildAttributesForBackCompatibilityDoesNotRestoreBuildableAttribute/SampleContext.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| using System.ComponentModel; | ||
| using System.ClientModel.Primitives; | ||
|
|
||
| namespace Sample | ||
| { | ||
| [ModelReaderWriterBuildable(typeof(object))] | ||
| [Description("bc")] | ||
| public partial class SampleContext : ModelReaderWriterContext | ||
| { | ||
| } | ||
| } |
56 changes: 56 additions & 0 deletions
56
...ator.ClientModel/test/Providers/MrwSerializationTypeDefinitions/BackCompatibilityTests.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| using System.Linq; | ||
| using System.Threading.Tasks; | ||
| using Microsoft.TypeSpec.Generator.ClientModel.Providers; | ||
| using Microsoft.TypeSpec.Generator.Input; | ||
| using Microsoft.TypeSpec.Generator.Primitives; | ||
| using Microsoft.TypeSpec.Generator.Providers; | ||
| using Microsoft.TypeSpec.Generator.Tests.Common; | ||
| using NUnit.Framework; | ||
|
|
||
| namespace Microsoft.TypeSpec.Generator.ClientModel.Tests.Providers.MrwSerializationTypeDefinitions | ||
| { | ||
| internal class BackCompatibilityTests | ||
| { | ||
| private class MockMrwProvider : MrwSerializationTypeDefinition | ||
| { | ||
| public MockMrwProvider(InputModelType inputModel, ModelProvider modelProvider) | ||
| : base(inputModel, modelProvider) | ||
| { | ||
| } | ||
|
|
||
| protected override MethodProvider[] BuildMethods() => []; | ||
| protected internal override FieldProvider[] BuildFields() => []; | ||
| protected override ConstructorProvider[] BuildConstructors() => []; | ||
| } | ||
|
|
||
| [Test] | ||
| public async Task BuildAttributesForBackCompatibilityDoesNotRestoreProxyAttribute() | ||
| { | ||
| var inputModel = InputFactory.Model("pet", properties: | ||
| [ | ||
| InputFactory.Property("name", InputPrimitiveType.String, isRequired: true) | ||
| ]); | ||
|
|
||
| var mockGenerator = await MockHelpers.LoadMockGeneratorAsync( | ||
| inputModels: () => [inputModel], | ||
| createSerializationsCore: (inputType, typeProvider) | ||
| => inputType is InputModelType modelType ? [new MockMrwProvider(modelType, (typeProvider as ModelProvider)!)] : [], | ||
| lastContractCompilation: async () => await Helpers.GetCompilationFromDirectoryAsync()); | ||
|
|
||
| var modelProvider = mockGenerator.Object.OutputLibrary.TypeProviders.Single(t => t is ModelProvider); | ||
| var serializationProvider = modelProvider.SerializationProviders.Single(t => t is MrwSerializationTypeDefinition); | ||
|
|
||
| // The last contract declares a PersistableModelProxy attribute (owned by generation and | ||
| // recomputed at generation time) alongside a Description attribute. Back-compat processing | ||
| // should only restore the non-proxy Description attribute. | ||
| serializationProvider.ProcessTypeForBackCompatibility(); | ||
|
|
||
| var writer = new TypeProviderWriter(serializationProvider); | ||
| var file = writer.Write(); | ||
| Assert.AreEqual(Helpers.GetExpectedFromFile(), file.Content); | ||
| } | ||
| } | ||
| } |
14 changes: 14 additions & 0 deletions
14
...BackCompatibilityTests/BuildAttributesForBackCompatibilityDoesNotRestoreProxyAttribute.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // <auto-generated/> | ||
|
|
||
| #nullable disable | ||
|
|
||
| using System.ClientModel.Primitives; | ||
| using System.ComponentModel; | ||
|
|
||
| namespace Sample.Models | ||
| { | ||
| [global::System.ComponentModel.DescriptionAttribute("bc")] | ||
| public partial class Pet : global::System.ClientModel.Primitives.IJsonModel<global::Sample.Models.Pet> | ||
|
jorgerangel-msft marked this conversation as resolved.
|
||
| { | ||
| } | ||
| } | ||
11 changes: 11 additions & 0 deletions
11
...CompatibilityTests/BuildAttributesForBackCompatibilityDoesNotRestoreProxyAttribute/Pet.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| using System.ComponentModel; | ||
| using System.ClientModel.Primitives; | ||
|
|
||
| namespace Sample.Models | ||
| { | ||
| [PersistableModelProxy(typeof(object))] | ||
| [Description("bc")] | ||
| public partial class Pet | ||
| { | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
.../ScmModelProviderTests/BuildAttributesForBackCompatibilityDoesNotRestoreProxyAttribute.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| // <auto-generated/> | ||
|
|
||
| #nullable disable | ||
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.ComponentModel; | ||
| using Sample; | ||
|
|
||
| namespace Sample.Models | ||
| { | ||
| [global::System.ComponentModel.DescriptionAttribute("bc")] | ||
| public partial class Pet | ||
| { | ||
| private protected readonly global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> _additionalBinaryDataProperties; | ||
|
|
||
| public Pet(string name) | ||
| { | ||
| global::Sample.Argument.AssertNotNull(name, nameof(name)); | ||
|
|
||
| Name = name; | ||
| } | ||
|
|
||
| internal Pet(string name, global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties) | ||
| { | ||
| Name = name; | ||
| _additionalBinaryDataProperties = additionalBinaryDataProperties; | ||
| } | ||
|
|
||
| public string Name { get; set; } | ||
| } | ||
| } |
11 changes: 11 additions & 0 deletions
11
...ModelProviderTests/BuildAttributesForBackCompatibilityDoesNotRestoreProxyAttribute/Pet.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| using System.ComponentModel; | ||
| using System.ClientModel.Primitives; | ||
|
|
||
| namespace Sample.Models | ||
| { | ||
| [PersistableModelProxy(typeof(object))] | ||
| [Description("bc")] | ||
| public partial class Pet | ||
| { | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.