neovim
neovim copied to clipboard
treesitter queries: multiple predicates in alternation cause error
Neovim version (nvim -v)
v0.8.0-dev+126-g95b7851f6 commit 1970d2ac43059639e4e2c83223d86397b38786ff
Vim (not Nvim) behaves the same?
no
Operating system/version
Ubuntu 22.10
Terminal name/version
st 0.8.2
$TERM environment variable
st-256color
Installation
build from repo
How to reproduce the issue
Have a file like this:
<?php
class Foo {
public function __construct() {
}
public function __toString() {
return "foo";
}
}
and invoke the following lua code:
local query = vim.treesitter.query.parse_query(
'php',
[[
[
(
(method_declaration
(visibility_modifier "public")
name: (name) @construct_name)
(#eq? @construct_name "__construct")
) @construct
(
(method_declaration
(visibility_modifier "public")
name: (name) @toString_name)
(#eq? @toString_name "__toString")
) @toString
]
]])
for id, _, _ in query:iter_captures(
vim.treesitter.get_parser(0, 'php'):parse()[1]:root(),
0, -- current buffer
0,
vim.api.nvim_buf_line_count(0)) do
print(vim.inspect(query.captures[id]))
end
Expected behavior
all four captures being print out
"construct"
"construct_name"
"toString"
"toString_name"
Actual behavior
this error message:
E5108: Error executing lua ...r/neovim/share/nvim/runtime/lua/vim/treesitter/query.lua:185: attempt to index local 'node' (a nil value)
stack traceback:
...r/neovim/share/nvim/runtime/lua/vim/treesitter/query.lua:185: in function 'get_node_text'
...r/neovim/share/nvim/runtime/lua/vim/treesitter/query.lua:222: in function 'handler'
...r/neovim/share/nvim/runtime/lua/vim/treesitter/query.lua:422: in function 'match_preds'
...r/neovim/share/nvim/runtime/lua/vim/treesitter/query.lua:508: in function '(for generator)'
[string ":lua"]:20: in function 'test'
[string ":lua"]:1: in main chunk
But removing either of the predicates results in the other one working correctly and no error beeing raised.
We fixed that exact bug before. I wonder what's now different. This get node for the third argument is missing a check https://github.com/neovim/neovim/blob/1e5daed67693f88d3ad515cf9e2d2f6d29c48a08/runtime/lua/vim/treesitter/query.lua#L278but here it seems to get triggered for the first argument where we should have a check https://github.com/neovim/neovim/blob/1e5daed67693f88d3ad515cf9e2d2f6d29c48a08/runtime/lua/vim/treesitter/query.lua#L267 (this check was added when the same problem as described surged the last time)
So what I think to have found out is:
the predicate_handlers['eq?'] function is invoked twice per match; once with each predicate. The first two of which with the following predicate and match values (ignoring active and pattern in match):
{ "eq?", 1, "__construct" } -- predicate of first call
{ "eq?", 3, "__toString" } -- predicate of second call
{ -- match
[3] = <userdata 1>, -- '__construct' method name node
[4] = <userdata 2>, -- '__construct' method node
}
The expression match[predicate[2]] in the very first call references the index 1 which is not set and therefore is the cause of this error.
I cannot judge wether the index given in the predicate or the absence of an node at this index in the match is the problem here.
In all invokations following this the match does contain four nodes, but they do change the indices while the second item of the predicates stay the same. Also the same nodes occure often multiple times in the same match.
I have not been able to figure out exactly how the match table is constructed, but I guess the stacktrace looks something like this:
raw_iter()
node:_rawquery()
lua_pushcclosure()
set_match
Okay I have just found out I had another, older neovim executable in my PATH... With the correct one this works just fine.
I am terribly sorry to have bothered you with such a dumb mistake.