关于 ast-grep
ast-grep Code Search 帮助开发者将自然语言搜索需求转成 ast-grep 规则,以结构方式检索代码。技能涵盖规则编写、测试、调试及使用 ast-grep 命令行搜索代码库。
主要功能
- 01将查询转为结构化规则
- 02编写简单及关联规则
- 03在代码片段或文件中测试规则
- 04检查 AST 并调试匹配
- 05用命令行搜索代码库
适用场景
- 01查找包含 await 的异步函数
- 02定位带指定参数的调用
- 03搜索缺少预期模式的代码
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ coleam00/ skills --skill ast-grep安装后在 Claude Code 中输入/ast-grep确认已加载。
附带文件references/rule_reference.md
详细介绍
ast-grep 代码搜索
概述
此技能可帮助将自然语言查询转换为 ast-grep 规则,以进行结构化代码搜索。ast-grep 使用抽象语法树(AST)模式,根据代码结构而非纯文本匹配代码,从而在大型代码库中实现强大而精确的代码搜索。
何时使用此技能
在以下情况下使用此技能:
- 需要使用结构匹配搜索代码模式(例如,“查找所有没有错误处理的异步函数”)
- 想要定位特定语言结构(例如,“查找所有带有特定参数的函数调用”)
- 请求的搜索需要理解代码结构,而非仅搜索文本
- 要求搜索具有特定 AST 特征的代码
- 需要执行传统文本搜索无法完成的复杂代码查询
通用工作流
按照以下流程帮助用户编写有效的 ast-grep 规则:
步骤 1:理解查询
清楚地了解用户想要查找的内容。如有需要,请提出澄清问题:
- 他们要查找的具体代码模式或结构是什么?
- 使用哪种编程语言?
- 是否需要考虑特定的边界情况或变体?
- 匹配结果应包含或排除哪些内容?
步骤 2:创建示例代码
编写一个简单的代码片段,表示用户想要匹配的内容。将其保存到临时文件中以便测试。
示例: 如果要搜索“使用 await 的异步函数”,请创建一个测试文件:
// test_example.js
async function example() {
const result = await fetchData();
return result;
}
步骤 3:编写 ast-grep 规则
将模式转换为 ast-grep 规则。先从简单规则开始,再根据需要增加复杂度。
关键原则:
- 对关系规则(
inside、has)始终使用stopBy: end,以确保搜索遍历到该方向的末尾 - 对简单结构使用
pattern - 对复杂结构使用带有
has/inside的kind - 使用
all、any或not将复杂查询拆分为较小的子规则
规则文件示例(test_rule.yml):
id: async-with-await
language: javascript
rule:
kind: function_declaration
has:
pattern: await $EXPR
stopBy: end
有关规则的完整文档,请参阅 references/rule_reference.md。
步骤 4:测试规则
使用 ast-grep CLI 验证规则是否匹配示例代码。主要有两种方法:
选项 A:使用内联规则测试(适用于快速迭代)
echo "async function test() { await fetch(); }" | ast-grep scan --inline-rules "id: test
language: javascript
rule:
kind: function_declaration
has:
pattern: await \$EXPR
stopBy: end" --stdin
选项 B:使用规则文件测试(复杂规则推荐使用)
ast-grep scan --rule test_rule.yml test_example.js
未匹配到结果时的调试方法:
- 简化规则(移除子规则)
- 如果关系规则中没有
stopBy: end,则添加该选项 - 使用
--debug-query了解 AST 结构(见下文) - 检查
kind值是否适用于该语言
步骤 5:搜索代码库
规则正确匹配示例代码后,搜索实际代码库:
对于简单模式搜索:
ast-grep run --pattern 'console.log($ARG)' --lang javascript /path/to/project
对于基于复杂规则的搜索:
ast-grep scan --rule my_rule.yml /path/to/project
对于内联规则(无需创建文件):
ast-grep scan --inline-rules "id: my-rule
language: javascript
rule:
pattern: \$PATTERN" /path/to/project
ast-grep CLI 命令
检查代码结构(--debug-query)
转储 AST 结构,以了解代码的解析方式:
ast-grep run --pattern 'async function example() { await fetch(); }' \
--lang javascript \
--debug-query=cst
可用格式:
cst:具体语法树(显示所有节点,包括标点符号)ast:抽象语法树(仅显示命名节点)pattern:显示 ast-grep 如何解析你的模式
使用此功能来:
- 查找节点的正确
kind值 - 了解要匹配的代码结构
- 调试模式未能匹配的原因
示例:
# See the structure of your target code
ast-grep run --pattern 'class User { constructor() {} }' \
--lang javascript \
--debug-query=cst
# See how ast-grep interprets your pattern
ast-grep run --pattern 'class $NAME { $$$BODY }' \
--lang javascript \
--debug-query=pattern
测试规则(使用 --stdin 扫描)
针对代码片段测试规则,无需创建文件:
echo "const x = await fetch();" | ast-grep scan --inline-rules "id: test
language: javascript
rule:
pattern: await \$EXPR" --stdin
添加 --json 以获取结构化输出:
echo "const x = await fetch();" | ast-grep scan --inline-rules "..." --stdin --json
使用模式搜索(run)
基于简单模式搜索单个 AST 节点匹配项:
# Basic pattern search
ast-grep run --pattern 'console.log($ARG)' --lang javascript .
# Search specific files
ast-grep run --pattern 'class $NAME' --lang python /path/to/project
# JSON output for programmatic use
ast-grep run --pattern 'function $NAME($$$)' --lang javascript --json .
适用场景:
- 简单的单节点匹配
- 无需复杂逻辑的快速搜索
- 不需要关系规则(inside/has)时
使用规则搜索(扫描)
基于 YAML 规则的搜索,适用于复杂结构查询:
# With rule file
ast-grep scan --rule my_rule.yml /path/to/project
# With inline rules
ast-grep scan --inline-rules "id: find-async
language: javascript
rule:
kind: function_declaration
has:
pattern: await \$EXPR
stopBy: end" /path/to/project
# JSON output
ast-grep scan --rule my_rule.yml --json /path/to/project
适用场景:
- 复杂的结构搜索
- 关系规则(inside、has、precedes、follows)
- 复合逻辑(all、any、not)
- 需要使用完整 YAML 规则的强大功能时
提示: 对于关系规则(inside/has),请始终添加 stopBy: end,以确保完整遍历。
编写有效规则的技巧
始终使用 stopBy: end
对于关系规则,除非有特定原因,否则请始终使用 stopBy: end:
has:
pattern: await $EXPR
stopBy: end
这样可以确保搜索遍历整个子树,而不是在遇到第一个不匹配的节点时停止。
从简单开始,再逐步增加复杂度
从可能奏效的最简单规则开始:
- 首先尝试
pattern - 如果不奏效,尝试使用
kind匹配节点类型 - 根据需要添加关系规则(
has、inside) - 使用复合规则(
all、any、not)组合复杂逻辑
选择合适的规则类型
- Pattern:用于简单、直接的代码匹配(例如,
console.log($ARG)) - Kind + Relational:用于复杂结构(例如,“包含 await 的函数”)
- Composite:用于逻辑组合(例如,“包含 await,但不在 try-catch 中的函数”)
使用 AST 检查进行调试
规则未匹配时:
- 使用
--debug-query=cst查看实际的 AST 结构 - 检查元变量是否被正确检测
- 验证节点
kind是否符合预期 - 确保关系规则的搜索方向正确
内联规则中的转义
使用 --inline-rules 时,请在 shell 命令中转义元变量:
- 使用
\$VAR代替$VAR(shell 会将$解释为变量) - 或使用单引号:
'$VAR'在大多数 shell 中都可用
示例:
# Correct: escaped $
ast-grep scan --inline-rules "rule: {pattern: 'console.log(\$ARG)'}" .
# Or use single quotes
ast-grep scan --inline-rules 'rule: {pattern: "console.log($ARG)"}' .
常见用例
查找包含特定内容的函数
查找使用 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:全面介绍 ast-grep 规则的文档,涵盖原子规则、关系规则、复合规则和元变量
需要详细了解规则语法时,请加载这些参考资料。