-
Notifications
You must be signed in to change notification settings - Fork 334
Enable customizing model base type to non-generated external types #9375
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
base: main
Are you sure you want to change the base?
Changes from all commits
bfda5c1
4ad917f
97394a1
75c90e5
09c89ed
532f0e7
4c79d16
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
| using Microsoft.TypeSpec.Generator.Primitives; | ||
| using Microsoft.TypeSpec.Generator.Statements; | ||
|
|
||
| namespace Microsoft.TypeSpec.Generator.Providers | ||
| { | ||
| /// <summary> | ||
| /// Represents a type from an external assembly (system or referenced assembly) that is not part of the current generation. | ||
| /// This provider is used when a generated model inherits from a type that exists in a referenced assembly | ||
| /// but doesn't have a Roslyn type symbol available in the customization compilation. | ||
| /// </summary> | ||
| internal sealed class SystemObjectTypeProvider : TypeProvider | ||
| { | ||
| private readonly CSharpType _type; | ||
|
|
||
| public SystemObjectTypeProvider(CSharpType type) | ||
| { | ||
| _type = type ?? throw new ArgumentNullException(nameof(type)); | ||
|
|
||
| if (string.IsNullOrEmpty(_type.Namespace)) | ||
| { | ||
| throw new ArgumentException("Type must have a namespace", nameof(type)); | ||
| } | ||
| } | ||
|
|
||
| private protected sealed override TypeProvider? BuildCustomCodeView(string? generatedTypeName = default, string? generatedTypeNamespace = default) => null; | ||
| private protected sealed override TypeProvider? BuildLastContractView(string? generatedTypeName = default, string? generatedTypeNamespace = default) => null; | ||
|
|
||
| protected override string BuildRelativeFilePath() => throw new InvalidOperationException("This type should not be writing in generation"); | ||
|
|
||
| protected override string BuildName() => _type.Name; | ||
|
|
||
| protected override string BuildNamespace() => _type.Namespace; | ||
|
|
||
| protected override IReadOnlyList<AttributeStatement> BuildAttributes() => []; | ||
|
|
||
| protected override CSharpType? BuildBaseType() => _type.BaseType; | ||
|
|
||
| protected override TypeSignatureModifiers BuildDeclarationModifiers() | ||
| { | ||
| // Default to public class since we don't have symbol information | ||
| return TypeSignatureModifiers.Public | TypeSignatureModifiers.Class; | ||
| } | ||
|
|
||
| protected internal override FieldProvider[] BuildFields() => []; | ||
|
|
||
| protected internal override PropertyProvider[] BuildProperties() => []; | ||
|
|
||
| protected internal override ConstructorProvider[] BuildConstructors() => []; | ||
|
|
||
| protected internal override MethodProvider[] BuildMethods() => []; | ||
|
|
||
| protected override bool GetIsEnum() => false; | ||
|
|
||
| protected override CSharpType BuildEnumUnderlyingType() => throw new InvalidOperationException("This type is not an enum"); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| #nullable disable | ||
|
|
||
| using Sample.Models; | ||
| using System.Collections.Generic; | ||
|
|
||
| namespace Sample.Models | ||
| { | ||
| public partial class MockInputModel : ExternalBaseModel | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @copilot can you add another test case with custom code, which updated the base model to a system type?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added test Fixed in commit 09c89ed. |
||
| { | ||
| } | ||
|
|
||
| // This simulates an external base type from another assembly/namespace | ||
| // that is not generated by the current generation run | ||
| public class ExternalBaseModel | ||
| { | ||
| public string ExternalProperty { get; set; } | ||
| public IDictionary<string, string> ExternalDictionary { get; set; } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| #nullable disable | ||
|
|
||
| using System; | ||
|
|
||
| namespace Sample.Models | ||
| { | ||
| // This test case shows a model inheriting from a system type (System.Exception). | ||
| // This simulates inheriting from types like Azure.ResourceManager.TrackedResourceData | ||
| // which are from referenced assemblies. | ||
| public partial class MockInputModel : Exception | ||
| { | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot Here you are assuming you can get the TypeSymbol of the base type from the custom code.
What if the base type is not defined within the custom code, then you can't get the TypeSymbol.
We need to add a new implementation of TypeProvider, let's name it
SystemObjectType, which represents a type from another assembly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're absolutely right. I've added
SystemObjectTypeProviderto handle cases where the base type is from a referenced assembly and cannot be found viaGetTypeByMetadataName.The implementation now:
CSharpTypeMap(cached)GetTypeByMetadataNameon the customization compilation (createsNamedTypeSymbolProviderif found)SystemObjectTypeProviderif the type symbol is not foundFixed in commit 75c90e5.