mirror of
https://github.com/neovim/neovim.git
synced 2025-11-10 12:35:29 +00:00
feat(lsp): Split out a diagnostics_to_items function from set_loclist
Makes it easier to re-use the logic to populate the quickfix list instead of the location list.
This commit is contained in:
@@ -1196,11 +1196,16 @@ get({bufnr}, {client_id}) *vim.lsp.diagnostic.get()*
|
|||||||
diagnostics. Else, return just the
|
diagnostics. Else, return just the
|
||||||
diagnostics associated with the client_id.
|
diagnostics associated with the client_id.
|
||||||
|
|
||||||
get_all() *vim.lsp.diagnostic.get_all()*
|
get_all({client_id}) *vim.lsp.diagnostic.get_all()*
|
||||||
Get all diagnostics for all clients
|
Get all diagnostics for clients
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
{client_id} number Restrict included diagnostics to the
|
||||||
|
client If nil, diagnostics of all clients are
|
||||||
|
included.
|
||||||
|
|
||||||
Return: ~
|
Return: ~
|
||||||
{bufnr:Diagnostic[]}
|
table with diagnostics grouped by bufnr (bufnr:Diagnostic[])
|
||||||
|
|
||||||
*vim.lsp.diagnostic.get_count()*
|
*vim.lsp.diagnostic.get_count()*
|
||||||
get_count({bufnr}, {severity}, {client_id})
|
get_count({bufnr}, {severity}, {client_id})
|
||||||
@@ -1725,6 +1730,19 @@ create_file({change}) *vim.lsp.util.create_file()*
|
|||||||
delete_file({change}) *vim.lsp.util.delete_file()*
|
delete_file({change}) *vim.lsp.util.delete_file()*
|
||||||
TODO: Documentation
|
TODO: Documentation
|
||||||
|
|
||||||
|
*vim.lsp.util.diagnostics_to_items()*
|
||||||
|
diagnostics_to_items({diagnostics_by_bufnr}, {predicate})
|
||||||
|
Convert diagnostics grouped by bufnr to a list of items for
|
||||||
|
use in the quickfix or location list.
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
{diagnostics_by_bufnr} table bufnr -> Diagnostic []
|
||||||
|
{predicate} an optional function to filter the
|
||||||
|
diagnostics.
|
||||||
|
|
||||||
|
Return: ~
|
||||||
|
table (A list of items)
|
||||||
|
|
||||||
*vim.lsp.util.extract_completion_items()*
|
*vim.lsp.util.extract_completion_items()*
|
||||||
extract_completion_items({result})
|
extract_completion_items({result})
|
||||||
Can be used to extract the completion items from a `textDocument/completion` request, which may return one of `CompletionItem[]` , `CompletionList` or null.
|
Can be used to extract the completion items from a `textDocument/completion` request, which may return one of `CompletionItem[]` , `CompletionList` or null.
|
||||||
|
|||||||
@@ -330,17 +330,21 @@ end
|
|||||||
-- Diagnostic Retrieval {{{
|
-- Diagnostic Retrieval {{{
|
||||||
|
|
||||||
|
|
||||||
--- Get all diagnostics for all clients
|
--- Get all diagnostics for clients
|
||||||
---
|
---
|
||||||
---@return {bufnr: Diagnostic[]}
|
---@param client_id number Restrict included diagnostics to the client
|
||||||
function M.get_all()
|
--- If nil, diagnostics of all clients are included.
|
||||||
|
---@return table with diagnostics grouped by bufnr (bufnr: Diagnostic[])
|
||||||
|
function M.get_all(client_id)
|
||||||
local diagnostics_by_bufnr = {}
|
local diagnostics_by_bufnr = {}
|
||||||
for bufnr, buf_diagnostics in pairs(diagnostic_cache) do
|
for bufnr, buf_diagnostics in pairs(diagnostic_cache) do
|
||||||
diagnostics_by_bufnr[bufnr] = {}
|
diagnostics_by_bufnr[bufnr] = {}
|
||||||
for _, client_diagnostics in pairs(buf_diagnostics) do
|
for cid, client_diagnostics in pairs(buf_diagnostics) do
|
||||||
|
if client_id == nil or cid == client_id then
|
||||||
vim.list_extend(diagnostics_by_bufnr[bufnr], client_diagnostics)
|
vim.list_extend(diagnostics_by_bufnr[bufnr], client_diagnostics)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
return diagnostics_by_bufnr
|
return diagnostics_by_bufnr
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1162,13 +1166,6 @@ function M.show_line_diagnostics(opts, bufnr, line_nr, client_id)
|
|||||||
return popup_bufnr, winnr
|
return popup_bufnr, winnr
|
||||||
end
|
end
|
||||||
|
|
||||||
local loclist_type_map = {
|
|
||||||
[DiagnosticSeverity.Error] = 'E',
|
|
||||||
[DiagnosticSeverity.Warning] = 'W',
|
|
||||||
[DiagnosticSeverity.Information] = 'I',
|
|
||||||
[DiagnosticSeverity.Hint] = 'I',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
--- Clear diagnotics and diagnostic cache
|
--- Clear diagnotics and diagnostic cache
|
||||||
---
|
---
|
||||||
@@ -1201,51 +1198,24 @@ end
|
|||||||
--- - Set the list with workspace diagnostics
|
--- - Set the list with workspace diagnostics
|
||||||
function M.set_loclist(opts)
|
function M.set_loclist(opts)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
|
|
||||||
local open_loclist = if_nil(opts.open_loclist, true)
|
local open_loclist = if_nil(opts.open_loclist, true)
|
||||||
|
local current_bufnr = api.nvim_get_current_buf()
|
||||||
local win_id = vim.api.nvim_get_current_win()
|
local diags = opts.workspace and M.get_all(opts.client_id) or {
|
||||||
local current_bufnr = vim.api.nvim_get_current_buf()
|
|
||||||
local diags = opts.workspace and M.get_all() or {
|
|
||||||
[current_bufnr] = M.get(current_bufnr, opts.client_id)
|
[current_bufnr] = M.get(current_bufnr, opts.client_id)
|
||||||
}
|
}
|
||||||
|
local predicate = function(d)
|
||||||
local items = {}
|
local severity = to_severity(opts.severity)
|
||||||
local insert_diag = function(bufnr, diag)
|
if severity then
|
||||||
local pos = diag.range.start
|
return d.severity == severity
|
||||||
local row = pos.line
|
|
||||||
|
|
||||||
local col = util.character_offset(bufnr, row, pos.character) or 0
|
|
||||||
|
|
||||||
table.insert(items, {
|
|
||||||
bufnr = bufnr,
|
|
||||||
lnum = row + 1,
|
|
||||||
col = col + 1,
|
|
||||||
text = diag.message,
|
|
||||||
type = loclist_type_map[diag.severity or DiagnosticSeverity.Error] or 'E',
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
severity = to_severity(opts.severity_limit)
|
||||||
for bufnr, diagnostic in pairs(diags) do
|
if severity then
|
||||||
if opts.severity then
|
return d.severity == severity
|
||||||
diagnostic = filter_to_severity_limit(opts.severity, diagnostic)
|
|
||||||
elseif opts.severity_limit then
|
|
||||||
diagnostic = filter_by_severity_limit(opts.severity_limit, diagnostic)
|
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
for _, diag in ipairs(diagnostic) do
|
|
||||||
insert_diag(bufnr, diag)
|
|
||||||
end
|
end
|
||||||
end
|
local items = util.diagnostics_to_items(diags, predicate)
|
||||||
|
local win_id = vim.api.nvim_get_current_win()
|
||||||
table.sort(items, function(a, b)
|
|
||||||
if a.bufnr == b.bufnr then
|
|
||||||
return a.lnum < b.lnum
|
|
||||||
else
|
|
||||||
return a.bufnr < b.bufnr
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
util.set_loclist(items, win_id)
|
util.set_loclist(items, win_id)
|
||||||
if open_loclist then
|
if open_loclist then
|
||||||
vim.cmd [[lopen]]
|
vim.cmd [[lopen]]
|
||||||
|
|||||||
@@ -30,6 +30,16 @@ local default_border = {
|
|||||||
{" ", "NormalFloat"},
|
{" ", "NormalFloat"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
local DiagnosticSeverity = protocol.DiagnosticSeverity
|
||||||
|
local loclist_type_map = {
|
||||||
|
[DiagnosticSeverity.Error] = 'E',
|
||||||
|
[DiagnosticSeverity.Warning] = 'W',
|
||||||
|
[DiagnosticSeverity.Information] = 'I',
|
||||||
|
[DiagnosticSeverity.Hint] = 'I',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
--@private
|
--@private
|
||||||
-- Check the border given by opts or the default border for the additional
|
-- Check the border given by opts or the default border for the additional
|
||||||
-- size it adds to a float.
|
-- size it adds to a float.
|
||||||
@@ -1878,6 +1888,40 @@ function M.lookup_section(settings, section)
|
|||||||
return settings
|
return settings
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Convert diagnostics grouped by bufnr to a list of items for use in the
|
||||||
|
--- quickfix or location list.
|
||||||
|
---
|
||||||
|
--@param diagnostics_by_bufnr table bufnr -> Diagnostic[]
|
||||||
|
--@param predicate an optional function to filter the diagnostics.
|
||||||
|
-- If present, only diagnostic items matching will be included.
|
||||||
|
--@return table (A list of items)
|
||||||
|
function M.diagnostics_to_items(diagnostics_by_bufnr, predicate)
|
||||||
|
local items = {}
|
||||||
|
for bufnr, diagnostics in pairs(diagnostics_by_bufnr or {}) do
|
||||||
|
for _, d in pairs(diagnostics) do
|
||||||
|
if not predicate or predicate(d) then
|
||||||
|
table.insert(items, {
|
||||||
|
bufnr = bufnr,
|
||||||
|
lnum = d.range.start.line + 1,
|
||||||
|
col = d.range.start.character + 1,
|
||||||
|
text = d.message,
|
||||||
|
type = loclist_type_map[d.severity or DiagnosticSeverity.Error] or 'E'
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(items, function(a, b)
|
||||||
|
if a.bufnr == b.bufnr then
|
||||||
|
return a.lnum < b.lnum
|
||||||
|
else
|
||||||
|
return a.bufnr < b.bufnr
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
return items
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
M._get_line_byte_from_position = get_line_byte_from_position
|
M._get_line_byte_from_position = get_line_byte_from_position
|
||||||
M._warn_once = warn_once
|
M._warn_once = warn_once
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,39 @@ describe('vim.lsp.diagnostic', function()
|
|||||||
eq(2, #result[1])
|
eq(2, #result[1])
|
||||||
eq('Diagnostic #1', result[1][1].message)
|
eq('Diagnostic #1', result[1][1].message)
|
||||||
end)
|
end)
|
||||||
|
it('Can convert diagnostic to quickfix items format', function()
|
||||||
|
local bufnr = exec_lua([[
|
||||||
|
local fake_uri = ...
|
||||||
|
return vim.uri_to_bufnr(fake_uri)
|
||||||
|
]], fake_uri)
|
||||||
|
local result = exec_lua([[
|
||||||
|
local bufnr = ...
|
||||||
|
vim.lsp.diagnostic.save(
|
||||||
|
{
|
||||||
|
make_error('Diagnostic #1', 1, 1, 1, 1),
|
||||||
|
make_error('Diagnostic #2', 2, 1, 2, 1),
|
||||||
|
}, bufnr, 1
|
||||||
|
)
|
||||||
|
return vim.lsp.util.diagnostics_to_items(vim.lsp.diagnostic.get_all())
|
||||||
|
]], bufnr)
|
||||||
|
local expected = {
|
||||||
|
{
|
||||||
|
bufnr = bufnr,
|
||||||
|
col = 2,
|
||||||
|
lnum = 2,
|
||||||
|
text = 'Diagnostic #1',
|
||||||
|
type = 'E'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bufnr = bufnr,
|
||||||
|
col = 2,
|
||||||
|
lnum = 3,
|
||||||
|
text = 'Diagnostic #2',
|
||||||
|
type = 'E'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
eq(expected, result)
|
||||||
|
end)
|
||||||
it('should be able to save and count a single client error', function()
|
it('should be able to save and count a single client error', function()
|
||||||
eq(1, exec_lua [[
|
eq(1, exec_lua [[
|
||||||
vim.lsp.diagnostic.save(
|
vim.lsp.diagnostic.save(
|
||||||
|
|||||||
Reference in New Issue
Block a user