From 48f05455949cd6df6f8d42140f64394eb0225397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Fu=C3=9Fenegger?= Date: Sun, 18 Dec 2022 03:19:15 +0100 Subject: [PATCH] fix(diagnostic): clear stale cache on reset (#21454) The BufWipeout autocmd is not 100% reliable and may leave stale entries in the cache. This is sort of a hack/workaround to ensure `vim.diagnostic.reset` calls don't fail if there are stale cache entries but instead clears them Fixes errors like Error executing vim.schedule lua callback: /usr/share/nvim/runtime/lua/vim/diagnostic.lua:1458: Invalid buffer id: 22 stack traceback: [C]: in function 'nvim_exec_autocmds' /usr/share/nvim/runtime/lua/vim/diagnostic.lua:1458: in function 'reset' (cherry picked from commit 1743359235206cbd9da2e0589f1caba37cce3b8c) --- runtime/lua/vim/diagnostic.lua | 24 ++++++++++++++++-------- test/functional/lua/diagnostic_spec.lua | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 98dbe0779b..97065ac1ab 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -916,7 +916,7 @@ M.handlers.signs = { end, hide = function(namespace, bufnr) local ns = M.get_namespace(namespace) - if ns.user_data.sign_group then + if ns.user_data.sign_group and vim.api.nvim_buf_is_valid(bufnr) then vim.fn.sign_unplace(ns.user_data.sign_group, { buffer = bufnr }) end end, @@ -971,7 +971,9 @@ M.handlers.underline = { local ns = M.get_namespace(namespace) if ns.user_data.underline_ns then diagnostic_cache_extmarks[bufnr][ns.user_data.underline_ns] = {} - vim.api.nvim_buf_clear_namespace(bufnr, ns.user_data.underline_ns, 0, -1) + if vim.api.nvim_buf_is_valid(bufnr) then + vim.api.nvim_buf_clear_namespace(bufnr, ns.user_data.underline_ns, 0, -1) + end end end, } @@ -1034,7 +1036,9 @@ M.handlers.virtual_text = { local ns = M.get_namespace(namespace) if ns.user_data.virt_text_ns then diagnostic_cache_extmarks[bufnr][ns.user_data.virt_text_ns] = {} - vim.api.nvim_buf_clear_namespace(bufnr, ns.user_data.virt_text_ns, 0, -1) + if vim.api.nvim_buf_is_valid(bufnr) then + vim.api.nvim_buf_clear_namespace(bufnr, ns.user_data.virt_text_ns, 0, -1) + end end end, } @@ -1423,11 +1427,15 @@ function M.reset(namespace, bufnr) M.hide(iter_namespace, iter_bufnr) end - vim.api.nvim_exec_autocmds('DiagnosticChanged', { - modeline = false, - buffer = iter_bufnr, - data = { diagnostics = {} }, - }) + if vim.api.nvim_buf_is_valid(iter_bufnr) then + vim.api.nvim_exec_autocmds('DiagnosticChanged', { + modeline = false, + buffer = iter_bufnr, + data = { diagnostics = {} }, + }) + else + diagnostic_cache[iter_bufnr] = nil + end end end diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua index 28a8679205..506c2097c9 100644 --- a/test/functional/lua/diagnostic_spec.lua +++ b/test/functional/lua/diagnostic_spec.lua @@ -159,6 +159,24 @@ describe('vim.diagnostic', function() ]]) end) + it('removes diagnostic from stale cache on reset', function() + local diagnostics = exec_lua [[ + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #1', 1, 1, 1, 1), + make_error('Diagnostic #2', 2, 1, 2, 1), + }) + local other_bufnr = vim.fn.bufadd('test | test') + vim.cmd('noautocmd bwipeout! ' .. diagnostic_bufnr) + return vim.diagnostic.get(diagnostic_bufnr) + ]] + eq(2, #diagnostics) + diagnostics = exec_lua [[ + vim.diagnostic.reset() + return vim.diagnostic.get() + ]] + eq(0, #diagnostics) + end) + it('resolves buffer number 0 to the current buffer', function() eq(2, exec_lua [[ vim.api.nvim_set_current_buf(diagnostic_bufnr)