mirror of
https://github.com/neovim/neovim.git
synced 2024-12-23 12:45:17 -07:00
fix(lsp): when renaming directory, check path prefix of buffer names (#27603)
For example, when renaming /path/to/dir, buffers like fern://drawer/file:///path/to/dir, /path/to/dir123 should not be matched.
This commit is contained in:
parent
04f723f1a5
commit
8addd27504
@ -2003,7 +2003,11 @@ rename({old_fname}, {new_fname}, {opts}) *vim.lsp.util.rename()*
|
||||
Rename old_fname to new_fname
|
||||
|
||||
Parameters: ~
|
||||
• {opts} (`table`)
|
||||
• {old_fname} (`string`)
|
||||
• {new_fname} (`string`)
|
||||
• {opts} (`table?`) options
|
||||
• overwrite? boolean
|
||||
• ignoreIfExists? boolean
|
||||
|
||||
*vim.lsp.util.show_document()*
|
||||
show_document({location}, {offset_encoding}, {opts})
|
||||
|
@ -639,13 +639,28 @@ function M.text_document_completion_list_to_complete_items(result, prefix)
|
||||
return vim.lsp._completion._lsp_to_complete_items(result, prefix)
|
||||
end
|
||||
|
||||
--- Get list of buffers for a directory
|
||||
local function get_dir_bufs(path)
|
||||
path = path:gsub('([^%w])', '%%%1')
|
||||
local function path_components(path)
|
||||
return vim.split(path, '/', { plain = true })
|
||||
end
|
||||
|
||||
local function path_under_prefix(path, prefix)
|
||||
for i, c in ipairs(prefix) do
|
||||
if c ~= path[i] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--- Get list of buffers whose filename matches the given path prefix (normalized full path)
|
||||
---@return integer[]
|
||||
local function get_bufs_with_prefix(prefix)
|
||||
prefix = path_components(prefix)
|
||||
local buffers = {}
|
||||
for _, v in ipairs(vim.api.nvim_list_bufs()) do
|
||||
local bufname = vim.api.nvim_buf_get_name(v)
|
||||
if bufname:find(path) then
|
||||
local bname = vim.api.nvim_buf_get_name(v)
|
||||
local path = path_components(vim.fs.normalize(bname, { expand_env = false }))
|
||||
if path_under_prefix(path, prefix) then
|
||||
table.insert(buffers, v)
|
||||
end
|
||||
end
|
||||
@ -654,24 +669,34 @@ end
|
||||
|
||||
--- Rename old_fname to new_fname
|
||||
---
|
||||
---@param opts (table)
|
||||
-- overwrite? bool
|
||||
-- ignoreIfExists? bool
|
||||
---@param old_fname string
|
||||
---@param new_fname string
|
||||
---@param opts? table options
|
||||
--- - overwrite? boolean
|
||||
--- - ignoreIfExists? boolean
|
||||
function M.rename(old_fname, new_fname, opts)
|
||||
opts = opts or {}
|
||||
local skip = not opts.overwrite or opts.ignoreIfExists
|
||||
|
||||
local old_fname_full = vim.uv.fs_realpath(vim.fs.normalize(old_fname, { expand_env = false }))
|
||||
if not old_fname_full then
|
||||
vim.notify('Invalid path: ' .. old_fname, vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
local target_exists = uv.fs_stat(new_fname) ~= nil
|
||||
if target_exists and not opts.overwrite or opts.ignoreIfExists then
|
||||
vim.notify('Rename target already exists. Skipping rename.')
|
||||
if target_exists and skip then
|
||||
vim.notify(new_fname .. ' already exists. Skipping rename.', vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
local oldbufs = {}
|
||||
local win = nil
|
||||
|
||||
if vim.fn.isdirectory(old_fname) == 1 then
|
||||
oldbufs = get_dir_bufs(old_fname)
|
||||
if vim.fn.isdirectory(old_fname_full) == 1 then
|
||||
oldbufs = get_bufs_with_prefix(old_fname_full)
|
||||
else
|
||||
local oldbuf = vim.fn.bufadd(old_fname)
|
||||
local oldbuf = vim.fn.bufadd(old_fname_full)
|
||||
table.insert(oldbufs, oldbuf)
|
||||
win = vim.fn.win_findbuf(oldbuf)[1]
|
||||
end
|
||||
@ -687,7 +712,7 @@ function M.rename(old_fname, new_fname, opts)
|
||||
local newdir = assert(vim.fs.dirname(new_fname))
|
||||
vim.fn.mkdir(newdir, 'p')
|
||||
|
||||
local ok, err = os.rename(old_fname, new_fname)
|
||||
local ok, err = os.rename(old_fname_full, new_fname)
|
||||
assert(ok, err)
|
||||
|
||||
if vim.fn.isdirectory(new_fname) == 0 then
|
||||
|
@ -2515,6 +2515,47 @@ describe('LSP', function()
|
||||
|
||||
os.remove(new_dir)
|
||||
end)
|
||||
it('Does not touch buffers that do not match path prefix', function()
|
||||
local old = tmpname()
|
||||
local new = tmpname()
|
||||
os.remove(old)
|
||||
os.remove(new)
|
||||
helpers.mkdir_p(old)
|
||||
|
||||
local result = exec_lua(
|
||||
[[
|
||||
local old = select(1, ...)
|
||||
local new = select(2, ...)
|
||||
|
||||
local old_prefixed = 'explorer://' .. old
|
||||
local old_suffixed = old .. '.bak'
|
||||
local new_prefixed = 'explorer://' .. new
|
||||
local new_suffixed = new .. '.bak'
|
||||
|
||||
local old_prefixed_buf = vim.fn.bufadd(old_prefixed)
|
||||
local old_suffixed_buf = vim.fn.bufadd(old_suffixed)
|
||||
local new_prefixed_buf = vim.fn.bufadd(new_prefixed)
|
||||
local new_suffixed_buf = vim.fn.bufadd(new_suffixed)
|
||||
|
||||
vim.lsp.util.rename(old, new)
|
||||
|
||||
return
|
||||
vim.api.nvim_buf_is_valid(old_prefixed_buf) and
|
||||
vim.api.nvim_buf_is_valid(old_suffixed_buf) and
|
||||
vim.api.nvim_buf_is_valid(new_prefixed_buf) and
|
||||
vim.api.nvim_buf_is_valid(new_suffixed_buf) and
|
||||
vim.api.nvim_buf_get_name(old_prefixed_buf) == old_prefixed and
|
||||
vim.api.nvim_buf_get_name(old_suffixed_buf) == old_suffixed and
|
||||
vim.api.nvim_buf_get_name(new_prefixed_buf) == new_prefixed and
|
||||
vim.api.nvim_buf_get_name(new_suffixed_buf) == new_suffixed
|
||||
]],
|
||||
old,
|
||||
new
|
||||
)
|
||||
eq(true, result)
|
||||
|
||||
os.remove(new)
|
||||
end)
|
||||
it(
|
||||
'Does not rename file if target exists and ignoreIfExists is set or overwrite is false',
|
||||
function()
|
||||
|
Loading…
Reference in New Issue
Block a user