From 03627396662033cff06004d8729b6ed89ea5c54a Mon Sep 17 00:00:00 2001 From: Qiaoqiao Zhang <55688292+qiaozha@users.noreply.github.com> Date: Mon, 29 Apr 2024 16:27:03 +0800 Subject: [PATCH] normalize-name-in-interface-and-type-alias (#2483) * normalize-name-in-interface-and-type-alias * fix main * fix alias * fix ci * fix ci * unify rlc enum and union name * Update packages/typespec-ts/test/modularUnit/enumUnion.spec.ts Co-authored-by: Mary Gao --------- Co-authored-by: Mary Gao --- .../typespec-ts/src/modular/buildCodeModel.ts | 20 ++++-- packages/typespec-ts/src/utils/modelUtils.ts | 13 ++-- .../generated/union-body/src/models.ts | 6 +- .../generated/union-body/src/outputModels.ts | 6 +- .../generated/unions/src/models.ts | 12 ++-- .../generated/unions/src/outputModels.ts | 12 ++-- .../generated/unions/src/index.ts | 4 +- .../generated/unions/src/models/index.ts | 4 +- .../generated/unions/src/models/models.ts | 8 +-- .../generated/unions/src/rest/models.ts | 12 ++-- .../generated/unions/src/rest/outputModels.ts | 12 ++-- .../test/modularUnit/enumUnion.spec.ts | 37 ++++++++++- .../test/unit/modelsGenerator.spec.ts | 64 +++++++++++++++++++ 13 files changed, 158 insertions(+), 52 deletions(-) diff --git a/packages/typespec-ts/src/modular/buildCodeModel.ts b/packages/typespec-ts/src/modular/buildCodeModel.ts index b4684ca16a..0760169660 100644 --- a/packages/typespec-ts/src/modular/buildCodeModel.ts +++ b/packages/typespec-ts/src/modular/buildCodeModel.ts @@ -314,6 +314,7 @@ function processModelProperties( // because it's impossible to have a anonymous model as the polymorphic base in typespec // the only possibility is the anonymous model is an alias for an union type which has already been taken care of in the combined types. if (newValue.name) { + newValue.name = normalizeName(newValue.name, NameType.Interface); discriminatorInfo?.aliases.push(`${newValue.name}`); newValue.alias = `${newValue.name}`; newValue.name = `${newValue.name}Union`; @@ -1108,9 +1109,10 @@ function emitEnum(context: SdkContext, type: Enum): Record { return { type: "enum", - name: getLibraryName(context, type) - ? getLibraryName(context, type) - : type.name, + name: normalizeName( + getLibraryName(context, type) ? getLibraryName(context, type) : type.name, + NameType.Interface + ), description: getDocStr(program, type), valueType: { type: enumMemberType(type.members.values().next().value) }, values: enumValues, @@ -1399,10 +1401,13 @@ function emitUnion( } return valueType; }); + const unionTypeName = unionName + ? normalizeName(unionName, NameType.Interface) + : undefined; return { nullable: sdkType.nullable, - name: unionName, - description: `Type of ${unionName}`, + name: unionTypeName, + description: `Type of ${unionTypeName}`, internal: true, type: "combined", types: variantTypes, @@ -1417,11 +1422,14 @@ function emitUnion( : variantTypes.map((x) => getTypeName(x).name).join(" | ") }; } else if (sdkType.kind === "enum") { - const typeName = getLibraryName(context, type) + let typeName = getLibraryName(context, type) ? getLibraryName(context, type) : sdkType.isGeneratedName ? type.name : sdkType.name; + typeName = typeName + ? normalizeName(typeName, NameType.Interface) + : undefined; return { name: typeName, nullable: sdkType.nullable, diff --git a/packages/typespec-ts/src/utils/modelUtils.ts b/packages/typespec-ts/src/utils/modelUtils.ts index ea2b97c147..847176ef83 100644 --- a/packages/typespec-ts/src/utils/modelUtils.ts +++ b/packages/typespec-ts/src/utils/modelUtils.ts @@ -401,10 +401,13 @@ function getSchemaForUnion( .map((item) => `${getTypeName(item, [SchemaContext.Output]) ?? item}`) .join(" | "); if (!union.expression) { - schema.name = union.name; + const unionName = union.name + ? normalizeName(union.name, NameType.Interface) + : undefined; + schema.name = unionName; schema.type = "object"; - schema.typeName = union.name; - schema.outputTypeName = union.name + "Output"; + schema.typeName = unionName; + schema.outputTypeName = unionName + "Output"; schema.alias = unionAlias; schema.outputAlias = outputUnionAlias; } else if (union.expression && !union.name) { @@ -938,8 +941,8 @@ function getSchemaForEnum(dpgContext: SdkContext, e: Enum) { const schema: any = { type: "object", name: e.name, - typeName: e.name, - outputTypeName: e.name + "Output", + typeName: normalizeName(e.name, NameType.Interface), + outputTypeName: normalizeName(e.name, NameType.Interface) + "Output", description: getDoc(dpgContext.program, e), memberType: type }; diff --git a/packages/typespec-ts/test/integration/generated/union-body/src/models.ts b/packages/typespec-ts/test/integration/generated/union-body/src/models.ts index ecdd11d559..297fdbb652 100644 --- a/packages/typespec-ts/test/integration/generated/union-body/src/models.ts +++ b/packages/typespec-ts/test/integration/generated/union-body/src/models.ts @@ -6,12 +6,12 @@ export interface RequestRegisterCC extends CommonRegistrationRequest { } export interface CommonRegistrationRequest { - payMethod: PAYMENT_METHODS; + payMethod: PaymentMethods; } export interface RequestRegisterVA { prop: string; } -/** Alias for PAYMENT_METHODS */ -export type PAYMENT_METHODS = "01"; +/** Alias for PaymentMethods */ +export type PaymentMethods = "01"; diff --git a/packages/typespec-ts/test/integration/generated/union-body/src/outputModels.ts b/packages/typespec-ts/test/integration/generated/union-body/src/outputModels.ts index 4f5c067f54..3a0e9ac78f 100644 --- a/packages/typespec-ts/test/integration/generated/union-body/src/outputModels.ts +++ b/packages/typespec-ts/test/integration/generated/union-body/src/outputModels.ts @@ -7,12 +7,12 @@ export interface RequestRegisterCCOutput } export interface CommonRegistrationRequestOutput { - payMethod: PAYMENT_METHODSOutput; + payMethod: PaymentMethodsOutput; } export interface RequestRegisterVAOutput { prop: string; } -/** Alias for PAYMENT_METHODSOutput */ -export type PAYMENT_METHODSOutput = "01"; +/** Alias for PaymentMethodsOutput */ +export type PaymentMethodsOutput = "01"; diff --git a/packages/typespec-ts/test/integration/generated/unions/src/models.ts b/packages/typespec-ts/test/integration/generated/unions/src/models.ts index 0d793788f7..fb37ff6a4b 100644 --- a/packages/typespec-ts/test/integration/generated/unions/src/models.ts +++ b/packages/typespec-ts/test/integration/generated/unions/src/models.ts @@ -11,9 +11,9 @@ export interface Dog { export interface EnumsOnlyCases { /** This should be receive/send the left variant */ - lr: LR | UD; + lr: Lr | Ud; /** This should be receive/send the up variant */ - ud: UD | UD; + ud: Ud | Ud; } export interface StringAndArrayCases { @@ -47,7 +47,7 @@ export interface MixedTypesCases { /** Alias for StringExtensibleNamedUnion */ export type StringExtensibleNamedUnion = string | "b" | "c"; -/** Alias for LR */ -export type LR = "left" | "right"; -/** Alias for UD */ -export type UD = "up" | "down"; +/** Alias for Lr */ +export type Lr = "left" | "right"; +/** Alias for Ud */ +export type Ud = "up" | "down"; diff --git a/packages/typespec-ts/test/integration/generated/unions/src/outputModels.ts b/packages/typespec-ts/test/integration/generated/unions/src/outputModels.ts index 96a3c89bef..68be9e59d2 100644 --- a/packages/typespec-ts/test/integration/generated/unions/src/outputModels.ts +++ b/packages/typespec-ts/test/integration/generated/unions/src/outputModels.ts @@ -11,9 +11,9 @@ export interface DogOutput { export interface EnumsOnlyCasesOutput { /** This should be receive/send the left variant */ - lr: LROutput | UDOutput; + lr: LrOutput | UdOutput; /** This should be receive/send the up variant */ - ud: UDOutput | UDOutput; + ud: UdOutput | UdOutput; } export interface StringAndArrayCasesOutput { @@ -47,7 +47,7 @@ export interface MixedTypesCasesOutput { /** Alias for StringExtensibleNamedUnionOutput */ export type StringExtensibleNamedUnionOutput = string | "b" | "c"; -/** Alias for LROutput */ -export type LROutput = "left" | "right"; -/** Alias for UDOutput */ -export type UDOutput = "up" | "down"; +/** Alias for LrOutput */ +export type LrOutput = "left" | "right"; +/** Alias for UdOutput */ +export type UdOutput = "up" | "down"; diff --git a/packages/typespec-ts/test/modularIntegration/generated/unions/src/index.ts b/packages/typespec-ts/test/modularIntegration/generated/unions/src/index.ts index a80f2133f1..46fbbd27bc 100644 --- a/packages/typespec-ts/test/modularIntegration/generated/unions/src/index.ts +++ b/packages/typespec-ts/test/modularIntegration/generated/unions/src/index.ts @@ -8,8 +8,8 @@ export { MixedLiteralsCases, StringAndArrayCases, EnumsOnlyCases, - LR, - UD, + Lr, + Ud, Dog, StringExtensibleNamedUnion, StringsOnlyGetOptionalParams, diff --git a/packages/typespec-ts/test/modularIntegration/generated/unions/src/models/index.ts b/packages/typespec-ts/test/modularIntegration/generated/unions/src/models/index.ts index cc0debfdcc..9bb05a3254 100644 --- a/packages/typespec-ts/test/modularIntegration/generated/unions/src/models/index.ts +++ b/packages/typespec-ts/test/modularIntegration/generated/unions/src/models/index.ts @@ -7,8 +7,8 @@ export { MixedLiteralsCases, StringAndArrayCases, EnumsOnlyCases, - LR, - UD, + Lr, + Ud, Dog, StringExtensibleNamedUnion, } from "./models.js"; diff --git a/packages/typespec-ts/test/modularIntegration/generated/unions/src/models/models.ts b/packages/typespec-ts/test/modularIntegration/generated/unions/src/models/models.ts index 67dc067ad0..56404618fb 100644 --- a/packages/typespec-ts/test/modularIntegration/generated/unions/src/models/models.ts +++ b/packages/typespec-ts/test/modularIntegration/generated/unions/src/models/models.ts @@ -36,15 +36,15 @@ export interface StringAndArrayCases { export interface EnumsOnlyCases { /** This should be receive/send the left variant */ - lr: LR | UD; + lr: Lr | Ud; /** This should be receive/send the up variant */ - ud: UD | UD; + ud: Ud | Ud; } /** */ -export type LR = "left" | "right"; +export type Lr = "left" | "right"; /** */ -export type UD = "up" | "down"; +export type Ud = "up" | "down"; export interface Dog { bark: string; diff --git a/packages/typespec-ts/test/modularIntegration/generated/unions/src/rest/models.ts b/packages/typespec-ts/test/modularIntegration/generated/unions/src/rest/models.ts index 0d793788f7..fb37ff6a4b 100644 --- a/packages/typespec-ts/test/modularIntegration/generated/unions/src/rest/models.ts +++ b/packages/typespec-ts/test/modularIntegration/generated/unions/src/rest/models.ts @@ -11,9 +11,9 @@ export interface Dog { export interface EnumsOnlyCases { /** This should be receive/send the left variant */ - lr: LR | UD; + lr: Lr | Ud; /** This should be receive/send the up variant */ - ud: UD | UD; + ud: Ud | Ud; } export interface StringAndArrayCases { @@ -47,7 +47,7 @@ export interface MixedTypesCases { /** Alias for StringExtensibleNamedUnion */ export type StringExtensibleNamedUnion = string | "b" | "c"; -/** Alias for LR */ -export type LR = "left" | "right"; -/** Alias for UD */ -export type UD = "up" | "down"; +/** Alias for Lr */ +export type Lr = "left" | "right"; +/** Alias for Ud */ +export type Ud = "up" | "down"; diff --git a/packages/typespec-ts/test/modularIntegration/generated/unions/src/rest/outputModels.ts b/packages/typespec-ts/test/modularIntegration/generated/unions/src/rest/outputModels.ts index 96a3c89bef..68be9e59d2 100644 --- a/packages/typespec-ts/test/modularIntegration/generated/unions/src/rest/outputModels.ts +++ b/packages/typespec-ts/test/modularIntegration/generated/unions/src/rest/outputModels.ts @@ -11,9 +11,9 @@ export interface DogOutput { export interface EnumsOnlyCasesOutput { /** This should be receive/send the left variant */ - lr: LROutput | UDOutput; + lr: LrOutput | UdOutput; /** This should be receive/send the up variant */ - ud: UDOutput | UDOutput; + ud: UdOutput | UdOutput; } export interface StringAndArrayCasesOutput { @@ -47,7 +47,7 @@ export interface MixedTypesCasesOutput { /** Alias for StringExtensibleNamedUnionOutput */ export type StringExtensibleNamedUnionOutput = string | "b" | "c"; -/** Alias for LROutput */ -export type LROutput = "left" | "right"; -/** Alias for UDOutput */ -export type UDOutput = "up" | "down"; +/** Alias for LrOutput */ +export type LrOutput = "left" | "right"; +/** Alias for UdOutput */ +export type UdOutput = "up" | "down"; diff --git a/packages/typespec-ts/test/modularUnit/enumUnion.spec.ts b/packages/typespec-ts/test/modularUnit/enumUnion.spec.ts index 9144689dfd..bf12dbac9e 100644 --- a/packages/typespec-ts/test/modularUnit/enumUnion.spec.ts +++ b/packages/typespec-ts/test/modularUnit/enumUnion.spec.ts @@ -842,17 +842,48 @@ describe("model type", () => { modelFile!.getFullText()!, ` export interface Test { - color: LR | UD; + color: Lr | Ud; } /** */ - export type LR = "left" | "right"; + export type Lr = "left" | "right"; /** */ - export type UD = "up" | "down"; + export type Ud = "up" | "down"; ` ); }); + it("non-standard enum/union name", async () => { + const modelFile = await emitModularModelsFromTypeSpec(` + union leftAndRight { + "left", + "right", + } + enum upAndDown { + up, + down, + } + model Test { + color: leftAndRight | upAndDown; + } + op read(@body body: Test): void; + `); + assert.ok(modelFile); + await assertEqualContent( + modelFile!.getFullText()!, + ` + export interface Test { + color: LeftAndRight | UpAndDown; + } + + /** Type of LeftAndRight */ + /** */ + export type LeftAndRight = "left" | "right"; + /** */ + export type UpAndDown = "up" | "down"; + ` + ); + }); it("nullable numeric literal", async () => { const modelFile = await emitModularModelsFromTypeSpec(` model Test { diff --git a/packages/typespec-ts/test/unit/modelsGenerator.spec.ts b/packages/typespec-ts/test/unit/modelsGenerator.spec.ts index defeee71c1..a7c4e2e3fb 100644 --- a/packages/typespec-ts/test/unit/modelsGenerator.spec.ts +++ b/packages/typespec-ts/test/unit/modelsGenerator.spec.ts @@ -235,6 +235,49 @@ describe("Input/output model type", () => { export type TranslationLanguageValuesOutput = "English" | "Chinese";` ); }); + it("should handle enum with non-standard name as property -> type alias with union", async () => { + const schemaOutput = await emitModelsFromTypeSpec(` + @doc("Extensible enum model description") + enum translationLanguageValues { + #suppress "@azure-tools/typespec-azure-core/documentation-required" "for test" + English, + #suppress "@azure-tools/typespec-azure-core/documentation-required" "for test" + Chinese, + } + model InputOutputModel { + @doc("Property description") + prop: translationLanguageValues; + } + @route("/models") + @get + op getModel(@body input: InputOutputModel): InputOutputModel; + `); + assert.ok(schemaOutput); + const { inputModelFile, outputModelFile } = schemaOutput!; + await assertEqualContent( + inputModelFile?.content!, + ` + export interface InputOutputModel { + /** Property description */ + prop: TranslationLanguageValues; + } + + /** Extensible enum model description */ + export type TranslationLanguageValues = "English" | "Chinese"; + ` + ); + await assertEqualContent( + outputModelFile?.content!, + ` + export interface InputOutputModelOutput { + /** Property description */ + prop: TranslationLanguageValuesOutput; + } + + /** Extensible enum model description */ + export type TranslationLanguageValuesOutput = "English" | "Chinese";` + ); + }); it("should handle enum as body -> type alias with union", async () => { const schemaOutput = await emitParameterFromTypeSpec(` #suppress "@azure-tools/typespec-azure-core/documentation-required" "for test" @@ -2282,6 +2325,27 @@ describe("Input/output model type", () => { }); }); + it("union with non-standard name whose variants are pure primitive types", async () => { + const tspDefinition = ` + union myNamedUnion { + one: string, + two: int32, + } + `; + const tspType = "myNamedUnion | null"; + const inputModelName = "MyNamedUnion | null"; + await verifyPropertyType(tspType, inputModelName, { + additionalTypeSpecDefinition: tspDefinition, + outputType: `MyNamedUnionOutput | null`, + additionalInputContent: ` + /** Alias for MyNamedUnion */ + export type MyNamedUnion = string | number;`, + additionalOutputContent: ` + /** Alias for MyNamedUnionOutput */ + export type MyNamedUnionOutput = string | number;` + }); + }); + it("union variants are pure constants", async () => { const tspDefinition = ` union StringExtensibleNamedUnion {