aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan <hello@iillexial.me>2023-03-14 13:08:37 +0100
committerGitHub <noreply@github.com>2023-03-14 05:08:37 -0700
commit4f7879dff0f0dc22ddf4cb2a2095b88605a3bab0 (patch)
tree1f2197d3fa7bfee21f427d9a39993b1962626654
parent8dde7c907ca9ad365895bded2c2f59e08f65d3ed (diff)
downloadrneovim-4f7879dff0f0dc22ddf4cb2a2095b88605a3bab0.tar.gz
rneovim-4f7879dff0f0dc22ddf4cb2a2095b88605a3bab0.tar.bz2
rneovim-4f7879dff0f0dc22ddf4cb2a2095b88605a3bab0.zip
fix(lsp): kill buffers after renaming a directory #22618
Problem: When LSP client renames a directory, opened buffers in the edfitor are not renamed or closed. Then `:wall` shows errors. https://github.com/neovim/neovim/blob/master/runtime/lua/vim/lsp/util.lua#L776 works correctly if you try to rename a single file, but doesn't delete old buffers with `old_fname` is a dir. Solution: Update the logic in runtime/lua/vim/lsp/util.lua:rename() Fixes #22617
-rw-r--r--runtime/lua/vim/lsp/util.lua48
-rw-r--r--test/functional/plugin/lsp_spec.lua28
2 files changed, 61 insertions, 15 deletions
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 82c9e3bc87..48faddfce1 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -743,6 +743,20 @@ local function bufwinid(bufnr)
end
end
+--- Get list of buffers for a directory
+---@private
+local function get_dir_bufs(path)
+ path = path:gsub('([^%w])', '%%%1')
+ local buffers = {}
+ for _, v in ipairs(vim.api.nvim_list_bufs()) do
+ local bufname = vim.api.nvim_buf_get_name(v):gsub('buffer://', '')
+ if bufname:find(path) then
+ table.insert(buffers, v)
+ end
+ end
+ return buffers
+end
+
--- Rename old_fname to new_fname
---
---@param opts (table)
@@ -755,12 +769,22 @@ function M.rename(old_fname, new_fname, opts)
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
- if vim.fn.isdirectory(old_fname) == 0 then
- api.nvim_buf_call(oldbuf, function()
+ local oldbufs = {}
+ local win = nil
+
+ if vim.fn.isdirectory(old_fname) == 1 then
+ oldbufs = get_dir_bufs(old_fname)
+ else
+ local oldbuf = vim.fn.bufadd(old_fname)
+ table.insert(oldbufs, oldbuf)
+ win = bufwinid(oldbuf)
+ end
+
+ for _, b in ipairs(oldbufs) do
+ vim.fn.bufload(b)
+ -- The there may be pending changes in the buffer
+ api.nvim_buf_call(b, function()
vim.cmd('w!')
end)
end
@@ -768,12 +792,16 @@ function M.rename(old_fname, new_fname, opts)
local ok, err = os.rename(old_fname, new_fname)
assert(ok, err)
- local newbuf = vim.fn.bufadd(new_fname)
- local win = bufwinid(oldbuf)
- if win then
- api.nvim_win_set_buf(win, newbuf)
+ if vim.fn.isdirectory(new_fname) == 0 then
+ local newbuf = vim.fn.bufadd(new_fname)
+ if win then
+ api.nvim_win_set_buf(win, newbuf)
+ end
+ end
+
+ for _, b in ipairs(oldbufs) do
+ api.nvim_buf_delete(b, {})
end
- api.nvim_buf_delete(oldbuf, { force = true })
end
---@private
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index ddbeef6d84..8b5e7d56ac 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -2200,7 +2200,22 @@ describe('LSP', function()
eq(true, exists)
os.remove(new)
end)
- it('Can rename a direcory', function()
+ it("Kills old buffer after renaming an existing file", function()
+ local old = helpers.tmpname()
+ write_file(old, 'Test content')
+ local new = helpers.tmpname()
+ os.remove(new) -- only reserve the name, file must not exist for the test scenario
+ local lines = exec_lua([[
+ local old = select(1, ...)
+ local oldbufnr = vim.fn.bufadd(old)
+ local new = select(2, ...)
+ vim.lsp.util.rename(old, new)
+ return vim.fn.bufloaded(oldbufnr)
+ ]], old, new)
+ eq(0, lines)
+ os.remove(new)
+ end)
+ it('Can rename a directory', function()
-- only reserve the name, file must not exist for the test scenario
local old_dir = helpers.tmpname()
local new_dir = helpers.tmpname()
@@ -2209,16 +2224,19 @@ describe('LSP', function()
helpers.mkdir_p(old_dir)
- local file = "file"
+ local file = 'file.txt'
write_file(old_dir .. pathsep .. file, 'Test content')
- exec_lua([[
+ local lines = exec_lua([[
local old_dir = select(1, ...)
local new_dir = select(2, ...)
+ local pathsep = select(3, ...)
+ local oldbufnr = vim.fn.bufadd(old_dir .. pathsep .. 'file')
vim.lsp.util.rename(old_dir, new_dir)
- ]], old_dir, new_dir)
-
+ return vim.fn.bufloaded(oldbufnr)
+ ]], old_dir, new_dir, pathsep)
+ eq(0, lines)
eq(false, exec_lua('return vim.loop.fs_stat(...) ~= nil', old_dir))
eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', new_dir))
eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', new_dir .. pathsep .. file))