name: ast-grep description: 编写ast-grep规则以执行结构性代码搜索和分析的指南。当用户需要使用抽象语法树(AST)模式搜索代码库、查找特定代码结构或执行超越简单文本搜索的复杂代码查询时使用此技能。当用户要求搜索代码模式、查找特定语言构造或定位具有特定结构特征的代码时,应使用此技能。
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 - 对于复杂结构使用
kind与has/inside - 使用
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值 - 理解您想要匹配的代码结构
- 调试模式不匹配的原因
示例:
# 查看目标代码的结构
ast-grep run --pattern 'class User { constructor() {} }' \\
--lang javascript \\
--debug-query=cst
# 查看ast-grep如何解释您的模式
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
使用模式搜索(运行)
简单模式搜索,用于单AST节点匹配:
# 基本模式搜索
ast-grep run --pattern 'console.log($ARG)' --lang javascript .
# 搜索特定文件
ast-grep run --pattern 'class $NAME' --lang python /path/to/project
# JSON输出,用于编程使用
ast-grep run --pattern 'function $NAME($$$)' --lang javascript --json .
何时使用:
- 简单、单节点匹配
- 无需复杂逻辑的快速搜索
- 当您不需要关系规则(inside/has)时
使用规则搜索(扫描)
YAML规则搜索,用于复杂结构查询:
# 使用规则文件
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
# JSON输出
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中工作
示例:
# 正确:转义的$
ast-grep scan --inline-rules "rule: {pattern: 'console.log(\\$ARG)'}" .
# 或使用单引号
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规则文档,涵盖原子规则、关系规则、复合规则和元变量
当需要详细的规则语法信息时,加载这些参考。