-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathrearrangeSequences.js
65 lines (61 loc) · 1.81 KB
/
rearrangeSequences.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* Moves up all expressions except the last one of a returned sequence or in an if statement.
* E.g. return a(), b(); -> a(); return b();
* if (a(), b()); -> a(); if (b());
* @param {Arborist} arb
* @param {Function} candidateFilter (optional) a filter to apply on the candidates list
* @return {Arborist}
*/
function rearrangeSequences(arb, candidateFilter = () => true) {
const relevantNodes = [
...(arb.ast[0].typeMap.ReturnStatement || []),
...(arb.ast[0].typeMap.IfStatement || []),
];
for (let i = 0; i < relevantNodes.length; i++) {
const n = relevantNodes[i];
if ((
n.type === 'ReturnStatement' && n.argument?.type === 'SequenceExpression' ||
n.type === 'IfStatement' && n.test.type === 'SequenceExpression'
) && candidateFilter(n)) {
const parent = n.parentNode;
const { expressions } = n.argument || n.test;
const statements = expressions.slice(0, -1).map(e => ({
type: 'ExpressionStatement',
expression: e
}));
const replacementNode = n.type === 'IfStatement' ? {
type: 'IfStatement',
test: expressions[expressions.length - 1],
consequent: n.consequent,
alternate: n.alternate
} : {
type: 'ReturnStatement',
argument: expressions[expressions.length - 1]
};
if (parent.type === 'BlockStatement') {
const currentIdx = parent.body.indexOf(n);
const replacementParent = {
type: 'BlockStatement',
body: [
...parent.body.slice(0, currentIdx),
...statements,
replacementNode,
...parent.body.slice(currentIdx + 1)
],
};
arb.markNode(parent, replacementParent);
} else {
const replacementParent = {
type: 'BlockStatement',
body: [
...statements,
replacementNode
]
};
arb.markNode(n, replacementParent);
}
}
}
return arb;
}
export default rearrangeSequences;