Skip to main content

TIP: Visit Children

有一个实用函数 ts.forEachChild 允许您访问 AST 中任何节点的所有子节点。

这是源代码的简化片段,以演示其功能:
export function forEachChild<T>(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T {
if (!node) {
return;
}
switch (node.kind) {
case SyntaxKind.BinaryExpression:
return visitNode(cbNode, (<BinaryExpression>node).left) ||
visitNode(cbNode, (<BinaryExpression>node).operatorToken) ||
visitNode(cbNode, (<BinaryExpression>node).right);
case SyntaxKind.IfStatement:
return visitNode(cbNode, (<IfStatement>node).expression) ||
visitNode(cbNode, (<IfStatement>node).thenStatement) ||
visitNode(cbNode, (<IfStatement>node).elseStatement);
// .... lots more

基本上,它会检查 node.kind 并基于此假设由 提供的接口 node 并调用 cbNode 子级的 。 但是请注意,此函数不会调用所有 visitNode 子项(例如 SyntaxKind.SemicolonToken)。如果你想要 AST 中一个节点的所有子节点,只需调用 .getChildrenNode

例如,这是一个打印AST节点详细信息的函数:
function printAllChildren(node: ts.Node, depth = 0) {
console.log(
new Array(depth + 1).join("----"),
ts.syntaxKindToName(node.kind),
node.pos,
node.end
);
depth++;
node.getChildren().forEach((c) => printAllChildren(c, depth));
}

当我们进一步讨论解析器时,我们将看到这个函数的示例用法。