SuperAPI AI Directory

ast-grep

Coding & development

View repository

Updated 10-16 05:06

About this skill

AST-Grep

AST-Grep (ast-grep/sg) is a fast and user-friendly tool for code search, linting, and large-scale code rewriting.

Execution Environment

Path Type Description
Usage Command-line tool, requires installation of ast-grep
Invocation Scenario Grammar-aware code search, structured code analysis, bulk code transformation
Working Directory Project root directory

Installation

# macOS
brew install ast-grep
Linux

cargo install ast-grep

Verify Installation

ast-grep --version


## 核心功能

### 1. 语法感知搜索

使用 AST(抽象语法树)进行代码搜索,而非简单的文本匹配。

```bash
# 搜索特定模式
ast-grep --lang python -p "def $FUNC($$$ARGS):"

# 搜索函数调用
ast-grep --lang ts -p "console.log($$$MSG)"

# 搜索条件语句
ast-grep --lang ts -p "if ($$COND) { $$$BODY }"

2. Code Linting

AST-based code checking, more precise than traditional linters.

# 扫描项目
ast-grep scan -r sgconfig.yml

# 扫描特定目录
ast-grep scan src/

# 扫描特定文件
ast-grep scan src/main.ts

3. Code Rewriting

Bulk transformation of code patterns.

# 简单替换
ast-grep run -p "oldFunction($$$ARGS)" -r "newFunction($$ARGS)" --lang ts

# 复杂转换(使用 YAML 规则)
ast-grep run -r rule.yml

4. Rule Testing

Test whether ast-grep rules are correct.

# 测试规则
ast-grep test -r rule.yml

# 测试特定模式
ast-grep test -p "pattern" --lang ts

Rule Development Process

General Process

  1. Understand the query: Clarify the user's needs, ask for more details when necessary
  2. Write an example: Write a simple code example that matches the query
  3. Write a rule: Write an ast-grep rule that matches the example
  4. Test the rule: Use test_match_code_rule to verify the rule
    • If it does not match, remove some sub-rules and debug
    • If using inside or has, make sure to use stopBy: end
  5. Search code: Use the rule to search the codebase

Rule Development Steps

  1. Decompose the query: Break the user query into smaller parts
  2. Identify sub-rules: Identify sub-rules that can be used to match the code
  3. Combine rules: Combine sub-rules using relational rules or composite rules
  4. Debug the rule: If the rule does not match the example code, remove some sub-rules and debug the non-matching parts
  5. Use tools: Use ast-grep mcp tools to dump the AST or dump the pattern query
  6. Test the rule: Use ast-grep mcp tools to test the rule against example code snippets

Rule Types

1. Atomic Rules

Match a single AST node based on intrinsic properties.

pattern - Pattern matching

# 字符串模式
pattern: console.log($ARG)

# 对象模式(更精细的控制)
pattern:
  selector: field_definition
  context: class { $F }
  strictness: relaxed

kind - Node type matching

kind: call_expression

regex - Regular expression matching

regex: ^[a-z]+$

nthChild - Position matching

# 数字
nthChild: 1

# An+B 公式
nthChild: 2n+1

# 对象形式
nthChild:
  position: 1
  reverse: true
  ofRule:
    kind: function_declaration

range - Range matching

range:
  start:
    line: 0
    column: 0
  end:
    line: 0
    column: 10

2. Relational Rules

Filter the target based on its relationship with other nodes.

inside - Inside a parent node

inside:
  pattern: class $C { $$$ }
  stopBy: end

has - Contains a child node

has:
  pattern: await $EXPR
  stopBy: end

precedes - Before a node

precedes:
  pattern: return $VAL

follows - After a node

follows:
  pattern: import $M from '$P'

stopBy - Search termination control

# neighbor(默认):在直接周围节点不匹配时停止
stopBy: neighbor

# end:搜索到方向末尾(inside 为根,has 为叶子)
stopBy: end

# 规则对象:在周围节点匹配提供的规则时停止(包含)
stopBy:
  pattern: class $END

field - Field matching

has:
  field: operator
  pattern: $$OP

3. Composite Rules

Combine other rules using logical operations.

all - Logical AND

all:
  - kind: call_expression
  - pattern: console.log($ARG)

any - Logical OR

any:
  - pattern: console.log($ARG)
  - pattern: console.warn($ARG)
  - pattern: console.error($ARG)

not - Logical NOT

not:
  pattern: console.log($ARG)

matches - Rule reuse

matches: my-utility-rule-id

Metavariables

$VAR - Single named node capture

# 有效
pattern: console.log($GREETING)

# 匹配
console.log('Hello World')

$$VAR - Single unnamed node capture

# 匹配操作符
rule:
  kind: binary_expression
  has:
    field: operator
    pattern: $$OP

$$$VAR - Multi-node capture

# 匹配零个或多个节点(非贪婪)
pattern: console.log($$$)

# 匹配可变参数
pattern: function $FUNC($$$ARGS) { $$$ }

_VAR - Non-capturing metavariable

# 不捕获,可以匹配不同内容
pattern: $_FUNC($_FUNC)

# 匹配
test(a)
testFunc(1 + 1)

Best practices for writing rules

  1. Always use stopBy: end: For relational rules, ensure the search reaches the end of the direction
has:
  pattern: await $EXPR
  stopBy: end
  1. Use pattern for simple structures: Use patterns directly when the code structure is simple
pattern: console.log($ARG)
  1. Use rule for complex structures: Use rules to break down when the code structure is complex
rule:
  kind: function_declaration
  has:
    pattern: await $EXPR
  1. Use kind for debugging: If pattern does not work, first use kind to match node types
# 先确认节点类型
kind: call_expression

# 再使用 has 或 inside
has:
  pattern: console.log($ARG)
  1. Add stopBy when relational rules have no match: Ensure the search reaches the end
inside:
  pattern: class $C { $$$ }
  stopBy: end

YAML rule configuration

Simple rules

# rule.yml
id: no-console-log
language: ts
rule:
  pattern: console.log($$$MSG)

Complex rules

# complex-rule.yml
id: prefer-const
language: ts
rule:
  all:
    - pattern: let $VAR = $INIT
    - not:
        pattern: $VAR = $EXPR

Rules with fixes

# fix-rule.yml
id: no-var
language: ts
rule:
  pattern: var $VAR = $INIT
fix: const $VAR = $INIT

Using relational rules

# async-without-await.yml
id: async-without-await
language: ts
rule:
  all:
    - pattern: async function $FUNC($$$ARGS) { $$$BODY }
    - not:
        has:
          pattern: await
          stopBy: end

Common scenarios

1. Find specific code patterns

# 查找所有 console.log
ast-grep -p "console.log($$$MSG)" --lang ts

# 查找所有未使用的变量
ast-grep -p "let $VAR = $INIT" --lang ts | grep -v "$VAR ="

2. Refactor code

# 替换 var 为 const
ast-grep run -p "var $VAR = $INIT" -r "const $VAR = $INIT" --lang ts

# 重命名函数
ast-grep run -p "oldFunc($$$ARGS)" -r "newFunc($$ARGS)" --lang ts

3. Code audit

# 查找潜在的安全问题
ast-grep -p "eval($$$EXPR)" --lang js

# 查找 SQL 注入风险
ast-grep -p "query('$$SQL')" --lang py

4. API migration

# 迁移旧 API 到新 API
ast-grep run -p "oldApi($$$ARGS)" -r "newApi($$ARGS)" --lang ts

# 批量更新导入
ast-grep run -p "from 'old-lib' import $$IMPORT" -r "from 'new-lib' import $$IMPORT" --lang ts

Comparison with other tools

Feature ast-grep grep ripgrep
Syntax-aware Yes No No
Code structure understanding Yes No No
Cross-language support Yes No No
Performance Fast Fast Fastest
Rewrite functionality Yes No No

Reference resources

Integrate with Pi workflow

Phase 1: Context retrieval

When you need to understand the code structure, use ast-grep for syntax-aware search:

# 查找特定模式
ast-grep -p "pattern" --lang <language>

Phase 4: Coding implementation

Use ast-grep for batch code transformation:

# 应用重构规则
ast-grep run -r rule.yml

Phase 5: Audit

Use ast-grep to verify code quality:

# 扫描潜在问题
ast-grep scan -r sgconfig.yml

Notes

  • ast-grep needs to be installed before use
  • Pattern syntax requires familiarity with AST structures
  • Complex rules are recommended to be tested before applying
  • It is recommended to back up code before large-scale refactoring
  • Use stopBy: end to ensure relational rule searches are complete
  • Metavariables must conform to syntax requirements ($VAR, $$VAR, $$$VAR)