6 knowledge files: rust, SOLID/DRY, ast-grep, karpathy, golang, caveman 65 chunks ingested to log/knowledge/learn/latest.jsonl Chunks on ## headings, SHA256 dedup, configurable chunk size
2.9 KiB
2.9 KiB
AST-Grep (sg) — Structural Code Search & Transform
Core Concept
- AST-grep searches/transforms code using Abstract Syntax Tree patterns, not regex.
- Pattern matches structural meaning, ignoring whitespace, comments, formatting.
- Works across: Rust, Go, Python, JS/TS, Java, C, C++, Ruby, Kotlin, Lua, CSS, HTML.
CLI Usage
sg --pattern 'unwrap()' -l rust— find all.unwrap()calls in Rust files.sg --pattern 'println!($$$ARGS)' -l rust— find all println macros with any args.sg --pattern '$A.unwrap()' --rewrite '$A.expect("TODO")' -l rust— rewrite unwrap to expect.sg scan— run lint rules fromsgconfig.yml.sg test— test rules against fixtures.
Pattern Syntax
$VARmatches single AST node (identifier, expression, etc).$$$VARSmatches zero or more nodes (variadic).$$VARmatches zero or one node (optional).- Literal code matches itself:
if true { $$$BODY }matches anyif trueblock.
Meta Variables
$Ain pattern captures node, available in--rewriteas$A.- Named captures: same name must match same content.
$A == $Amatchesx == xbut notx == y. $_is anonymous — matches anything without capturing.
Rule YAML Format
id: no-unwrap
language: rust
rule:
pattern: $A.unwrap()
not:
inside:
kind: test_function
fix: $A.expect("handle error")
message: "Use .expect() instead of .unwrap() in production code"
severity: warning
Composite Rules
all: [rule1, rule2]— both must match.any: [rule1, rule2]— either matches.not: rule— negation.matches: rule-id— reference another rule.inside: { kind: function_item }— must be inside a function.has: { pattern: $EXPR }— must contain sub-pattern.follows: { pattern: ... }— must follow another pattern.precedes: { pattern: ... }— must precede another pattern.
Kind Selectors
kind: function_item— match AST node type directly.kind: call_expression— match function calls.- Use
sg --debug-query='println!("hello")'to see AST node kinds.
Configuration (sgconfig.yml)
ruleDirs:
- rules/
testConfigs:
- rules/tests/
Advanced Patterns
- Find unused variables:
let $VAR = $EXPR;where$VARnot referenced later. - Find API migrations:
old_function($$$ARGS)→new_function($$$ARGS). - Enforce patterns: ensure all error handling uses
?not.unwrap(). - Security: find
eval($EXPR), SQL injection patterns, hardcoded secrets.
Integration
- CI/CD:
sg scan --jsonfor machine-readable output. - Pre-commit hooks:
sg scan --rule rules/on staged files. - Editor: VSCode extension, LSP support.
- Programmatic:
@ast-grep/napiNode.js binding for custom tools.
vs Regex
- Regex:
unwrap\(\)matches in comments, strings, docs. AST-grep: only actual code. - Regex can't match nested structures. AST-grep handles
if { if { unwrap() } }. - AST-grep understands scope, types, structure. Regex is text-level.