如何在ts-morph中用getPreviousSibling获取目标节点而非语法点?
问题描述
使用ts-morph解析标识符定义时,处理fn.bind(this)这类代码时,找到bind标识符后调用getPreviousSibling()返回的是点号(.),而非预期的fn。需要一种更可靠的方式获取bind所属的左侧表达式(比如fn或this.fn中的主体部分),避免连续两次调用getPreviousSibling()。
解决方案
利用ts-morph的节点类型判断和内置方法实现,步骤如下:
- 获取
bind标识符的父节点,它属于PropertyAccessExpression类型(对应x.y这种属性访问语法)。 - 调用父节点的
getExpression()方法,直接获取属性访问左侧的表达式节点,这就是目标的fn(或this.fn中的this)。 - 若需提取最内层标识符,可对返回的表达式做类型判断后进一步处理。
修改后的示例代码:
import { Project, SyntaxKind, PropertyAccessExpression } from "ts-morph"; console.clear(); const project = new Project(); const file = project.createSourceFile( "foo.ts", ` const fn = () => {} const fn2 = fn.bind(this); const fn3 = this.fn.bind(this); ` ); const identifiers = file.getDescendantsOfKind(SyntaxKind.Identifier); const bind = identifiers.find((i) => i.getText() === "bind"); if (bind) { // 获取父节点并断言为PropertyAccessExpression const propertyAccess = bind.getParent() as PropertyAccessExpression; // 获取左侧表达式 const targetExpr = propertyAccess.getExpression(); console.log({ targetExpr: targetExpr.getText() }); // 输出"fn"或"this.fn" // 提取最内层的标识符 if (targetExpr.isKind(SyntaxKind.PropertyAccessExpression)) { console.log({ innerId: targetExpr.getNameNode().getText() }); // 输出"fn" } else if (targetExpr.isKind(SyntaxKind.Identifier)) { console.log({ id: targetExpr.getText() }); // 输出"fn" } }
说明
PropertyAccessExpression是ts-morph对x.y这类语法的节点封装,getExpression()直接返回左侧的x部分,比手动遍历兄弟节点更可靠,面对嵌套属性访问(如a.b.c.bind())时,能直接拿到最外层的a.b.c。- 若需提取深层标识符,可递归或逐层判断节点类型,调用
getNameNode()获取属性名标识符。
内容的提问来源于stack exchange,提问作者Jon Sud
相关产品推荐
相关产品推荐

