commit 9c8d06e08608e9fb916473cba1af65b58609392e
parent 15ff45444325a4395b564bafad9d38e04f2501f9
Author: GenchoXD <42417659+Emagjby@users.noreply.github.com>
Date: Sun, 8 Feb 2026 23:22:13 +0200
test(lsp/diagnostic): clearing diagnostics #37759
Problem:
Diagnostic lifecycle invariants (clearing on empty publish and buffer
deletion) were previously implicit and not directly covered by functional
tests, allowing regressions to go unnoticed.
Solution:
Add functional regression tests asserting that diagnostics are cleared
when an LSP server publishes an empty diagnostic set and when the
associated buffer is deleted. Assertions are scoped to the client
diagnostic namespace and use public diagnostic APIs only.
Diffstat:
1 file changed, 61 insertions(+), 0 deletions(-)
diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua
@@ -208,6 +208,67 @@ describe('vim.lsp.diagnostic', function()
end)
)
end)
+
+ it('clears diagnostics for the client namespace on empty publish', function()
+ local before_clear, after_clear = exec_lua(function()
+ local ns = vim.lsp.diagnostic.get_namespace(client_id)
+
+ -- Publish diagnostics
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, {
+ uri = fake_uri,
+ diagnostics = {
+ _G.make_error('Diagnostic', 0, 0, 0, 0),
+ },
+ }, { client_id = client_id })
+
+ local before_clear = vim.diagnostic.get(diagnostic_bufnr, { namespace = ns })
+
+ -- Publish empty diagnostics
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, {
+ uri = fake_uri,
+ diagnostics = {},
+ }, { client_id = client_id })
+
+ local after_clear = vim.diagnostic.get(diagnostic_bufnr, { namespace = ns })
+
+ return before_clear, after_clear
+ end)
+
+ eq(1, #before_clear)
+ eq(0, #after_clear)
+ end)
+
+ it('clears diagnostics when buffer is deleted', function()
+ local before_delete, after_delete = exec_lua(function()
+ local ns = vim.lsp.diagnostic.get_namespace(client_id)
+
+ -- Publish diagnostics
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, {
+ uri = fake_uri,
+ diagnostics = {
+ _G.make_error('Diagnostic', 0, 0, 0, 0),
+ },
+ }, { client_id = client_id })
+
+ local before_delete = vim.diagnostic.get(diagnostic_bufnr, { namespace = ns })
+
+ -- Avoid deleting the currently displayed buffer (Windows teardown edge case)
+ local scratch = vim.api.nvim_create_buf(false, true)
+ vim.api.nvim_win_set_buf(0, scratch)
+
+ -- Delete the buffer deterministically
+ vim.api.nvim_buf_delete(diagnostic_bufnr, { force = true })
+
+ -- Query remaining diagnostics via valid access path
+ -- (deleted buffer cannot be queried directly)
+ local after_delete = vim.diagnostic.get(nil, { namespace = ns })
+
+ return before_delete, after_delete
+ end)
+
+ eq(1, #before_delete)
+ eq(0, #after_delete)
+ end)
end)
describe('vim.lsp.diagnostic.on_diagnostic', function()