如何使用VS Code语言API在TypeScript中构建代码图

如何使用VS Code语言API在TypeScript中构建代码图

💡 原文英文,约4400词,阅读约需16分钟。
📝

内容提要

LLM生成大量代码使代码审查变难。本文介绍用TypeScript和VS Code语言API构建代码图:将函数作为节点、调用作为边,通过文档符号和调用层次API发现关系,用BFS多跳遍历,处理循环、并发、缓存和过期引用,并过滤依赖目录。该图可用于依赖探索、变更影响分析和AI上下文选择。

🔎

延伸解读

为什么需要代码图

LLM生成大量代码使代码审查变难,传统逐文件阅读方式效率低下。将代码库建模为图(函数为节点、调用为边)后,诸如“谁调用了这个函数”等问题转化为图遍历问题,便于依赖探索和变更影响分析。

利用VS Code语言API而非自建解析器

VS Code已通过语言扩展提供文档符号和调用层次等语义信息。直接使用这些API可以避免为每种语言编写解析器和符号解析器,且能处理跨文件、导入、别名等复杂情况,让图构建器更专注于图逻辑。

处理语言服务状态与性能

调用层次项与语言服务状态绑定,可能过期导致空结果。文章建议存储可重建的普通数据、跟踪项年龄并重试可疑空结果。同时使用BFS多跳遍历,并通过并发限制和缓存控制对语言服务的请求压力。

代码图的局限与定位

基于静态调用层次的图无法完全表示动态调度、反射、事件发射器等运行时关系,因此应视为语义近似而非精确运行时模型。此外,不同语言扩展对文档符号和调用层次的支持程度不同,会影响图的质量。

❓

Q&A

为什么现在代码审查变得越来越困难?

因为编码助手(如LLM)能在几分钟内生成数百甚至数千行代码,跨越数百个文件,导致传统逐行审查方式崩溃,审查时间超过编写时间。

如何用VS Code语言API构建代码图?

使用VS Code的四个命令:vscode.executeDocumentSymbolProvider查找文档符号,vscode.prepareCallHierarchy解析位置到调用层次项,vscode.provideIncomingCalls查找调用者,vscode.provideOutgoingCalls查找被调用者。将函数作为节点,调用作为边,通过BFS多跳遍历构建图。

代码图中的节点和边分别代表什么?

节点代表函数或方法(SymbolRow),边代表调用关系(CallEdge),方向始终为调用者→被调用者。

如何处理代码图中的循环依赖?

使用Map记录每个节点已探索的剩余深度,仅当新路径能探索更深时才重新访问节点,避免无限循环。

为什么有些调用边会消失?如何解决?

因为CallHierarchyItem与语言服务状态绑定,状态过期会导致查询返回空数组。解决方案:存储NodeRef而非活动项,跟踪项年龄(epoch),对可疑空结果重试。

代码图有哪些局限性?

静态调用图无法解析动态调度、反射、依赖注入、事件发射器、回调、运行时生成代码和框架特定行为,因此只是语义近似而非完美运行时模型。

🏷️

标签

➡️

继续阅读