56 lines
1.6 KiB
JavaScript
56 lines
1.6 KiB
JavaScript
export const TRAVERSAL_PATH = {
|
|
ArrayExpression: ['elements'],
|
|
ArrayPattern: ['elements'],
|
|
AssignmentExpression: ['left', 'right'],
|
|
AwaitExpression: ['argument'],
|
|
BinaryExpression: ['left', 'right'],
|
|
BlockStatement: ['body'],
|
|
BreakStatement: [],
|
|
CallExpression: ['arguments', 'callee'],
|
|
ChainExpression: ['expression'],
|
|
ConditionalExpression: ['alternate', 'consequent', 'test'],
|
|
DoWhileStatement: ['body', 'test'],
|
|
ExpressionStatement: ['expression'],
|
|
ForOfStatement: ['body', 'left', 'right'],
|
|
ForStatement: ['body', 'init', 'test', 'update'],
|
|
Identifier: [],
|
|
IfStatement: ['alternate', 'consequent', 'test'],
|
|
MemberExpression: ['object', 'property'],
|
|
Literal: [],
|
|
LogicalExpression: ['left', 'right'],
|
|
ObjectExpression: ['properties'],
|
|
ObjectPattern: ['properties'],
|
|
Program: ['body'],
|
|
Property: ['key', 'value'],
|
|
ReturnStatement: ['argument'],
|
|
SpreadElement: ['argument'],
|
|
UnaryExpression: ['argument'],
|
|
UpdateExpression: ['argument'],
|
|
VariableDeclaration: ['declarations'],
|
|
VariableDeclarator: ['id', 'init'],
|
|
WhileStatement: ['body', 'test'],
|
|
};
|
|
|
|
export default function traverse(node, visitor) {
|
|
/* v8 ignore next 3 */
|
|
if (!(node.type in TRAVERSAL_PATH)) {
|
|
throw new Error(`node type ${node.type} not traversable. (${Object.keys(node).join(', ')})`);
|
|
}
|
|
visitor(node, 'enter');
|
|
for (const key of TRAVERSAL_PATH[node.type]) {
|
|
if (Array.isArray(node[key])) {
|
|
for (const child of node[key]) {
|
|
if (child) {
|
|
traverse(child, visitor);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (node[key]) {
|
|
traverse(node[key], visitor);
|
|
}
|
|
}
|
|
}
|
|
visitor(node, 'exit');
|
|
}
|