Skip to content

Commit 892f5f1

Browse files
feat: add cheatsheet
1 parent 34c1311 commit 892f5f1

File tree

3 files changed

+356
-0
lines changed

3 files changed

+356
-0
lines changed
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
# Rule Cheat Sheet
2+
3+
This cheat sheet provides a concise overview of ast-grep's rule object configuration, covering Atomic, Relational, and Composite rules, along with notes on Utility rules. It's designed as a handy reference for common usage.
4+
5+
6+
<script setup>
7+
import CheatSheet from '../../src/cheatsheet/SheetTable.vue'
8+
import Item from '../../src/cheatsheet/Item.vue'
9+
</script>
10+
11+
## Atomic Rules Cheat Sheet
12+
13+
These are your precision tools, matching individual AST nodes based on their inherent properties.
14+
15+
<CheatSheet title="⚛️ Atomic Rules" variant="danger">
16+
17+
<Item>
18+
19+
```yaml
20+
pattern: console.log($ARG)
21+
```
22+
23+
🧩 Match a node by code structure. e.g. `console.log` call with a single `$ARG`
24+
25+
</Item>
26+
27+
<Item>
28+
29+
```yaml
30+
pattern:
31+
context: '{ key: value }'
32+
selector: pair
33+
```
34+
35+
🧩 To parse ambiguous patterns, use `context` and specify `selector` AST to search.
36+
37+
</Item>
38+
39+
<Item>
40+
41+
```yaml
42+
kind: if_statement
43+
```
44+
🏷️ Match an AST node by its `kind` name
45+
</Item>
46+
47+
<Item>
48+
49+
```yaml
50+
regex: ^regex.+$
51+
```
52+
53+
🔍 Matches node text content against a [Rust regular expression](https://docs.rs/regex/latest/regex/)
54+
55+
</Item>
56+
57+
<Item>
58+
59+
```yaml
60+
nthChild: 1
61+
```
62+
63+
🔢 Find a node by its **1-based index** among its _named siblings_
64+
65+
</Item>
66+
67+
<Item>
68+
69+
```yaml
70+
nthChild:
71+
position: 2
72+
reverse: true
73+
ofRule: { kind: argument_list }
74+
```
75+
76+
🔢 Advanced positional control: `position`, `reverse` (count from end), or filter siblings using `ofRule`
77+
78+
</Item>
79+
80+
<Item>
81+
82+
```yaml
83+
range:
84+
start: { line: 0, column: 0 }
85+
end: { line: 0, column: 13 }
86+
```
87+
88+
🎯 Matches a node based on its character span: 0-based, inclusive start, exclusive end
89+
90+
</Item>
91+
92+
</CheatSheet>
93+
94+
## Relational Rules Cheat Sheet
95+
96+
These powerful rules define how nodes relate to each other structurally. Think of them as your AST GPS!
97+
98+
<CheatSheet title="🔗 Relational Rules" variant="warning">
99+
100+
<Item>
101+
102+
```yaml
103+
inside:
104+
kind: function_declaration
105+
```
106+
107+
🏠 Target node must appear **inside** its _parent/ancestor_ node matching the sub-rule
108+
109+
</Item>
110+
111+
<Item>
112+
113+
```yaml
114+
has:
115+
kind: method_definition
116+
```
117+
118+
🌳 Target node must **have** a _child/descendant_ node matching the sub-rule
119+
120+
</Item>
121+
122+
<Item>
123+
124+
```yaml
125+
has:
126+
kind: statement_block
127+
field: body
128+
```
129+
130+
🌳 `field` makes `has`/`inside` match nodes by their [semantic role](/advanced/core-concepts.html#kind-vs-field)
131+
132+
</Item>
133+
134+
<Item>
135+
136+
```yaml
137+
precedes:
138+
pattern: function $FUNC() { $$ }
139+
```
140+
141+
◀️ Target node must appear _before_ another node matching the sub-rule
142+
143+
</Item>
144+
145+
<Item>
146+
147+
```yaml
148+
follows:
149+
pattern: let x = 10;
150+
```
151+
152+
▶️ Target node must appear _after_ another node matching the sub-rule.
153+
154+
</Item>
155+
156+
<Item>
157+
158+
```yaml
159+
inside:
160+
kind: function_declaration
161+
stopBy: end
162+
```
163+
164+
🏠 `stopBy` makes relational rules search all the way to the end, not just immediate neighbors.
165+
166+
</Item>
167+
168+
</CheatSheet>
169+
170+
## Composite Rules Cheat Sheet
171+
172+
Combine multiple rules using Boolean logic. Crucially, these operations apply to a single target node!
173+
174+
<CheatSheet title="🧠 Composite Rules" variant="tip">
175+
176+
<Item>
177+
178+
```yaml
179+
all:
180+
- pattern: const $VAR = $VALUE
181+
- has: { kind: string_literal }
182+
```
183+
184+
✅ Node must satisfy **ALL** the rules in the list.
185+
186+
</Item>
187+
188+
<Item>
189+
190+
```yaml
191+
any:
192+
- pattern: let $X = $Y
193+
- pattern: const $X = $Y
194+
```
195+
196+
🧡 Node must satisfy **AT LEAST ONE** of the rules in the list.
197+
198+
</Item>
199+
200+
<Item>
201+
202+
```yaml
203+
not:
204+
pattern: console.log($$)
205+
```
206+
207+
🚫 Node must **NOT** satisfy the specified sub-rule.
208+
209+
</Item>
210+
211+
<Item>
212+
213+
```yaml
214+
matches: is-function-call
215+
```
216+
217+
🔄 Matches the node if that utility rule matches it. Your gateway to modularity!
218+
219+
</Item>
220+
221+
</CheatSheet>
222+
223+
## Utility Rules Cheat Sheet
224+
225+
Define reusable rule definitions to cut down on duplication and build complex, maintainable rule sets.
226+
227+
<CheatSheet title="📦 Utility Rules" variant="info">
228+
229+
<Item>
230+
231+
```yaml
232+
rules:
233+
- id: find-my-pattern
234+
rule:
235+
matches: my-local-check
236+
utils:
237+
my-local-check:
238+
kind: identifier
239+
regex: '^my'
240+
```
241+
242+
🏡 Defined within the `utils` field of your current config file. Only accessible within that file.
243+
244+
</Item>
245+
246+
<Item>
247+
248+
```yaml
249+
# In utils/my-global-check.yml
250+
id: my-global-check
251+
language: javascript
252+
rule:
253+
kind: variable_declarator
254+
has:
255+
kind: number_literal
256+
```
257+
258+
🌍 Defined in separate YAML files in global `utilsDirs` folders, accessible across your entire project.
259+
260+
</Item>
261+
262+
</CheatSheet>

website/src/cheatsheet/Item.vue

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<script setup lang="ts">
2+
import { useSlots } from 'vue'
3+
const slots = useSlots()
4+
const [code, ...other] = slots.default?.() || []
5+
</script>
6+
7+
<template>
8+
<tr class="item">
9+
<td class="code-cell">
10+
<component :is="code"/>
11+
</td>
12+
<td class="description-cell">
13+
<component v-for="(item, index) in other" :key="index" :is="item"/>
14+
</td>
15+
</tr>
16+
</template>
17+
18+
19+
<style scoped>
20+
/* override */
21+
.code-cell:deep(div[class*='language-']) {
22+
margin: 0;
23+
}
24+
25+
.description-cell:deep(p) {
26+
margin: 0;
27+
}
28+
29+
tr.item {
30+
background-color: transparent;
31+
border-top: 1px solid rgba(0, 0, 0, 0.05);
32+
}
33+
td {
34+
border: none;
35+
background-color: transparent;
36+
}
37+
code.example {
38+
white-space: pre;
39+
display: block;
40+
}
41+
td.code-cell {
42+
width: 50%;
43+
padding-right: 0;
44+
}
45+
</style>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<script setup lang="ts">
2+
const props = defineProps({
3+
title: {
4+
type: String,
5+
required: true
6+
},
7+
variant: {
8+
type: String,
9+
default: 'danger'
10+
}
11+
})
12+
</script>
13+
<template>
14+
<table class="custom-block" :class="props.variant">
15+
<tbody>
16+
<tr class="title custom-block" :class="props.variant">
17+
<td colspan="3">
18+
{{props.title}}
19+
</td>
20+
</tr>
21+
<slot/>
22+
</tbody>
23+
</table>
24+
</template>
25+
26+
27+
<style scoped>
28+
table.custom-block {
29+
width: 100%;
30+
border-collapse: collapse;
31+
border: none;
32+
padding-top: 0;
33+
padding-left: 0;
34+
padding-right: 0;
35+
}
36+
thead, tbody {
37+
width: 100%;
38+
border: none;
39+
}
40+
tr.title {
41+
font-weight: bold;
42+
border: none;
43+
text-align: center;
44+
border: none;
45+
}
46+
.title td {
47+
border: none;
48+
}
49+
</style>

0 commit comments

Comments
 (0)