关于 code-structural-search
使用 ast-grep 进行代码结构搜索的技能,适合需要按语法模式而非关键词查找或修改代码的开发者与编码 Agent。提供按语言区分的示例,并建议先用 ripgrep 缩小范围,再进行 AST 匹配。
主要功能
- 01基于 AST 的代码模式匹配
- 02支持 20 多种语言
- 03按语言提供模式示例
- 04先用 ripgrep 缩小搜索范围
- 05结构化重构模式
- 06模式验证指导
适用场景
- 01按参数数量查找函数
- 02定位错误处理或数据库查询模式
- 03审查潜在安全问题代码
- 04查找待重构的弃用 API 用法
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ oimiragieo/ agent-studio --skill code-structural-search安装后在 Claude Code 中输入/code-structural-search确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
PATTERNS.mdREADME.mdcommands/code-structural-search.mdhooks/post-execute.cjspre-execute.cjsreferences/research-requirements.mdrules/code-structural-search.mdschemas/input.schema.jsonoutput.schema.jsonscripts/main.cjstemplates/implementation-template.md详细介绍
代码结构搜索
使用 ast-grep 进行基于 AST 的代码模式匹配。
适用场景
- 按结构而非关键字查找代码
- “查找所有有 3 个参数的函数”
- “查找所有继承 X 的类”
- “查找所有数据库查询”
- “查找所有错误处理模式”
- 精确重构代码(更改确切的模式)
接口
Skill({ skill: 'code-structural-search', args: 'pattern-here --lang ts' });
语言支持
ast-grep 通过 tree-sitter 支持 20 多种语言:
| 语言 | 标志 | 文件扩展名 |
|---|---|---|
| JavaScript | --lang js | .js, .jsx |
| TypeScript | --lang ts | .ts, .tsx |
| Python | --lang py | .py, .pyi |
| Go | --lang go | .go |
| Rust | --lang rs | .rs |
| Java | --lang java | .java |
| C | --lang c | .c, .h |
| C++ | --lang cpp | .cpp, .cc, .hpp, .hh |
| C# | --lang cs | .cs |
| Kotlin | --lang kt | .kt, .kts |
| Swift | --lang swift | .swift |
| PHP | --lang php | .php |
| Ruby | --lang rb | .rb |
| Lua | --lang lua | .lua |
| Elixir | --lang ex | .ex, .exs |
| HTML | --lang html | .html, .htm |
| CSS | --lang css | .css |
| JSON | --lang json | .json |
| Bash | --lang bash | .sh, .bash |
| Thrift | --lang thrift | .thrift |
模式示例
JavaScript/TypeScript
查找所有函数:
function $NAME($ARGS) { $$ }
查找恰好有 2 个参数的函数:
function $NAME($A, $B) { $$ }
查找异步函数:
async function $NAME($ARGS) { $$ }
查找类方法:
class $NAME {
$METHOD($ARGS) { $$ }
}
查找箭头函数:
const $NAME = ($ARGS) => { $$ }
查找 console.log 语句:
console.log($$$)
查找 try-catch 代码块:
try { $$ } catch ($ERR) { $$ }
Python
查找所有函数:
def $NAME($ARGS): $$$
查找类定义:
class $NAME: $$$
查找异步函数:
async def $NAME($ARGS): $$$
查找导入语句:
import $MODULE
查找 from 导入语句:
from $MODULE import $$$
Go
查找所有函数:
func $NAME($ARGS) $RETURN { $$ }
查找结构体定义:
type $NAME struct { $$$ }
查找接口定义:
type $NAME interface { $$$ }
Rust
查找所有函数:
fn $NAME($ARGS) -> $RETURN { $$ }
查找 impl 代码块:
impl $NAME { $$$ }
查找 pub 函数:
pub fn $NAME($ARGS) -> $RETURN { $$ }
Java
查找所有方法:
public $RETURN $NAME($ARGS) { $$ }
查找类定义:
public class $NAME { $$$ }
查找接口定义:
public interface $NAME { $$$ }
模式语法
| 符号 | 含义 | 示例 |
|---|---|---|
$NAME | 单个节点/标识符 | function $NAME() {} |
$$$ | 零个或多个语句/节点 | class $NAME { $$$ } |
$$ | 零个或多个语句(代码块) | if ($COND) { $$ } |
$_ | 匿名通配符(丢弃匹配项) | console.log($_) |
性能
- 速度:每次搜索 <50ms(通常情况下)
- 最好与语义搜索(Phase 1)结合使用
- 首先使用 ripgrep 初步查找文件
与其他工具的对比
与 Ripgrep (grep) 对比:
- Ripgrep:快速文本搜索,可查找关键字
- ast-grep:结构搜索,可查找精确的代码模式
- 先使用 ripgrep → 再使用 ast-grep 细化结果
与语义搜索(Phase 1)对比:
- 语义搜索:理解代码含义
- ast-grep:理解代码结构
- 结合使用:效果最佳(Phase 2)
使用工作流
-
使用 ripgrep 进行广泛搜索:
Skill({ skill: 'ripgrep', args: 'authenticate --type ts' }) -
使用 ast-grep 进行结构细化:
Skill({ skill: 'code-structural-search', args: 'function authenticate($$$) { $$ } --lang ts' }) -
使用 Phase 1 进行语义理解:
Skill({ skill: 'code-semantic-search', args: 'authentication logic' })
常见用例
安全模式
查找未经验证的输入:
router.post($PATH, ($REQ, $RES) => { $$ })
查找 SQL 查询(可能存在注入风险):
db.query(`SELECT * FROM ${$VAR}`)
查找 eval 的使用:
eval($$$)
代码质量模式
查找嵌套层级过深的函数:
function $NAME($ARGS) {
if ($COND) {
if ($COND2) {
if ($COND3) { $$ }
}
}
}
查找参数列表过长的函数(>5 个参数):
function $NAME($A, $B, $C, $D, $E, $F, $$$) { $$ }
查找未使用的变量:
const $NAME = $VALUE;
重构模式
查找旧 API 用法:
oldAPI.deprecatedMethod($$$)
查找回调模式(转换为 async/await):
$FUNC($ARGS, ($ERR, $DATA) => { $$ })
查找 React 类组件(转换为 hooks):
class $NAME extends React.Component { $$$ }
铁律
- 始终通过
--lang标志指定语言 — 如果不指定语言标志,ast-grep 会应用启发式规则,导致误报;请指定--lang ts、--lang py等,以便准确解析 AST。 - 始终先使用 ripgrep/关键词搜索缩小目标范围 — 对整个代码库进行结构化搜索速度很慢;先用 ripgrep 查找候选文件,再用 ast-grep 进行精确匹配。
- 绝不使用正则表达式匹配结构化代码模式 — 正则表达式无法处理格式差异、嵌套结构和多行代码;AST 模式不受格式影响,语义也更精确。
- 在项目范围内运行前,始终先用已知匹配项测试模式 — 语法错误的模式会静默地匹配不到任何内容;大范围应用前,请确认该模式至少能找到一个已知示例。
- 变量参数列表始终使用
$$$,不要使用*或.— ast-grep 使用元变量语法($NAME、$$$、$$);在模式中使用正则表达式或 glob 语法会导致静默失败。
反模式
| 反模式 | 失败原因 | 正确做法 |
|---|---|---|
未使用 --lang 标志 | 使用了错误的解析器;导致误报和漏报 | 始终指定 --lang ts、--lang py 等 |
| 未先用 ripgrep 过滤就对整个项目运行 | 大型代码库中速度很慢;会产生许多无关结果 | 先用 ripgrep 找出候选文件 |
| 使用正则表达式进行结构化匹配 | 无法处理多行、空白差异和嵌套结构 | 使用 ast-grep AST 模式($NAME、$$$ 等) |
| 未经测试就对整个代码库使用模式 | 错误的模式会静默地返回空结果 | 先在一个已知匹配项上测试 |
使用 * 或 . 作为通配符 | 不是有效的 ast-grep 语法;会被忽略或报错 | 单个节点使用 $NAME,序列使用 $$$ |
记忆协议(强制)
开始前:
阅读 .claude/context/memory/learnings.md
完成后:
- 新模式 →
.claude/context/memory/learnings.md - 发现问题 →
.claude/context/memory/issues.md - 作出决策 →
.claude/context/memory/decisions.md
假定会发生中断:如果没有记录在记忆中,就等于没有发生。