返回 Skill 列表
extension
分类: 开发与工程无需 API Key

ast-grep-search

使用ast-grep通过结构查找和替换代码模式。当您需要根据AST结构(而不仅仅是文本)匹配代码时,请使用此工具,例如查找具有特定签名的所有函数、跨文件替换API模式或检测正则表达式无法可靠匹配的代码反模式。

person作者: jakexiaohubgithub

ast-grep Structural Code Search & Refactoring

Structural code search and refactoring using ast-grep — matches code by its AST (abstract syntax tree) rather than text patterns.

When to Use ast-grep vs Grep/ripgrep

| Use ast-grep when... | Use grep/rg when... | |---------------------|---------------------| | Pattern depends on code structure | Simple text or regex match | | Need to match any number of arguments | Searching logs, docs, config | | Refactoring across many files | One-off literal string search | | Finding anti-patterns (empty catch, etc.) | Language doesn't matter | | Replacing while preserving variables | Quick filename/line check |

Decision rule: If your search pattern contains wildcards for "any expression," "any arguments," or "any function name," use ast-grep.

Pattern Syntax

| Pattern | Matches | Example | |---------|---------|---------| | $VAR | Single AST node | console.log($MSG) | | $$$ARGS | Zero or more nodes | func($$$ARGS) | | $_ | Single node (no capture) | $_ == $_ | | $A == $A | Same node repeated | Finds x == x (not x == y) |

Essential Commands

Search for Patterns

# Find structural patterns
ast-grep -p 'console.log($$$)' --lang js
ast-grep -p 'def $FUNC($$$): $$$' --lang py
ast-grep -p 'fn $NAME($$$) -> $RET { $$$ }' --lang rs

# Search in specific directory
ast-grep -p 'import $PKG' --lang js src/

# JSON output for parsing
ast-grep -p 'pattern' --lang js --json=compact

Search and Replace

# Preview changes (default - shows matches)
ast-grep -p 'var $V = $X' -r 'const $V = $X' --lang js

# Apply changes to all files
ast-grep -p 'var $V = $X' -r 'const $V = $X' --lang js -U

# Interactive review
ast-grep -p 'oldAPI($$$ARGS)' -r 'newAPI($$$ARGS)' --lang py -i

# Convert function syntax
ast-grep -p 'function($$$ARGS) { return $EXPR }' \
         -r '($$$ARGS) => $EXPR' --lang js -U

# Update import paths
ast-grep -p "import $NAME from '@old/$PATH'" \
         -r "import $NAME from '@new/$PATH'" --lang ts -U

Language Codes

| Code | Language | Code | Language | |------|----------|------|----------| | js | JavaScript | py | Python | | ts | TypeScript | rs | Rust | | jsx | JSX | go | Go | | tsx | TSX | java | Java | | cpp | C++ | rb | Ruby | | c | C | php | PHP |

Common Patterns by Language

JavaScript/TypeScript

# Find React hooks
ast-grep -p 'const [$STATE, $SETTER] = useState($INIT)' --lang jsx

# Find async functions
ast-grep -p 'async function $NAME($$$) { $$$ }' --lang js

# Find type assertions
ast-grep -p '$EXPR as $TYPE' --lang ts

# Find empty catch blocks
ast-grep -p 'try { $$$ } catch ($E) { }' --lang js

# Find eval usage (security)
ast-grep -p 'eval($$$)' --lang js

# Find innerHTML (XSS risk)
ast-grep -p '$ELEM.innerHTML = $$$' --lang js

# Find specific imports
ast-grep -p "import { $$$IMPORTS } from '$PKG'" --lang js

Python

# Find class definitions
ast-grep -p 'class $NAME($$$BASES): $$$' --lang py

# Find decorated functions
ast-grep -p '@$DECORATOR\ndef $FUNC($$$): $$$' --lang py

# Find dangerous shell calls
ast-grep -p 'os.system($$$)' --lang py

# Find SQL concatenation (injection risk)
ast-grep -p '"SELECT * FROM " + $VAR' --lang py

Rust

# Find unsafe blocks
ast-grep -p 'unsafe { $$$ }' --lang rs

# Find impl blocks
ast-grep -p 'impl $TRAIT for $TYPE { $$$ }' --lang rs

# Find public functions
ast-grep -p 'pub fn $NAME($$$) { $$$ }' --lang rs

Go

# Find goroutines
ast-grep -p 'go $FUNC($$$)' --lang go

# Find defer statements
ast-grep -p 'defer $FUNC($$$)' --lang go

# Find error handling
ast-grep -p 'if err != nil { $$$ }' --lang go

Common Refactoring Recipes

# Replace deprecated API calls
ast-grep -p 'oldAPI.$METHOD($$$)' -r 'newAPI.$METHOD($$$)' --lang js -U

# Rename a function across files
ast-grep -p 'oldName($$$ARGS)' -r 'newName($$$ARGS)' --lang py -U

# Remove console.log statements
ast-grep -p 'console.log($$$)' -r '' --lang js -U

# Convert require to import
ast-grep -p 'const $NAME = require($PKG)' \
         -r 'import $NAME from $PKG' --lang js -i

# Add error handling wrapper
ast-grep -p 'await $EXPR' \
         -r 'await $EXPR.catch(handleError)' --lang ts -i

Command-Line Flags

| Flag | Purpose | |------|---------| | -p, --pattern | Search pattern | | -r, --rewrite | Replacement pattern | | -l, --lang | Target language | | -i, --interactive | Review changes one by one | | -U, --update-all | Apply all changes | | --json | JSON output (compact, stream, pretty) | | -A N | Lines after match | | -B N | Lines before match | | -C N | Lines around match | | --debug-query | Debug pattern parsing |

YAML Rules (Scan Mode)

For reusable rules, use ast-grep scan with YAML configuration:

# Scan with config
ast-grep scan -c sgconfig.yml

# Run specific rule
ast-grep scan -r rule-name

# Initialize a rules project
ast-grep new project my-linter
ast-grep new rule no-console-log

Minimal rule file:

id: no-empty-catch
language: JavaScript
severity: warning
message: Empty catch block hides errors
rule:
  pattern: try { $$$ } catch ($E) { }
fix: |
  try { $$$ } catch ($E) { console.error($E) }

For comprehensive YAML rule syntax, constraints, transformations, and testing, see REFERENCE.md.

Agentic Optimizations

| Context | Command | |---------|---------| | Quick structural search | ast-grep -p 'pattern' --lang js --json=compact | | Count matches | ast-grep -p 'pattern' --lang js --json=stream \| wc -l | | File list only | ast-grep -p 'pattern' --json=stream \| jq -r '.file' \| sort -u | | Batch refactor | ast-grep -p 'old' -r 'new' --lang js -U | | Scan with rules | ast-grep scan --json | | Debug pattern | ast-grep -p 'pattern' --debug-query --lang js |

Quick Reference

# 1. Search for pattern
ast-grep -p 'pattern' --lang js src/

# 2. Preview rewrite
ast-grep -p 'old' -r 'new' --lang js

# 3. Apply rewrite
ast-grep -p 'old' -r 'new' --lang js -U

# 4. Scan with rules
ast-grep scan -c sgconfig.yml

# 5. Debug pattern
ast-grep -p 'pattern' --debug-query --lang js