From 022ef7633815c19b855b5e0cc581c85c412d070a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 11 Dec 2025 01:34:19 +0000 Subject: [PATCH 1/2] Initial plan From db32868c30c069b2b1dafd9c2f650f9f28ab9fcf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 11 Dec 2025 01:40:24 +0000 Subject: [PATCH 2/2] Add code changes and test for customizing base model with existing spec base Co-authored-by: live1206 <5196139+live1206@users.noreply.github.com> --- .../src/Providers/ModelProvider.cs | 40 +++++++++---------- .../ModelProviders/ModelCustomizationTests.cs | 32 +++++++++++++++ .../MockInputModel.cs | 11 +++++ 3 files changed, 63 insertions(+), 20 deletions(-) create mode 100644 packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/TestData/ModelCustomizationTests/CanCustomizeBaseModelWithSpecBase/MockInputModel.cs diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelProvider.cs index b126b0338ad..c3ccaab3f69 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelProvider.cs @@ -242,32 +242,32 @@ private static bool IsDiscriminator(InputProperty property) private ModelProvider? BuildBaseModelProvider() { - if (_inputModel.BaseModel == null) + // consider models that have been customized to inherit from a different model + if (CustomCodeView?.BaseType != null) { - // consider models that have been customized to inherit from a different model - if (CustomCodeView?.BaseType != null) - { - var baseType = CustomCodeView.BaseType; + var baseType = CustomCodeView.BaseType; - // If the custom base type doesn't have a resolved namespace, then try to resolve it from the input model map. - // This will happen if a model is customized to inherit from another generated model, but that generated model - // was not also defined in custom code so Roslyn does not recognize it. - if (string.IsNullOrEmpty(baseType.Namespace)) - { - if (CodeModelGenerator.Instance.TypeFactory.InputModelTypeNameMap.TryGetValue(baseType.Name, out var baseInputModel)) - { - baseType = CodeModelGenerator.Instance.TypeFactory.CreateCSharpType(baseInputModel); - } - } - if (baseType != null && CodeModelGenerator.Instance.TypeFactory.CSharpTypeMap.TryGetValue( - baseType, - out var customBaseType) && - customBaseType is ModelProvider customBaseModel) + // If the custom base type doesn't have a resolved namespace, then try to resolve it from the input model map. + // This will happen if a model is customized to inherit from another generated model, but that generated model + // was not also defined in custom code so Roslyn does not recognize it. + if (string.IsNullOrEmpty(baseType.Namespace)) + { + if (CodeModelGenerator.Instance.TypeFactory.InputModelTypeNameMap.TryGetValue(baseType.Name, out var baseInputModel)) { - return customBaseModel; + baseType = CodeModelGenerator.Instance.TypeFactory.CreateCSharpType(baseInputModel); } } + if (baseType != null && CodeModelGenerator.Instance.TypeFactory.CSharpTypeMap.TryGetValue( + baseType, + out var customBaseType) && + customBaseType is ModelProvider customBaseModel) + { + return customBaseModel; + } + } + if (_inputModel.BaseModel == null) + { return null; } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/ModelCustomizationTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/ModelCustomizationTests.cs index d97e46be381..069698a0283 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/ModelCustomizationTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/ModelCustomizationTests.cs @@ -1441,6 +1441,38 @@ public async Task DiscriminatorPropertyNotGeneratedIfOnCustomizedBase() Assert.AreEqual("Sample.Models", modelProvider.BaseType!.Namespace); } + [Test] + public async Task CanCustomizeBaseModelWithSpecBase() + { + var specBaseModel = InputFactory.Model( + "specBaseModel", + properties: [InputFactory.Property("specBaseProp", InputPrimitiveType.String)], + usage: InputModelTypeUsage.Json); + var customBaseModel = InputFactory.Model( + "customBaseModel", + properties: [InputFactory.Property("customBaseProp", InputPrimitiveType.String)], + usage: InputModelTypeUsage.Json); + var childModel = InputFactory.Model( + "mockInputModel", + properties: [InputFactory.Property("childProp", InputPrimitiveType.String)], + baseModel: specBaseModel, + usage: InputModelTypeUsage.Json); + + var mockGenerator = await MockHelpers.LoadMockGeneratorAsync( + inputModelTypes: [childModel, specBaseModel, customBaseModel], + compilation: async () => await Helpers.GetCompilationFromDirectoryAsync()); + + var modelProvider = mockGenerator.Object.OutputLibrary.TypeProviders.Single(t => t.Name == "MockInputModel"); + + // should have customized base type, not the spec base type + Assert.IsNotNull(modelProvider.BaseType); + Assert.IsNotNull(modelProvider.BaseTypeProvider); + Assert.AreEqual("CustomBaseModel", modelProvider.BaseType!.Name); + Assert.AreEqual("Sample.Models", modelProvider.BaseType!.Namespace); + Assert.AreEqual(1, modelProvider.BaseTypeProvider!.Properties.Count); + Assert.AreEqual("CustomBaseProp", modelProvider.BaseTypeProvider.Properties[0].Name); + } + private class NameSpaceVisitor : LibraryVisitor { protected override TypeProvider? VisitType(TypeProvider type) diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/TestData/ModelCustomizationTests/CanCustomizeBaseModelWithSpecBase/MockInputModel.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/TestData/ModelCustomizationTests/CanCustomizeBaseModelWithSpecBase/MockInputModel.cs new file mode 100644 index 00000000000..44027f26c31 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/TestData/ModelCustomizationTests/CanCustomizeBaseModelWithSpecBase/MockInputModel.cs @@ -0,0 +1,11 @@ +#nullable disable + +using Sample; +using SampleTypeSpec; + +namespace Sample.Models +{ + public partial class MockInputModel : CustomBaseModel + { + } +}