Files
poimen-memory/knowledge/ast-grep.md
T
rock 762acea610
Build and Push / Test (push) Failing after 6s
Build and Push / Build and push image (push) Skipped
feat: add 'mem learn' CLI for markdown knowledge ingestion
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
2026-08-29 22:04:14 -07:00

79 lines
2.9 KiB
Markdown

# 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 from `sgconfig.yml`.
- `sg test` — test rules against fixtures.
## Pattern Syntax
- `$VAR` matches single AST node (identifier, expression, etc).
- `$$$VARS` matches zero or more nodes (variadic).
- `$$VAR` matches zero or one node (optional).
- Literal code matches itself: `if true { $$$BODY }` matches any `if true` block.
## Meta Variables
- `$A` in pattern captures node, available in `--rewrite` as `$A`.
- Named captures: same name must match same content. `$A == $A` matches `x == x` but not `x == y`.
- `$_` is anonymous — matches anything without capturing.
## Rule YAML Format
```yaml
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)
```yaml
ruleDirs:
- rules/
testConfigs:
- rules/tests/
```
## Advanced Patterns
- Find unused variables: `let $VAR = $EXPR;` where `$VAR` not 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 --json` for machine-readable output.
- Pre-commit hooks: `sg scan --rule rules/` on staged files.
- Editor: VSCode extension, LSP support.
- Programmatic: `@ast-grep/napi` Node.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.