diff options
author | vanaigr <vanaigranov@gmail.com> | 2024-05-16 09:57:58 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-16 16:57:58 +0200 |
commit | 4b029163345333a2c6975cd0dace6613b036ae47 (patch) | |
tree | ef4b6f914f6415d019e0a6fb64f1e8fd355aa5bc /runtime/lua/vim/treesitter/query.lua | |
parent | 31dc6279693886a628119cd6c779e580faab32fd (diff) | |
download | rneovim-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 'runtime/lua/vim/treesitter/query.lua')
-rw-r--r-- | runtime/lua/vim/treesitter/query.lua | 13 |
1 files changed, 2 insertions, 11 deletions
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 36c78b7f1d..ef5c2143a7 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -457,17 +457,8 @@ local predicate_handlers = { end for _, node in ipairs(nodes) do - local ancestor_types = {} --- @type table<string, boolean> - for _, type in ipairs({ unpack(predicate, 3) }) do - ancestor_types[type] = true - end - - local cur = node:parent() - while cur do - if ancestor_types[cur:type()] then - return true - end - cur = cur:parent() + if node:__has_ancestor(predicate) then + return true end end return false |