aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorglepnir <glephunter@gmail.com>2025-03-11 20:10:09 +0800
committerGitHub <noreply@github.com>2025-03-11 05:10:09 -0700
commita14fca432b963b01ae9b47598f5d787520402810 (patch)
tree31c1cdc976eb661e15e80cbece52bd058f1432f4
parent55bdb077b7069c018cc5ccf682417770abec5b4a (diff)
downloadrneovim-a14fca432b963b01ae9b47598f5d787520402810.tar.gz
rneovim-a14fca432b963b01ae9b47598f5d787520402810.tar.bz2
rneovim-a14fca432b963b01ae9b47598f5d787520402810.zip
fix(lsp): improve LSP floating preview window cleanup #31353
Problem: The current implementation creates a unique autocommand group for each floating preview window, which is inefficient and can lead to numerous autocommand groups. Solution: Use a single shared autocommand group with improved window validation to properly clean up LSP floating preview windows.
-rw-r--r--runtime/lua/vim/lsp/util.lua31
-rw-r--r--test/functional/plugin/lsp/utils_spec.lua58
2 files changed, 45 insertions, 44 deletions
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index ef177e903f..307a55c2a2 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -1622,23 +1622,24 @@ function M.open_floating_preview(contents, syntax, opts)
api.nvim_win_set_var(floating_winnr, opts.focus_id, bufnr)
end
api.nvim_buf_set_var(bufnr, 'lsp_floating_preview', floating_winnr)
+ api.nvim_win_set_var(floating_winnr, 'lsp_floating_bufnr', bufnr)
end
- local augroup_name = ('nvim.closing_floating_preview_%d'):format(floating_winnr)
- local ok =
- pcall(api.nvim_get_autocmds, { group = augroup_name, pattern = tostring(floating_winnr) })
- if not ok then
- api.nvim_create_autocmd('WinClosed', {
- group = api.nvim_create_augroup(augroup_name, {}),
- pattern = tostring(floating_winnr),
- callback = function()
- if api.nvim_buf_is_valid(bufnr) then
- vim.b[bufnr].lsp_floating_preview = nil
- end
- api.nvim_del_augroup_by_name(augroup_name)
- end,
- })
- end
+ api.nvim_create_autocmd('WinClosed', {
+ group = api.nvim_create_augroup('nvim.closing_floating_preview', { clear = true }),
+ callback = function(args)
+ local winid = tonumber(args.match)
+ local ok, preview_bufnr = pcall(api.nvim_win_get_var, winid, 'lsp_floating_bufnr')
+ if
+ ok
+ and api.nvim_buf_is_valid(preview_bufnr)
+ and winid == vim.b[preview_bufnr].lsp_floating_preview
+ then
+ vim.b[bufnr].lsp_floating_preview = nil
+ return true
+ end
+ end,
+ })
vim.wo[floating_winnr].foldenable = false -- Disable folding.
vim.wo[floating_winnr].wrap = opts.wrap -- Soft wrapping.
diff --git a/test/functional/plugin/lsp/utils_spec.lua b/test/functional/plugin/lsp/utils_spec.lua
index 7bfb354c2e..fac9a2c69d 100644
--- a/test/functional/plugin/lsp/utils_spec.lua
+++ b/test/functional/plugin/lsp/utils_spec.lua
@@ -267,38 +267,38 @@ describe('vim.lsp.util', function()
eq(56, opts.height)
end)
+ end)
+ end)
- describe('vim.lsp.util.open_floating_preview', function()
- local var_name = 'lsp_floating_preview'
- local curbuf = api.nvim_get_current_buf()
-
- it('clean bufvar after fclose', function()
- exec_lua(function()
- vim.lsp.util.open_floating_preview({ 'test' }, '', { height = 5, width = 2 })
- end)
- eq(true, api.nvim_win_is_valid(api.nvim_buf_get_var(curbuf, var_name)))
- command('fclose')
- eq(
- 'Key not found: lsp_floating_preview',
- pcall_err(api.nvim_buf_get_var, curbuf, var_name)
- )
- end)
+ describe('open_floating_preview', function()
+ before_each(function()
+ n.clear()
+ Screen.new(10, 10)
+ feed('9i<CR><Esc>G4k')
+ end)
- it('clean bufvar after CursorMoved', function()
- local result = exec_lua(function()
- vim.lsp.util.open_floating_preview({ 'test' }, '', { height = 5, width = 2 })
- local winnr = vim.b[vim.api.nvim_get_current_buf()].lsp_floating_preview
- local result = vim.api.nvim_win_is_valid(winnr)
- vim.api.nvim_feedkeys(vim.keycode('G'), 'txn', false)
- return result
- end)
- eq(true, result)
- eq(
- 'Key not found: lsp_floating_preview',
- pcall_err(api.nvim_buf_get_var, curbuf, var_name)
- )
- end)
+ local var_name = 'lsp_floating_preview'
+ local curbuf = api.nvim_get_current_buf()
+
+ it('clean bufvar after fclose', function()
+ exec_lua(function()
+ vim.lsp.util.open_floating_preview({ 'test' }, '', { height = 5, width = 2 })
+ end)
+ eq(true, api.nvim_win_is_valid(api.nvim_buf_get_var(curbuf, var_name)))
+ command('fclose')
+ eq('Key not found: lsp_floating_preview', pcall_err(api.nvim_buf_get_var, curbuf, var_name))
+ end)
+
+ it('clean bufvar after CursorMoved', function()
+ local result = exec_lua(function()
+ vim.lsp.util.open_floating_preview({ 'test' }, '', { height = 5, width = 2 })
+ local winnr = vim.b[vim.api.nvim_get_current_buf()].lsp_floating_preview
+ local result = vim.api.nvim_win_is_valid(winnr)
+ vim.api.nvim_feedkeys(vim.keycode('G'), 'txn', false)
+ return result
end)
+ eq(true, result)
+ eq('Key not found: lsp_floating_preview', pcall_err(api.nvim_buf_get_var, curbuf, var_name))
end)
end)