7.5 KiB
ast-grep Comprehensive Reference Guide
This guide provides comprehensive ast-grep knowledge for structural code search and transformation.
Core ast-grep Concepts
Pattern Syntax
- Use actual code syntax for the target language
- Use metavariables to capture patterns:
$VAR- matches any single AST node (expression, identifier, etc.)$$$ARGS- matches multiple nodes (zero or more)$$STMT- matches multiple statements
Basic Commands
# Search for pattern
ast-grep -p 'PATTERN'
# Specify language (always prefer explicit language)
ast-grep -l typescript -p 'PATTERN'
# Search and replace (preview)
ast-grep -p 'OLD_PATTERN' -r 'NEW_PATTERN'
# Apply changes (after verification)
ast-grep -p 'OLD_PATTERN' -r 'NEW_PATTERN' --update-all
# JSON output (for parsing)
ast-grep -p 'PATTERN' --json
CRITICAL CONSTRAINT: You cannot use interactive mode (-i) - you cannot respond to interactive prompts.
Recommended Workflow
1. Search Phase (Discovery)
# First, find matches to understand scope
ast-grep -l LANG -p 'PATTERN' [file_or_dir]
# Count matches to verify expectations
ast-grep -p 'PATTERN' | wc -l
2. Verification Phase (Before Changes)
- Always run search first to see what will match
- Review matches to ensure pattern is correct
- Verify no false positives
3. Application Phase (Making Changes)
Two viable strategies:
Strategy A: Direct Application (for high confidence scenarios)
ast-grep -p 'OLD' -r 'NEW' # Preview first
ast-grep -p 'OLD' -r 'NEW' --update-all # Apply after thorough review
Strategy B: Hybrid Approach (RECOMMENDED for maximum control)
- Use ast-grep to find matches:
ast-grep -l LANG -p 'PATTERN' - Read the files to see actual context
- Use Edit tool to apply changes with precise control
This combines ast-grep's structural search with Edit's precision.
4. Validation Phase
# After changes, verify the new pattern exists
ast-grep -p 'NEW_PATTERN' [file_or_dir]
Common Use Cases with Examples
1. Function Call Refactoring
# Find all calls to a function
ast-grep -l typescript -p 'oldFunction($$$ARGS)'
# Replace with new function
ast-grep -l typescript -p 'oldFunction($$$ARGS)' -r 'newFunction($$$ARGS)'
2. Method Rename
# Find method calls on any object
ast-grep -l javascript -p '$OBJ.oldMethod($$$ARGS)' -r '$OBJ.newMethod($$$ARGS)'
3. Import Statement Changes
# TypeScript/JavaScript: change import source
ast-grep -l typescript -p 'import $WHAT from "old-package"' -r 'import $WHAT from "new-package"'
4. Adding Parameters to Function Calls
# Add a new parameter to all calls
ast-grep -l javascript -p 'doThing($ARG1, $ARG2)' -r 'doThing($ARG1, $ARG2, { new: true })'
5. Find Complex Patterns
# Find try-catch blocks with specific pattern
ast-grep -l javascript -p 'try { $$$BODY } catch ($ERR) { console.error($$$) }'
# Find async functions
ast-grep -l typescript -p 'async function $NAME($$$ARGS) { $$$BODY }'
6. Class Method Changes
# Find all methods in classes
ast-grep -l typescript -p 'class $CLASS { $$$A $METHOD($$$PARAMS) { $$$BODY } $$$B }'
Language-Specific Tips
JavaScript/TypeScript (-l typescript or -l javascript)
- Works for: .js, .jsx, .ts, .tsx
- Patterns use JS/TS syntax exactly as written
- Arrow functions:
($$$ARGS) => $BODY - Always use
-l typescriptfor TypeScript files
Python (-l python)
- Indentation in pattern matters less than structure
- Use Python syntax:
def $NAME($$$ARGS):
Go (-l go)
- Use Go syntax:
func $NAME($$$ARGS) $RET { $$$ } - Package/import matching:
import "$PKG"
Rust (-l rust)
- Use Rust syntax:
fn $NAME($$$ARGS) -> $RET { $$$ } - Match macros:
println!($$$ARGS)
Best Practices
1. Always Verify Before Applying
# NEVER apply changes without seeing matches first
# BAD: ast-grep -p 'pattern' -r 'replacement' --update-all
# GOOD:
ast-grep -p 'pattern' # Review matches
ast-grep -p 'pattern' -r 'replacement' # Preview changes
ast-grep -p 'pattern' -r 'replacement' --update-all # Apply only after review
2. Always Use Explicit Language Flag
# BAD: ast-grep -p 'pattern' # May auto-detect incorrectly
# GOOD: ast-grep -l typescript -p 'pattern' # Explicit and reliable
3. Start Specific, Broaden if Needed
- Begin with very specific patterns
- If no matches, gradually make pattern more general
- Use metavariables for parts that vary, keep fixed parts specific
4. Use Metavariables Appropriately
$VAR- single expression (e.g.,$X + $Y)$$$ARGS- multiple items in lists (e.g., function arguments)$$STMT- multiple statements (e.g., function body)
5. Combine with Other Tools
# Use ast-grep to find, pipe to other tools
ast-grep -p 'pattern' | rg -e 'additional-filter'
# Use ast-grep to find locations, then Edit to apply
ast-grep -l typescript -p 'pattern' # Find matches
# Then use Edit tool with precise context
Common Pitfalls to Avoid
1. Overly Broad Patterns
❌ ast-grep -p '$X' - matches everything
✓ ast-grep -l typescript -p 'specificFunction($X)' - targeted
2. Forgetting Language Flag
❌ ast-grep -p 'pattern' - may misdetect language
✓ ast-grep -l typescript -p 'pattern' - explicit
3. Not Verifying Before --update-all
❌ ast-grep -p 'old' -r 'new' --update-all - blind changes
✓ Preview first, verify matches, then apply
4. Expecting Exact Text Matching
ast-grep matches structure, not text:
foo( x )andfoo(x)are the same structurally- Line breaks don't matter in most cases
- Comments are typically ignored
5. Using for Non-Code Files
ast-grep won't help with:
- Markdown content
- JSON/YAML values (not code structure)
- Plain text files
- Comments (usually)
Error Handling
If ast-grep fails or is unavailable:
- Fall back to text-based tools immediately
- Don't apologize excessively - just use the alternative approach
If pattern doesn't match:
- Verify language detection: ensure
-l LANGis used - Simplify pattern - start with minimal matching case
- Check syntax - ensure pattern is valid code for target language
- Fall back to Grep for discovery, then use Edit
If too many matches:
- Make pattern more specific
- Add context to pattern (surrounding code)
- Use directory/file path to narrow scope
- Consider using ast-grep for finding, Edit for selective changes
Integration with Edit Tool
Hybrid Strategy (Recommended for Precision)
When maximum control is needed:
- Use ast-grep to identify locations:
ast-grep -l typescript -p 'pattern'
-
Read the matched files to see actual context
-
Use Edit tool with precise old_string/new_string based on actual file content
This combines ast-grep's structural search with Edit's precise control. This is often the best approach because:
- ast-grep finds the right locations structurally
- Edit gives precise control over the exact changes
- Each match can be handled differently if needed
- Lower risk of unintended changes
Summary: Key Principles
- ast-grep solves the "not unique" problem by matching code structure instead of text
- Always verify before applying - search first, review matches, then apply
- Always use explicit language flag (
-l typescript,-l python, etc.) - Use metavariables correctly -
$VARfor single nodes,$$$ARGSfor multiple - Consider hybrid approach - ast-grep for finding, Edit for applying
- Fall back gracefully - if ast-grep doesn't work, use text tools without hesitation