如何在ts-morph中获取下一个兄弟节点并忽略Token?
问题
我尝试使用ts-morph中的getNextSibling方法获取下一个兄弟节点,但得到的都是DotToken或OpenBracketToken这类无关节点。我需要获取带有实际内容的节点,比如Identifier、StringLiteral、BinaryExpression等类型的节点,请问有没有安全的方法忽略这些Token节点?
示例代码
import { Identifier, Project, SyntaxKind } from "ts-morph"; console.clear(); const project = new Project(); const sourceFile = project.createSourceFile( "foo.ts", ` foo.bar.some(); foo[bar].some(); foo['bar'].some(); foo['bar' + 'other'].some(); ` ); const foos = sourceFile .getDescendantsOfKind(SyntaxKind.Identifier) .filter((i) => i.getText() === "foo"); foos.forEach((foo) => { const s = foo.getNextSibling(); console.log({ s: s.getText() }); // 输出: . [ [ [ });
解决方案
可以通过遍历后续兄弟节点并过滤Token类型节点的方式实现,以下是两种可行方法:
方法1:直接过滤后续兄弟节点
利用getNextSiblings()获取所有后续兄弟,筛选出非Token类型的节点:
foos.forEach((foo) => { const nextSignificantNode = foo.getNextSiblings().find(sibling => { const kindName = SyntaxKind[sibling.getKind()]; return !kindName.endsWith("Token"); }); console.log({ s: nextSignificantNode?.getText() }); });
方法2:循环查找有效节点
写一个工具函数逐步遍历兄弟节点,直到找到非Token节点:
function getNextSignificantSibling(node: any) { let next = node.getNextSibling(); while (next) { const kindName = SyntaxKind[next.getKind()]; if (!kindName.endsWith("Token")) { return next; } next = next.getNextSibling(); } return undefined; } // 使用示例 foos.forEach((foo) => { const s = getNextSignificantSibling(foo); console.log({ s: s?.getText() }); // 输出: bar bar 'bar' 'bar' + 'other' });
原理说明
在TypeScript的AST结构中,DotToken、OpenBracketToken这类属于语法标记Token,它们是AST的组成部分但不携带业务逻辑相关内容。通过判断节点的语法Kind名称是否以"Token"结尾,可以快速过滤这类节点,定位到真正包含内容的表达式或标识符节点。
内容的提问来源于stack exchange,提问作者Jon Sud
相关产品推荐
相关产品推荐

