0
# Tree & Node
1
2
Syntax tree navigation and manipulation functionality. Trees represent the complete parsed structure of source code, while Nodes represent individual elements within the tree hierarchy.
3
4
## Tree Capabilities
5
6
### Tree Creation and Management
7
8
Trees are created by parsers and represent immutable syntax structures.
9
10
```typescript { .api }
11
/**
12
* Create a shallow copy of the syntax tree (very fast operation)
13
* @returns New Tree instance sharing internal structure
14
*/
15
copy(): Tree;
16
17
/**
18
* Delete the syntax tree and free its resources
19
*/
20
delete(): void;
21
22
/** The language that was used to parse the syntax tree */
23
language: Language;
24
```
25
26
### Root Node Access
27
28
Access the root node of the syntax tree.
29
30
```typescript { .api }
31
/**
32
* Get the root node of the syntax tree
33
*/
34
get rootNode(): Node;
35
36
/**
37
* Get the root node with its position shifted forward by the given offset
38
* @param offsetBytes - Byte offset to apply
39
* @param offsetExtent - Point offset to apply
40
* @returns Root node with adjusted position
41
*/
42
rootNodeWithOffset(offsetBytes: number, offsetExtent: Point): Node;
43
```
44
45
**Usage Example:**
46
47
```typescript
48
const tree = parser.parse("let x = 1 + 2;");
49
const root = tree.rootNode;
50
51
console.log(root.type); // "program"
52
console.log(root.toString()); // S-expression representation
53
54
// Get root with offset (useful for embedded parsing)
55
const offsetRoot = tree.rootNodeWithOffset(10, { row: 1, column: 0 });
56
```
57
58
### Tree Editing
59
60
Synchronize trees with source code changes for incremental parsing.
61
62
```typescript { .api }
63
/**
64
* Edit the syntax tree to keep it in sync with source code changes
65
* @param edit - Description of the edit in both byte offsets and row/column coordinates
66
*/
67
edit(edit: Edit): void;
68
69
/**
70
* Compare this tree to a new tree and get ranges where structure changed
71
* @param other - New tree representing the same document after edits
72
* @returns Array of ranges with syntactic structure changes
73
*/
74
getChangedRanges(other: Tree): Range[];
75
```
76
77
**Usage Example:**
78
79
```typescript
80
const tree = parser.parse("let x = 1;");
81
82
// Edit the tree to reflect source change: "let x = 1;" → "let x = 42;"
83
tree.edit({
84
startIndex: 8,
85
oldEndIndex: 9,
86
newEndIndex: 10,
87
startPosition: { row: 0, column: 8 },
88
oldEndPosition: { row: 0, column: 9 },
89
newEndPosition: { row: 0, column: 10 }
90
});
91
92
// Parse the updated source
93
const newTree = parser.parse("let x = 42;", tree);
94
95
// Get changed ranges
96
const changes = tree.getChangedRanges(newTree);
97
console.log("Changed ranges:", changes);
98
```
99
100
### Tree Navigation
101
102
Create tree cursors and access parsing ranges.
103
104
```typescript { .api }
105
/**
106
* Create a new TreeCursor starting from the root of the tree
107
* @returns TreeCursor for efficient tree traversal
108
*/
109
walk(): TreeCursor;
110
111
/**
112
* Get the included ranges that were used to parse the syntax tree
113
* @returns Array of ranges that were included during parsing
114
*/
115
getIncludedRanges(): Range[];
116
```
117
118
## Node Capabilities
119
120
### Node Identity and Position
121
122
Access node identification and location information.
123
124
```typescript { .api }
125
/** Unique numeric ID for this node within the tree */
126
id: number;
127
128
/** The byte index where this node starts */
129
startIndex: number;
130
131
/** The position where this node starts */
132
startPosition: Point;
133
134
/** The tree that this node belongs to */
135
tree: Tree;
136
137
/**
138
* Get the byte index where this node ends
139
*/
140
get endIndex(): number;
141
142
/**
143
* Get the position where this node ends
144
*/
145
get endPosition(): Point;
146
```
147
148
### Node Type Information
149
150
Access node type and classification details.
151
152
```typescript { .api }
153
/**
154
* Get this node's type as a numerical id
155
*/
156
get typeId(): number;
157
158
/**
159
* Get the node's type as a numerical id as it appears in the grammar, ignoring aliases
160
*/
161
get grammarId(): number;
162
163
/**
164
* Get this node's type as a string
165
*/
166
get type(): string;
167
168
/**
169
* Get this node's symbol name as it appears in the grammar, ignoring aliases
170
*/
171
get grammarType(): string;
172
```
173
174
**Usage Example:**
175
176
```typescript
177
const root = tree.rootNode;
178
const firstChild = root.firstChild;
179
180
if (firstChild) {
181
console.log("Type:", firstChild.type); // e.g., "lexical_declaration"
182
console.log("Type ID:", firstChild.typeId); // e.g., 42
183
console.log("Grammar type:", firstChild.grammarType);
184
console.log("Position:", firstChild.startPosition); // { row: 0, column: 0 }
185
console.log("Byte range:", firstChild.startIndex, "-", firstChild.endIndex);
186
}
187
```
188
189
### Node Classification
190
191
Check node properties and error states.
192
193
```typescript { .api }
194
/**
195
* Check if this node is named (corresponds to named rules in grammar)
196
*/
197
get isNamed(): boolean;
198
199
/**
200
* Check if this node is extra (like comments, not required by grammar)
201
*/
202
get isExtra(): boolean;
203
204
/**
205
* Check if this node represents a syntax error
206
*/
207
get isError(): boolean;
208
209
/**
210
* Check if this node is missing (inserted by parser for error recovery)
211
*/
212
get isMissing(): boolean;
213
214
/**
215
* Check if this node has been edited
216
*/
217
get hasChanges(): boolean;
218
219
/**
220
* Check if this node contains any syntax errors anywhere within it
221
*/
222
get hasError(): boolean;
223
```
224
225
### Node Content and State
226
227
Access node text content and parse state information.
228
229
```typescript { .api }
230
/**
231
* Get the string content of this node
232
*/
233
get text(): string;
234
235
/**
236
* Get this node's parse state
237
*/
238
get parseState(): number;
239
240
/**
241
* Get the parse state after this node
242
*/
243
get nextParseState(): number;
244
```
245
246
### Node Comparison
247
248
Compare nodes for equality.
249
250
```typescript { .api }
251
/**
252
* Check if this node is equal to another node
253
* @param other - Node to compare with
254
* @returns True if nodes are equal
255
*/
256
equals(other: Node): boolean;
257
```
258
259
### Child Node Access
260
261
Access child nodes by index and field.
262
263
```typescript { .api }
264
/**
265
* Get the node's child at the given index (0-based)
266
* @param index - Child index to retrieve
267
* @returns Child node or null if index is out of bounds
268
*/
269
child(index: number): Node | null;
270
271
/**
272
* Get this node's named child at the given index
273
* @param index - Named child index to retrieve
274
* @returns Named child node or null if index is out of bounds
275
*/
276
namedChild(index: number): Node | null;
277
278
/**
279
* Get this node's child with the given numerical field id
280
* @param fieldId - Field ID to look up
281
* @returns Child node or null if no child has this field
282
*/
283
childForFieldId(fieldId: number): Node | null;
284
285
/**
286
* Get the first child with the given field name
287
* @param fieldName - Field name to look up
288
* @returns Child node or null if no child has this field
289
*/
290
childForFieldName(fieldName: string): Node | null;
291
```
292
293
**Usage Examples:**
294
295
```typescript
296
const statement = tree.rootNode.firstChild; // e.g., "lexical_declaration"
297
298
if (statement) {
299
// Access by index
300
const firstChild = statement.child(0); // e.g., "let" keyword
301
302
// Access by field name
303
const declarations = statement.childForFieldName("declarations");
304
305
// Get field names
306
const fieldName = statement.fieldNameForChild(1);
307
console.log("Field name for child 1:", fieldName);
308
}
309
```
310
311
### Field Name Lookup
312
313
Get field names for child nodes.
314
315
```typescript { .api }
316
/**
317
* Get the field name of this node's child at the given index
318
* @param index - Child index to check
319
* @returns Field name or null if child has no field name
320
*/
321
fieldNameForChild(index: number): string | null;
322
323
/**
324
* Get the field name of this node's named child at the given index
325
* @param index - Named child index to check
326
* @returns Field name or null if child has no field name
327
*/
328
fieldNameForNamedChild(index: number): string | null;
329
```
330
331
### Multiple Children Access
332
333
Get arrays of children by field.
334
335
```typescript { .api }
336
/**
337
* Get an array of this node's children with a given field name
338
* @param fieldName - Field name to filter by
339
* @returns Array of child nodes with the given field name
340
*/
341
childrenForFieldName(fieldName: string): (Node | null)[];
342
343
/**
344
* Get an array of this node's children with a given field id
345
* @param fieldId - Field ID to filter by
346
* @returns Array of child nodes with the given field ID
347
*/
348
childrenForFieldId(fieldId: number): (Node | null)[];
349
```
350
351
### Child Navigation by Position
352
353
Find children by byte offset.
354
355
```typescript { .api }
356
/**
357
* Get the node's first child that contains or starts after the given byte offset
358
* @param index - Byte offset to search from
359
* @returns Child node or null if no such child exists
360
*/
361
firstChildForIndex(index: number): Node | null;
362
363
/**
364
* Get the node's first named child that contains or starts after the given byte offset
365
* @param index - Byte offset to search from
366
* @returns Named child node or null if no such child exists
367
*/
368
firstNamedChildForIndex(index: number): Node | null;
369
```
370
371
### Child Counts and Direct Access
372
373
Get child counts and direct child access.
374
375
```typescript { .api }
376
/**
377
* Get this node's number of children
378
*/
379
get childCount(): number;
380
381
/**
382
* Get this node's number of named children
383
*/
384
get namedChildCount(): number;
385
386
/**
387
* Get this node's first child
388
*/
389
get firstChild(): Node | null;
390
391
/**
392
* Get this node's first named child
393
*/
394
get firstNamedChild(): Node | null;
395
396
/**
397
* Get this node's last child
398
*/
399
get lastChild(): Node | null;
400
401
/**
402
* Get this node's last named child
403
*/
404
get lastNamedChild(): Node | null;
405
406
/**
407
* Get array of all children
408
*/
409
get children(): (Node | null)[];
410
411
/**
412
* Get array of all named children
413
*/
414
get namedChildren(): (Node | null)[];
415
```
416
417
### Sibling Navigation
418
419
Navigate between sibling nodes.
420
421
```typescript { .api }
422
/**
423
* Get this node's next sibling
424
*/
425
get nextSibling(): Node | null;
426
427
/**
428
* Get this node's previous sibling
429
*/
430
get previousSibling(): Node | null;
431
432
/**
433
* Get this node's next named sibling
434
*/
435
get nextNamedSibling(): Node | null;
436
437
/**
438
* Get this node's previous named sibling
439
*/
440
get previousNamedSibling(): Node | null;
441
```
442
443
### Descendant Operations
444
445
Work with descendant nodes in the subtree.
446
447
```typescript { .api }
448
/**
449
* Get the descendants of this node that are the given type(s)
450
* @param types - Node type name or array of type names to search for
451
* @param startPosition - Optional start position to limit search
452
* @param endPosition - Optional end position to limit search
453
* @returns Array of matching descendant nodes
454
*/
455
descendantsOfType(types: string | string[], startPosition?: Point, endPosition?: Point): (Node | null)[];
456
457
/**
458
* Get the node's number of descendants, including one for the node itself
459
*/
460
get descendantCount(): number;
461
462
/**
463
* Get the smallest node within this node that spans the given byte range
464
* @param start - Start byte index
465
* @param end - End byte index (optional, defaults to start)
466
* @returns Smallest node spanning the range or null
467
*/
468
descendantForIndex(start: number, end?: number): Node | null;
469
470
/**
471
* Get the smallest named node within this node that spans the given byte range
472
* @param start - Start byte index
473
* @param end - End byte index (optional, defaults to start)
474
* @returns Smallest named node spanning the range or null
475
*/
476
namedDescendantForIndex(start: number, end?: number): Node | null;
477
478
/**
479
* Get the smallest node within this node that spans the given point range
480
* @param start - Start position
481
* @param end - End position (optional, defaults to start)
482
* @returns Smallest node spanning the range or null
483
*/
484
descendantForPosition(start: Point, end?: Point): Node | null;
485
486
/**
487
* Get the smallest named node within this node that spans the given point range
488
* @param start - Start position
489
* @param end - End position (optional, defaults to start)
490
* @returns Smallest named node spanning the range or null
491
*/
492
namedDescendantForPosition(start: Point, end?: Point): Node | null;
493
```
494
495
**Usage Examples:**
496
497
```typescript
498
// Find all identifier nodes
499
const identifiers = tree.rootNode.descendantsOfType("identifier");
500
console.log("Found identifiers:", identifiers.length);
501
502
// Find node at specific position
503
const nodeAtCursor = tree.rootNode.descendantForPosition({ row: 0, column: 5 });
504
console.log("Node at cursor:", nodeAtCursor?.type);
505
506
// Find all function declarations
507
const functions = tree.rootNode.descendantsOfType("function_declaration");
508
```
509
510
### Parent and Ancestor Navigation
511
512
Navigate up the tree hierarchy.
513
514
```typescript { .api }
515
/**
516
* Get this node's immediate parent
517
*/
518
get parent(): Node | null;
519
520
/**
521
* Get the node that contains the given descendant
522
* @param descendant - Descendant node to find container for
523
* @returns Node containing the descendant (may be descendant itself)
524
*/
525
childWithDescendant(descendant: Node): Node | null;
526
```
527
528
### Tree Cursor Creation
529
530
Create efficient tree cursors from nodes.
531
532
```typescript { .api }
533
/**
534
* Create a new TreeCursor starting from this node
535
* Note: The given node is considered the root of the cursor
536
* @returns TreeCursor for efficient traversal
537
*/
538
walk(): TreeCursor;
539
```
540
541
### Node Editing
542
543
Edit individual nodes to sync with source changes.
544
545
```typescript { .api }
546
/**
547
* Edit this node to keep it in-sync with source code changes
548
* Only needed when keeping specific Node instances after tree edits
549
* @param edit - Description of the edit
550
*/
551
edit(edit: Edit): void;
552
```
553
554
### String Representation
555
556
Get textual representation of nodes.
557
558
```typescript { .api }
559
/**
560
* Get the S-expression representation of this node
561
* @returns String representation showing the tree structure
562
*/
563
toString(): string;
564
```
565
566
**Usage Example:**
567
568
```typescript
569
const tree = parser.parse("let x = 1 + 2;");
570
console.log(tree.rootNode.toString());
571
// Output: (program (lexical_declaration (let) (variable_declarator (identifier) (number))))
572
```