From 2435d72283ca20a013567fbc867b31b131dc9f74 Mon Sep 17 00:00:00 2001 From: "Au." Date: Thu, 17 Apr 2025 22:46:18 +0800 Subject: [PATCH] fix(lsp): opts.reuse_win does not jump if buf is already open #33476 Problem: `vim.lsp.buf.[implementation|definition|...]({ reuse_win = true })` does not jump cursor to existing window if buffer is already open. Steps to reproduce: 1. `nvim repro.lua` 2. Insert anything that lsp can read to open the library definition/implementation, e.g., `vim.keymap.set` 3. open `repro.lua` buffer and the library buffer side by side. 4. type `gd` over `set` to jump to the library definition. The open buffer is scrolled to the target line, but cursor does not jump. Solution: Call nvim_set_current_win if necessary. (cherry picked from commit 6926fc1615c94a0172b455e64d025c5851485831) --- runtime/lua/vim/lsp/buf.lua | 8 +++++++- test/functional/plugin/lsp_spec.lua | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index bd78f1ad50..3fc567b694 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -215,7 +215,13 @@ local function get_locations(method, opts) vim.fn.settagstack(vim.fn.win_getid(win), { items = tagstack }, 't') vim.bo[b].buflisted = true - local w = opts.reuse_win and vim.fn.win_findbuf(b)[1] or win + local w = win + if opts.reuse_win then + w = vim.fn.win_findbuf(b)[1] or w + if w ~= win then + api.nvim_set_current_win(w) + end + end api.nvim_win_set_buf(w, b) api.nvim_win_set_cursor(w, { item.lnum, item.col - 1 }) vim._with({ win = w }, function() diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 2275831966..1ee145f920 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -5230,7 +5230,7 @@ describe('LSP', function() end) describe('lsp.buf.definition', function() - it('jumps to single location', function() + it('jumps to single location and can reuse win', function() exec_lua(create_server_definition) local result = exec_lua(function() local bufnr = vim.api.nvim_get_current_buf() @@ -5256,8 +5256,10 @@ describe('LSP', function() vim.api.nvim_win_set_cursor(win, { 3, 6 }) local client_id = assert(vim.lsp.start({ name = 'dummy', cmd = server.cmd })) vim.lsp.buf.definition() - vim.lsp.stop_client(client_id) return { + win = win, + bufnr = bufnr, + client_id = client_id, cursor = vim.api.nvim_win_get_cursor(win), messages = server.messages, tagstack = vim.fn.gettagstack(win), @@ -5269,6 +5271,15 @@ describe('LSP', function() eq('x', result.tagstack.items[1].tagname) eq(3, result.tagstack.items[1].from[2]) eq(7, result.tagstack.items[1].from[3]) + + n.feed(':vnew') + api.nvim_win_set_buf(0, result.bufnr) + api.nvim_win_set_cursor(0, { 3, 6 }) + n.feed(':=vim.lsp.buf.definition({ reuse_win = true })') + eq(result.win, api.nvim_get_current_win()) + exec_lua(function() + vim.lsp.stop_client(result.client_id) + end) end) it('merges results from multiple servers', function() exec_lua(create_server_definition)