diff --git a/spec/integration/corpus_specs.cc b/spec/integration/corpus_specs.cc index 3653809d..ec01574f 100644 --- a/spec/integration/corpus_specs.cc +++ b/spec/integration/corpus_specs.cc @@ -29,8 +29,8 @@ static void expect_a_consistent_tree(TSNode node, TSDocument *document) { AssertThat(start_char, !IsGreaterThan(end_char)); AssertThat(start_point, !IsGreaterThan(end_point)); - size_t last_child_end_char = 0; - TSPoint last_child_end_point = {0, 0}; + size_t last_child_end_char = start_char; + TSPoint last_child_end_point = start_point; for (size_t i = 0; i < child_count; i++) { TSNode child = ts_node_child(node, i); @@ -39,17 +39,10 @@ static void expect_a_consistent_tree(TSNode node, TSDocument *document) { TSPoint child_start_point = ts_node_start_point(child); TSPoint child_end_point = ts_node_end_point(child); - if (i > 0) { - AssertThat(child_start_char, !IsLessThan(last_child_end_char)); - AssertThat(child_start_point, !IsLessThan(last_child_end_point)); - last_child_end_char = child_end_char; - last_child_end_point = child_end_point; - } - - AssertThat(child_start_char, !IsLessThan(start_char)); - AssertThat(child_end_char, !IsGreaterThan(end_char)); - AssertThat(child_start_point, !IsLessThan(start_point)); - AssertThat(child_end_point, !IsGreaterThan(end_point)); + AssertThat(child_start_char, !IsLessThan(last_child_end_char)); + AssertThat(child_start_point, !IsLessThan(last_child_end_point)); + last_child_end_char = child_end_char; + last_child_end_point = child_end_point; expect_a_consistent_tree(child, document); @@ -57,8 +50,14 @@ static void expect_a_consistent_tree(TSNode node, TSDocument *document) { some_child_has_changes = true; } - if (child_count > 0) + if (child_count > 0) { + AssertThat(end_char, !IsLessThan(last_child_end_char)); + + if (!has_changes) + AssertThat(end_point, !IsLessThan(last_child_end_point)); + AssertThat(has_changes, Equals(some_child_has_changes)); + } } START_TEST diff --git a/spec/runtime/tree_spec.cc b/spec/runtime/tree_spec.cc index 6420a206..08e3cb7d 100644 --- a/spec/runtime/tree_spec.cc +++ b/spec/runtime/tree_spec.cc @@ -3,6 +3,22 @@ #include "runtime/tree.h" #include "runtime/length.h" +void assert_consistent(const TSTree *tree) { + if (tree->child_count == 0) + return; + AssertThat(tree->children[0]->padding, Equals(tree->padding)); + + TSLength total_children_size = ts_length_zero(); + for (size_t i = 0; i < tree->child_count; i++) { + TSTree *child = tree->children[i]; + AssertThat(child->context.offset, Equals(total_children_size)); + assert_consistent(child); + total_children_size = ts_length_add(total_children_size, ts_tree_total_size(child)); + } + + AssertThat(total_children_size, Equals(ts_tree_total_size(tree))); +}; + START_TEST enum { @@ -163,14 +179,6 @@ describe("Tree", []() { ts_tree_release(tree); }); - auto assert_consistent = [&](const TSTree *tree) { - AssertThat(tree->children[0]->padding, Equals(tree->padding)); - - TSLength total_children_size = ts_length_zero(); - for (size_t i = 0; i < tree->child_count; i++) - total_children_size = ts_length_add(total_children_size, ts_tree_total_size(tree->children[i])); - AssertThat(total_children_size, Equals(ts_tree_total_size(tree))); - }; describe("edits within a tree's padding", [&]() { it("resizes the padding of the tree and its leftmost descendants", [&]() { diff --git a/src/runtime/tree.c b/src/runtime/tree.c index 777649e3..73747ab2 100644 --- a/src/runtime/tree.c +++ b/src/runtime/tree.c @@ -335,37 +335,38 @@ void ts_tree_edit(TSTree *self, TSInputEdit edit) { bool found_first_child = false; long remainder_to_delete = edit.chars_removed - edit.chars_inserted; - size_t child_left = 0, child_right = 0; + TSLength child_left, child_right = ts_length_zero(); for (size_t i = 0; i < self->child_count; i++) { TSTree *child = self->children[i]; - size_t child_size = ts_tree_total_chars(child); child_left = child_right; - child_right += child_size; if (!found_first_child) { - if (child_right >= start) { + child_right = ts_length_add(child_left, ts_tree_total_size(child)); + if (child_right.chars >= start) { found_first_child = true; - size_t chars_removed = min(edit.chars_removed, child_right - start); + size_t chars_removed = min(edit.chars_removed, child_right.chars - start); remainder_to_delete -= (chars_removed - edit.chars_inserted); ts_tree_edit(child, (TSInputEdit){ - .position = start - child_left, + .position = start - child_left.chars, .chars_inserted = edit.chars_inserted, .chars_removed = chars_removed, }); + child_right = ts_length_add(child_left, ts_tree_total_size(child)); } } else { if (remainder_to_delete > 0) { - size_t chars_removed = min(remainder_to_delete, child_size); + size_t chars_removed = min(remainder_to_delete, ts_tree_total_chars(child)); remainder_to_delete -= chars_removed; ts_tree_edit( child, (TSInputEdit){ .position = 0, .chars_inserted = 0, .chars_removed = chars_removed, }); - } else { - break; } + child_right = ts_length_add(child_right, ts_tree_total_size(child)); } + + child->context.offset = child_left; } }