Documentation Index
Fetch the complete documentation index at: https://mintlify.com/tree-sitter/tree-sitter/llms.txt
Use this file to discover all available pages before exploring further.
The Tree class represents the syntactic structure of a source code file. It is returned by the Parser.parse() method and provides access to the root node of the syntax tree.
Properties
rootNode
Get the root node of the syntax tree.
Example:
const tree = parser.parse('let x = 1;');
const root = tree.rootNode;
console.log(root.type); // 'program'
console.log(root.childCount); // 1
language
The language that was used to parse the syntax tree.
readonly language: Language
Example:
const tree = parser.parse('let x = 1;');
console.log(tree.language.name); // 'javascript'
Methods
copy()
Create a shallow copy of the syntax tree. This is very fast.
Returns: A new Tree instance that shares the same internal data
Example:
const tree1 = parser.parse('let x = 1;');
const tree2 = tree1.copy();
// Both trees represent the same parse
console.log(tree1.rootNode.equals(tree2.rootNode)); // true
// But they are separate objects
console.log(tree1 === tree2); // false
Copying a tree is useful when you need to keep multiple versions around for comparison or to preserve a tree before editing.
delete()
Delete the syntax tree and free its resources.
Example:
const tree = parser.parse('let x = 1;');
// ... use tree ...
tree.delete(); // Clean up
edit(edit)
Edit the syntax tree to keep it in sync with source code that has been edited.
Parameters:
edit - An Edit object describing the change in both byte offsets and row/column coordinates
Example:
const sourceCode = 'let x = 1;';
const tree = parser.parse(sourceCode);
// Change 'let' to 'const'
const newSourceCode = 'const x = 1;';
tree.edit({
startIndex: 0,
oldEndIndex: 3,
newEndIndex: 5,
startPosition: { row: 0, column: 0 },
oldEndPosition: { row: 0, column: 3 },
newEndPosition: { row: 0, column: 5 },
});
// Re-parse with the edited tree for incremental parsing
const newTree = parser.parse(newSourceCode, tree);
After calling edit(), you should pass the tree to parser.parse() as the second argument. This allows the parser to reuse parts of the old tree, making parsing much faster.
walk()
Create a new TreeCursor starting from the root of the tree.
Returns: A TreeCursor positioned at the root node
Example:
const tree = parser.parse('let x = 1;');
const cursor = tree.walk();
console.log(cursor.nodeType); // 'program'
if (cursor.gotoFirstChild()) {
console.log(cursor.nodeType); // 'lexical_declaration'
}
Using a cursor is more efficient than recursively accessing nodes via properties, especially for deep traversals.
rootNodeWithOffset(offsetBytes, offsetExtent)
Get the root node with its position shifted forward by the given offset.
rootNodeWithOffset(offsetBytes: number, offsetExtent: Point): Node
Parameters:
offsetBytes - The byte offset to add
offsetExtent - The position offset to add
Returns: A Node representing the root, but with adjusted positions
Example:
const tree = parser.parse('let x = 1;');
// Get root node with positions offset
const offsetRoot = tree.rootNodeWithOffset(100, { row: 10, column: 0 });
console.log(offsetRoot.startIndex); // 100 (instead of 0)
console.log(offsetRoot.startPosition); // { row: 10, column: 0 }
This is useful when parsing embedded languages or when you need to map tree positions to different offsets in a larger document.
getChangedRanges(other)
Compare this edited syntax tree to a new syntax tree representing the same document, returning the ranges whose syntactic structure has changed.
getChangedRanges(other: Tree): Range[]
Parameters:
other - The new tree to compare against
Returns: An array of Range objects representing the changed regions
Example:
const oldCode = 'let x = 1;';
const newCode = 'const x = 1;';
// Parse original
const oldTree = parser.parse(oldCode);
// Edit the tree
oldTree.edit({
startIndex: 0,
oldEndIndex: 3,
newEndIndex: 5,
startPosition: { row: 0, column: 0 },
oldEndPosition: { row: 0, column: 3 },
newEndPosition: { row: 0, column: 5 },
});
// Re-parse
const newTree = parser.parse(newCode, oldTree);
// Get changed ranges
const changes = oldTree.getChangedRanges(newTree);
console.log(changes);
// [{
// startPosition: { row: 0, column: 0 },
// endPosition: { row: 0, column: 5 },
// startIndex: 0,
// endIndex: 5
// }]
For this to work correctly, you must call tree.edit() on the old tree before re-parsing. The ranges returned represent the minimal set of changes needed to update any cached information based on the tree.
getIncludedRanges()
Get the ranges of text that were included when parsing the syntax tree.
getIncludedRanges(): Range[]
Returns: An array of Range objects that were used during parsing
Example:
const ranges = [
{
startIndex: 0,
endIndex: 10,
startPosition: { row: 0, column: 0 },
endPosition: { row: 0, column: 10 },
},
];
const tree = parser.parse(sourceCode, null, { includedRanges: ranges });
const included = tree.getIncludedRanges();
console.log(included); // Same as 'ranges'
Edit Class
The Edit class represents an edit operation and provides helper methods for editing points and ranges.
Constructor
class Edit {
constructor({
startIndex: number,
oldEndIndex: number,
newEndIndex: number,
startPosition: Point,
oldEndPosition: Point,
newEndPosition: Point,
})
}
Properties
startIndex: number; // The start index of the change
oldEndIndex: number; // The end index before the edit
newEndIndex: number; // The end index after the edit
startPosition: Point; // The start position of the change
oldEndPosition: Point; // The end position before the edit
newEndPosition: Point; // The end position after the edit
Methods
editPoint(point, index)
Edit a point and index to keep them in sync with an edit operation.
editPoint(point: Point, index: number): { point: Point; index: number }
Example:
import { Edit } from 'web-tree-sitter';
const edit = new Edit({
startIndex: 0,
oldEndIndex: 3,
newEndIndex: 5,
startPosition: { row: 0, column: 0 },
oldEndPosition: { row: 0, column: 3 },
newEndPosition: { row: 0, column: 5 },
});
const result = edit.editPoint({ row: 0, column: 10 }, 10);
console.log(result);
// { point: { row: 0, column: 12 }, index: 12 }
editRange(range)
Edit a range to keep it in sync with an edit operation.
editRange(range: Range): Range
Example:
const range = {
startIndex: 5,
endIndex: 10,
startPosition: { row: 0, column: 5 },
endPosition: { row: 0, column: 10 },
};
const newRange = edit.editRange(range);
console.log(newRange);
Usage Patterns
Incremental Parsing
The most common use of tree editing is for incremental parsing:
let tree = parser.parse(sourceCode);
// Later, when the code changes
function handleEdit(startIndex, oldEndIndex, newEndIndex, startPos, oldEndPos, newEndPos) {
// 1. Edit the tree
tree.edit({
startIndex,
oldEndIndex,
newEndIndex,
startPosition: startPos,
oldEndPosition: oldEndPos,
newEndPosition: newEndPos,
});
// 2. Re-parse with the old tree
const newTree = parser.parse(newSourceCode, tree);
// 3. Get changed ranges if needed
const changes = tree.getChangedRanges(newTree);
// 4. Update to use the new tree
tree.delete();
tree = newTree;
return changes;
}
Preserving Trees
Use copy() when you need to keep multiple versions:
const history = [];
let tree = parser.parse(sourceCode);
history.push(tree.copy()); // Save a copy
// Make changes...
tree.edit(edit);
tree = parser.parse(newCode, tree);
history.push(tree.copy()); // Save another copy
// Later, compare versions
const changes = history[0].getChangedRanges(history[1]);
See Also