mirror of
https://github.com/neovim/neovim.git
synced 2026-05-04 13:05:05 +00:00
fix(lsp/diagnostic): key resultId by client and identifier
Previously, resultId for diagnostics was keyed only by client_id, which could cause issues when multiple identifiers are used by the same client. This change introduces a composite key of client_id and identifier for client_result_id, ensuring correct tracking of diagnostic results per identifier. Updates all relevant logic to use the new keying scheme.
This commit is contained in:
@@ -15,7 +15,7 @@ local augroup = api.nvim_create_augroup('nvim.lsp.diagnostic', {})
|
|||||||
|
|
||||||
---@class (private) vim.lsp.diagnostic.BufState
|
---@class (private) vim.lsp.diagnostic.BufState
|
||||||
---@field pull_kind 'document'|'workspace'|'disabled' Whether diagnostics are being updated via document pull, workspace pull, or disabled.
|
---@field pull_kind 'document'|'workspace'|'disabled' Whether diagnostics are being updated via document pull, workspace pull, or disabled.
|
||||||
---@field client_result_id table<integer, string?> Latest responded `resultId`
|
---@field client_result_id table<string, string?> Latest responded `resultId`, keyed by `client_id.identifier`
|
||||||
|
|
||||||
---@type table<integer, vim.lsp.diagnostic.BufState>
|
---@type table<integer, vim.lsp.diagnostic.BufState>
|
||||||
local bufstates = {}
|
local bufstates = {}
|
||||||
@@ -147,6 +147,13 @@ local function tags_vim_to_lsp(diagnostic)
|
|||||||
return tags
|
return tags
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param client_id integer
|
||||||
|
---@param identifier string|nil
|
||||||
|
---@return string
|
||||||
|
local function result_id_key(client_id, identifier)
|
||||||
|
return string.format('%d.%s', client_id, identifier or 'nil')
|
||||||
|
end
|
||||||
|
|
||||||
--- Converts the input `vim.Diagnostic`s to LSP diagnostics.
|
--- Converts the input `vim.Diagnostic`s to LSP diagnostics.
|
||||||
--- @param diagnostics vim.Diagnostic[]
|
--- @param diagnostics vim.Diagnostic[]
|
||||||
--- @return lsp.Diagnostic[]
|
--- @return lsp.Diagnostic[]
|
||||||
@@ -281,14 +288,15 @@ function M.on_diagnostic(error, result, ctx)
|
|||||||
local client_id = ctx.client_id
|
local client_id = ctx.client_id
|
||||||
local bufnr = assert(ctx.bufnr)
|
local bufnr = assert(ctx.bufnr)
|
||||||
local bufstate = bufstates[bufnr]
|
local bufstate = bufstates[bufnr]
|
||||||
bufstate.client_result_id[client_id] = result.resultId
|
---@type lsp.DocumentDiagnosticParams
|
||||||
|
local params = ctx.params
|
||||||
|
local key = result_id_key(client_id, params.identifier)
|
||||||
|
bufstate.client_result_id[key] = result.resultId
|
||||||
|
|
||||||
if result.kind == 'unchanged' then
|
if result.kind == 'unchanged' then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type lsp.DocumentDiagnosticParams
|
|
||||||
local params = ctx.params
|
|
||||||
handle_diagnostics(params.textDocument.uri, client_id, result.items, params.identifier or true)
|
handle_diagnostics(params.textDocument.uri, client_id, result.items, params.identifier or true)
|
||||||
|
|
||||||
for uri, related_result in pairs(result.relatedDocuments or {}) do
|
for uri, related_result in pairs(result.relatedDocuments or {}) do
|
||||||
@@ -304,7 +312,7 @@ function M.on_diagnostic(error, result, ctx)
|
|||||||
or { pull_kind = 'document', client_result_id = {} }
|
or { pull_kind = 'document', client_result_id = {} }
|
||||||
bufstates[related_bufnr] = related_bufstate
|
bufstates[related_bufnr] = related_bufstate
|
||||||
|
|
||||||
related_bufstate.client_result_id[client_id] = related_result.resultId
|
related_bufstate.client_result_id[key] = related_result.resultId
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -383,11 +391,12 @@ function M._refresh(bufnr, client_id, only_visible)
|
|||||||
for _, client in ipairs(clients) do
|
for _, client in ipairs(clients) do
|
||||||
---@param cap lsp.DiagnosticRegistrationOptions
|
---@param cap lsp.DiagnosticRegistrationOptions
|
||||||
client:_provider_foreach(method, function(cap)
|
client:_provider_foreach(method, function(cap)
|
||||||
|
local key = result_id_key(client.id, cap.identifier)
|
||||||
---@type lsp.DocumentDiagnosticParams
|
---@type lsp.DocumentDiagnosticParams
|
||||||
local params = {
|
local params = {
|
||||||
identifier = cap.identifier,
|
identifier = cap.identifier,
|
||||||
textDocument = util.make_text_document_params(bufnr),
|
textDocument = util.make_text_document_params(bufnr),
|
||||||
previousResultId = bufstate.client_result_id[client.id],
|
previousResultId = bufstate.client_result_id[key],
|
||||||
}
|
}
|
||||||
client:request(method, params, nil, bufnr)
|
client:request(method, params, nil, bufnr)
|
||||||
end)
|
end)
|
||||||
@@ -481,19 +490,20 @@ end
|
|||||||
|
|
||||||
--- Returns the result IDs from the reports provided by the given client.
|
--- Returns the result IDs from the reports provided by the given client.
|
||||||
--- @return lsp.PreviousResultId[]
|
--- @return lsp.PreviousResultId[]
|
||||||
local function previous_result_ids(client_id)
|
--- @param client_id integer
|
||||||
|
--- @param identifier string|nil
|
||||||
|
local function previous_result_ids(client_id, identifier)
|
||||||
local results = {} ---@type lsp.PreviousResultId[]
|
local results = {} ---@type lsp.PreviousResultId[]
|
||||||
|
local key = result_id_key(client_id, identifier)
|
||||||
|
|
||||||
for bufnr, state in pairs(bufstates) do
|
for bufnr, state in pairs(bufstates) do
|
||||||
if state.pull_kind ~= 'disabled' then
|
if state.pull_kind ~= 'disabled' then
|
||||||
for buf_client_id, result_id in pairs(state.client_result_id) do
|
local result_id = state.client_result_id[key]
|
||||||
if buf_client_id == client_id then
|
if result_id then
|
||||||
results[#results + 1] = {
|
results[#results + 1] = {
|
||||||
uri = vim.uri_from_bufnr(bufnr),
|
uri = vim.uri_from_bufnr(bufnr),
|
||||||
value = result_id,
|
value = result_id,
|
||||||
}
|
}
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -535,7 +545,8 @@ function M._workspace_diagnostics(opts)
|
|||||||
-- state if we're not pulling document diagnostics for this buffer.
|
-- state if we're not pulling document diagnostics for this buffer.
|
||||||
if bufstates[bufnr].pull_kind == 'workspace' and report.kind == 'full' then
|
if bufstates[bufnr].pull_kind == 'workspace' and report.kind == 'full' then
|
||||||
handle_diagnostics(report.uri, ctx.client_id, report.items, params.identifier or true)
|
handle_diagnostics(report.uri, ctx.client_id, report.items, params.identifier or true)
|
||||||
bufstates[bufnr].client_result_id[ctx.client_id] = report.resultId
|
local key = result_id_key(ctx.client_id, params.identifier)
|
||||||
|
bufstates[bufnr].client_result_id[key] = report.resultId
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -547,7 +558,7 @@ function M._workspace_diagnostics(opts)
|
|||||||
--- @type lsp.WorkspaceDiagnosticParams
|
--- @type lsp.WorkspaceDiagnosticParams
|
||||||
local params = {
|
local params = {
|
||||||
identifier = cap.identifier,
|
identifier = cap.identifier,
|
||||||
previousResultIds = previous_result_ids(client.id),
|
previousResultIds = previous_result_ids(client.id, cap.identifier),
|
||||||
}
|
}
|
||||||
|
|
||||||
client:request('workspace/diagnostic', params, handler)
|
client:request('workspace/diagnostic', params, handler)
|
||||||
|
|||||||
Reference in New Issue
Block a user