diff --git a/.chronus/changes/enum_mix_type-2024-4-21-20-58-13.md b/.chronus/changes/enum_mix_type-2024-4-21-20-58-13.md new file mode 100644 index 0000000000..bded09ca6a --- /dev/null +++ b/.chronus/changes/enum_mix_type-2024-4-21-20-58-13.md @@ -0,0 +1,7 @@ +--- +changeKind: breaking +packages: + - "@azure-tools/typespec-client-generator-core" +--- + +support enum value with mix types \ No newline at end of file diff --git a/packages/typespec-client-generator-core/src/interfaces.ts b/packages/typespec-client-generator-core/src/interfaces.ts index b5174d24d9..bdf9bfd1bd 100644 --- a/packages/typespec-client-generator-core/src/interfaces.ts +++ b/packages/typespec-client-generator-core/src/interfaces.ts @@ -329,7 +329,7 @@ export interface SdkEnumType extends SdkTypeBase { kind: "enum"; name: string; isGeneratedName: boolean; - valueType: SdkBuiltInType; + valueType: SdkBuiltInType | SdkUnionType; values: SdkEnumValueType[]; isFixed: boolean; isFlags: boolean; @@ -345,7 +345,7 @@ export interface SdkEnumValueType extends SdkTypeBase { name: string; value: string | number; enumType: SdkEnumType; - valueType: SdkBuiltInType; + valueType: SdkBuiltInType | SdkUnionType; } export interface SdkConstantType extends SdkTypeBase { diff --git a/packages/typespec-client-generator-core/src/types.ts b/packages/typespec-client-generator-core/src/types.ts index 21b25a056c..e2947fb04c 100644 --- a/packages/typespec-client-generator-core/src/types.ts +++ b/packages/typespec-client-generator-core/src/types.ts @@ -788,22 +788,33 @@ export function getSdkModelWithDiagnostics( function getSdkEnumValueType( context: TCGCContext, values: (string | number | undefined)[] -): [SdkBuiltInType, readonly Diagnostic[]] { - const diagnostics = createDiagnosticCollector(); - let kind: "string" | "int32" | "float32" = "string"; +): SdkBuiltInType | SdkUnionType { + let stringType: SdkBuiltInType | undefined = undefined; + let numberType: SdkBuiltInType | undefined = undefined; + for (const value of values) { if (typeof value === "number") { - kind = intOrFloat(value); - if (kind === "float32") { - break; + const calType = intOrFloat(value); + if (numberType === undefined || (numberType.kind === "int32" && calType === "float32")) { + numberType = getTypeSpecBuiltInType(context, calType); } - } else if (typeof value === "string") { - kind = "string"; - break; + } else { + stringType = getTypeSpecBuiltInType(context, "string"); } } - return diagnostics.wrap(getTypeSpecBuiltInType(context, kind!)); + if (stringType === undefined || numberType === undefined) { + return stringType ?? numberType!; + } else { + return { + kind: "union", + values: [stringType, numberType], + name: "", + isGeneratedName: false, + crossLanguageDefinitionId: "", + decorators: [], + }; + } } function getUnionAsEnumValueType( @@ -874,11 +885,9 @@ function getSdkEnumWithDiagnostics( details: docWrapper.details, doc: getDoc(context.program, type), summary: getSummary(context.program, type), - valueType: diagnostics.pipe( - getSdkEnumValueType( - context, - [...type.members.values()].map((v) => v.value) - ) + valueType: getSdkEnumValueType( + context, + [...type.members.values()].map((v) => v.value) ), values: [], isFixed: true, // enums are always fixed after we switch to use union to represent extensible enum @@ -949,11 +958,9 @@ export function getSdkUnionEnumWithDiagnostics( summary: getSummary(context.program, union), valueType: diagnostics.pipe(getUnionAsEnumValueType(context, type.union)) ?? - diagnostics.pipe( - getSdkEnumValueType( - context, - [...type.flattenedMembers.values()].map((v) => v.value) - ) + getSdkEnumValueType( + context, + [...type.flattenedMembers.values()].map((v) => v.value) ), values: [], isFixed: !type.open, @@ -995,11 +1002,9 @@ function getKnownValuesEnum( details: docWrapper.details, doc: getDoc(context.program, type), summary: getSummary(context.program, type), - valueType: diagnostics.pipe( - getSdkEnumValueType( - context, - [...knownValues.members.values()].map((v) => v.value) - ) + valueType: getSdkEnumValueType( + context, + [...knownValues.members.values()].map((v) => v.value) ), values: [], isFixed: false, diff --git a/packages/typespec-client-generator-core/test/types/enum-types.test.ts b/packages/typespec-client-generator-core/test/types/enum-types.test.ts index c2ffcc4b42..57b1c76a65 100644 --- a/packages/typespec-client-generator-core/test/types/enum-types.test.ts +++ b/packages/typespec-client-generator-core/test/types/enum-types.test.ts @@ -793,4 +793,24 @@ describe("typespec-client-generator-core: enum types", () => { strictEqual(testModel.access, "public"); strictEqual(testModel.usage, UsageFlags.Input | UsageFlags.Json); }); + + it("mix type enums", async () => { + await runner.compileWithBuiltInService( + ` + @usage(Usage.input | Usage.output) + @access(Access.public) + enum MixTypeEnum { + One: 1, + Two: "2", + Three: 3.2, + } + ` + ); + const enums = runner.context.sdkPackage.enums; + strictEqual(enums.length, 1); + strictEqual(enums[0].name, "MixTypeEnum"); + strictEqual(enums[0].valueType.kind, "union"); + strictEqual(enums[0].valueType.values[0].kind, "string"); + strictEqual(enums[0].valueType.values[1].kind, "float32"); + }); });