264 lines
7.5 KiB
Markdown
264 lines
7.5 KiB
Markdown
# 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
|
|
```bash
|
|
# 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)
|
|
```bash
|
|
# 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)
|
|
```bash
|
|
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)
|
|
1. Use ast-grep to find matches: `ast-grep -l LANG -p 'PATTERN'`
|
|
2. Read the files to see actual context
|
|
3. Use Edit tool to apply changes with precise control
|
|
|
|
This combines ast-grep's structural search with Edit's precision.
|
|
|
|
## 4. Validation Phase
|
|
```bash
|
|
# After changes, verify the new pattern exists
|
|
ast-grep -p 'NEW_PATTERN' [file_or_dir]
|
|
```
|
|
|
|
---
|
|
|
|
# Common Use Cases with Examples
|
|
|
|
## 1. Function Call Refactoring
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# Find method calls on any object
|
|
ast-grep -l javascript -p '$OBJ.oldMethod($$$ARGS)' -r '$OBJ.newMethod($$$ARGS)'
|
|
```
|
|
|
|
## 3. Import Statement Changes
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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 typescript` for 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
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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 )` and `foo(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:
|
|
1. Fall back to text-based tools immediately
|
|
2. Don't apologize excessively - just use the alternative approach
|
|
|
|
## If pattern doesn't match:
|
|
1. Verify language detection: ensure `-l LANG` is used
|
|
2. Simplify pattern - start with minimal matching case
|
|
3. Check syntax - ensure pattern is valid code for target language
|
|
4. Fall back to Grep for discovery, then use Edit
|
|
|
|
## If too many matches:
|
|
1. Make pattern more specific
|
|
2. Add context to pattern (surrounding code)
|
|
3. Use directory/file path to narrow scope
|
|
4. Consider using ast-grep for finding, Edit for selective changes
|
|
|
|
---
|
|
|
|
# Integration with Edit Tool
|
|
|
|
## Hybrid Strategy (Recommended for Precision)
|
|
|
|
When maximum control is needed:
|
|
|
|
1. **Use ast-grep to identify locations:**
|
|
```bash
|
|
ast-grep -l typescript -p 'pattern'
|
|
```
|
|
|
|
2. **Read the matched files** to see actual context
|
|
|
|
3. **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
|
|
|
|
1. **ast-grep solves the "not unique" problem** by matching code structure instead of text
|
|
2. **Always verify before applying** - search first, review matches, then apply
|
|
3. **Always use explicit language flag** (`-l typescript`, `-l python`, etc.)
|
|
4. **Use metavariables correctly** - `$VAR` for single nodes, `$$$ARGS` for multiple
|
|
5. **Consider hybrid approach** - ast-grep for finding, Edit for applying
|
|
6. **Fall back gracefully** - if ast-grep doesn't work, use text tools without hesitation
|