mirror of
https://github.com/neovim/neovim.git
synced 2026-07-09 19:09:39 +00:00
fix(lsp): refresh document-pull buffers on workspace/diagnostic/refresh #40623
When a server supports both document and workspace pull diagnostics, `on_refresh` only dispatched a `workspace/diagnostic` request. The workspace response handler skips buffers with `pull_kind == "document"` (i.e. all buffers opened by the user), so their diagnostics went stale until the next `didChange` or `didOpen` event. Change `on_refresh` to always refresh document-pull buffers via `textDocument/diagnostic`, regardless of whether the server also supports workspace diagnostics. This ensures that opened buffers see updated diagnostics (e.g. after a save triggers an external tool like PHPStan) without requiring the user to re-enter insert mode.
This commit is contained in:
@@ -405,13 +405,16 @@ function M.on_refresh(err, _, ctx)
|
||||
end
|
||||
if client:supports_method('workspace/diagnostic') then
|
||||
M._workspace_diagnostics({ client_id = ctx.client_id })
|
||||
else
|
||||
for bufnr in pairs(client.attached_buffers or {}) do
|
||||
local provider = Diagnostics.active[bufnr]
|
||||
local state = provider and provider.client_state[ctx.client_id]
|
||||
if state and state.pull_kind == 'document' then
|
||||
provider:refresh(ctx.client_id)
|
||||
end
|
||||
end
|
||||
|
||||
-- Always refresh document-pull buffers. Workspace diagnostics only cover
|
||||
-- buffers with pull_kind == 'workspace', so open buffers must be refreshed
|
||||
-- individually or their diagnostics go stale until the next didChange.
|
||||
for bufnr in pairs(client.attached_buffers or {}) do
|
||||
local provider = Diagnostics.active[bufnr]
|
||||
local state = provider and provider.client_state[ctx.client_id]
|
||||
if state and state.pull_kind == 'document' then
|
||||
provider:refresh(ctx.client_id)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -825,14 +825,24 @@ describe('vim.lsp.diagnostic', function()
|
||||
local fake_uri_3 = 'file:///fake/uri3'
|
||||
exec_lua(create_server_definition)
|
||||
exec_lua(function()
|
||||
_G.requests = 0
|
||||
_G.workspace_requests = 0
|
||||
_G.doc_requests = 0
|
||||
_G.server = _G._create_server({
|
||||
capabilities = {
|
||||
diagnosticProvider = { workspaceDiagnostics = true },
|
||||
},
|
||||
handlers = {
|
||||
['textDocument/diagnostic'] = function(_, _, callback)
|
||||
_G.doc_requests = _G.doc_requests + 1
|
||||
callback(nil, {
|
||||
kind = 'full',
|
||||
items = {
|
||||
_G.make_warning('Refreshed Diagnostic', 4, 4, 4, 4),
|
||||
},
|
||||
})
|
||||
end,
|
||||
['workspace/diagnostic'] = function(_, _, callback)
|
||||
_G.requests = _G.requests + 1
|
||||
_G.workspace_requests = _G.workspace_requests + 1
|
||||
callback(nil, {
|
||||
items = {
|
||||
{
|
||||
@@ -850,8 +860,26 @@ describe('vim.lsp.diagnostic', function()
|
||||
client_id = assert(vim.lsp.start({ name = 'dummy', cmd = _G.server.cmd }))
|
||||
end)
|
||||
|
||||
-- Seed the opened buffer with a document diagnostic so on_refresh must
|
||||
-- re-request it even when workspace diagnostics are supported.
|
||||
exec_lua(function()
|
||||
vim.lsp.diagnostic.on_diagnostic(nil, {
|
||||
kind = 'full',
|
||||
items = {
|
||||
_G.make_error('Initial Diagnostic', 4, 4, 4, 4),
|
||||
},
|
||||
}, {
|
||||
params = {
|
||||
textDocument = { uri = fake_uri },
|
||||
},
|
||||
uri = fake_uri,
|
||||
client_id = client_id,
|
||||
bufnr = diagnostic_bufnr,
|
||||
}, {})
|
||||
end)
|
||||
|
||||
eq(
|
||||
0,
|
||||
1,
|
||||
exec_lua(function()
|
||||
return #vim.diagnostic.get()
|
||||
end)
|
||||
@@ -870,17 +898,31 @@ describe('vim.lsp.diagnostic', function()
|
||||
end)
|
||||
)
|
||||
|
||||
local requests, diags = exec_lua(function()
|
||||
vim.lsp.diagnostic.on_refresh(nil, nil, {
|
||||
method = 'workspace/diagnostic/refresh',
|
||||
client_id = client_id,
|
||||
})
|
||||
|
||||
return _G.requests, vim.diagnostic.get()
|
||||
exec_lua(function()
|
||||
_G.doc_requests = 0
|
||||
end)
|
||||
eq(1, requests)
|
||||
eq(1, #diags)
|
||||
eq(1, diags[1].severity)
|
||||
|
||||
local workspace_requests, doc_requests, diags, opened_diags, workspace_diags = exec_lua(
|
||||
function()
|
||||
vim.lsp.diagnostic.on_refresh(nil, nil, {
|
||||
method = 'workspace/diagnostic/refresh',
|
||||
client_id = client_id,
|
||||
})
|
||||
|
||||
return _G.workspace_requests,
|
||||
_G.doc_requests,
|
||||
vim.diagnostic.get(),
|
||||
vim.diagnostic.get(diagnostic_bufnr),
|
||||
vim.diagnostic.get(vim.uri_to_bufnr(fake_uri_3))
|
||||
end
|
||||
)
|
||||
eq(1, workspace_requests)
|
||||
eq(1, doc_requests)
|
||||
eq(2, #diags)
|
||||
eq(1, #opened_diags)
|
||||
eq(2, opened_diags[1].severity)
|
||||
eq(1, #workspace_diags)
|
||||
eq(1, workspace_diags[1].severity)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
Reference in New Issue
Block a user