Skip to content
This repository was archived by the owner on Jan 14, 2019. It is now read-only.

Commit f11e368

Browse files
armano2JamesHenry
authored andcommitted
feat: change logic of distinguishing patterns from statements (#118)
BREAKING CHANGE: This changes the AST
1 parent 868e760 commit f11e368

File tree

4 files changed

+69
-256
lines changed

4 files changed

+69
-256
lines changed

src/convert.ts

Lines changed: 51 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ interface ConvertConfig {
3535
node: ts.Node;
3636
parent?: ts.Node | null;
3737
inTypeMode?: boolean;
38+
allowPattern?: boolean;
3839
ast: ts.SourceFile;
3940
additionalOptions: ConvertAdditionalOptions;
4041
}
@@ -83,26 +84,40 @@ export default function convert(config: ConvertConfig): ESTreeNode | null {
8384
loc: nodeUtils.getLoc(node, ast)
8485
};
8586

86-
function converter(child?: ts.Node, inTypeMode?: boolean): ESTreeNode | null {
87+
function converter(
88+
child?: ts.Node,
89+
inTypeMode?: boolean,
90+
allowPattern?: boolean
91+
): ESTreeNode | null {
8792
if (!child) {
8893
return null;
8994
}
9095
return convert({
9196
node: child,
9297
parent: node,
9398
inTypeMode,
99+
allowPattern,
94100
ast,
95101
additionalOptions
96102
});
97103
}
98104

105+
/**
106+
* Converts a TypeScript node into an ESTree node.
107+
* @param {ts.Node} child the child ts.Node
108+
* @returns {ESTreeNode|null} the converted ESTree node
109+
*/
110+
function convertPattern(child?: ts.Node): ESTreeNode | null {
111+
return converter(child, config.inTypeMode, true);
112+
}
113+
99114
/**
100115
* Converts a TypeScript node into an ESTree node.
101116
* @param {ts.Node} child the child ts.Node
102117
* @returns {ESTreeNode|null} the converted ESTree node
103118
*/
104119
function convertChild(child?: ts.Node): ESTreeNode | null {
105-
return converter(child, config.inTypeMode);
120+
return converter(child, config.inTypeMode, false);
106121
}
107122

108123
/**
@@ -111,7 +126,7 @@ export default function convert(config: ConvertConfig): ESTreeNode | null {
111126
* @returns {ESTreeNode|null} the converted ESTree node
112127
*/
113128
function convertChildType(child?: ts.Node): ESTreeNode | null {
114-
return converter(child, true);
129+
return converter(child, true, false);
115130
}
116131

117132
/**
@@ -632,7 +647,7 @@ export default function convert(config: ConvertConfig): ESTreeNode | null {
632647
case SyntaxKind.ForOfStatement: {
633648
Object.assign(result, {
634649
type: SyntaxKind[node.kind],
635-
left: convertChild(node.initializer),
650+
left: convertPattern(node.initializer),
636651
right: convertChild(node.expression),
637652
body: convertChild(node.statement)
638653
});
@@ -691,7 +706,7 @@ export default function convert(config: ConvertConfig): ESTreeNode | null {
691706
case SyntaxKind.VariableDeclaration: {
692707
Object.assign(result, {
693708
type: AST_NODE_TYPES.VariableDeclarator,
694-
id: convertChild(node.name),
709+
id: convertPattern(node.name),
695710
init: convertChild(node.initializer)
696711
});
697712

@@ -746,42 +761,11 @@ export default function convert(config: ConvertConfig): ESTreeNode | null {
746761
break;
747762

748763
case SyntaxKind.ArrayLiteralExpression: {
749-
const arrayAssignNode = nodeUtils.findAncestorOfKind(
750-
node,
751-
SyntaxKind.BinaryExpression
752-
);
753-
const arrayIsInForOf =
754-
node.parent && node.parent.kind === SyntaxKind.ForOfStatement;
755-
const arrayIsInForIn =
756-
node.parent && node.parent.kind === SyntaxKind.ForInStatement;
757-
let arrayIsInAssignment;
758-
759-
if (arrayAssignNode) {
760-
if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) {
761-
arrayIsInAssignment = false;
762-
} else if (node.parent.kind === SyntaxKind.CallExpression) {
763-
arrayIsInAssignment = false;
764-
} else if (
765-
nodeUtils.getBinaryExpressionType(
766-
(arrayAssignNode as any).operatorToken
767-
) === AST_NODE_TYPES.AssignmentExpression
768-
) {
769-
arrayIsInAssignment =
770-
nodeUtils.findChildOfKind(
771-
(arrayAssignNode as any).left,
772-
SyntaxKind.ArrayLiteralExpression,
773-
ast
774-
) === node || (arrayAssignNode as any).left === node;
775-
} else {
776-
arrayIsInAssignment = false;
777-
}
778-
}
779-
780764
// TypeScript uses ArrayLiteralExpression in destructuring assignment, too
781-
if (arrayIsInAssignment || arrayIsInForOf || arrayIsInForIn) {
765+
if (config.allowPattern) {
782766
Object.assign(result, {
783767
type: AST_NODE_TYPES.ArrayPattern,
784-
elements: node.elements.map(convertChild)
768+
elements: node.elements.map(convertPattern)
785769
});
786770
} else {
787771
Object.assign(result, {
@@ -793,59 +777,30 @@ export default function convert(config: ConvertConfig): ESTreeNode | null {
793777
}
794778

795779
case SyntaxKind.ObjectLiteralExpression: {
796-
const ancestorNode = nodeUtils.findFirstMatchingAncestor(
797-
node,
798-
parentNode =>
799-
parentNode.kind === SyntaxKind.BinaryExpression ||
800-
parentNode.kind === SyntaxKind.ArrowFunction
801-
);
802-
const objectAssignNode =
803-
ancestorNode &&
804-
ancestorNode.kind === SyntaxKind.BinaryExpression &&
805-
(ancestorNode as any).operatorToken.kind === SyntaxKind.FirstAssignment
806-
? ancestorNode
807-
: null;
808-
809-
let objectIsInAssignment = false;
810-
811-
if (objectAssignNode) {
812-
if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) {
813-
objectIsInAssignment = false;
814-
} else if ((objectAssignNode as any).left === node) {
815-
objectIsInAssignment = true;
816-
} else if (node.parent.kind === SyntaxKind.CallExpression) {
817-
objectIsInAssignment = false;
818-
} else {
819-
objectIsInAssignment =
820-
nodeUtils.findChildOfKind(
821-
(objectAssignNode as any).left,
822-
SyntaxKind.ObjectLiteralExpression,
823-
ast
824-
) === node;
825-
}
826-
}
827-
828780
// TypeScript uses ObjectLiteralExpression in destructuring assignment, too
829-
if (objectIsInAssignment) {
781+
if (config.allowPattern) {
830782
Object.assign(result, {
831783
type: AST_NODE_TYPES.ObjectPattern,
832-
properties: node.properties.map(convertChild)
784+
properties: node.properties.map(convertPattern)
833785
});
834786
} else {
835787
Object.assign(result, {
836788
type: AST_NODE_TYPES.ObjectExpression,
837789
properties: node.properties.map(convertChild)
838790
});
839791
}
840-
841792
break;
842793
}
843794

844795
case SyntaxKind.PropertyAssignment:
845796
Object.assign(result, {
846797
type: AST_NODE_TYPES.Property,
847798
key: convertChild(node.name),
848-
value: convertChild(node.initializer),
799+
value: converter(
800+
node.initializer,
801+
config.inTypeMode,
802+
config.allowPattern
803+
),
849804
computed: nodeUtils.isComputedProperty(node.name),
850805
method: false,
851806
shorthand: false,
@@ -860,7 +815,7 @@ export default function convert(config: ConvertConfig): ESTreeNode | null {
860815
key: convertChild(node.name),
861816
value: {
862817
type: AST_NODE_TYPES.AssignmentPattern,
863-
left: convertChild(node.name),
818+
left: convertPattern(node.name),
864819
right: convertChild(node.objectAssignmentInitializer),
865820
loc: result.loc,
866821
range: result.range
@@ -1208,7 +1163,7 @@ export default function convert(config: ConvertConfig): ESTreeNode | null {
12081163
case SyntaxKind.ArrayBindingPattern:
12091164
Object.assign(result, {
12101165
type: AST_NODE_TYPES.ArrayPattern,
1211-
elements: node.elements.map(convertChild)
1166+
elements: node.elements.map(convertPattern)
12121167
});
12131168
break;
12141169

@@ -1219,7 +1174,7 @@ export default function convert(config: ConvertConfig): ESTreeNode | null {
12191174
case SyntaxKind.ObjectBindingPattern:
12201175
Object.assign(result, {
12211176
type: AST_NODE_TYPES.ObjectPattern,
1222-
properties: node.elements.map(convertChild)
1177+
properties: node.elements.map(convertPattern)
12231178
});
12241179
break;
12251180

@@ -1387,50 +1342,19 @@ export default function convert(config: ConvertConfig): ESTreeNode | null {
13871342

13881343
// Patterns
13891344

1345+
case SyntaxKind.SpreadAssignment:
13901346
case SyntaxKind.SpreadElement: {
1391-
let type = AST_NODE_TYPES.SpreadElement;
1392-
1393-
if (
1394-
node.parent &&
1395-
node.parent.parent &&
1396-
node.parent.parent.kind === SyntaxKind.BinaryExpression
1397-
) {
1398-
if ((node.parent.parent as ts.BinaryExpression).left === node.parent) {
1399-
type = AST_NODE_TYPES.RestElement;
1400-
} else if (
1401-
(node.parent.parent as ts.BinaryExpression).right === node.parent
1402-
) {
1403-
type = AST_NODE_TYPES.SpreadElement;
1404-
}
1405-
}
1406-
1407-
Object.assign(result, {
1408-
type,
1409-
argument: convertChild(node.expression)
1410-
});
1411-
break;
1412-
}
1413-
case SyntaxKind.SpreadAssignment: {
1414-
let type = AST_NODE_TYPES.SpreadElement;
1415-
1416-
if (
1417-
node.parent &&
1418-
node.parent.parent &&
1419-
node.parent.parent.kind === SyntaxKind.BinaryExpression
1420-
) {
1421-
if ((node.parent.parent as ts.BinaryExpression).right === node.parent) {
1422-
type = AST_NODE_TYPES.SpreadElement;
1423-
} else if (
1424-
(node.parent.parent as ts.BinaryExpression).left === node.parent
1425-
) {
1426-
type = AST_NODE_TYPES.RestElement;
1427-
}
1347+
if (config.allowPattern) {
1348+
Object.assign(result, {
1349+
type: AST_NODE_TYPES.RestElement,
1350+
argument: convertPattern(node.expression)
1351+
});
1352+
} else {
1353+
Object.assign(result, {
1354+
type: AST_NODE_TYPES.SpreadElement,
1355+
argument: convertChild(node.expression)
1356+
});
14281357
}
1429-
1430-
Object.assign(result, {
1431-
type,
1432-
argument: convertChild(node.expression)
1433-
});
14341358
break;
14351359
}
14361360

@@ -1788,44 +1712,21 @@ export default function convert(config: ConvertConfig): ESTreeNode | null {
17881712
(result as any).expressions.push(right);
17891713
}
17901714
} else {
1715+
const type = nodeUtils.getBinaryExpressionType(node.operatorToken);
17911716
Object.assign(result, {
1792-
type: nodeUtils.getBinaryExpressionType(node.operatorToken),
1717+
type,
17931718
operator: nodeUtils.getTextForTokenKind(node.operatorToken.kind),
1794-
left: convertChild(node.left),
1719+
left: converter(
1720+
node.left,
1721+
config.inTypeMode,
1722+
type === AST_NODE_TYPES.AssignmentExpression
1723+
),
17951724
right: convertChild(node.right)
17961725
});
17971726

17981727
// if the binary expression is in a destructured array, switch it
17991728
if (result.type === AST_NODE_TYPES.AssignmentExpression) {
1800-
const upperArrayNode = nodeUtils.findFirstMatchingAncestor(
1801-
node,
1802-
parent =>
1803-
parent.kind === SyntaxKind.ArrayLiteralExpression ||
1804-
parent.kind === SyntaxKind.ObjectLiteralExpression
1805-
);
1806-
const upperArrayAssignNode =
1807-
upperArrayNode &&
1808-
nodeUtils.findAncestorOfKind(
1809-
upperArrayNode,
1810-
SyntaxKind.BinaryExpression
1811-
);
1812-
1813-
let upperArrayIsInAssignment;
1814-
1815-
if (upperArrayAssignNode) {
1816-
if ((upperArrayAssignNode as any).left === upperArrayNode) {
1817-
upperArrayIsInAssignment = true;
1818-
} else {
1819-
upperArrayIsInAssignment =
1820-
nodeUtils.findChildOfKind(
1821-
(upperArrayAssignNode as any).left,
1822-
SyntaxKind.ArrayLiteralExpression,
1823-
ast
1824-
) === upperArrayNode;
1825-
}
1826-
}
1827-
1828-
if (upperArrayIsInAssignment) {
1729+
if (config.allowPattern) {
18291730
delete (result as any).operator;
18301731
result.type = AST_NODE_TYPES.AssignmentPattern;
18311732
}

0 commit comments

Comments
 (0)