fix(treesitter): #has-parent? errors on a node with no parent

Problem:
The #has-parent? predicate indexes the result of node:parent() without
checking it, so a capture that matches a tree's root node raises

    query.lua:600: attempt to index a nil value

instead of simply not matching. In a highlights query that breaks
highlighting for the whole buffer. The sibling #has-ancestor? predicate
handles the same situation.

Solution:
Treat a missing parent as "does not match".

AI-assisted
This commit is contained in:
Volodymyr Chernetskyi
2026-09-04 18:20:15 +02:00
committed by Christian Clason
parent e8a0b400d8
commit 2f5df7add7
2 changed files with 22 additions and 1 deletions

View File

@@ -597,7 +597,8 @@ local predicate_handlers = {
end
for _, node in ipairs(nodes) do
if vim.list_contains({ unpack(predicate, 3) }, node:parent():type()) then
local parent = node:parent()
if parent and vim.list_contains({ unpack(predicate, 3) }, parent:type()) then
return true
end
end

View File

@@ -452,6 +452,26 @@ void ui_refresh(void)
eq({}, result)
end)
it('supports builtin predicate has-parent?', function()
insert([[
int x = 123;
enum C { y = 124 };]])
local result = exec_lua(
get_query_result,
[[((number_literal) @literal (#has-parent? @literal "init_declarator"))]]
)
eq({ { 'literal', 'number_literal', { 0, 8, 0, 11 }, '123' } }, result)
-- The root node has no parent: the predicate does not match, rather than
-- erroring on the nil parent.
result = exec_lua(
get_query_result,
[[((translation_unit) @root (#has-parent? @root "translation_unit"))]]
)
eq({}, result)
end)
it('allows loading query with escaped quotes and capture them `#{lua,vim}-match`?', function()
insert('char* astring = "Hello World!";')