From 315dff328518f5003bbbfcf6934e3edcb26e7be4 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 9 Jan 2018 12:33:51 -0800 Subject: [PATCH] Add an API for getting a node's child index --- include/tree_sitter/runtime.h | 1 + src/runtime/node.c | 19 +++++++++++++++++++ test/runtime/node_test.cc | 12 ++++++++++++ 3 files changed, 32 insertions(+) diff --git a/include/tree_sitter/runtime.h b/include/tree_sitter/runtime.h index 9f51b549..c4dde4fe 100644 --- a/include/tree_sitter/runtime.h +++ b/include/tree_sitter/runtime.h @@ -92,6 +92,7 @@ TSNode ts_node_child(TSNode, uint32_t); TSNode ts_node_named_child(TSNode, uint32_t); uint32_t ts_node_child_count(TSNode); uint32_t ts_node_named_child_count(TSNode); +uint32_t ts_node_child_index(TSNode); TSNode ts_node_next_sibling(TSNode); TSNode ts_node_next_named_sibling(TSNode); TSNode ts_node_prev_sibling(TSNode); diff --git a/src/runtime/node.c b/src/runtime/node.c index cec988cf..e4353e5b 100644 --- a/src/runtime/node.c +++ b/src/runtime/node.c @@ -329,6 +329,25 @@ TSNode ts_node_parent(TSNode self) { return result; } +uint32_t ts_node_child_index(TSNode self) { + const Tree *tree = ts_node__tree(self); + uint32_t result = 0; + + for (;;) { + const Tree *parent = tree->context.parent; + uint32_t index = tree->context.index; + if (!parent) return UINT32_MAX; + for (uint32_t i = 0; i < index; i++) { + Tree *child = parent->children[i]; + result += child->visible ? 1 : child->visible_child_count; + } + if (parent->visible) break; + tree = parent; + } + + return result; +} + TSNode ts_node_child(TSNode self, uint32_t child_index) { return ts_node__child(self, child_index, true); } diff --git a/test/runtime/node_test.cc b/test/runtime/node_test.cc index fcc7552d..bb620244 100644 --- a/test/runtime/node_test.cc +++ b/test/runtime/node_test.cc @@ -243,6 +243,18 @@ describe("Node", [&]() { }); }); + describe("child_index()", [&]() { + it("returns the index of the node within its parent", [&]() { + AssertThat(ts_node_child_index(ts_node_child(root_node, 0)), Equals(0u)); + AssertThat(ts_node_child_index(ts_node_child(root_node, 1)), Equals(1u)); + AssertThat(ts_node_child_index(ts_node_child(root_node, 2)), Equals(2u)); + AssertThat(ts_node_child_index(ts_node_child(root_node, 3)), Equals(3u)); + AssertThat(ts_node_child_index(ts_node_child(root_node, 4)), Equals(4u)); + AssertThat(ts_node_child_index(ts_node_child(root_node, 5)), Equals(5u)); + AssertThat(ts_node_child_index(ts_node_child(root_node, 6)), Equals(6u)); + }); + }); + describe("symbols()", [&]() { it("returns an iterator that yields each of the node's symbols", [&]() { const TSLanguage *language = ts_document_language(document);