aboutsummaryrefslogtreecommitdiff
path: root/test/functional/treesitter/node_spec.lua
diff options
context:
space:
mode:
authorvanaigr <vanaigranov@gmail.com>2024-05-16 09:57:58 -0500
committerGitHub <noreply@github.com>2024-05-16 16:57:58 +0200
commit4b029163345333a2c6975cd0dace6613b036ae47 (patch)
treeef4b6f914f6415d019e0a6fb64f1e8fd355aa5bc /test/functional/treesitter/node_spec.lua
parent31dc6279693886a628119cd6c779e580faab32fd (diff)
downloadrneovim-4b029163345333a2c6975cd0dace6613b036ae47.tar.gz
rneovim-4b029163345333a2c6975cd0dace6613b036ae47.tar.bz2
rneovim-4b029163345333a2c6975cd0dace6613b036ae47.zip
perf(treesitter): use child_containing_descendant() in has-ancestor? (#28512)
Problem: `has-ancestor?` is O(n²) for the depth of the tree since it iterates over each of the node's ancestors (bottom-up), and each ancestor takes O(n) time. This happens because tree-sitter's nodes don't store their parent nodes, and the tree is searched (top-down) each time a new parent is requested. Solution: Make use of new `ts_node_child_containing_descendant()` in tree-sitter v0.22.6 (which is now the minimum required version) to rewrite the `has-ancestor?` predicate in C to become O(n). For a sample file, decreases the time taken by `has-ancestor?` from 360ms to 6ms.
Diffstat (limited to 'test/functional/treesitter/node_spec.lua')
-rw-r--r--test/functional/treesitter/node_spec.lua26
1 files changed, 26 insertions, 0 deletions
diff --git a/test/functional/treesitter/node_spec.lua b/test/functional/treesitter/node_spec.lua
index 8adec82774..96579f296b 100644
--- a/test/functional/treesitter/node_spec.lua
+++ b/test/functional/treesitter/node_spec.lua
@@ -143,4 +143,30 @@ describe('treesitter node API', function()
eq(28, lua_eval('root:byte_length()'))
eq(3, lua_eval('child:byte_length()'))
end)
+
+ it('child_containing_descendant() works', function()
+ insert([[
+ int main() {
+ int x = 3;
+ }]])
+
+ exec_lua([[
+ tree = vim.treesitter.get_parser(0, "c"):parse()[1]
+ root = tree:root()
+ main = root:child(0)
+ body = main:child(2)
+ statement = body:child(1)
+ declarator = statement:child(1)
+ value = declarator:child(1)
+ ]])
+
+ eq(lua_eval('main:type()'), lua_eval('root:child_containing_descendant(value):type()'))
+ eq(lua_eval('body:type()'), lua_eval('main:child_containing_descendant(value):type()'))
+ eq(lua_eval('statement:type()'), lua_eval('body:child_containing_descendant(value):type()'))
+ eq(
+ lua_eval('declarator:type()'),
+ lua_eval('statement:child_containing_descendant(value):type()')
+ )
+ eq(vim.NIL, lua_eval('declarator:child_containing_descendant(value)'))
+ end)
end)