mirror of
https://github.com/neovim/neovim
synced 2025-07-20 13:22:26 +00:00
fix(lsp): don't send foreign diagnostics to servers in buf.code_action (#29501)
`buf.code_action` always included diagnostics on a given line from all clients. Servers should only receive diagnostics they published, and in the exact same format they sent it. Should fix https://github.com/neovim/neovim/issues/29500
This commit is contained in:
committed by
GitHub
parent
32e128f209
commit
720b309c78
@ -852,14 +852,10 @@ function M.code_action(opts)
|
|||||||
if opts.diagnostics or opts.only then
|
if opts.diagnostics or opts.only then
|
||||||
opts = { options = opts }
|
opts = { options = opts }
|
||||||
end
|
end
|
||||||
local context = opts.context or {}
|
local context = opts.context and vim.deepcopy(opts.context) or {}
|
||||||
if not context.triggerKind then
|
if not context.triggerKind then
|
||||||
context.triggerKind = vim.lsp.protocol.CodeActionTriggerKind.Invoked
|
context.triggerKind = vim.lsp.protocol.CodeActionTriggerKind.Invoked
|
||||||
end
|
end
|
||||||
if not context.diagnostics then
|
|
||||||
local bufnr = api.nvim_get_current_buf()
|
|
||||||
context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics(bufnr)
|
|
||||||
end
|
|
||||||
local mode = api.nvim_get_mode().mode
|
local mode = api.nvim_get_mode().mode
|
||||||
local bufnr = api.nvim_get_current_buf()
|
local bufnr = api.nvim_get_current_buf()
|
||||||
local win = api.nvim_get_current_win()
|
local win = api.nvim_get_current_win()
|
||||||
@ -901,6 +897,18 @@ function M.code_action(opts)
|
|||||||
else
|
else
|
||||||
params = util.make_range_params(win, client.offset_encoding)
|
params = util.make_range_params(win, client.offset_encoding)
|
||||||
end
|
end
|
||||||
|
if not context.diagnostics then
|
||||||
|
local ns_push = vim.lsp.diagnostic.get_namespace(client.id, false)
|
||||||
|
local ns_pull = vim.lsp.diagnostic.get_namespace(client.id, true)
|
||||||
|
local diagnostics = {}
|
||||||
|
local lnum = api.nvim_win_get_cursor(0)[1] - 1
|
||||||
|
vim.list_extend(diagnostics, vim.diagnostic.get(bufnr, { namespace = ns_pull, lnum = lnum }))
|
||||||
|
vim.list_extend(diagnostics, vim.diagnostic.get(bufnr, { namespace = ns_push, lnum = lnum }))
|
||||||
|
---@diagnostic disable-next-line: no-unknown
|
||||||
|
context.diagnostics = vim.tbl_map(function(d)
|
||||||
|
return d.user_data.lsp
|
||||||
|
end, diagnostics)
|
||||||
|
end
|
||||||
params.context = context
|
params.context = context
|
||||||
client.request(ms.textDocument_codeAction, params, on_result, bufnr)
|
client.request(ms.textDocument_codeAction, params, on_result, bufnr)
|
||||||
end
|
end
|
||||||
|
@ -122,13 +122,7 @@ local function diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)
|
|||||||
code = diagnostic.code,
|
code = diagnostic.code,
|
||||||
_tags = tags_lsp_to_vim(diagnostic, client_id),
|
_tags = tags_lsp_to_vim(diagnostic, client_id),
|
||||||
user_data = {
|
user_data = {
|
||||||
lsp = {
|
lsp = diagnostic,
|
||||||
-- usage of user_data.lsp.code is deprecated in favor of the top-level code field
|
|
||||||
code = diagnostic.code,
|
|
||||||
codeDescription = diagnostic.codeDescription,
|
|
||||||
relatedInformation = diagnostic.relatedInformation,
|
|
||||||
data = diagnostic.data,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end, diagnostics)
|
end, diagnostics)
|
||||||
@ -157,8 +151,11 @@ local function diagnostic_vim_to_lsp(diagnostics)
|
|||||||
---@param diagnostic vim.Diagnostic
|
---@param diagnostic vim.Diagnostic
|
||||||
---@return lsp.Diagnostic
|
---@return lsp.Diagnostic
|
||||||
return vim.tbl_map(function(diagnostic)
|
return vim.tbl_map(function(diagnostic)
|
||||||
return vim.tbl_extend('keep', {
|
local user_data = diagnostic.user_data or {}
|
||||||
-- "keep" the below fields over any duplicate fields in diagnostic.user_data.lsp
|
if user_data.lsp then
|
||||||
|
return user_data.lsp
|
||||||
|
end
|
||||||
|
return {
|
||||||
range = {
|
range = {
|
||||||
start = {
|
start = {
|
||||||
line = diagnostic.lnum,
|
line = diagnostic.lnum,
|
||||||
@ -174,7 +171,7 @@ local function diagnostic_vim_to_lsp(diagnostics)
|
|||||||
source = diagnostic.source,
|
source = diagnostic.source,
|
||||||
code = diagnostic.code,
|
code = diagnostic.code,
|
||||||
tags = tags_vim_to_lsp(diagnostic),
|
tags = tags_vim_to_lsp(diagnostic),
|
||||||
}, diagnostic.user_data and (diagnostic.user_data.lsp or {}) or {})
|
}
|
||||||
end, diagnostics)
|
end, diagnostics)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -366,6 +363,7 @@ end
|
|||||||
--- Structured: { [1] = {...}, [5] = {.... } }
|
--- Structured: { [1] = {...}, [5] = {.... } }
|
||||||
---@private
|
---@private
|
||||||
function M.get_line_diagnostics(bufnr, line_nr, opts, client_id)
|
function M.get_line_diagnostics(bufnr, line_nr, opts, client_id)
|
||||||
|
vim.deprecate('vim.lsp.diagnostic.get_line_diagnostics', 'vim.diagnostic.get', '0.12')
|
||||||
convert_severity(opts)
|
convert_severity(opts)
|
||||||
local diag_opts = {} --- @type vim.diagnostic.GetOpts
|
local diag_opts = {} --- @type vim.diagnostic.GetOpts
|
||||||
|
|
||||||
|
@ -98,33 +98,6 @@ describe('vim.lsp.diagnostic', function()
|
|||||||
clear()
|
clear()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('vim.lsp.diagnostic', function()
|
|
||||||
it('maintains LSP information when translating diagnostics', function()
|
|
||||||
local result = exec_lua [[
|
|
||||||
local diagnostics = {
|
|
||||||
make_error("Error 1", 1, 1, 1, 5),
|
|
||||||
}
|
|
||||||
|
|
||||||
diagnostics[1].code = 42
|
|
||||||
diagnostics[1].data = "Hello world"
|
|
||||||
|
|
||||||
vim.lsp.diagnostic.on_publish_diagnostics(nil, {
|
|
||||||
uri = fake_uri,
|
|
||||||
diagnostics = diagnostics,
|
|
||||||
}, {client_id=client_id})
|
|
||||||
|
|
||||||
return {
|
|
||||||
vim.diagnostic.get(diagnostic_bufnr, {lnum=1})[1],
|
|
||||||
vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1)[1],
|
|
||||||
}
|
|
||||||
]]
|
|
||||||
eq({ code = 42, data = 'Hello world' }, result[1].user_data.lsp)
|
|
||||||
eq(42, result[1].code)
|
|
||||||
eq(42, result[2].code)
|
|
||||||
eq('Hello world', result[2].data)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
describe('vim.lsp.diagnostic.on_publish_diagnostics', function()
|
describe('vim.lsp.diagnostic.on_publish_diagnostics', function()
|
||||||
it('allows configuring the virtual text via vim.lsp.with', function()
|
it('allows configuring the virtual text via vim.lsp.with', function()
|
||||||
local expected_spacing = 10
|
local expected_spacing = 10
|
||||||
|
Reference in New Issue
Block a user