From 50fe34ecc66877bead1f0ae55afe28b88e5eda10 Mon Sep 17 00:00:00 2001 From: Aleksei Androsov Date: Wed, 4 Aug 2021 13:13:17 +0300 Subject: [PATCH] fix: resolve import collisions for enums (#341) Similar to #339. Also fixes generated functions --- .../avoid-import-conflicts/simple-test.ts | 24 +++- integration/avoid-import-conflicts/simple.bin | Bin 577 -> 1254 bytes .../avoid-import-conflicts/simple.proto | 13 ++ integration/avoid-import-conflicts/simple.ts | 134 +++++++++++++++++- .../avoid-import-conflicts/simple2.bin | Bin 273 -> 486 bytes .../avoid-import-conflicts/simple2.proto | 6 + integration/avoid-import-conflicts/simple2.ts | 38 +++++ src/enums.ts | 10 +- 8 files changed, 210 insertions(+), 15 deletions(-) diff --git a/integration/avoid-import-conflicts/simple-test.ts b/integration/avoid-import-conflicts/simple-test.ts index 7d64d7224..dd326d1e5 100644 --- a/integration/avoid-import-conflicts/simple-test.ts +++ b/integration/avoid-import-conflicts/simple-test.ts @@ -1,7 +1,21 @@ -import { Simple } from './simple'; +import { Simple, SimpleEnum as LocalSimpleEnum, SimpleEnums } from './simple'; +import { SimpleEnum as ImportSimpleEnum } from './simple2'; -describe('simple', () => { - it('generates types correctly', () => { - const simple = Simple.fromPartial({}); +describe('Simple', () => { + it('type checking works correctly for interfaces', () => { + const simple: Simple = { + name: 'foo', + otherSimple: { + name: 'bar', + age: 1, + }, + } }); -}); + + it('type checking works correctly for enums', () => { + const simpleEnum: SimpleEnums = { + localEnum: LocalSimpleEnum.LOCAL_BAR, + importEnum: ImportSimpleEnum.IMPORT_FOO, + } + }); +}) diff --git a/integration/avoid-import-conflicts/simple.bin b/integration/avoid-import-conflicts/simple.bin index 9ad985f0e854ef02848b9db733dcad0e7f62f04e..6680f2c9a145b733359cb56e8e8f436646ef1984 100644 GIT binary patch literal 1254 zcmaKrO>Yx15QhD=U*pZL*J;%#AQ1vcsE0@mT#*RSN>o8XOF35oMFlBosx)xu|Kcxj z;71{5?A>G+A#Q#>?~KQu$B^EBUEM4fqnpioyY9!aG7oo?`JHJ=H`n5C=4r3cWz&wIZTycaL7U zqmpJB3O7qkBgn(7h8ab)GZGNd&PeD*Xspl!*4d*6P4sjNJ>5c2x6so~^iuJ##w)Zk z-Ghi-q{aO@hUlda2CfTkRnG7Y=>yQE^4Q&1ar%=+_!Jaa&iEfhAvBuKkt>G^%bET? h_is4ew-8UN5XZE_zb>Xx{o-&?$1tsU^tk>2e*n4yp+W!v literal 577 zcmaLTu};G<5C-70&vu+k(xkT#RY;UfOpz#W(FG|yL6IUrqNFOF`Z(Q>fbk(E%v`CCvnRGXpWXpB`&=Al1gCiS-4x20H%o4Dy` zE(mu|Z7JQ8Zv43Y5M)>Z7(tdq$_T)Il8gchB9aPNq3?-MfnY?tpoEkH35-fIrKEk( zKG~4mqKdPS(4}HIp1DfPVyuKa(=rOlcQy&ho#{pXXnKIV^OvL<37g^DtGPyX|1ZKV zCEe+{Jq}JiMzYE4QLrAKo9WK>b5x4{QpzbNiOxd8MF3OaRs)!tg6SEUo`LBZn4W?e Xc^yy;qxt1?U}kw4ItOO1)&cAX8>> 3) { + case 1: + message.localEnum = reader.int32() as any; + break; + case 2: + message.importEnum = reader.int32() as any; + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): SimpleEnums { + const message = { ...baseSimpleEnums } as SimpleEnums; + if (object.localEnum !== undefined && object.localEnum !== null) { + message.localEnum = simpleEnumFromJSON(object.localEnum); + } else { + message.localEnum = 0; + } + if (object.importEnum !== undefined && object.importEnum !== null) { + message.importEnum = simpleEnumFromJSON3(object.importEnum); + } else { + message.importEnum = 0; + } + return message; + }, + + toJSON(message: SimpleEnums): unknown { + const obj: any = {}; + message.localEnum !== undefined && (obj.localEnum = simpleEnumToJSON(message.localEnum)); + message.importEnum !== undefined && (obj.importEnum = simpleEnumToJSON4(message.importEnum)); + return obj; + }, + + fromPartial(object: DeepPartial): SimpleEnums { + const message = { ...baseSimpleEnums } as SimpleEnums; + if (object.localEnum !== undefined && object.localEnum !== null) { + message.localEnum = object.localEnum; + } else { + message.localEnum = 0; + } + if (object.importEnum !== undefined && object.importEnum !== null) { + message.importEnum = object.importEnum; + } else { + message.importEnum = 0; + } + return message; + }, +}; + type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; export type DeepPartial = T extends Builtin ? T diff --git a/integration/avoid-import-conflicts/simple2.bin b/integration/avoid-import-conflicts/simple2.bin index d5a010893488ef3bc0479a4825508b676f607b28..13d5fc14992832a9c66765f883b9df7034c8e010 100644 GIT binary patch literal 486 zcmY+B%SyyB6o!+NOWTu98;=UbmCQ<9%tBwl5obVADs^1T2t@?vf|rf&`?`7G9Hgo8Wo5_W^IPHnjFMg*Pte}QEh5zG<*KdZp*+f( zIFm=Ud}=G;Bh!TO_zbc0XX}p@?-Z9ew{^34xR}kS_ty(As6gz`=5_7y51&sP@2@EmkNFk)*r9doV kHX2AV`S>np9J#K00A6#D^kS&%Qa2E!MrnG3PEvBY&OWLom;dURV@$?7B`VIL2 diff --git a/integration/avoid-import-conflicts/simple2.proto b/integration/avoid-import-conflicts/simple2.proto index 6b128e8a5..2072c0f56 100644 --- a/integration/avoid-import-conflicts/simple2.proto +++ b/integration/avoid-import-conflicts/simple2.proto @@ -1,6 +1,12 @@ syntax = "proto3"; package simple2; +enum SimpleEnum { + IMPORT_DEFAULT = 0; + IMPORT_FOO = 10; + IMPORT_BAR = 11; +} + message Simple { string name = 1; int32 age = 2; diff --git a/integration/avoid-import-conflicts/simple2.ts b/integration/avoid-import-conflicts/simple2.ts index 0ea85d86f..31433569f 100644 --- a/integration/avoid-import-conflicts/simple2.ts +++ b/integration/avoid-import-conflicts/simple2.ts @@ -4,6 +4,44 @@ import * as Long from 'long'; export const protobufPackage = 'simple2'; +export enum SimpleEnum { + IMPORT_DEFAULT = 0, + IMPORT_FOO = 10, + IMPORT_BAR = 11, + UNRECOGNIZED = -1, +} + +export function simpleEnumFromJSON(object: any): SimpleEnum { + switch (object) { + case 0: + case 'IMPORT_DEFAULT': + return SimpleEnum.IMPORT_DEFAULT; + case 10: + case 'IMPORT_FOO': + return SimpleEnum.IMPORT_FOO; + case 11: + case 'IMPORT_BAR': + return SimpleEnum.IMPORT_BAR; + case -1: + case 'UNRECOGNIZED': + default: + return SimpleEnum.UNRECOGNIZED; + } +} + +export function simpleEnumToJSON(object: SimpleEnum): string { + switch (object) { + case SimpleEnum.IMPORT_DEFAULT: + return 'IMPORT_DEFAULT'; + case SimpleEnum.IMPORT_FOO: + return 'IMPORT_FOO'; + case SimpleEnum.IMPORT_BAR: + return 'IMPORT_BAR'; + default: + return 'UNKNOWN'; + } +} + export interface Simple { name: string; age: number; diff --git a/src/enums.ts b/src/enums.ts index 64d46b55c..f75f50aaa 100644 --- a/src/enums.ts +++ b/src/enums.ts @@ -57,7 +57,8 @@ export function generateEnumFromJson(ctx: Context, fullName: string, enumDesc: E const { options, utils } = ctx; const chunks: Code[] = []; - chunks.push(code`export function ${camelCase(fullName)}FromJSON(object: any): ${fullName} {`); + const functionName = camelCase(fullName) + 'FromJSON'; + chunks.push(code`export function ${def(functionName)}(object: any): ${fullName} {`); chunks.push(code`switch (object) {`); for (const valueDesc of enumDesc.value) { @@ -92,7 +93,8 @@ export function generateEnumFromJson(ctx: Context, fullName: string, enumDesc: E export function generateEnumToJson(fullName: string, enumDesc: EnumDescriptorProto): Code { const chunks: Code[] = []; - chunks.push(code`export function ${camelCase(fullName)}ToJSON(object: ${fullName}): string {`); + const functionName = camelCase(fullName) + 'ToJSON'; + chunks.push(code`export function ${def(functionName)}(object: ${fullName}): string {`); chunks.push(code`switch (object) {`); for (const valueDesc of enumDesc.value) { @@ -108,7 +110,9 @@ export function generateEnumToJson(fullName: string, enumDesc: EnumDescriptorPro /** Generates a function with a big switch statement to encode our string enum -> int value. */ export function generateEnumToNumber(fullName: string, enumDesc: EnumDescriptorProto): Code { const chunks: Code[] = []; - chunks.push(code`export function ${camelCase(fullName)}ToNumber(object: ${fullName}): number {`); + + const functionName = camelCase(fullName) + 'ToNumber'; + chunks.push(code`export function ${def(functionName)}(object: ${fullName}): number {`); chunks.push(code`switch (object) {`); for (const valueDesc of enumDesc.value) { chunks.push(code`case ${fullName}.${valueDesc.name}: return ${valueDesc.number};`);