28 lines
909 B
TypeScript
28 lines
909 B
TypeScript
import * as t from "@babel/types";
|
|
|
|
/** Visit every Babel AST node in deterministic source-tree order. */
|
|
export const traverseJavaScriptAst = (
|
|
root: t.Node,
|
|
visitor: {
|
|
readonly enter: (node: t.Node, parent: t.Node | null) => void;
|
|
readonly exit?: (node: t.Node, parent: t.Node | null) => void;
|
|
},
|
|
): void => {
|
|
const visit = (node: t.Node, parent: t.Node | null): void => {
|
|
visitor.enter(node, parent);
|
|
for (const child of childNodes(node)) visit(child, node);
|
|
visitor.exit?.(node, parent);
|
|
};
|
|
visit(root, null);
|
|
};
|
|
|
|
const childNodes = (node: t.Node): t.Node[] => {
|
|
const keys: readonly string[] = t.VISITOR_KEYS[node.type] ?? [];
|
|
return keys.flatMap((key) => {
|
|
const value: unknown = Reflect.get(node, key);
|
|
if (t.isNode(value)) return [value];
|
|
if (!Array.isArray(value)) return [];
|
|
return value.filter((item): item is t.Node => t.isNode(item));
|
|
});
|
|
};
|