diff --git a/spec/runtime/language_specs.cc b/spec/runtime/language_specs.cc index ce3a368a..81bd54fa 100644 --- a/spec/runtime/language_specs.cc +++ b/spec/runtime/language_specs.cc @@ -1,5 +1,6 @@ #include "runtime/runtime_spec_helper.h" #include +#include "runtime/length.h" #include "runtime/helpers/read_test_entries.h" #include "runtime/helpers/spy_input.h" #include "runtime/helpers/log_debugger.h" @@ -11,6 +12,35 @@ extern "C" const TSLanguage *ts_language_golang(); extern "C" const TSLanguage *ts_language_c(); extern "C" const TSLanguage *ts_language_cpp(); +void expect_the_correct_tree(TSNode node, TSDocument *doc, string tree_string) { + const char *node_string = ts_node_string(node, doc); + AssertThat(node_string, Equals(tree_string)); + free((void *)node_string); +} + +void expect_a_consistent_tree(TSNode node, TSDocument *doc) { + TSLength start = ts_node_pos(node); + TSLength end = ts_length_add(start, ts_node_size(node)); + size_t child_count = ts_node_child_count(node); + + bool has_changes = ts_node_has_changes(node); + bool some_child_has_changes = false; + + for (size_t i = 0; i < child_count; i++) { + TSNode child = ts_node_child(node, i); + TSLength child_start = ts_node_pos(child); + TSLength child_end = ts_length_add(child_start, ts_node_size(child)); + + AssertThat(child_start.chars, IsGreaterThan(start.chars) || Equals(start.chars)); + AssertThat(child_end.chars, IsLessThan(end.chars) || Equals(end.chars)); + if (ts_node_has_changes(child)) + some_child_has_changes = true; + } + + if (child_count > 0) + AssertThat(has_changes, Equals(some_child_has_changes)); +} + START_TEST map languages({ @@ -43,18 +73,14 @@ describe("Languages", [&]() { for (auto &entry : test_entries_for_language(pair.first)) { SpyInput *input; - auto expect_the_correct_tree = [&](string tree_string) { - const char *node_string = ts_node_string(ts_document_root_node(doc), doc); - AssertThat(node_string, Equals(tree_string)); - free((void *)node_string); - }; - auto it_handles_edit_sequence = [&](string name, std::function edit_sequence){ it(("parses " + entry.description + ": " + name).c_str(), [&]() { input = new SpyInput(entry.input, 3); ts_document_set_input(doc, input->input()); edit_sequence(); - expect_the_correct_tree(entry.tree_string); + TSNode root_node = ts_document_root_node(doc); + expect_the_correct_tree(root_node, doc, entry.tree_string); + expect_a_consistent_tree(root_node, doc); delete input; }); }; diff --git a/src/runtime/tree.c b/src/runtime/tree.c index 40350477..e7894303 100644 --- a/src/runtime/tree.c +++ b/src/runtime/tree.c @@ -40,6 +40,7 @@ static void ts_tree__set_children(TSTree *self, TSTree **children, size_t child_count) { self->children = children; self->child_count = child_count; + self->visible_child_count = 0; for (size_t i = 0; i < child_count; i++) { TSTree *child = children[i]; ts_tree_retain(child);