rea/src/domain/javascriptSemanticTraversal.ts

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));
});
};