or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdlanguage.mdparser.mdquery.mdtree-cursor.mdtree-node.md

tree-node.mddocs/

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

```