Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[main]: parameter.inner: selected smaller range than expected #700

Open
przepompownia opened this issue Oct 9, 2024 · 4 comments
Open
Labels
bug Something isn't working

Comments

@przepompownia
Copy link
Contributor

przepompownia commented Oct 9, 2024

Sometimes inner parameter selection ignores the current scope and selects the first parameter in the nested scope instead.

To Reproduce
Steps to reproduce the behavior:
init.lua:

local thisInitFile = debug.getinfo(1).source:match('@?(.*)')
local cwd = vim.fs.dirname(thisInitFile)
local appname = vim.env.NVIM_APPNAME or 'nvim'

vim.env.XDG_CONFIG_HOME = cwd
vim.env.XDG_DATA_HOME = vim.fs.joinpath(cwd, '.xdg', 'data')
vim.env.XDG_STATE_HOME = vim.fs.joinpath(cwd, '.xdg', 'state')
vim.env.XDG_CACHE_HOME = vim.fs.joinpath(cwd, '.xdg', 'cache')
vim.fn.mkdir(vim.fs.joinpath(vim.env.XDG_CACHE_HOME, appname), 'p')
local stdPathConfig = vim.fn.stdpath('config')

vim.opt.runtimepath:prepend(stdPathConfig)
vim.opt.packpath:prepend(stdPathConfig)

local function gitClone(url, installPath, branch)
  if vim.fn.isdirectory(installPath) ~= 0 then
    return
  end

  local command = {'git', 'clone', '--', url, installPath}
  if branch then
    table.insert(command, 3, '--branch')
    table.insert(command, 4, branch)
  end

  vim.notify(('Cloning %s dependency into %s...'):format(url, installPath), vim.log.levels.INFO, {})
  local sysObj = vim.system(command, {}):wait()
  if sysObj.code ~= 0 then
    error(sysObj.stderr)
  end
  vim.notify(sysObj.stdout)
  vim.notify(sysObj.stderr, vim.log.levels.WARN)
end

local pluginsPath = vim.fs.joinpath(cwd, 'nvim/pack/plugins/opt')
vim.fn.mkdir(pluginsPath, 'p')
pluginsPath = vim.uv.fs_realpath(pluginsPath)

--- @type table<string, {url:string, branch: string?}>
local plugins = {
  ['nvim-treesitter-textobjects'] = {url = 'https://github.com/nvim-treesitter/nvim-treesitter-textobjects', branch = 'main'},
}

for name, repo in pairs(plugins) do
  local installPath = vim.fs.joinpath(pluginsPath, name)
  gitClone(repo.url, installPath, repo.branch)
  vim.cmd.packadd({args = {name}, bang = true})
end

vim.keymap.set({'x', 'o'}, 'ip', function ()
  require 'nvim-treesitter-textobjects.select'.select_textobject('@parameter.inner', 'textobjects')
end)
vim.go.hlsearch = false

local function foo()
  vim.print(1, tonumber('1'), {'x'})
end

vim.api.nvim_feedkeys(vim.keycode('/tonumber<CR>'), 'n', false)
  1. nvim --clean -u init.lua init.lua
  2. type vip (for me '1' is selected)
  3. escape visual mode, go to space before {x} and type vip again (for me 'x' is selected).

Expected behavior
Selected:

  • tonumber('1') in step 2.
  • {'x'} in step 3.

Output of :checkhealth vim.treesitter

vim.treesitter: require("vim.treesitter.health").check()
  • Nvim runtime ABI version: 14
  • OK Parser: c ABI: 14, path: .../nvim-from-src/lib/nvim/parser/c.so
  • OK Parser: lua ABI: 14, path: .../nvim-from-src/lib/nvim/parser/lua.so
  • OK Parser: markdown ABI: 14, path: .../nvim-from-src/lib/nvim/parser/markdown.so
  • OK Parser: markdown_inline ABI: 14, path: .../nvim-from-src/lib/nvim/parser/markdown_inline.so
  • OK Parser: query ABI: 14, path: .../nvim-from-src/lib/nvim/parser/query.so
  • OK Parser: vim ABI: 14, path: .../nvim-from-src/lib/nvim/parser/vim.so
  • OK Parser: vimdoc ABI: 14, path: .../nvim-from-src/lib/nvim/parser/vimdoc.so
  • Can load WASM parsers: false

Output of nvim --version

v0.11.0-dev-941+gcd8e15e33
@przepompownia przepompownia added the bug Something isn't working label Oct 9, 2024
@Juhan280
Copy link
Contributor

The master branch works as expected.

But when I try your script to reproduce, the command vip gives the following error:

E5108: Error executing lua: ...r-textobjects/lua/nvim-treesitter-textobjects/shared.lua:91: attempt t
o index a nil value
stack traceback:
        ...r-textobjects/lua/nvim-treesitter-textobjects/shared.lua:91: in function 'fn'
        ...r-textobjects/lua/nvim-treesitter-textobjects/shared.lua:39: in function 'get_query_matche
s'
        ...r-textobjects/lua/nvim-treesitter-textobjects/shared.lua:167: in function 'fn'
        ...r/share/nvim/runtime/lua/vim/treesitter/languagetree.lua:491: in function 'for_each_tree'
        ...r-textobjects/lua/nvim-treesitter-textobjects/shared.lua:164: in function 'get_capture_ran
ges_recursively'
        ...r-textobjects/lua/nvim-treesitter-textobjects/shared.lua:359: in function 'textobject_at_p
oint'
        ...r-textobjects/lua/nvim-treesitter-textobjects/select.lua:155: in function 'select_textobje
ct'
        /data/data/com.termux/files/usr/tmp/init.lua:51: in function 
Press ENTER or type command to continue

nvim --version

NVIM v0.10.2
Build type: Release
LuaJIT 2.1.1727870382

@przepompownia
Copy link
Contributor Author

przepompownia commented Oct 14, 2024

@Juhan280 I doubt that the main branch is intended to be compatible with Nvim 0.10.*, although calling iter_matches with {all = true} (default in master on Nvim) allows at least to avoid the error (not checked if it works in general and whether it makes any sense).

@przepompownia
Copy link
Contributor Author

From the :InspectTree perspective the query

(arguments
"," @parameter.outer
.
(_) @parameter.inner @parameter.outer)
looks good:

Image

@przepompownia
Copy link
Contributor Author

local function is_in_range(range, row, col)
local start_row, start_col, end_row, end_col = unpack(range) ---@type integer, integer, integer, integer
end_col = end_col - 1
local is_in_rows = start_row <= row and end_row >= row
local is_after_start_col_if_needed = true
if start_row == row then
is_after_start_col_if_needed = col >= start_col
end
local is_before_end_col_if_needed = true
if end_row == row then
is_before_end_col_if_needed = col <= end_col
end
return is_in_rows and is_after_start_col_if_needed and is_before_end_col_if_needed
end

Image

Having vim.print(1, tonumber('1')) as the only line we get false from is_in_range({0, 11, 0, 26}, 0, 26).

I tried

diff --git a/lua/nvim-treesitter-textobjects/shared.lua b/lua/nvim-treesitter-textobjects/shared.lua
index 69a804c..69bd750 100644
--- a/lua/nvim-treesitter-textobjects/shared.lua
+++ b/lua/nvim-treesitter-textobjects/shared.lua
@@ -236,7 +236,7 @@ local function is_in_range(range, row, col)
   end
   local is_before_end_col_if_needed = true
   if end_row == row then
-    is_before_end_col_if_needed = col <= end_col
+    is_before_end_col_if_needed = col - 1 <= end_col
   end
   return is_in_rows and is_after_start_col_if_needed and is_before_end_col_if_needed
 end

but it breaks selection when the cursor is on the closing brace in vim.keymap.set({'x', 'o'}, 'ip', function () end) (I haven't check yet how matched ranges look in that case).

@przepompownia przepompownia changed the title [main]: incorrect inner parameter selection [main]: parameter.inner: selected smaller range than expected Oct 14, 2024
przepompownia added a commit to przepompownia/nvim-treesitter-textobjects that referenced this issue Oct 15, 2024
The logic of including a point in a range needs `-1` end_col offset
only if the point is from the cursor position
but not from the end of another range.

Fixes nvim-treesitter#700
przepompownia added a commit to przepompownia/nvim-treesitter-textobjects that referenced this issue Oct 15, 2024
The logic of including a point in a range needs `-1` end_col offset
only if the point is from the cursor position
but not from the end of another range.

Fixes nvim-treesitter#700
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants