mirror of
https://github.com/neovim/neovim
synced 2025-07-20 12:32:28 +00:00
fix(diagnostic): remove invalid buffers from cache (#16397)
Errors were being caused by invalid buffers being kept around in diagnostic_cache, so add a metatable to diagnostic_cache which attaches to new buffers in the cache, removing them after they are invalidated. Closes #16391. Co-authored-by: Gregory Anders <8965202+gpanders@users.noreply.github.com>
This commit is contained in:
@ -43,9 +43,7 @@ local bufnr_and_namespace_cacher_mt = {
|
||||
bufnr = vim.api.nvim_get_current_buf()
|
||||
end
|
||||
|
||||
if rawget(t, bufnr) == nil then
|
||||
rawset(t, bufnr, {})
|
||||
end
|
||||
|
||||
return rawget(t, bufnr)
|
||||
end,
|
||||
@ -59,8 +57,24 @@ local bufnr_and_namespace_cacher_mt = {
|
||||
end,
|
||||
}
|
||||
|
||||
local diagnostic_cleanup = setmetatable({}, bufnr_and_namespace_cacher_mt)
|
||||
local diagnostic_cache = setmetatable({}, bufnr_and_namespace_cacher_mt)
|
||||
local diagnostic_cache = setmetatable({}, {
|
||||
__index = function(t, bufnr)
|
||||
if not bufnr or bufnr == 0 then
|
||||
bufnr = vim.api.nvim_get_current_buf()
|
||||
end
|
||||
|
||||
vim.api.nvim_buf_attach(bufnr, false, {
|
||||
on_detach = function()
|
||||
rawset(t, bufnr, nil) -- clear cache
|
||||
end
|
||||
})
|
||||
|
||||
rawset(t, bufnr, {})
|
||||
|
||||
return rawget(t, bufnr)
|
||||
end,
|
||||
})
|
||||
|
||||
local diagnostic_cache_extmarks = setmetatable({}, bufnr_and_namespace_cacher_mt)
|
||||
local diagnostic_attached_buffers = {}
|
||||
local diagnostic_disabled = {}
|
||||
@ -284,11 +298,6 @@ local function set_diagnostic_cache(namespace, bufnr, diagnostics)
|
||||
diagnostic_cache[bufnr][namespace] = diagnostics
|
||||
end
|
||||
|
||||
---@private
|
||||
local function clear_diagnostic_cache(namespace, bufnr)
|
||||
diagnostic_cache[bufnr][namespace] = nil
|
||||
end
|
||||
|
||||
---@private
|
||||
local function restore_extmarks(bufnr, last)
|
||||
for ns, extmarks in pairs(diagnostic_cache_extmarks[bufnr]) do
|
||||
@ -651,19 +660,8 @@ function M.set(namespace, bufnr, diagnostics, opts)
|
||||
}
|
||||
|
||||
if vim.tbl_isempty(diagnostics) then
|
||||
clear_diagnostic_cache(namespace, bufnr)
|
||||
diagnostic_cache[bufnr][namespace] = nil
|
||||
else
|
||||
if not diagnostic_cleanup[bufnr][namespace] then
|
||||
diagnostic_cleanup[bufnr][namespace] = true
|
||||
|
||||
-- Clean up our data when the buffer unloads.
|
||||
vim.api.nvim_buf_attach(bufnr, false, {
|
||||
on_detach = function(_, b)
|
||||
clear_diagnostic_cache(namespace, b)
|
||||
diagnostic_cleanup[b][namespace] = nil
|
||||
end
|
||||
})
|
||||
end
|
||||
set_diagnostic_cache(namespace, bufnr, diagnostics)
|
||||
end
|
||||
|
||||
@ -1326,7 +1324,7 @@ function M.reset(namespace, bufnr)
|
||||
for _, iter_bufnr in ipairs(buffers) do
|
||||
local namespaces = namespace and {namespace} or vim.tbl_keys(diagnostic_cache[iter_bufnr])
|
||||
for _, iter_namespace in ipairs(namespaces) do
|
||||
clear_diagnostic_cache(iter_namespace, iter_bufnr)
|
||||
diagnostic_cache[iter_bufnr][iter_namespace] = nil
|
||||
M.hide(iter_namespace, iter_bufnr)
|
||||
end
|
||||
end
|
||||
|
@ -343,6 +343,16 @@ describe('vim.diagnostic', function()
|
||||
eq(0, result[5])
|
||||
eq(3, result[6])
|
||||
end)
|
||||
|
||||
it("doesn't error after bwipeout on buffer", function()
|
||||
exec_lua [[
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { lnum = 0, end_lnum = 0, col = 0, end_col = 0 })
|
||||
vim.cmd("bwipeout! " .. diagnostic_bufnr)
|
||||
|
||||
vim.diagnostic.show(diagnostic_ns)
|
||||
vim.diagnostic.hide(diagnostic_ns)
|
||||
]]
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('enable() and disable()', function()
|
||||
@ -629,6 +639,15 @@ describe('vim.diagnostic', function()
|
||||
]])
|
||||
|
||||
end)
|
||||
|
||||
it("doesn't error after bwipeout called on buffer", function()
|
||||
exec_lua [[
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { lnum = 0, end_lnum = 0, col = 0, end_col = 0 })
|
||||
vim.cmd("bwipeout! " .. diagnostic_bufnr)
|
||||
|
||||
vim.diagnostic.reset(diagnostic_ns)
|
||||
]]
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('get_next_pos()', function()
|
||||
|
Reference in New Issue
Block a user