如何用ts-morph或TypeScript编译器API查找函数调用关系?
使用 ts-morph/TypeScript 编译器API 追踪函数调用关系
核心:从调用表达式定位对应函数声明
你已经能获取函数声明和函数体内的调用表达式,接下来关键是靠TypeScript的类型检查器(TypeChecker)解析调用表达式对应的符号(Symbol),进而找到关联的函数声明。
用 ts-morph 实现的具体操作
先拿到类型检查器
不管是从整个项目还是单个源文件,先获取TypeChecker实例——这是解析符号的核心:const typeChecker = project.getTypeChecker(); // project是你创建的ts-morph Project实例解析调用表达式的符号
遍历每个函数里的CallExpression,调用getSymbol()拿到对应的符号,注意跳过无效的调用:functionDeclaration.getChildrenOfKind(SyntaxKind.CallExpression).forEach(callExpr => { const symbol = typeChecker.getSymbolAtLocation(callExpr.expression); if (!symbol) return; // 比如全局未定义的函数,这里会拿不到符号 });从符号找到函数声明
符号的getDeclarations()会返回该符号的所有声明节点,筛选出函数声明类型即可:const targetFuncs = symbol.getDeclarations()?.filter( decl => decl.getKind() === SyntaxKind.FunctionDeclaration ) as FunctionDeclaration[];这里要注意:如果调用的是第三方库或全局函数,可能拿不到本地的声明节点,得确保这些代码在TypeScript的类型检查范围内。
处理方法调用这类特殊场景
比如obj.foo()这种方法调用,不能直接解析整个表达式,得拆分处理:if (callExpr.expression.getKind() === SyntaxKind.PropertyAccessExpression) { const propAccess = callExpr.expression as PropertyAccessExpression; const methodSymbol = typeChecker.getSymbolAtLocation(propAccess.name); // 后续同样用getDeclarations()找方法的声明节点 }
用 TypeScript 原生编译器API 实现的思路
逻辑和ts-morph完全一致,只是API更底层:
- 通过
program.getTypeChecker()获取类型检查器 - 遍历源文件里的函数声明,找到函数体内的
CallExpression节点 - 对调用表达式的
expression节点,调用typeChecker.getSymbolAtLocation()获取符号 - 从符号的
declarations数组里筛选出FunctionDeclaration或FunctionExpression类型的节点
几个要注意的点
- 跨文件调用:得把所有相关文件都加入项目/程序,不然类型检查器没法解析跨文件的符号
- 重载函数:
getDeclarations()可能返回多个重载声明,需要结合调用时的参数进一步匹配 - 匿名/箭头函数:这类函数没有命名符号,没法用这个方法直接追踪,得结合上下文分析
内容的提问来源于stack exchange,提问作者guidupuy
相关产品推荐
相关产品推荐

