diff options
author | Mathias Fußenegger <mfussenegger@users.noreply.github.com> | 2021-11-14 12:55:16 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-14 12:55:16 +0100 |
commit | ee3a58d42e7fce666eef570db6f2944c29303d98 (patch) | |
tree | 9421bec34f8700525c77f1a931643583b5d6aa7f | |
parent | 2ef9d2a663db35c73b93606dbe882ca697072cc3 (diff) | |
download | rneovim-ee3a58d42e7fce666eef570db6f2944c29303d98.tar.gz rneovim-ee3a58d42e7fce666eef570db6f2944c29303d98.tar.bz2 rneovim-ee3a58d42e7fce666eef570db6f2944c29303d98.zip |
fix(lsp): ensure buffers are re-attached on rename (#16266)
If a LSP server sent a workspace edit containing a rename the buffers
file name changed without the server receiving a close notification for
the old buffer and without the client properly re-attaching on the new
file.
This affected `Move` code-actions in nvim-jdtls, but also
`vim.lsp.buf.rename` on a class level.
-rw-r--r-- | runtime/lua/vim/lsp.lua | 6 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 21 | ||||
-rw-r--r-- | test/functional/plugin/lsp_spec.lua | 1 |
3 files changed, 22 insertions, 6 deletions
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 7fa70af779..0fc0a7a7aa 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -472,7 +472,11 @@ local function text_document_did_open_handler(bufnr, client) -- Next chance we get, we should re-do the diagnostics vim.schedule(function() - vim.lsp.diagnostic.redraw(bufnr, client.id) + -- Protect against a race where the buffer disappears + -- between `did_open_handler` and the scheduled function firing. + if vim.api.nvim_buf_is_valid(bufnr) then + vim.lsp.diagnostic.redraw(bufnr, client.id) + end end) end diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 27210dc385..a4b7b9922b 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -549,18 +549,29 @@ end -- ignoreIfExists? bool function M.rename(old_fname, new_fname, opts) opts = opts or {} - local bufnr = vim.fn.bufadd(old_fname) - vim.fn.bufload(bufnr) local target_exists = vim.loop.fs_stat(new_fname) ~= nil if target_exists and not opts.overwrite or opts.ignoreIfExists then vim.notify('Rename target already exists. Skipping rename.') return end + local oldbuf = vim.fn.bufadd(old_fname) + vim.fn.bufload(oldbuf) + + -- The there may be pending changes in the buffer + api.nvim_buf_call(oldbuf, function() + vim.cmd('w!') + end) + local ok, err = os.rename(old_fname, new_fname) assert(ok, err) - api.nvim_buf_call(bufnr, function() - vim.cmd('saveas! ' .. vim.fn.fnameescape(new_fname)) - end) + + local newbuf = vim.fn.bufadd(new_fname) + for _, win in pairs(api.nvim_list_wins()) do + if api.nvim_win_get_buf(win) == oldbuf then + api.nvim_win_set_buf(win, newbuf) + end + end + api.nvim_buf_delete(oldbuf, { force = true }) end diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index ae7612ab08..228fc06e9b 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -1735,6 +1735,7 @@ describe('LSP', function() -- after rename the target file must have the contents of the source file local bufnr = vim.fn.bufadd(new) + vim.fn.bufload(new) return vim.api.nvim_buf_get_lines(bufnr, 0, -1, true) ]], old, new) eq({'Test content'}, lines) |