Incremental โ
What you'll learn โ
- Editor-style update: describe an edit, reparse, and diff the trees.
Complete example โ
examples/incremental_parse.zig:
zig
var old_tree = try parser.parseString("1 + 2");
defer old_tree.deinit();
const edit = treesitter.InputEdit{
.start_byte = 4,
.old_end_byte = 5,
.new_end_byte = 6,
.start_point = .{ .row = 0, .column = 4 },
.old_end_point = .{ .row = 0, .column = 5 },
.new_end_point = .{ .row = 0, .column = 6 },
};
var new_tree = try parser.parse(&old_tree, edit, "1 + 22");
defer new_tree.deinit();
const ranges = try old_tree.getChangedRanges(&new_tree);
defer old_tree.freeChangedRanges(ranges);
for (ranges) |r| {
std.debug.print("changed: bytes [{d}, {d}]\n", .{ r.start_byte, r.end_byte });
}Running the example โ
sh
zig build run-incremental_parseExpected output โ
text
before: 1 + 2
after: 1 + 22
changed: bytes [4, 6]Input โ
Original source 1 + 2.
Edit โ
Insert one byte at offset 4 (2 โ 22): start 4, old end 5, new end 6, same row, columns adjusted.
Result โ
New tree for 1 + 22 with only bytes [4, 6] reported changed. The untouched 1 + prefix reuses old subtrees (parser.reused_node_count > 0).
API used โ
Memory ownership โ
Both trees coexist; the old tree is only read during reuse. Each deinit frees its own pool.
Performance considerations โ
Trailing edits reuse large subtrees in single clones; leading-edge edits re-examine more. See Performance.
