From 0540a54cda0e00c48c37477c7331a6d2e4368ae7 Mon Sep 17 00:00:00 2001 From: tadelesh Date: Tue, 21 May 2024 20:57:40 +0800 Subject: [PATCH 1/4] support enum value with mix types --- .../src/interfaces.ts | 4 +- .../src/types.ts | 41 +++++++++++++------ .../test/types.test.ts | 20 +++++++++ 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/packages/typespec-client-generator-core/src/interfaces.ts b/packages/typespec-client-generator-core/src/interfaces.ts index d6f2550405..6ce5d76dab 100644 --- a/packages/typespec-client-generator-core/src/interfaces.ts +++ b/packages/typespec-client-generator-core/src/interfaces.ts @@ -249,7 +249,7 @@ export interface SdkEnumType extends SdkTypeBase { kind: "enum"; name: string; isGeneratedName: boolean; - valueType: SdkBuiltInType; + valueType: SdkBuiltInType | SdkUnionType; values: SdkEnumValueType[]; isFixed: boolean; isFlags: boolean; @@ -265,7 +265,7 @@ export interface SdkEnumValueType extends SdkTypeBase { name: string; value: string | number; enumType: SdkEnumType; - valueType: SdkBuiltInType; + valueType: SdkBuiltInType | SdkUnionType; } export interface SdkConstantType extends SdkTypeBase { kind: "constant"; diff --git a/packages/typespec-client-generator-core/src/types.ts b/packages/typespec-client-generator-core/src/types.ts index ce1cdc9874..c9268da050 100644 --- a/packages/typespec-client-generator-core/src/types.ts +++ b/packages/typespec-client-generator-core/src/types.ts @@ -609,10 +609,13 @@ function getSdkEnumValueType( | IterableIterator | IterableIterator> | IterableIterator> -): SdkBuiltInType { - let kind: "string" | "int32" | "float32" = "string"; - let type: EnumMember | UnionVariant; +): SdkBuiltInType | SdkUnionType { + let stringType: SdkBuiltInType | undefined = undefined; + let numberType: SdkBuiltInType | undefined = undefined; + for (const value of values) { + let type: EnumMember | UnionVariant; + if ((value as EnumMember).kind) { type = value as EnumMember; } else { @@ -620,20 +623,32 @@ function getSdkEnumValueType( } if (typeof value.value === "number") { - kind = intOrFloat(value.value); - if (kind === "float32") { - break; + const calType = intOrFloat(value.value); + if (numberType === undefined || (numberType.kind === "int32" && calType === "float32")) { + numberType = { + ...getSdkTypeBaseHelper(context, type!, calType), + encode: calType, + }; } - } else if (typeof value.value === "string") { - kind = "string"; - break; + } else { + stringType = { + ...getSdkTypeBaseHelper(context, type!, "string"), + encode: "string", + }; } } - return { - ...getSdkTypeBaseHelper(context, type!, kind!), - encode: kind!, - }; + if (stringType === undefined || numberType === undefined) { + return stringType ?? numberType!; + } else { + return { + kind: "union", + values: [stringType, numberType], + nullable: false, + name: "", + isGeneratedName: false, + }; + } } function getUnionAsEnumValueType(context: TCGCContext, union: Union): SdkBuiltInType | undefined { diff --git a/packages/typespec-client-generator-core/test/types.test.ts b/packages/typespec-client-generator-core/test/types.test.ts index 62983aee26..7e35075b63 100644 --- a/packages/typespec-client-generator-core/test/types.test.ts +++ b/packages/typespec-client-generator-core/test/types.test.ts @@ -1830,6 +1830,26 @@ describe("typespec-client-generator-core: types", () => { strictEqual(enums[1].name, "UD"); strictEqual(enums[1].usage, UsageFlags.Input); }); + + 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.experimental_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"); + }); }); describe("SdkBodyModelPropertyType", () => { From d3ed4cc1c840a4a9400e9c164d651a9f1b7afd96 Mon Sep 17 00:00:00 2001 From: tadelesh Date: Tue, 21 May 2024 20:58:18 +0800 Subject: [PATCH 2/4] changelog --- .chronus/changes/enum_mix_type-2024-4-21-20-58-13.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .chronus/changes/enum_mix_type-2024-4-21-20-58-13.md 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 From 3ccfe0a1e137da2cf347600620c559fdf3aa3772 Mon Sep 17 00:00:00 2001 From: tadelesh Date: Tue, 27 Aug 2024 15:48:17 +0800 Subject: [PATCH 3/4] resolve conflict --- .../src/types.ts | 56 ++++++++++--------- .../test/types/enum-types.test.ts | 20 +++++++ 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/packages/typespec-client-generator-core/src/types.ts b/packages/typespec-client-generator-core/src/types.ts index 21b25a056c..5c2c0d6fef 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,12 +885,11 @@ function getSdkEnumWithDiagnostics( details: docWrapper.details, doc: getDoc(context.program, type), summary: getSummary(context.program, type), - valueType: diagnostics.pipe( + 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 isFlags: false, @@ -949,11 +959,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 +1003,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, @@ -1314,8 +1320,8 @@ function updateMultiPartInfo( : undefined, contentType: httpOperationPart.body.contentTypeProperty ? diagnostics.pipe( - getSdkModelPropertyType(context, httpOperationPart.body.contentTypeProperty, operation) - ) + getSdkModelPropertyType(context, httpOperationPart.body.contentTypeProperty, operation) + ) : undefined, defaultContentTypes: httpOperationPart.body.contentTypes, }; 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"); + }); }); From c669e119a5d40d5ec6b452271804b00f6dd77326 Mon Sep 17 00:00:00 2001 From: tadelesh Date: Tue, 27 Aug 2024 15:51:58 +0800 Subject: [PATCH 4/4] format --- .../typespec-client-generator-core/src/types.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/typespec-client-generator-core/src/types.ts b/packages/typespec-client-generator-core/src/types.ts index 5c2c0d6fef..e2947fb04c 100644 --- a/packages/typespec-client-generator-core/src/types.ts +++ b/packages/typespec-client-generator-core/src/types.ts @@ -885,11 +885,10 @@ function getSdkEnumWithDiagnostics( details: docWrapper.details, doc: getDoc(context.program, type), summary: getSummary(context.program, type), - valueType: - 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 isFlags: false, @@ -1320,8 +1319,8 @@ function updateMultiPartInfo( : undefined, contentType: httpOperationPart.body.contentTypeProperty ? diagnostics.pipe( - getSdkModelPropertyType(context, httpOperationPart.body.contentTypeProperty, operation) - ) + getSdkModelPropertyType(context, httpOperationPart.body.contentTypeProperty, operation) + ) : undefined, defaultContentTypes: httpOperationPart.body.contentTypes, };