用途
ast-grep 是一个基于抽象语法树(AST)的结构化代码搜索与分析工具。它使用 AST 模式来匹配代码的结构,而不仅仅是文本,因此可以在大型代码库中进行强大而精确的代码搜索。本技能帮助用户将自然语言查询翻译为 ast-grep 规则。
适用场景
当用户有以下需求时可以使用本技能:
- 需要使用结构化匹配搜索代码模式(例如“查找所有没有错误处理的异步函数”)
- 想要定位特定的语言构造(例如“查找所有带特定参数的函数调用”)
- 请求的搜索需要理解代码结构而非仅文本
- 要求搜索具有特定 AST 特征的代码
- 需要执行传统文本搜索无法处理的复杂代码查询
使用方式
总体工作流程
-
理解查询:明确用户想要查找的内容,必要时提出澄清问题,包括:具体的代码模式或结构、编程语言、需要考虑的边界情况或变体、匹配中应包含或排除的内容。
-
创建示例代码:编写一个代表用户想要匹配内容的简单代码片段,保存到临时文件用于测试。
-
编写 ast-grep 规则:将模式翻译为 ast-grep 规则。关键原则:关系规则(inside、has)始终使用
stopBy: end以确保搜索进行到方向的末尾;简单结构使用pattern;复杂结构使用kind配合has/inside;使用all、any或not将复杂查询拆分为更小的子规则。 -
测试规则:使用 ast-grep CLI 验证规则是否匹配示例代码。
-
搜索代码库:规则正确匹配示例代码后,搜索实际代码库。
ast-grep CLI 命令
检查代码结构(--debug-query):
ast-grep run --pattern 'async function example() { await fetch(); }' \
--lang javascript \
--debug-query=cst
可用格式:cst(具体语法树,显示所有节点包括标点)、ast(抽象语法树,仅显示命名节点)、pattern(显示 ast-grep 如何解释你的模式)。
测试规则(scan with --stdin):
echo "const x = await fetch();" | ast-grep scan --inline-rules "id: test
language: javascript
rule:
pattern: await \$EXPR" --stdin
添加 --json 可获得结构化输出。
使用模式搜索(run):
ast-grep run --pattern 'console.log($ARG)' --lang javascript .
ast-grep run --pattern 'class $NAME' --lang python /path/to/project
ast-grep run --pattern 'function $NAME($$$)' --lang javascript --json .
适用于简单、单节点匹配,快速搜索,不需要关系规则(inside/has)的场景。
使用规则搜索(scan):
ast-grep scan --rule my_rule.yml /path/to/project
ast-grep scan --inline-rules "id: find-async
language: javascript
rule:
kind: function_declaration
has:
pattern: await \$EXPR
stopBy: end" /path/to/project
ast-grep scan --rule my_rule.yml --json /path/to/project
适用于复杂结构搜索、关系规则(inside、has、precedes、follows)、复合逻辑(all、any、not),以及需要完整 YAML 规则能力的场景。
编写有效规则的技巧
- 始终使用 stopBy: end:对于关系规则,除非有特定理由,否则始终使用
stopBy: end,确保搜索遍历整个子树而非在第一个不匹配节点处停止。 - 从简单开始,再增加复杂度:先尝试 pattern;如果不行,尝试用 kind 匹配节点类型;按需添加关系规则(has、inside);用复合规则(all、any、not)组合复杂逻辑。
- 使用正确的规则类型:pattern 用于简单直接的代码匹配;kind + 关系规则用于复杂结构;复合规则用于逻辑组合。
- 用 AST 检查调试:规则不匹配时,使用
--debug-query=cst查看实际 AST 结构,检查元变量是否正确检测,验证节点 kind 是否符合预期,确保关系规则搜索方向正确。 - 内联规则中的转义:使用
--inline-rules时,在 shell 命令中转义元变量,使用\$VAR代替$VAR,或使用单引号。
常见用例
查找包含特定内容的函数(查找使用 await 的异步函数):
ast-grep scan --inline-rules "id: async-await
language: javascript
rule:
all:
- kind: function_declaration
- has:
pattern: await \$EXPR
stopBy: end" /path/to/project
查找特定上下文中的代码(查找类方法中的 console.log):
ast-grep scan --inline-rules "id: console-in-class
language: javascript
rule:
pattern: console.log(\$\$\$)
inside:
kind: method_definition
stopBy: end" /path/to/project
查找缺少预期模式的代码(查找没有 try-catch 的异步函数):
ast-grep scan --inline-rules "id: async-no-trycatch
language: javascript
rule:
all:
- kind: function_declaration
- has:
pattern: await \$EXPR
stopBy: end
- not:
has:
pattern: try { \$\$\$ } catch (\$E) { \$\$\$ }
stopBy: end" /path/to/project
资源
references/ 目录包含 ast-grep 规则语法的详细文档:rule_reference.md 涵盖原子规则、关系规则、复合规则和元变量。需要详细规则语法信息时可加载这些参考。
限制
资料中未提供关于支持的语言列表、性能限制、安装方式或收费信息的具体说明。