From 8b1c7c25a75221d075de4839febb0c325e37f58c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BA=84=E9=BB=9B=E6=B7=B3=E5=8D=8E?= Date: Sat, 11 May 2024 18:10:39 +0800 Subject: [PATCH] fix return type become tuple type from interface type (#124) * fix return type become tuple type from interface type * bump to 0.12.1 --- package-lock.json | 4 ++-- package.json | 2 +- src/parser/ValueParser.ts | 38 +++++++++++++++----------------------- test/value-parser-test.ts | 39 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 55 insertions(+), 28 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9ece0e5..a116e2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ts-gyb", - "version": "0.12.0", + "version": "0.12.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ts-gyb", - "version": "0.12.0", + "version": "0.12.1", "license": "MIT", "dependencies": { "chalk": "^4.1.1", diff --git a/package.json b/package.json index 225306b..4a54ac5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ts-gyb", - "version": "0.12.0", + "version": "0.12.1", "description": "Generate Native API based on TS interface", "repository": { "type": "git", diff --git a/src/parser/ValueParser.ts b/src/parser/ValueParser.ts index e3058e0..681c7f5 100644 --- a/src/parser/ValueParser.ts +++ b/src/parser/ValueParser.ts @@ -267,9 +267,9 @@ export class ValueParser { } let nullable = false; - let isTuple = false; - const valueTypes: ValueType[] = []; - const tupleMembers: Field[] = []; + const valueTypes: NonEmptyType[] = []; + let hasTupleType = false; + const tupleOrInterfaceTypes: (TupleType | InterfaceType)[] = []; const literalValues: { type: BasicTypeValue.string | BasicTypeValue.number; value: Value; @@ -295,23 +295,15 @@ export class ValueParser { return; } - const newValueType = this.valueTypeFromTypeNode(typeNode); + const newValueType = this.valueTypeFromTypeNode(typeNode) as NonEmptyType; - if (valueTypes.length === 0) { - isTuple = isInterfaceType(newValueType) || isTupleType(newValueType); + valueTypes.push(newValueType); + if (isTupleType(newValueType)) { + hasTupleType = true; + tupleOrInterfaceTypes.push(newValueType); } - - if (isTuple) { - if (isInterfaceType(newValueType) || isTupleType(newValueType)) { - tupleMembers.push(...newValueType.members); - } else { - throw new ValueParserError( - `type ${node.getText()} is invalid`, - 'Use `multiple tuple types` or `union value types` or `type union`' - ); - } - } else { - valueTypes.push(newValueType); + if (isInterfaceType(newValueType)) { + tupleOrInterfaceTypes.push(newValueType); } }); @@ -348,24 +340,24 @@ export class ValueParser { return literalKind; } - if (valueTypes.length === 0 && tupleMembers.length === 0) { + if (valueTypes.length === 0) { throw new ValueParserError( `type ${node.getText()} is invalid`, 'Type must contain one supported non empty type' ); } - if (valueTypes.length > 0 && tupleMembers.length > 0) { + if (hasTupleType && valueTypes.length !== tupleOrInterfaceTypes.length) { throw new ValueParserError( `mixing ${node.getText()} is invalid`, 'Type must contain types or tuples' ); } - if (isTuple) { + if (hasTupleType) { const value: TupleType = { kind: ValueTypeKind.tupleType, - members: tupleMembers, + members: tupleOrInterfaceTypes.map((type) => type.members).flat(), }; if (nullable) { const optionalType: OptionalType = { @@ -378,7 +370,7 @@ export class ValueParser { } if (valueTypes.length === 1) { - if (!isOptionalType(valueTypes[0]) && nullable) { + if (nullable) { return { kind: ValueTypeKind.optionalType, wrappedType: valueTypes[0], diff --git a/test/value-parser-test.ts b/test/value-parser-test.ts index 9ba1ce5..1f1773f 100644 --- a/test/value-parser-test.ts +++ b/test/value-parser-test.ts @@ -32,6 +32,42 @@ describe('ValueParser', () => { expect(parseFunc()).to.deep.equal({ name: 'mockedMethod', parameters: [], returnType: null, isAsync: true, documentation: '', }); }) }); + + it('Return type', () => { + let customTypesCode = ` + export interface SelectionRect { + start: number; + } + ` + const methodCode = ` + mockedMethod(): SelectionRect; + `; + withTempMethodParser(methodCode, parseFunc => { + expect(parseFunc()).to.deep.equal({ + name: 'mockedMethod', + parameters: [], + returnType: { + name: 'SelectionRect', + customTags: {}, + methods: [], + documentation: '', + kind: 'interfaceType', + members: [ + { + documentation: '', + name: 'start', + type: { + kind: 'basicType', + value: 'number', + }, + }, + ], + }, + isAsync: false, + documentation: '', + }); + }, new Set(), customTypesCode) + }); }); describe('Parameters type', () => { @@ -184,7 +220,6 @@ describe('ValueParser', () => { } `; testValueType('merged interface and tuple', 'InterfaceWithStringField | { numberField: number }', tupleWithMembersType, new Set(), interfacesCode); - testValueType('merged interfaces to tuple', 'InterfaceWithStringField | InterfaceWithNumberField', tupleWithMembersType, new Set(), interfacesCode); }) describe('Parse enum type', () => { @@ -287,7 +322,7 @@ describe('ValueParser', () => { testValueType('string interface dictionary', 'DictionaryInterface', { kind: ValueTypeKind.dictionaryType, keyType: DictionaryKeyType.string, valueType: numberType }, new Set(), dictionaryCode); }); - describe('Parse optional type', () => { + describe('Parse union type', () => { it('Empty types union', () => { const valueTypeCode = 'null | undefined'; withTempValueParser(valueTypeCode, parseFunc => {