From cef6827182d17f2a13649689403ce7a6fb8922a9 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 25 Aug 2014 09:31:27 -0700 Subject: [PATCH] Add find_for_range function for Nodes --- include/tree_sitter/runtime.h | 3 +- spec/runtime/node_spec.cc | 55 +++++++++++++++++++++++++---------- src/runtime/node.c | 12 +++++--- 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/include/tree_sitter/runtime.h b/include/tree_sitter/runtime.h index fb2ee50c..6a3d5a36 100644 --- a/include/tree_sitter/runtime.h +++ b/include/tree_sitter/runtime.h @@ -29,7 +29,8 @@ size_t ts_node_size(const TSNode *); TSSymbol ts_node_sym(const TSNode *); TSNode *ts_node_child(TSNode *, size_t); size_t ts_node_child_count(const TSNode *); -TSNode *ts_node_find_pos(TSNode *, size_t); +TSNode *ts_node_find_for_pos(TSNode *, size_t); +TSNode *ts_node_find_for_range(TSNode *, size_t, size_t); TSNode *ts_node_parent(TSNode *node); TSNode *ts_node_next_sibling(TSNode *node); TSNode *ts_node_prev_sibling(TSNode *node); diff --git a/spec/runtime/node_spec.cc b/spec/runtime/node_spec.cc index 2f816c30..24f389a6 100644 --- a/spec/runtime/node_spec.cc +++ b/spec/runtime/node_spec.cc @@ -92,26 +92,49 @@ describe("Node", []() { }); }); - describe("find_pos", [&]() { - it("can retrieve the leaf node at a given position", [&]() { - TSNode *number1 = ts_node_find_pos(root, 3); - TSNode *number2 = ts_node_find_pos(root, 7); - - AssertThat(ts_node_name(number1), Equals("number")); - AssertThat(ts_node_size(number1), Equals(2)); - - AssertThat(ts_node_name(number2), Equals("number")); - AssertThat(ts_node_size(number2), Equals(1)); - - ts_node_release(number1); - ts_node_release(number2); + describe("find_for_range", [&]() { + describe("when there is a leaf node that spans the given range exactly", [&]() { + it("returns that leaf node", [&]() { + TSNode *number = ts_node_find_for_range(root, 10, 12); + AssertThat(ts_node_name(number), Equals("number")); + AssertThat(ts_node_size(number), Equals(3)); + AssertThat(ts_node_pos(number), Equals(10)); + ts_node_release(number); + }); }); - it("returns higher-level nodes when no leaf is at the given position", [&]() { - TSNode *node = ts_node_find_pos(root, 6); + describe("when there is a leaf node that extends beyond the given range", [&]() { + it("returns that leaf node", [&]() { + TSNode *number = ts_node_find_for_range(root, 10, 11); + AssertThat(ts_node_name(number), Equals("number")); + AssertThat(ts_node_size(number), Equals(3)); + AssertThat(ts_node_pos(number), Equals(10)); + ts_node_release(number); + number = ts_node_find_for_range(root, 11, 12); + AssertThat(ts_node_name(number), Equals("number")); + AssertThat(ts_node_size(number), Equals(3)); + AssertThat(ts_node_pos(number), Equals(10)); + ts_node_release(number); + }); + }); + + describe("when there is no leaf node that spans the given range", [&]() { + it("returns the smallest node that does span the range", [&]() { + TSNode *node = ts_node_find_for_range(root, 6, 7); + AssertThat(ts_node_name(node), Equals("array")); + AssertThat(ts_node_pos(node), Equals(2)); + AssertThat(ts_node_size(node), Equals(12)); + ts_node_release(node); + }); + }); + }); + + describe("find_for_pos", [&]() { + it("finds the smallest node that spans the given position", [&]() { + TSNode *node = ts_node_find_for_pos(root, 6); AssertThat(ts_node_name(node), Equals("array")); - + AssertThat(ts_node_pos(node), Equals(2)); ts_node_release(node); }); }); diff --git a/src/runtime/node.c b/src/runtime/node.c index ea67a032..b6b94117 100644 --- a/src/runtime/node.c +++ b/src/runtime/node.c @@ -77,19 +77,19 @@ TSNode *ts_node_child(TSNode *parent, size_t index) { parent->names); } -TSNode *ts_node_find_pos(TSNode *parent, size_t position) { +TSNode *ts_node_find_for_range(TSNode *parent, size_t min, size_t max) { size_t child_count; TSChildWithPosition *children = ts_tree_visible_children(parent->content, &child_count); for (size_t i = 0; i < child_count; i++) { TSChildWithPosition child = children[i]; size_t child_left = child.position + child.tree->offset; - if (child_left > position) + if (child_left > min) break; - if (child_left + child.tree->size > position) { + if (child_left + child.tree->size >= max) { TSNode *node = ts_node_make(child.tree, parent, i, child.position, parent->names); - TSNode *result = ts_node_find_pos(node, position); + TSNode *result = ts_node_find_for_range(node, min, max); ts_node_release(node); return result; } @@ -98,3 +98,7 @@ TSNode *ts_node_find_pos(TSNode *parent, size_t position) { ts_node_retain(parent); return parent; } + +TSNode *ts_node_find_for_pos(TSNode *parent, size_t position) { + return ts_node_find_for_range(parent, position, position); +}