mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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.
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user