如何用 goose 内置的 analyze 工具跟踪代码库中函数的调用关系?
【免费下载链接】goosean open source, extensible AI agent that goes beyond code suggestions - install, execute, edit, and test with any LLM项目地址: https://gitcode.com/GitHub_Trending/goose3/goose
当你要重构一个函数、排查某个函数的调用来源,或者接手一个陌生代码库时,需要回答这类问题:authenticate这个函数定义在哪里?哪些函数在调用它?它自己又调用了谁?goose 内置的 Analyze 平台扩展提供了一个analyze工具,可以在代码库范围内构建调用图,直接给出某个符号的定义位置、传入调用(incoming calls)和传出调用(outgoing calls)。该扩展默认启用,无需额外配置;它基于 tree-sitter 解析代码,支持 Rust、Python、JavaScript、TypeScript/TSX、Go、Java、Kotlin、Swift、Ruby 等语言的常见文件扩展名(完整列表见 languages.rs)。
analyze 的三种模式与本次要用的参数
analyze工具根据入参工作在三种模式中,典型流程是「目录 → 文件 → 符号」:
- 目录路径(无
focus):返回带 LOC、函数数、类数的文件树,深度受max_depth限制; - 文件路径(无
focus):返回该文件的函数(含签名)、类、导入和调用次数; - 任意路径 +
focus:返回该符号的调用图。这就是跟踪函数调用关系的模式,符号匹配区分大小写。
完整参数表见 codebase-analysis.md,本文跟踪调用关系时涉及的核心参数如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
path | 无(必填) | 要分析的文件或目录的绝对/相对路径 |
focus | None | 要跟踪的符号名。跨文件跟踪时,path必须是目录 |
follow_depth | 2 | 从聚焦符号出发的追踪步数:0=只显示定义位置,1=直接调用者/被调用者,2=再往上一层,以此类推 |
max_depth | 3 | path为目录时的子目录遍历层数(0=不限制);也限制focus模式的扫描深度 |
force | false | 结果超过 50,000 字符时是否仍返回完整输出 |
执行步骤:跟踪一个函数的调用链
在 goose 会话中,工具既可以通过自然语言触发,也可以用直接命令调用。以文档中的示例场景为例:假设项目里有一个authenticate函数分散在auth.py、api.py、admin.py、tests/等多个文件中。
方式一:自然语言。直接对 goose 说:
Trace the dependencies for the authenticate function或 "Show me the call graph for the authenticate function"。
方式二:直接命令。指定目录范围和要跟踪的符号:
# 跟踪 authenticate 函数在 src/ 范围内的使用情况 analyze path="src/" focus="authenticate"调用链需要追得更深时,加上follow_depth:
# 从 UserClass 出发追踪 3 层调用链,扫描整个项目目录 analyze path="." focus="UserClass" follow_depth=3path可以按实际项目替换为包含目标代码的目录(如.、src/、crates/)。follow_depth=1只列出直接调用者和被调用者,适合先看直接关系;follow_depth=0只显示符号定义在哪里,适合先定位再展开。
如何读取和核对输出
focus模式的输出由固定结构组成(见 format.rs 的实现):
- 首行
FOCUS: <符号> (N defs, M refs):定义数量和直接引用(第 1 层调用者与被调用者)总数; DEF 文件:函数:行号:符号的定义位置,可能有多条(多个文件里同名定义);IN:/IN (tests)::传入调用链,即谁在调用这个符号,测试代码单独成组;OUT:/OUT (tests)::传出调用链,即这个符号内部调用了谁;- 末尾
N files analyzed:本次扫描覆盖的文件数。
调用链用→连接,每一段是文件:符号:行号。测试文件(如*_test.py、.test.ts、/tests/目录下的文件)会被自动识别并归入(tests)组,方便你区分生产代码引用和测试引用。
文档中给出了一份示例输出(文档示例,非固定结果):对authenticate的查询返回了auth.py第 15 行的定义、api.py:25的login_handler()等传入调用,以及db.py:102的validate_credentials()等传出调用。
核对方式:如果符号不在扫描范围内,工具会明确返回Symbol 'xxx' not found in N analyzed files.——看到这条消息时先扩大path目录或减小max_depth限制的影响,而不是认为调用链为空。符号名区分大小写,查不到时先确认拼写与实际定义一致。
输出过大或扫描范围不对时如何处理
当分析结果超过 50,000 字符时,工具不会返回内容,而是返回一条提示:Output too large (N chars, limit 50000). Use 'force: true' to override, or narrow scope with max_depth/focus.文档给出的处理选项:
- 收窄范围:把
path指向具体子目录或文件,而不是整个仓库; - 减小深度:目录分析用
max_depth=1或max_depth=2限制遍历层数; force=true:绕过大小警告拿回完整输出。文档明确提示这会占用大量会话上下文,只在前两种方案不够时用;- 交给 subagent:让子代理去分析并只带回摘要,例如 "Use a subagent to analyze the entire src/ directory and summarize the main components",避免主会话被长输出填满(详见 subagents)。
另外两条来自文档的性能建议:先用小范围(具体文件或子目录)试探,再扩大;用.gitignore排除node_modules/、构建产物等无关文件,减少扫描量。
限制与下一步
几点边界需要注意:
focus的跨文件跟踪要求path是目录;path指向单个文件时,focus只在该文件内生效;- 语言支持以文件扩展名注册,未注册扩展名的文件会被跳过,目录模式的输出里会有一行
(N files skipped: no parser)标明跳过数量; - 调用图基于 tree-sitter 的调用表达式解析,输出反映的是源码中可解析的调用,文档未承诺对间接调用(如回调、动态分发)的完整覆盖。
完成一次调用链跟踪后,如果确认要改动这个函数,可以结合 codebase-analysis.md 中的目录结构模式(analyze path="src/")先了解所在模块的组织方式,再带着DEF/IN给出的文件和行号进入实际修改;大目录的分析摘要可继续交给 subagent 完成。
【免费下载链接】goosean open source, extensible AI agent that goes beyond code suggestions - install, execute, edit, and test with any LLM项目地址: https://gitcode.com/GitHub_Trending/goose3/goose
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考