You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:56:34