AST-Grep Patterns (Optional Reference)
August 24, 2026 · View on GitHub
Common ast-grep patterns for automated code review in parallel development workflows.
Contents
When to Use
- Code Reviewer Agent needs automated pattern checking
- Refactoring workflow requires duplicate code detection
- Project has defined code structure standards
- Validating parallel-generated code consistency
MCP Tools
mcp__ast-grep__find_code - Find code by AST pattern
mcp__ast-grep__find_code_by_rule - Find by YAML rule
mcp__ast-grep__test_match_code_rule - Validate code against rule
mcp__ast-grep__dump_syntax_tree - Debug syntax structure
Common Patterns
Vue 3 SFC Structure Validation
Check if component has <script setup>:
id: vue-script-setup
language: vue
rule:
pattern: '<script setup>$$$</script>'
Check for proper TypeScript usage in template:
id: vue-ts-props
language: vue
rule:
pattern: 'defineProps<$$$>'
TypeScript Quality Checks
Ban any type:
id: no-any-type
language: typescript
rule:
pattern: ': any'
not:
has: 'as any'
Ensure async functions have error handling:
id: async-error-handling
language: typescript
rule:
pattern: 'async $FUNC($$$) { $$$ }'
not:
ast:
kind: try_statement
Rust Quality Checks
Ban unwrap() in production code (allow in tests):
id: no-unwrap-production
language: rust
rule:
pattern: '$EXPR.unwrap()'
not:
has:
kind: function_item
name: '$NAME'
within:
kind: module
name: 'tests'
Ensure ? operator is used for error propagation:
id: prefer-question-operator
language: rust
rule:
pattern: 'match $EXPR { Ok(v) => v, Err(e) => return Err(e) }'
Check for proper error handling in Result returns:
id: proper-result-handling
language: rust
rule:
pattern: 'async fn $NAME($$$) -> Result<$RET, $ERR> { $$$ }'
not:
has:
kind: macro_invocation
text: '?'
Validate Send + Sync trait bounds for concurrent types:
id: send-sync-bounds
language: rust
rule:
pattern: 'pub struct $NAME<T> { $$$ }'
not:
has:
kind: impl_item
constraints: 'T: Send + Sync'
Check for missing lifetime annotations:
id: lifetime-annotation
language: rust
rule:
pattern: 'fn $NAME(&$SELF, &$OTHER: &$TYPE) -> &$RT'
not:
has:
kind: lifetime_parameter
Swift Quality Checks
Ban try! (force-try that crashes on error):
id: no-force-try
language: swift
rule:
pattern: 'try! $EXPR'
Ban fatalError() outside of test code:
id: no-fatalerror-production
language: swift
rule:
pattern: 'fatalError($MSG)'
not:
inside:
kind: class_declaration
regex: 'Tests$'
Detect closures capturing self without [weak self] (advisory — high false positive rate):
id: missing-weak-self
language: swift
rule:
pattern: '{ $$$ in $$$ self $$$ }'
not:
has:
kind: capture_list_item
field: name
regex: 'weak'
Important caveat: This pattern matches ALL closures referencing self without [weak self], including non-escaping closures (Button actions, ForEach, onAppear, .map, .filter, etc.) that do NOT need weak self. Non-escaping closures are deallocated with the calling scope — they cannot create retain cycles. Reserve [weak self] for:
- Closures stored as properties (escaping)
- Closures passed to async callbacks (URLSession completion, DispatchQueue.asyncAfter)
- Closures captured by long-lived objects
This pattern produces a high false positive rate in SwiftUI code. Treat matches as advisory suggestions for review, not as bugs.
Detect non-Sendable types lacking explicit conformance — advisory, only relevant for types crossing actor boundaries:
id: missing-sendable
language: swift
rule:
pattern: 'class $NAME { $$$ }'
not:
has:
kind: inherit
pattern: 'Sendable'
Note: Most classes in iOS apps (ViewModels, ViewControllers, Managers) are @MainActor-isolated and do NOT need Sendable conformance. This pattern only matters for types passed across actor boundaries (e.g., data models passed to a background actor, response types from network calls). Treat matches as advisory for cross-actor types only, not as a blanket requirement.
Detect DispatchQueue.main.async when @MainActor should be used:
id: dispatch-main-async-suspect
language: swift
rule:
pattern: 'DispatchQueue.main.async { $$$ }'
Ban sleep() in test code (use expectations instead):
id: no-sleep-in-tests
language: swift
rule:
pattern: 'sleep($N)'
inside:
kind: class_declaration
regex: 'Tests$'
Detect @State mutation inside computed property bodies — advisory pattern, relies on manual review:
id: state-mutation-in-computed-property
language: swift
rule:
pattern: 'var $NAME: $TYPE { $BODY }'
has:
kind: assignment
Note: This pattern flags any computed property containing an assignment, which may or may not be a @State mutation. SwiftUI emits a runtime warning ("Modifying state during view update") when a @State property is mutated during a view body evaluation. AST-level detection is inherently imprecise for this check — rely on the runtime warning and manual review rather than pattern matching alone.
Detect ObservedObject that should be @StateObject (ownership issue):
id: observedobject-instead-of-stateobject
language: swift
rule:
pattern: '@ObservedObject var $NAME = $INIT'
Detect ObservableObject usage that should migrate to @Observable (advisory — new code should prefer @Observable):
id: observableobject-should-be-observable
language: swift
rule:
pattern: '$CLASS: ObservableObject'
Note: @Observable (Swift Observation framework) replaces ObservableObject + @Published for new ViewModels. It provides property-level change tracking instead of object-level notifications, reducing unnecessary view re-renders. Existing stable code using ObservableObject does not need immediate migration — apply on-touch when modifying a ViewModel. SwiftUI views consuming @Observable ViewModels use @State (ownership) or receive the instance via @Environment instead of @StateObject / @ObservedObject.
Detect @Published that should be plain properties under @Observable:
id: published-in-observable
language: swift
rule:
pattern: '@Published var $NAME'
inside:
kind: class_declaration
has:
pattern: '@Observable'
This detects a common migration error: @Published has no effect inside @Observable classes. Remove @Published — @Observable tracks all stored properties automatically.
Detect empty catch blocks (silent error swallowing):
id: empty-catch
language: swift
rule:
pattern: 'catch { }'
Check for Task without actor isolation when calling MainActor methods:
id: task-without-mainactor
language: swift
rule:
pattern: 'Task { $$$ }'
not:
has:
pattern: 'Task { @MainActor in $$$ }'
Python Quality Checks
Detect mutable default arguments (list/dict/set defaults are shared across calls — a common source of bugs):
id: mutable-default-argument
language: python
rule:
pattern: 'def $FUNC($$$, $PARAM=[])'
id: mutable-default-argument-dict
language: python
rule:
pattern: 'def $FUNC($$$, $PARAM={})'
id: mutable-default-argument-set
language: python
rule:
pattern: 'def $FUNC($$$, $PARAM=set())'
Ban bare except: (catches all exceptions including KeyboardInterrupt and SystemExit):
id: no-bare-except
language: python
rule:
pattern: 'except:'
Detect except Exception followed by pass (silently swallows all errors):
id: silent-exception-swallow
language: python
rule:
pattern: 'except Exception: pass'
Detect eval() usage (security risk — arbitrary code execution):
id: no-eval
language: python
rule:
pattern: 'eval($EXPR)'
Detect exec() usage (same security risk):
id: no-exec
language: python
rule:
pattern: 'exec($EXPR)'
Detect wildcard imports in production code (pollutes namespace, hides dependencies):
id: no-wildcard-import
language: python
rule:
pattern: 'from $MODULE import *'
Detect assert statements outside test files (assertions are stripped with -O flag — not for runtime validation):
id: assert-in-production
language: python
rule:
pattern: 'assert $EXPR'
not:
inside:
kind: module
regex: 'test_'
Detect string concatenation or f-string in SQL queries (SQL injection risk — advisory, high false positive rate):
id: sql-string-concat
language: python
rule:
pattern: 'cursor.execute($STR + $$$)'
id: sql-f-string
language: python
rule:
pattern: 'cursor.execute(f$$$)'
Note: These SQL patterns have high false positive rates — they flag any string concatenation or f-string passed to execute(). Parameterized queries using cursor.execute("SELECT ... WHERE id = %s", (id,)) are safe and will not be flagged. Treat matches as advisory suggestions for review.
Detect == None instead of is None (identity check is the Pythonic way):
id: none-equality-check
language: python
rule:
pattern: '$EXPR == None'
Detect type(x) == Y instead of isinstance(x, Y) (fails for subclasses):
id: type-equality-check
language: python
rule:
pattern: 'type($EXPR) == $TYPE'
Import Statement Patterns
Find all composables imports:
id: composables-imports
language: typescript
rule:
pattern: "import $$$ from '@/composables/$$$'"
Check for relative imports beyond parent:
id: no-deep-relative-imports
language: typescript
rule:
pattern: "from '../../$$$'"
Component Naming Conventions
Vue component files should match component name:
id: vue-component-name-match
language: vue
rule:
pattern: 'export default { name: "$$$" }'
Duplicate Code Detection
Find similar function structures:
id: function-pattern
language: typescript
rule:
pattern: 'function $NAME($$$) { return $EXPR }'
Find similar component options:
id: vue-options-api
language: vue
rule:
pattern: 'export default { $$$ }'
Workflow Integration Examples
Feature Development Workflow
Phase 6: Integration & Review
Web (Vue/React):
Task(solidforge:code-reviewer): Review AppHeader implementation
- Use ast-grep to validate structure patterns
- Check for banned patterns (any, console.log, etc.)
- Verify naming conventions
iOS (Swift/SwiftUI):
Task(solidforge:code-reviewer): Review SwiftUI feature implementation
- Check for try! and fatalError in production code
- Validate [weak self] in closures
- Detect DispatchQueue.main.async that should use @MainActor
- Find missing Sendable conformance on shared types
Python:
Task(solidforge:code-reviewer): Review Python feature implementation
- Check for mutable default arguments ([], {}, set())
- Detect bare except: and silent exception swallowing
- Flag eval() and exec() usage
- Find wildcard imports (from X import *)
- Detect SQL string concatenation (injection risk)
- Flag assert in non-test code
Refactoring Workflow
Phase 1: Analysis
Web:
Task(solidforge:architect): Analyze codebase for refactoring opportunities
- Use ast-grep to find duplicate code structures
- Identify components with similar patterns
- Report consolidation opportunities
iOS:
Task(solidforge:architect): Analyze Swift codebase for refactoring opportunities
- Use ast-grep to find missing @MainActor annotations
- Detect force-unwrap and force-try patterns
- Identify empty catch blocks swallowing errors
- Find @ObservedObject that should be @StateObject
Python:
Task(solidforge:architect): Analyze Python codebase for refactoring opportunities
- Detect mutable default arguments
- Find bare except: and silent error swallowing
- Flag wildcard imports
- Detect eval()/exec() usage
- Find type(x) == Y that should use isinstance()
Project-Specific Rules
Important: These patterns are project-specific. Each project should define its own rules in:
- Project
.cursor/rules/or project-specific skill - Team coding standards
- Architecture documentation
Notes
- Optional Reference: This file is provided as a reference only. Code Reviewer Agents may or may not use these patterns based on project needs.
- Performance Considerations: ast-grep is fast for single-file searches but may be slow for large codebases. Use targeted searches.
- Complementary Tools: ast-grep works well alongside linters (ESLint, Prettier) and type checkers. It is not a replacement.
- Pattern Quality: Poorly written patterns may produce false positives or miss issues. Test patterns before relying on them.