From def41108bd4f03aee4810171b0f65395c814cbfa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 19:59:57 +0000 Subject: [PATCH 1/8] Initial plan From c71203fe2e4fe1c47bb62ca4100cb0c2b22d33e0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 20:11:52 +0000 Subject: [PATCH 2/8] fix(compiler): return undefined for unrecognized scalar constructor in serializeValueAsJson Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com> --- ...-as-json-custom-scalar-2026-2-25-20-0-0.md | 7 ++++++ packages/compiler/src/lib/examples.ts | 2 +- .../compiler/test/decorators/examples.test.ts | 22 +++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 .chronus/changes/fix-ice-serialize-value-as-json-custom-scalar-2026-2-25-20-0-0.md diff --git a/.chronus/changes/fix-ice-serialize-value-as-json-custom-scalar-2026-2-25-20-0-0.md b/.chronus/changes/fix-ice-serialize-value-as-json-custom-scalar-2026-2-25-20-0-0.md new file mode 100644 index 00000000000..7f8835d022c --- /dev/null +++ b/.chronus/changes/fix-ice-serialize-value-as-json-custom-scalar-2026-2-25-20-0-0.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@typespec/compiler" +--- + +core - Fix ICE in `serializeValueAsJson` when a custom scalar initializer has no recognized constructor (e.g. `S.i()` with no args). Now returns `undefined` instead of crashing. diff --git a/packages/compiler/src/lib/examples.ts b/packages/compiler/src/lib/examples.ts index 9516fd638a6..90d61d0b278 100644 --- a/packages/compiler/src/lib/examples.ts +++ b/packages/compiler/src/lib/examples.ts @@ -229,7 +229,7 @@ function serializeScalarValueAsJson( const result = resolveKnownScalar(program, value.scalar); if (result === undefined) { - return serializeValueAsJson(program, value.value.args[0], value.value.args[0].type); + return undefined; } encodeAs = encodeAs ?? result.encodeAs; diff --git a/packages/compiler/test/decorators/examples.test.ts b/packages/compiler/test/decorators/examples.test.ts index 141e05655cf..35538fb7941 100644 --- a/packages/compiler/test/decorators/examples.test.ts +++ b/packages/compiler/test/decorators/examples.test.ts @@ -130,6 +130,28 @@ describe("@example", () => { code: "unassignable", }); }); + + it("returns undefined for custom scalar with no-argument initializer", async () => { + const { program, examples, target } = await getExamplesFor(` + @example(test.i()) + @test scalar test { + init i(); + } + `); + expect(examples).toHaveLength(1); + expect(serializeValueAsJson(program, examples[0].value, target)).toBeUndefined(); + }); + + it("returns undefined for custom scalar with initializer", async () => { + const { program, examples, target } = await getExamplesFor(` + @example(test.i("foo")) + @test scalar test { + init i(s: string); + } + `); + expect(examples).toHaveLength(1); + expect(serializeValueAsJson(program, examples[0].value, target)).toBeUndefined(); + }); }); describe("enum", () => { From e2f42d96f5c77884249de2ce80c82733e9751212 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 23:54:33 +0000 Subject: [PATCH 3/8] fix(compiler): only return undefined for no-arg scalar constructor, preserve args[0] behavior Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com> --- packages/compiler/src/lib/examples.ts | 6 +++++- packages/compiler/test/decorators/examples.test.ts | 8 ++++---- packages/openapi3/test/models.test.ts | 13 +++++++++++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/packages/compiler/src/lib/examples.ts b/packages/compiler/src/lib/examples.ts index 90d61d0b278..1307ae96fbd 100644 --- a/packages/compiler/src/lib/examples.ts +++ b/packages/compiler/src/lib/examples.ts @@ -229,7 +229,11 @@ function serializeScalarValueAsJson( const result = resolveKnownScalar(program, value.scalar); if (result === undefined) { - return undefined; + const firstArg = value.value.args[0]; + if (firstArg === undefined) { + return undefined; + } + return serializeValueAsJson(program, firstArg, firstArg.type); } encodeAs = encodeAs ?? result.encodeAs; diff --git a/packages/compiler/test/decorators/examples.test.ts b/packages/compiler/test/decorators/examples.test.ts index 35538fb7941..2d372d37657 100644 --- a/packages/compiler/test/decorators/examples.test.ts +++ b/packages/compiler/test/decorators/examples.test.ts @@ -142,15 +142,15 @@ describe("@example", () => { expect(serializeValueAsJson(program, examples[0].value, target)).toBeUndefined(); }); - it("returns undefined for custom scalar with initializer", async () => { + it("serializes first argument for custom scalar with initializer", async () => { const { program, examples, target } = await getExamplesFor(` - @example(test.i("foo")) + @example(test.name("Shorty")) @test scalar test { - init i(s: string); + init name(value: string); } `); expect(examples).toHaveLength(1); - expect(serializeValueAsJson(program, examples[0].value, target)).toBeUndefined(); + expect(serializeValueAsJson(program, examples[0].value, target)).toEqual("Shorty"); }); }); diff --git a/packages/openapi3/test/models.test.ts b/packages/openapi3/test/models.test.ts index 7ce314dec71..1f27ce141e3 100644 --- a/packages/openapi3/test/models.test.ts +++ b/packages/openapi3/test/models.test.ts @@ -275,6 +275,19 @@ worksFor(supportedVersions, ({ diagnoseOpenApiFor, oapiForModel, openApiFor }) = expect(res.schemas.Pet.properties.name.default).toEqual("Shorty"); }); + it("scalar with no-argument initializer used as a default value does not crash", async () => { + const res = await oapiForModel( + "M", + ` + scalar S { init i(); } + + model M { p: S = S.i(); } + `, + ); + + expect(res.schemas.M.properties.p.default).toBeUndefined(); + }); + it("encode know scalar as a default value", async () => { const res = await oapiForModel( "Test", From d3d86c9645db086fb318e6eb43dca76f937bd801 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 03:13:07 +0000 Subject: [PATCH 4/8] fix(compiler): return undefined for all unrecognized scalar constructors in serializeValueAsJson Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com> --- packages/compiler/src/lib/examples.ts | 6 +----- packages/compiler/test/decorators/examples.test.ts | 4 ++-- packages/openapi3/test/models.test.ts | 4 ++-- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/compiler/src/lib/examples.ts b/packages/compiler/src/lib/examples.ts index 1307ae96fbd..90d61d0b278 100644 --- a/packages/compiler/src/lib/examples.ts +++ b/packages/compiler/src/lib/examples.ts @@ -229,11 +229,7 @@ function serializeScalarValueAsJson( const result = resolveKnownScalar(program, value.scalar); if (result === undefined) { - const firstArg = value.value.args[0]; - if (firstArg === undefined) { - return undefined; - } - return serializeValueAsJson(program, firstArg, firstArg.type); + return undefined; } encodeAs = encodeAs ?? result.encodeAs; diff --git a/packages/compiler/test/decorators/examples.test.ts b/packages/compiler/test/decorators/examples.test.ts index 2d372d37657..b6d75bf81ec 100644 --- a/packages/compiler/test/decorators/examples.test.ts +++ b/packages/compiler/test/decorators/examples.test.ts @@ -142,7 +142,7 @@ describe("@example", () => { expect(serializeValueAsJson(program, examples[0].value, target)).toBeUndefined(); }); - it("serializes first argument for custom scalar with initializer", async () => { + it("returns undefined for custom scalar with string-argument initializer", async () => { const { program, examples, target } = await getExamplesFor(` @example(test.name("Shorty")) @test scalar test { @@ -150,7 +150,7 @@ describe("@example", () => { } `); expect(examples).toHaveLength(1); - expect(serializeValueAsJson(program, examples[0].value, target)).toEqual("Shorty"); + expect(serializeValueAsJson(program, examples[0].value, target)).toBeUndefined(); }); }); diff --git a/packages/openapi3/test/models.test.ts b/packages/openapi3/test/models.test.ts index 1f27ce141e3..e883f803d29 100644 --- a/packages/openapi3/test/models.test.ts +++ b/packages/openapi3/test/models.test.ts @@ -262,7 +262,7 @@ worksFor(supportedVersions, ({ diagnoseOpenApiFor, oapiForModel, openApiFor }) = }); }); - it("scalar used as a default value", async () => { + it("scalar with unknown constructor used as a default value produces no default and no diagnostic", async () => { const res = await oapiForModel( "Pet", ` @@ -272,7 +272,7 @@ worksFor(supportedVersions, ({ diagnoseOpenApiFor, oapiForModel, openApiFor }) = `, ); - expect(res.schemas.Pet.properties.name.default).toEqual("Shorty"); + expect(res.schemas.Pet.properties.name.default).toBeUndefined(); }); it("scalar with no-argument initializer used as a default value does not crash", async () => { From 5b6687bdcb05d03a2d5e89e86f3db393a8bc3625 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 20:30:48 +0000 Subject: [PATCH 5/8] test(openapi3): add test for known scalar constructors producing correct default values Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com> --- packages/openapi3/test/models.test.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/openapi3/test/models.test.ts b/packages/openapi3/test/models.test.ts index e883f803d29..d88c53d8773 100644 --- a/packages/openapi3/test/models.test.ts +++ b/packages/openapi3/test/models.test.ts @@ -288,6 +288,21 @@ worksFor(supportedVersions, ({ diagnoseOpenApiFor, oapiForModel, openApiFor }) = expect(res.schemas.M.properties.p.default).toBeUndefined(); }); + it("known scalar constructors used as default values produce correct defaults", async () => { + const res = await oapiForModel( + "Foo", + ` + model Foo { + int32Prop: int32 = int32(12); + stringProp: string = string("this is the string value"); + } + `, + ); + + expect(res.schemas.Foo.properties.int32Prop.default).toEqual(12); + expect(res.schemas.Foo.properties.stringProp.default).toEqual("this is the string value"); + }); + it("encode know scalar as a default value", async () => { const res = await oapiForModel( "Test", From 4f77a593d5ec1641cb5496435eba52756abda551 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 20:54:46 +0000 Subject: [PATCH 6/8] chore: merge latest main changes (Fix to customized base type #9885) Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com> --- .../src/Providers/ModelProvider.cs | 22 +++++++- .../src/TypeFactory.cs | 20 ++----- .../ModelProviders/ModelCustomizationTests.cs | 55 +++++++++++++++++++ .../MockInputModel.cs | 7 +++ 4 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/TestData/ModelCustomizationTests/CanCustomizeBaseModelToRenamedGeneratedModel/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 4682a736fb4..c7c8949dda4 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 @@ -300,9 +300,27 @@ private static bool IsDiscriminator(InputProperty property) // 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)) + // Cheap check: the base model may already be created and registered under the right name. + if (CodeModelGenerator.Instance.TypeFactory.TypeProvidersByName.TryGetValue( + baseType.Name, out var resolvedProvider) && + resolvedProvider is ModelProvider resolvedModel) { - baseType = CodeModelGenerator.Instance.TypeFactory.CreateCSharpType(baseInputModel); + return resolvedModel; + } + + // Force-create all input models so that visitors run (which may rename models + // via TypeProvider.Update) and TypeProvidersByName is fully populated. + // This is a no-op for models that have already been created. + foreach (var model in CodeModelGenerator.Instance.InputLibrary.InputNamespace.Models) + { + CodeModelGenerator.Instance.TypeFactory.CreateModel(model); + } + + if (CodeModelGenerator.Instance.TypeFactory.TypeProvidersByName.TryGetValue( + baseType.Name, out resolvedProvider) && + resolvedProvider is ModelProvider resolvedAfterCreate) + { + return resolvedAfterCreate; } } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/TypeFactory.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/TypeFactory.cs index 3f40150c468..a6454ee6f79 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/TypeFactory.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/TypeFactory.cs @@ -39,20 +39,6 @@ public class TypeFactory internal HashSet UnionVariantTypesToKeep { get; } = []; - internal IDictionary InputModelTypeNameMap - { - get - { - if (_inputModelTypeNameMap == null) - { - _inputModelTypeNameMap = CodeModelGenerator.Instance.InputLibrary.InputNamespace.Models.ToDictionary(m => m.Name.ToIdentifierName(), m => m); - } - - return _inputModelTypeNameMap; - } - } - private IDictionary? _inputModelTypeNameMap; - protected internal TypeFactory() { } @@ -190,6 +176,10 @@ protected internal TypeFactory() if (InputTypeToModelProvider.TryGetValue(model, out var modelProvider)) return modelProvider; + // Add sentinel before construction to prevent re-entrant creation of the same model + // (e.g., when BuildBaseModelProvider triggers CreateModel for all input models). + InputTypeToModelProvider[model] = null; + modelProvider = CreateModelCore(model); foreach (var visitor in Visitors) @@ -197,7 +187,7 @@ protected internal TypeFactory() modelProvider = visitor.PreVisitModel(model, modelProvider); } - InputTypeToModelProvider.Add(model, modelProvider); + InputTypeToModelProvider[model] = modelProvider; if (modelProvider != 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 12ca5d62946..556948c476e 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 @@ -6,6 +6,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.TypeSpec.Generator.Input; +using Microsoft.TypeSpec.Generator.Input.Extensions; using Microsoft.TypeSpec.Generator.Primitives; using Microsoft.TypeSpec.Generator.Providers; using Microsoft.TypeSpec.Generator.Tests.Common; @@ -1570,6 +1571,60 @@ private class TestNamespaceVisitor : NameSpaceVisitor } } + [Test] + public async Task CanCustomizeBaseModelToRenamedGeneratedModel() + { + // This test verifies that when a base model is renamed (e.g., by a library visitor), + // a child model whose custom code inherits from the renamed name correctly resolves the base type. + // The base model is NOT defined in custom code, so Roslyn cannot resolve the namespace. + var baseModel = InputFactory.Model( + "baseModel", + properties: [InputFactory.Property("baseProp", InputPrimitiveType.String)], + usage: InputModelTypeUsage.Json); + var childModel = InputFactory.Model( + "mockInputModel", + properties: [InputFactory.Property("childProp", InputPrimitiveType.String)], + usage: InputModelTypeUsage.Json); + + var mockGenerator = await MockHelpers.LoadMockGeneratorAsync( + inputModelTypes: [childModel, baseModel], + compilation: async () => await Helpers.GetCompilationFromDirectoryAsync()); + + // Simulate a visitor renaming the base model (e.g., adding a "Resource" suffix) + mockGenerator.Object.AddVisitor(new BaseModelRenameVisitor("BaseModel", "RenamedBaseModel")); + + var modelProvider = mockGenerator.Object.OutputLibrary.TypeProviders.Single(t => t.Name == "MockInputModel") as ModelProvider; + + Assert.IsNotNull(modelProvider); + Assert.IsNotNull(modelProvider!.BaseModelProvider); + Assert.IsNotNull(modelProvider.BaseType); + Assert.AreEqual("RenamedBaseModel", modelProvider.BaseType!.Name); + Assert.AreEqual("Sample.Models", modelProvider.BaseType!.Namespace); + Assert.AreEqual(1, modelProvider.BaseModelProvider!.Properties.Count); + Assert.AreEqual("BaseProp", modelProvider.BaseModelProvider.Properties[0].Name); + } + + private class BaseModelRenameVisitor : LibraryVisitor + { + private readonly string _originalName; + private readonly string _newName; + + public BaseModelRenameVisitor(string originalName, string newName) + { + _originalName = originalName; + _newName = newName; + } + + protected internal override ModelProvider? PreVisitModel(InputModelType model, ModelProvider? type) + { + if (type != null && model.Name.ToIdentifierName() == _originalName) + { + type.Update(name: _newName); + } + return type; + } + } + [Test] public async Task CanCustomizeBaseModelToExternalType() { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/TestData/ModelCustomizationTests/CanCustomizeBaseModelToRenamedGeneratedModel/MockInputModel.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/TestData/ModelCustomizationTests/CanCustomizeBaseModelToRenamedGeneratedModel/MockInputModel.cs new file mode 100644 index 00000000000..8adbb6e2bac --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/TestData/ModelCustomizationTests/CanCustomizeBaseModelToRenamedGeneratedModel/MockInputModel.cs @@ -0,0 +1,7 @@ +#nullable disable + +namespace Sample.Models; + +internal partial class MockInputModel : RenamedBaseModel +{ +} From c6d28efff843d8692a48c0cffebbc1e8f74a2bb4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 21:02:32 +0000 Subject: [PATCH 7/8] revert: remove inadvertent csharp emitter file changes from PR Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com> --- .../src/Providers/ModelProvider.cs | 22 +------- .../src/TypeFactory.cs | 20 +++++-- .../ModelProviders/ModelCustomizationTests.cs | 55 ------------------- .../MockInputModel.cs | 7 --- 4 files changed, 17 insertions(+), 87 deletions(-) delete mode 100644 packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/TestData/ModelCustomizationTests/CanCustomizeBaseModelToRenamedGeneratedModel/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 c7c8949dda4..4682a736fb4 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 @@ -300,27 +300,9 @@ private static bool IsDiscriminator(InputProperty property) // was not also defined in custom code so Roslyn does not recognize it. if (string.IsNullOrEmpty(baseType.Namespace)) { - // Cheap check: the base model may already be created and registered under the right name. - if (CodeModelGenerator.Instance.TypeFactory.TypeProvidersByName.TryGetValue( - baseType.Name, out var resolvedProvider) && - resolvedProvider is ModelProvider resolvedModel) + if (CodeModelGenerator.Instance.TypeFactory.InputModelTypeNameMap.TryGetValue(baseType.Name, out var baseInputModel)) { - return resolvedModel; - } - - // Force-create all input models so that visitors run (which may rename models - // via TypeProvider.Update) and TypeProvidersByName is fully populated. - // This is a no-op for models that have already been created. - foreach (var model in CodeModelGenerator.Instance.InputLibrary.InputNamespace.Models) - { - CodeModelGenerator.Instance.TypeFactory.CreateModel(model); - } - - if (CodeModelGenerator.Instance.TypeFactory.TypeProvidersByName.TryGetValue( - baseType.Name, out resolvedProvider) && - resolvedProvider is ModelProvider resolvedAfterCreate) - { - return resolvedAfterCreate; + baseType = CodeModelGenerator.Instance.TypeFactory.CreateCSharpType(baseInputModel); } } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/TypeFactory.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/TypeFactory.cs index a6454ee6f79..3f40150c468 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/TypeFactory.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/TypeFactory.cs @@ -39,6 +39,20 @@ public class TypeFactory internal HashSet UnionVariantTypesToKeep { get; } = []; + internal IDictionary InputModelTypeNameMap + { + get + { + if (_inputModelTypeNameMap == null) + { + _inputModelTypeNameMap = CodeModelGenerator.Instance.InputLibrary.InputNamespace.Models.ToDictionary(m => m.Name.ToIdentifierName(), m => m); + } + + return _inputModelTypeNameMap; + } + } + private IDictionary? _inputModelTypeNameMap; + protected internal TypeFactory() { } @@ -176,10 +190,6 @@ protected internal TypeFactory() if (InputTypeToModelProvider.TryGetValue(model, out var modelProvider)) return modelProvider; - // Add sentinel before construction to prevent re-entrant creation of the same model - // (e.g., when BuildBaseModelProvider triggers CreateModel for all input models). - InputTypeToModelProvider[model] = null; - modelProvider = CreateModelCore(model); foreach (var visitor in Visitors) @@ -187,7 +197,7 @@ protected internal TypeFactory() modelProvider = visitor.PreVisitModel(model, modelProvider); } - InputTypeToModelProvider[model] = modelProvider; + InputTypeToModelProvider.Add(model, modelProvider); if (modelProvider != 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 556948c476e..12ca5d62946 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 @@ -6,7 +6,6 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.TypeSpec.Generator.Input; -using Microsoft.TypeSpec.Generator.Input.Extensions; using Microsoft.TypeSpec.Generator.Primitives; using Microsoft.TypeSpec.Generator.Providers; using Microsoft.TypeSpec.Generator.Tests.Common; @@ -1571,60 +1570,6 @@ private class TestNamespaceVisitor : NameSpaceVisitor } } - [Test] - public async Task CanCustomizeBaseModelToRenamedGeneratedModel() - { - // This test verifies that when a base model is renamed (e.g., by a library visitor), - // a child model whose custom code inherits from the renamed name correctly resolves the base type. - // The base model is NOT defined in custom code, so Roslyn cannot resolve the namespace. - var baseModel = InputFactory.Model( - "baseModel", - properties: [InputFactory.Property("baseProp", InputPrimitiveType.String)], - usage: InputModelTypeUsage.Json); - var childModel = InputFactory.Model( - "mockInputModel", - properties: [InputFactory.Property("childProp", InputPrimitiveType.String)], - usage: InputModelTypeUsage.Json); - - var mockGenerator = await MockHelpers.LoadMockGeneratorAsync( - inputModelTypes: [childModel, baseModel], - compilation: async () => await Helpers.GetCompilationFromDirectoryAsync()); - - // Simulate a visitor renaming the base model (e.g., adding a "Resource" suffix) - mockGenerator.Object.AddVisitor(new BaseModelRenameVisitor("BaseModel", "RenamedBaseModel")); - - var modelProvider = mockGenerator.Object.OutputLibrary.TypeProviders.Single(t => t.Name == "MockInputModel") as ModelProvider; - - Assert.IsNotNull(modelProvider); - Assert.IsNotNull(modelProvider!.BaseModelProvider); - Assert.IsNotNull(modelProvider.BaseType); - Assert.AreEqual("RenamedBaseModel", modelProvider.BaseType!.Name); - Assert.AreEqual("Sample.Models", modelProvider.BaseType!.Namespace); - Assert.AreEqual(1, modelProvider.BaseModelProvider!.Properties.Count); - Assert.AreEqual("BaseProp", modelProvider.BaseModelProvider.Properties[0].Name); - } - - private class BaseModelRenameVisitor : LibraryVisitor - { - private readonly string _originalName; - private readonly string _newName; - - public BaseModelRenameVisitor(string originalName, string newName) - { - _originalName = originalName; - _newName = newName; - } - - protected internal override ModelProvider? PreVisitModel(InputModelType model, ModelProvider? type) - { - if (type != null && model.Name.ToIdentifierName() == _originalName) - { - type.Update(name: _newName); - } - return type; - } - } - [Test] public async Task CanCustomizeBaseModelToExternalType() { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/TestData/ModelCustomizationTests/CanCustomizeBaseModelToRenamedGeneratedModel/MockInputModel.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/TestData/ModelCustomizationTests/CanCustomizeBaseModelToRenamedGeneratedModel/MockInputModel.cs deleted file mode 100644 index 8adbb6e2bac..00000000000 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/TestData/ModelCustomizationTests/CanCustomizeBaseModelToRenamedGeneratedModel/MockInputModel.cs +++ /dev/null @@ -1,7 +0,0 @@ -#nullable disable - -namespace Sample.Models; - -internal partial class MockInputModel : RenamedBaseModel -{ -} From 8bfc3110366277f8bd9ca1dafae818cdf063ccb5 Mon Sep 17 00:00:00 2001 From: Mark Cowlishaw <1054056+markcowl@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:02:31 -0800 Subject: [PATCH 8/8] Update .chronus/changes/fix-ice-serialize-value-as-json-custom-scalar-2026-2-25-20-0-0.md Co-authored-by: Timothee Guerin --- ...-serialize-value-as-json-custom-scalar-2026-2-25-20-0-0.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.chronus/changes/fix-ice-serialize-value-as-json-custom-scalar-2026-2-25-20-0-0.md b/.chronus/changes/fix-ice-serialize-value-as-json-custom-scalar-2026-2-25-20-0-0.md index 7f8835d022c..25affad8bba 100644 --- a/.chronus/changes/fix-ice-serialize-value-as-json-custom-scalar-2026-2-25-20-0-0.md +++ b/.chronus/changes/fix-ice-serialize-value-as-json-custom-scalar-2026-2-25-20-0-0.md @@ -4,4 +4,6 @@ packages: - "@typespec/compiler" --- -core - Fix ICE in `serializeValueAsJson` when a custom scalar initializer has no recognized constructor (e.g. `S.i()` with no args). Now returns `undefined` instead of crashing. +Fix crash when using custom scalar initializer in examples or default values + [API] Fix crash in `serializeValueAsJson` when a custom scalar initializer has no recognized constructor (e.g. `S.i()` with no args). Now returns `undefined` instead of crashing. +