grepai调用图提取技术揭秘:tree-sitter AST与正则双模式解析10+种编程语言
【免费下载链接】grepaiSemantic Search & Call Graphs for AI Agents (100% Local)项目地址: https://gitcode.com/gh_mirrors/gr/grepai
grepai 是一款 100% 本地运行的 AI 时代代码搜索工具,其调用图提取(Call Graph)能力可回答"谁调用了这个函数?这个函数又依赖谁?"这类关键问题。本文揭秘其底层实现:通过tree-sitter AST 精确解析与正则快速解析双模式引擎,支持 Go、Python、JavaScript、TypeScript 等10+ 种编程语言的符号提取与调用链追踪,全程无需任何云端服务。
为什么 AI Agent 需要调用图?
想象一下:你要修改ProcessPayment函数,但不敢确定它影响范围。grepai 的trace命令可以瞬间给出答案:
- callers(调用者):谁在调用它?
- callees(被调用者):它依赖哪些函数?
- graph(调用图):以指定深度展开完整调用链
这正是 grepai 面向 AI Agent 场景设计的核心能力之一——用结构化上下文替代原始搜索结果,大幅降低 token 消耗。
双模式架构:一个接口,两种引擎
整个提取系统围绕一个统一接口设计,定义在 trace/trace.go:
type SymbolExtractor interface { ExtractSymbols(...) // 提取符号定义(函数、方法、类…) ExtractReferences(...) // 提取引用(函数调用、属性读写…) Mode() string // 返回 "fast" 或 "precise" }| 模式 | 引擎 | 特点 | 适用场景 |
|---|---|---|---|
| ⚡fast(默认) | 正则模式 | 零额外依赖、速度极快 | 大型代码库、日常使用 |
| 🔍precise | tree-sitter AST 模式 | 精确解析、可提取文档注释 | 复杂代码、精度优先 |
一条命令即可切换:
grepai trace callers "Login" --mode fast grepai trace callers "Login" --mode precise模式参数定义见 cli/trace.go,也可在.grepai/config.yaml中通过trace.mode固定配置。
正则模式:轻量而聪明的"快速通道"
每种语言一套模式表
正则模式的核心是一张语言模式注册表(trace/patterns.go),每种语言定义了五类定义模式(函数、方法、类、接口、类型)和两类调用模式(函数调用、方法调用)。以 Go 为例(trace/patterns.go):
// func FunctionName(params) Functions: regexp.MustCompile(`(?m)^func\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(`) // func (r *Receiver) MethodName(params) Methods: regexp.MustCompile(`(?m)^func\s+\(\w+\s+\*?([A-Za-z_][A-Za-z0-9_]*)\)\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(`)提取器 trace/extractor.go 按扩展名匹配模式,从每个匹配中还原出符号名、行号、签名和是否导出等信息。
两个精巧的细节
注释与字符串屏蔽:正则匹配最怕"误伤"——注释里的
foo()会被当成调用吗?不会。buildIgnoredMask(trace/extractor.go)先用一个状态机扫描全文,把行注释、块注释、字符串字面量全部标记为"忽略区",还专门处理了 F# 的(* *)嵌套块注释和 Lua 的--[[ ]]长字符串。函数边界定位:调用图需要知道"这次调用发生在哪个函数体内"。边界检测按语言特性分三路走(trace/extractor.go):
- 大括号语言(Go、JS、C、Rust…)→ 计数配对
{},跳过字符串干扰 - 缩进语言(Python、F#)→ 找到下一行缩进不深的语句
- Lua → 追踪
function到end的嵌套
- 大括号语言(Go、JS、C、Rust…)→ 计数配对
连状态读写都能追踪
对 JavaScript/TypeScript,grepai 还额外提取属性读写引用:store.uid = ...算 write、this.count.value算 read,甚至识别 Vue/Pinia 的storeToRefs解构别名。这让前端状态流也能纳入分析——grepai refs readers "uid"就能找到所有读取该状态的位置。
tree-sitter 模式:AST 精确解析
precise 模式(trace/extractor_ts.go)为每种语言内置了 tree-sitter 语法解析器,直接遍历抽象语法树:
- 按节点类型识别
function_declaration、method_declaration等 - 通过命名字段精准取符号名和接收者类型(Go 方法的 receiver)
- 顺带提取docstring文档注释(trace/extractor_ts.go),为 AI 提供语义描述
- 天然免疫正则的误报:注释、字符串里的"伪调用"在 AST 里根本不是调用节点
亮点:自研 F# 语法绑定
主流语言的解析器可直接引用现成库,但 F# 需要完整的语法文件。grepai 项目内直接维护了一份 F# tree-sitter 语法(fsharp/ 目录,其中parser.c是超过 80 万行的生成代码),通过 CGO 绑定接入(fsharp/binding.go)。这就是为什么精确模式能覆盖 C# 和 F# 这类少见的 .NET 语言。
💡 注意:precise 模式需要 CGO 依赖,须以
treesitter构建标签编译;默认构建即为 fast 模式,开箱即用。
10+ 种语言支持一览
| 语言 | 扩展名 | 正则模式 | tree-sitter 模式 |
|---|---|---|---|
| Go | .go | ✅ | ✅ |
| TypeScript | .ts.tsx | ✅ | ✅ |
| JavaScript | .js.jsx | ✅ | ✅ |
| Python | .py | ✅ | ✅ |
| PHP | .php | ✅ | ✅ |
| C# | .cs | ✅ | ✅ |
| F# | .fs.fsx.fsi | ✅ | ✅ |
| C | .c.h | ✅ | — |
| C++ | .cpp.hpp.cc.cxx | ✅ | — |
| Rust | .rs | ✅ | — |
| Zig | .zig | ✅ | — |
| Java | .java | ✅ | — |
| Lua | .lua | ✅ | — |
| Pascal/Delphi | .pas.dpr | ✅ | — |
完整列表参见官方文档 docs/src/content/docs/trace.md。
从符号到调用图:边是如何连起来的
数据流非常清晰:
- 符号索引:
grepai watch启动守护进程,文件变更时自动增量提取 - 边构建:每条引用若能定位到所在函数(调用者),就生成一条
CallEdge(调用者 → 被调用者,含文件与行号),逻辑见 trace/store.go - 图查询:
GetCallGraph从根符号出发按 BFS 逐层展开,--depth N控制深度 - 持久化:索引保存在项目本地的
.grepai/symbols.gob,代码永远不出本机
grepai watch # 后台索引,自动保鲜 grepai trace callers "ValidateToken" # 谁调用了它? grepai trace graph "AuthMiddleware" --depth 2 --json # 结构化输出,喂给 AI工作区模式下,--workspace还能跨项目聚合调用图——前端调后端 API 的完整链路一目了然。
总结
grepai 调用图提取的设计哲学可以概括为一句话:接口统一、双轨并行、本地闭环。
- 🎯 正则模式负责"广"——14 种语言开箱即用,无依赖、速度快
- 🧬 tree-sitter 模式负责"准"——AST 级别解析 + docstring,啃下复杂代码
- 📊 所有结果落到
.grepai/symbols.gob本地文件,AI Agent 通过--json即取即用
无论你是想评估一次重构的影响面,还是给 AI 喂上精准的调用上下文,这套双模式解析引擎都是背后可靠的支撑。
更多使用细节,可查看官方文档 docs/src/content/docs/trace.md 与快速上手指南 docs/src/content/docs/quickstart.md。
【免费下载链接】grepaiSemantic Search & Call Graphs for AI Agents (100% Local)项目地址: https://gitcode.com/gh_mirrors/gr/grepai
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考