From f6da44fdbb87dc3960a5326f727bf5886dfec7fb Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 6 Sep 2016 21:33:19 -0700 Subject: [PATCH] Add ts_node_descendant_for_byte_range --- include/tree_sitter/runtime.h | 2 ++ spec/runtime/node_spec.cc | 20 ++++++++++++++++++-- src/runtime/node.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/include/tree_sitter/runtime.h b/include/tree_sitter/runtime.h index 3fed02ce..1b2c90b6 100644 --- a/include/tree_sitter/runtime.h +++ b/include/tree_sitter/runtime.h @@ -81,6 +81,8 @@ TSNode ts_node_prev_sibling(TSNode); TSNode ts_node_prev_named_sibling(TSNode); TSNode ts_node_descendant_for_char_range(TSNode, size_t, size_t); TSNode ts_node_named_descendant_for_char_range(TSNode, size_t, size_t); +TSNode ts_node_descendant_for_byte_range(TSNode, size_t, size_t); +TSNode ts_node_named_descendant_for_byte_range(TSNode, size_t, size_t); TSNode ts_node_descendant_for_point_range(TSNode, TSPoint, TSPoint); TSNode ts_node_named_descendant_for_point_range(TSNode, TSPoint, TSPoint); diff --git a/spec/runtime/node_spec.cc b/spec/runtime/node_spec.cc index 9c7e0e39..33754c2d 100644 --- a/spec/runtime/node_spec.cc +++ b/spec/runtime/node_spec.cc @@ -392,7 +392,7 @@ describe("Node", []() { }); describe("descendant_for_char_range(start, end)", [&]() { - it("returns the smallest concrete node that spans the given range", [&]() { + it("returns the smallest node that spans the given range", [&]() { TSNode node1 = ts_node_descendant_for_char_range(array_node, colon_index, colon_index); AssertThat(ts_node_name(node1, document), Equals(":")); AssertThat(ts_node_start_byte(node1), Equals(colon_index)); @@ -409,7 +409,23 @@ describe("Node", []() { }); }); - describe("named_descendant_for_point_range(start, end)", [&]() { + describe("descendant_for_byte_range(start, end)", [&]() { + it("returns the smallest concrete node that spans the given range", [&]() { + ts_document_set_input_string(document, "[\"αβγδ\", \"αβγδ\"]"); + ts_document_parse(document); + TSNode array_node = ts_document_root_node(document); + + TSNode node1 = ts_node_descendant_for_char_range(array_node, 7, 7); + AssertThat(ts_node_name(node1, document), Equals(",")); + + TSNode node2 = ts_node_descendant_for_byte_range(array_node, 6, 10); + AssertThat(ts_node_name(node2, document), Equals("string")); + AssertThat(ts_node_start_byte(node2), Equals(1)); + AssertThat(ts_node_end_byte(node2), Equals(11)); + }); + }); + + describe("descendant_for_point_range(start, end)", [&]() { it("returns the smallest concrete node that spans the given range", [&]() { TSNode node1 = ts_node_descendant_for_point_range(array_node, {6, 7}, {6, 7}); AssertThat(ts_node_name(node1, document), Equals(":")); diff --git a/src/runtime/node.c b/src/runtime/node.c index 5fed59dd..e28a646b 100644 --- a/src/runtime/node.c +++ b/src/runtime/node.c @@ -169,6 +169,33 @@ static inline TSNode ts_node__descendant_for_char_range(TSNode self, size_t min, return last_visible_node; } +static inline TSNode ts_node__descendant_for_byte_range(TSNode self, size_t min, + size_t max, + bool include_anonymous) { + TSNode node = self; + TSNode last_visible_node = self; + + bool did_descend = true; + while (did_descend) { + did_descend = false; + + for (size_t i = 0; i < ts_node__tree(node)->child_count; i++) { + TSNode child = ts_node__direct_child(node, i); + if (ts_node_start_byte(child) > min) + break; + if (ts_node_end_byte(child) > max) { + node = child; + if (ts_node__is_relevant(node, include_anonymous)) + last_visible_node = node; + did_descend = true; + break; + } + } + } + + return last_visible_node; +} + static inline TSNode ts_node__descendant_for_point_range(TSNode self, TSPoint min, TSPoint max, @@ -330,6 +357,14 @@ TSNode ts_node_named_descendant_for_char_range(TSNode self, size_t min, size_t m return ts_node__descendant_for_char_range(self, min, max, false); } +TSNode ts_node_descendant_for_byte_range(TSNode self, size_t min, size_t max) { + return ts_node__descendant_for_byte_range(self, min, max, true); +} + +TSNode ts_node_named_descendant_for_byte_range(TSNode self, size_t min, size_t max) { + return ts_node__descendant_for_byte_range(self, min, max, false); +} + TSNode ts_node_descendant_for_point_range(TSNode self, TSPoint min, TSPoint max) { return ts_node__descendant_for_point_range(self, min, max, true); }