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:
smolck
2021-11-21 19:40:06 -06:00
committed by GitHub
parent 0d967f0298
commit 04bfd20bb8
2 changed files with 40 additions and 23 deletions

View File

@@ -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
rawset(t, bufnr, {})
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