From 7ffee0dfbfd1d972797231030a83b728ae1ea3ee Mon Sep 17 00:00:00 2001 From: glepnir Date: Thu, 9 Apr 2026 05:10:52 +0800 Subject: [PATCH] fix(lsp): apply_text_edits causes unwanted BufDelete events #38778 Problem: Since 2f6d1d3c887a87d9402137425b418dd12a904aac, `apply_text_edits` unconditionally sets `buflisted=true`, causing spurious BufDelete events if plugins restore the original 'buflisted' state on unlisted buffers: https://github.com/neovim/neovim/blob/65ef6cec1cb766334c59d3255595dfe523b11020/src/nvim/option.c#L2159-L2169 Solution: - Don't set 'buflisted' in `apply_text_edits`. Set it more narrowly, in `apply_workspace_edit` where the semantics requires affected buffers to be visible to the user. - Also skip setting 'buflisted' if it would not be changed, to avoid redundant `OptionSet` events. (cherry picked from commit 6473d007e7b9f7f14b06190117f0bb0269fa938c) --- runtime/lua/vim/lsp/util.lua | 10 +++++++++- test/functional/plugin/lsp_spec.lua | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index b58286b7b7..80991322c3 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -312,7 +312,6 @@ function M.apply_text_edits(text_edits, bufnr, position_encoding, change_annotat if not api.nvim_buf_is_loaded(bufnr) then vim.fn.bufload(bufnr) end - vim.bo[bufnr].buflisted = true local marks = {} --- @type table local has_eol_text_edit = false @@ -710,7 +709,12 @@ function M.apply_workspace_edit(workspace_edit, position_encoding) elseif change.kind then --- @diagnostic disable-line:undefined-field error(string.format('Unsupported change: %q', vim.inspect(change))) else + local bufnr = vim.uri_to_bufnr(change.textDocument.uri) M.apply_text_document_edit(change, idx, position_encoding, workspace_edit.changeAnnotations) + -- avoid triggering OptionSet + if not vim.bo[bufnr].buflisted then + vim.bo[bufnr].buflisted = true + end end end return @@ -724,6 +728,10 @@ function M.apply_workspace_edit(workspace_edit, position_encoding) for uri, changes in pairs(all_changes) do local bufnr = vim.uri_to_bufnr(uri) M.apply_text_edits(changes, bufnr, position_encoding, workspace_edit.changeAnnotations) + -- avoid triggering OptionSet + if not vim.bo[bufnr].buflisted then + vim.bo[bufnr].buflisted = true + end end end diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 05bd2b7c41..9b12641730 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -2639,6 +2639,7 @@ describe('LSP', function() return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false) end, make_workspace_edit(edits)) ) + eq(true, api.nvim_get_option_value('buflisted', { buf = target_bufnr })) end) it('apply_workspace_edit applies multiple edits', function()