mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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
This commit is contained in:
parent
8dde7c907c
commit
4f7879dff0
@ -743,6 +743,20 @@ local function bufwinid(bufnr)
|
|||||||
end
|
end
|
||||||
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
|
--- Rename old_fname to new_fname
|
||||||
---
|
---
|
||||||
---@param opts (table)
|
---@param opts (table)
|
||||||
@ -755,12 +769,22 @@ function M.rename(old_fname, new_fname, opts)
|
|||||||
vim.notify('Rename target already exists. Skipping rename.')
|
vim.notify('Rename target already exists. Skipping rename.')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local oldbuf = vim.fn.bufadd(old_fname)
|
|
||||||
vim.fn.bufload(oldbuf)
|
|
||||||
|
|
||||||
-- The there may be pending changes in the buffer
|
local oldbufs = {}
|
||||||
if vim.fn.isdirectory(old_fname) == 0 then
|
local win = nil
|
||||||
api.nvim_buf_call(oldbuf, function()
|
|
||||||
|
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!')
|
vim.cmd('w!')
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@ -768,12 +792,16 @@ function M.rename(old_fname, new_fname, opts)
|
|||||||
local ok, err = os.rename(old_fname, new_fname)
|
local ok, err = os.rename(old_fname, new_fname)
|
||||||
assert(ok, err)
|
assert(ok, err)
|
||||||
|
|
||||||
local newbuf = vim.fn.bufadd(new_fname)
|
if vim.fn.isdirectory(new_fname) == 0 then
|
||||||
local win = bufwinid(oldbuf)
|
local newbuf = vim.fn.bufadd(new_fname)
|
||||||
if win then
|
if win then
|
||||||
api.nvim_win_set_buf(win, newbuf)
|
api.nvim_win_set_buf(win, newbuf)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, b in ipairs(oldbufs) do
|
||||||
|
api.nvim_buf_delete(b, {})
|
||||||
end
|
end
|
||||||
api.nvim_buf_delete(oldbuf, { force = true })
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@private
|
---@private
|
||||||
|
@ -2200,7 +2200,22 @@ describe('LSP', function()
|
|||||||
eq(true, exists)
|
eq(true, exists)
|
||||||
os.remove(new)
|
os.remove(new)
|
||||||
end)
|
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
|
-- only reserve the name, file must not exist for the test scenario
|
||||||
local old_dir = helpers.tmpname()
|
local old_dir = helpers.tmpname()
|
||||||
local new_dir = helpers.tmpname()
|
local new_dir = helpers.tmpname()
|
||||||
@ -2209,16 +2224,19 @@ describe('LSP', function()
|
|||||||
|
|
||||||
helpers.mkdir_p(old_dir)
|
helpers.mkdir_p(old_dir)
|
||||||
|
|
||||||
local file = "file"
|
local file = 'file.txt'
|
||||||
write_file(old_dir .. pathsep .. file, 'Test content')
|
write_file(old_dir .. pathsep .. file, 'Test content')
|
||||||
|
|
||||||
exec_lua([[
|
local lines = exec_lua([[
|
||||||
local old_dir = select(1, ...)
|
local old_dir = select(1, ...)
|
||||||
local new_dir = select(2, ...)
|
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)
|
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(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))
|
||||||
eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', new_dir .. pathsep .. file))
|
eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', new_dir .. pathsep .. file))
|
||||||
|
Loading…
Reference in New Issue
Block a user