From 5038b4f836bc903db5d4f1ff20a9df6bd37418ab Mon Sep 17 00:00:00 2001 From: Aidin Abedi Date: Mon, 6 Apr 2020 00:27:38 +0200 Subject: [PATCH] Add support for properties of values in an array (#119) * add tests for properties of values in an array * add support for properties of values in an array * cosmetic changes --- src/PropTree.ts | 7 ++++++- src/create_helpers.ts | 2 +- src/type_resolve_helpers.ts | 25 ++++++++++++++++++------- test/expected/function_all.d.ts | 9 +++++++-- test/expected/property_all.d.ts | 10 ++++++++++ test/fixtures/function_all.js | 11 +++++++++++ test/fixtures/property_all.js | 11 +++++++++++ 7 files changed, 64 insertions(+), 11 deletions(-) diff --git a/src/PropTree.ts b/src/PropTree.ts index 856ca5b..863b2bf 100644 --- a/src/PropTree.ts +++ b/src/PropTree.ts @@ -56,7 +56,12 @@ export class PropTree if (parts.length > 1) { parts.pop(); - const parentName = parts.join('.'); + let parentName = parts.join('.'); + if (parentName.endsWith('[]')) + { + parentName = parentName.substring(0, parentName.length - '[]'.length); + } + const parent = this.nodes[parentName]; if (!parent) diff --git a/src/create_helpers.ts b/src/create_helpers.ts index d21eea1..683531d 100644 --- a/src/create_helpers.ts +++ b/src/create_helpers.ts @@ -214,7 +214,7 @@ export function createClass(doclet: IClassDoclet, children?: ts.Node[]): ts.Clas { const node = tree.roots[i]; const opt = node.prop.optional ? ts.createToken(ts.SyntaxKind.QuestionToken) : undefined; - const t = node.children.length ? createTypeLiteral(node.children) : resolveType(node.prop.type); + const t = node.children.length ? createTypeLiteral(node.children, node) : resolveType(node.prop.type); const property = ts.createProperty( undefined, diff --git a/src/type_resolve_helpers.ts b/src/type_resolve_helpers.ts index 40d79a9..3d2dce2 100644 --- a/src/type_resolve_helpers.ts +++ b/src/type_resolve_helpers.ts @@ -687,7 +687,7 @@ export function resolveTypeName(name: string, doclet?: TTypedDoclet): ts.TypeNod return resolveComplexTypeName(name); } -export function resolveTypeLiteral(props?: IDocletProp[]): ts.TypeLiteralNode +export function resolveTypeLiteral(props?: IDocletProp[]): ts.TypeNode { if (!props) return ts.createTypeLiteralNode([]); @@ -697,15 +697,15 @@ export function resolveTypeLiteral(props?: IDocletProp[]): ts.TypeLiteralNode return createTypeLiteral(tree.roots); } -export function createTypeLiteral(nodes: IPropDesc[]): ts.TypeLiteralNode +export function createTypeLiteral(children: IPropDesc[], parent?: IPropDesc): ts.TypeNode { const members: ts.PropertySignature[] = []; - for (let i = 0; i < nodes.length; ++i) + for (let i = 0; i < children.length; ++i) { - const node = nodes[i]; + const node = children[i]; const opt = node.prop.optional ? ts.createToken(ts.SyntaxKind.QuestionToken) : undefined; - const t = node.children.length ? createTypeLiteral(node.children) : resolveType(node.prop.type); + const t = node.children.length ? createTypeLiteral(node.children, node) : resolveType(node.prop.type); members.push(ts.createPropertySignature( undefined, // modifiers @@ -716,7 +716,18 @@ export function createTypeLiteral(nodes: IPropDesc[]): ts.TypeLiteralNode )); } - return ts.createTypeLiteralNode(members); + let node: ts.TypeNode = ts.createTypeLiteralNode(members); + + if (parent) + { + const names = parent.prop.type.names; + if (names.length === 1 && names[0].toLowerCase() === 'array.') + { + node = ts.createArrayTypeNode(node); + } + } + + return node; } export function createFunctionParams(doclet: IFunctionDoclet | ITypedefDoclet | IClassDoclet): ts.ParameterDeclaration[] @@ -747,7 +758,7 @@ export function createFunctionParams(doclet: IFunctionDoclet | ITypedefDoclet | const node = tree.roots[i]; const opt = resolveOptionalParameter(node.prop); const dots = resolveVariableParameter(node.prop); - let type = node.children.length ? createTypeLiteral(node.children) : resolveType(node.prop.type); + let type = node.children.length ? createTypeLiteral(node.children, node) : resolveType(node.prop.type); if (dots) { diff --git a/test/expected/function_all.d.ts b/test/expected/function_all.d.ts index 5402f77..b063092 100644 --- a/test/expected/function_all.d.ts +++ b/test/expected/function_all.d.ts @@ -5,9 +5,14 @@ declare function test1(a?: number, input: { declare function test2(x: any[], y: any[], z: any[], w: any[][]): void; +declare function test3(myObjs: { + foo: number; + bar: boolean; + test1: string; + test2?: string[]; +}[]): void; + declare class Test12345 { static f(): number[]; static f(key: string): number; } - - diff --git a/test/expected/property_all.d.ts b/test/expected/property_all.d.ts index 0bc4dda..40c703e 100644 --- a/test/expected/property_all.d.ts +++ b/test/expected/property_all.d.ts @@ -54,3 +54,13 @@ declare class PropTest6 { myProp: boolean; myProp: boolean; } + +declare class PropTest7 { + constructor(); + myProps: { + foo: number; + bar: boolean; + test1: string; + test2?: string[]; + }[]; +} diff --git a/test/fixtures/function_all.js b/test/fixtures/function_all.js index ea7c8f4..e770bc9 100644 --- a/test/fixtures/function_all.js +++ b/test/fixtures/function_all.js @@ -18,6 +18,17 @@ function test1(input) { function test2(x, y, z, w) { } +/** + * @function + * @param {object[]} myObjs + * @param {number} myObjs[].foo + * @param {boolean} myObjs[].bar + * @param {string} myObjs[].test1 + * @param {string[]} [myObjs[].test2] + */ +function test3(myObjs) { +} + /** * @class */ diff --git a/test/fixtures/property_all.js b/test/fixtures/property_all.js index 5f453bb..a56b23b 100644 --- a/test/fixtures/property_all.js +++ b/test/fixtures/property_all.js @@ -74,3 +74,14 @@ var PropTest6 = function() { */ this.myProp = true; } + +/** + * @constructor + * @property {object[]} myProps + * @property {number} myProps[].foo + * @property {boolean} myProps[].bar + * @property {string} myProps[].test1 + * @property {string[]} [myProps[].test2] + */ +var PropTest7 = function() { +}