feat(parsing): parse object and array destructurings correctly (#76) · buehler/node-typescript-parser@97cb4ce
11import {
2-ArrayBindingPattern,
32FunctionDeclaration,
43Identifier,
4+isTupleTypeNode,
5+isTypeLiteralNode,
6+isTypeReferenceNode,
57MethodDeclaration,
68MethodSignature,
79Node,
8-ObjectBindingPattern,
910ParameterDeclaration,
11+PropertySignature,
1012SyntaxKind,
1113VariableStatement,
1214} from 'typescript';
@@ -15,9 +17,18 @@ import { ConstructorDeclaration as TshConstructor } from '../declarations/Constr
1517import { DefaultDeclaration as TshDefault } from '../declarations/DefaultDeclaration';
1618import { FunctionDeclaration as TshFunction } from '../declarations/FunctionDeclaration';
1719import { MethodDeclaration as TshMethod } from '../declarations/MethodDeclaration';
18-import { ParameterDeclaration as TshParameter } from '../declarations/ParameterDeclaration';
20+import {
21+ArrayBoundParameterDeclaration,
22+ObjectBoundParameterDeclaration,
23+ParameterDeclaration as TshParameter,
24+} from '../declarations/ParameterDeclaration';
1925import { Resource } from '../resources/Resource';
20-import { isArrayBindingPattern, isIdentifier, isObjectBindingPattern } from '../type-guards/TypescriptGuards';
26+import {
27+isArrayBindingPattern,
28+isIdentifier,
29+isObjectBindingPattern,
30+isPropertySignature,
31+} from '../type-guards/TypescriptGuards';
2132import { parseIdentifier } from './identifier-parser';
2233import { getDefaultResourceIdentifier, getNodeType, isNodeDefaultExported, isNodeExported } from './parse-utilities';
2334import { parseVariable } from './variable-parser';
@@ -63,22 +74,51 @@ export function parseMethodParams(
6374): TshParameter[] {
6475return node.parameters.reduce(
6576(all: TshParameter[], cur: ParameterDeclaration) => {
66-let params = all;
77+const params = all;
6778if (isIdentifier(cur.name)) {
6879params.push(new TshParameter(
6980(cur.name as Identifier).text, getNodeType(cur.type), cur.getStart(), cur.getEnd(),
7081));
71-} else if (isObjectBindingPattern(cur.name) || isArrayBindingPattern(cur.name)) {
72-const identifiers = cur.name as ObjectBindingPattern | ArrayBindingPattern;
73-const elements = [...identifiers.elements];
74-// TODO: BindingElement
75-params = params.concat(<TshParameter[]>elements.map((o: any) => {
76-if (isIdentifier(o.name)) {
77-return new TshParameter(
78-(o.name as Identifier).text, undefined, o.getStart(), o.getEnd(),
79-);
80-}
81-}).filter(Boolean));
82+} else if (isObjectBindingPattern(cur.name)) {
83+const elements = cur.name.elements;
84+let types: (string | undefined)[] = [];
85+const boundParam = new ObjectBoundParameterDeclaration(cur.getStart(), cur.getEnd());
86+87+if (cur.type && isTypeReferenceNode(cur.type)) {
88+boundParam.typeReference = getNodeType(cur.type);
89+} else if (cur.type && isTypeLiteralNode(cur.type)) {
90+types = cur.type.members
91+.filter(member => isPropertySignature(member))
92+.map((signature: any) => getNodeType((signature as PropertySignature).type));
93+}
94+95+boundParam.parameters = elements.map((bindingElement, index) => new TshParameter(
96+bindingElement.name.getText(),
97+types[index],
98+bindingElement.getStart(),
99+bindingElement.getEnd(),
100+));
101+102+params.push(boundParam);
103+} else if (isArrayBindingPattern(cur.name)) {
104+const elements = cur.name.elements;
105+let types: (string | undefined)[] = [];
106+const boundParam = new ArrayBoundParameterDeclaration(cur.getStart(), cur.getEnd());
107+108+if (cur.type && isTypeReferenceNode(cur.type)) {
109+boundParam.typeReference = getNodeType(cur.type);
110+} else if (cur.type && isTupleTypeNode(cur.type)) {
111+types = cur.type.elementTypes.map(type => getNodeType(type));
112+}
113+114+boundParam.parameters = elements.map((bindingElement, index) => new TshParameter(
115+bindingElement.getText(),
116+types[index],
117+bindingElement.getStart(),
118+bindingElement.getEnd(),
119+));
120+121+params.push(boundParam);
82122}
83123return params;
84124},