neovim icon indicating copy to clipboard operation
neovim copied to clipboard

treesitter queries: multiple predicates in alternation cause error

Open DrWursterich opened this issue 3 years ago • 1 comments
trafficstars

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.

DrWursterich avatar Sep 13 '22 16:09 DrWursterich

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)

theHamsta avatar Sep 13 '22 23:09 theHamsta

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

DrWursterich avatar Sep 14 '22 22:09 DrWursterich

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.

DrWursterich avatar Sep 16 '22 10:09 DrWursterich