solidity-antlr4
Version:
Solidity Lang Lexer and Parser by official ANTLR4 grammar
81 lines (80 loc) • 2.5 kB
JavaScript
import { clone, matches as lodashMatches } from "lodash-es";
import { isSyntaxNode, isSyntaxNodeList, keysInNode } from "../ast/base.js";
export function traverse(astOrPath, callback) {
let ast;
let globalParentPath = null;
if (astOrPath.type && !astOrPath.matches) {
ast = astOrPath;
} else {
ast = astOrPath.node;
globalParentPath = astOrPath;
}
let shouldStop = false;
const stop = () => {
shouldStop = true;
};
const traverseInner = (tree, parentPath) => {
const depth = parentPath?.depth !== void 0 ? parentPath.depth + 1 : 0;
if (isSyntaxNodeList(tree)) {
const nodeList = [];
for (let index = 0; index < tree.length; index += 1) {
if (shouldStop)
break;
nodeList.push(traverseInner(tree[index], parentPath));
}
return nodeList;
} else if (isSyntaxNode(tree)) {
let node = clone(tree);
const rewrite = (newNode) => {
node = newNode;
};
const matches = (filter) => lodashMatches(filter)(node);
const getFlattenParents = (maxDepth = Number.MAX_SAFE_INTEGER) => {
const nodes = [];
const recursion = (p) => {
if (p.parentPath && nodes.length < maxDepth) {
nodes.unshift(p.parentPath.node);
recursion(p.parentPath);
}
};
recursion(path);
return nodes;
};
const checkOffset = (offset) => {
if (offset === void 0)
return true;
return node.range[0] <= offset && offset <= node.range[1];
};
const path = {
path: [parentPath?.path, node.type].filter((t) => t !== void 0 && t !== null).join("."),
depth,
node,
parentPath,
stop,
rewrite,
getFlattenParents,
matches,
checkOffset
};
const exitCallback = callback(path);
if (shouldStop)
return node;
if (!isSyntaxNode(node))
return node;
const keys = keysInNode(node);
for (let index = 0; index < keys.length; index += 1) {
const valueInKey = node[keys[index]];
if (isSyntaxNode(valueInKey) || isSyntaxNodeList(valueInKey)) {
node[keys[index]] = traverseInner(valueInKey, path);
} else {
node[keys[index]] = valueInKey;
}
}
if (exitCallback && typeof exitCallback === "function")
exitCallback();
return node;
}
return tree;
};
return traverseInner(ast, globalParentPath);
}