aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/lsp.txt24
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua72
-rw-r--r--runtime/lua/vim/lsp/util.lua44
-rw-r--r--test/functional/plugin/lsp/diagnostic_spec.lua33
4 files changed, 119 insertions, 54 deletions
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index dd52fcf22a..531374620a 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -1196,11 +1196,16 @@ get({bufnr}, {client_id}) *vim.lsp.diagnostic.get()*
diagnostics. Else, return just the
diagnostics associated with the client_id.
-get_all() *vim.lsp.diagnostic.get_all()*
- Get all diagnostics for all clients
+get_all({client_id}) *vim.lsp.diagnostic.get_all()*
+ Get all diagnostics for clients
+
+ Parameters: ~
+ {client_id} number Restrict included diagnostics to the
+ client If nil, diagnostics of all clients are
+ included.
Return: ~
- {bufnr:Diagnostic[]}
+ table with diagnostics grouped by bufnr (bufnr:Diagnostic[])
*vim.lsp.diagnostic.get_count()*
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()*
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()*
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.
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 06f2babde4..dabe400e0d 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -330,15 +330,19 @@ end
-- Diagnostic Retrieval {{{
---- Get all diagnostics for all clients
+--- Get all diagnostics for clients
---
----@return {bufnr: Diagnostic[]}
-function M.get_all()
+---@param client_id number Restrict included diagnostics to the client
+--- 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 = {}
for bufnr, buf_diagnostics in pairs(diagnostic_cache) do
diagnostics_by_bufnr[bufnr] = {}
- for _, client_diagnostics in pairs(buf_diagnostics) do
- vim.list_extend(diagnostics_by_bufnr[bufnr], client_diagnostics)
+ 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)
+ end
end
end
return diagnostics_by_bufnr
@@ -1162,13 +1166,6 @@ function M.show_line_diagnostics(opts, bufnr, line_nr, client_id)
return popup_bufnr, winnr
end
-local loclist_type_map = {
- [DiagnosticSeverity.Error] = 'E',
- [DiagnosticSeverity.Warning] = 'W',
- [DiagnosticSeverity.Information] = 'I',
- [DiagnosticSeverity.Hint] = 'I',
-}
-
--- Clear diagnotics and diagnostic cache
---
@@ -1201,51 +1198,24 @@ end
--- - Set the list with workspace diagnostics
function M.set_loclist(opts)
opts = opts or {}
-
local open_loclist = if_nil(opts.open_loclist, true)
-
- local win_id = vim.api.nvim_get_current_win()
- local current_bufnr = vim.api.nvim_get_current_buf()
- local diags = opts.workspace and M.get_all() or {
+ local current_bufnr = api.nvim_get_current_buf()
+ local diags = opts.workspace and M.get_all(opts.client_id) or {
[current_bufnr] = M.get(current_bufnr, opts.client_id)
}
-
- local items = {}
- local insert_diag = function(bufnr, diag)
- local pos = diag.range.start
- 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
-
- for bufnr, diagnostic in pairs(diags) do
- if opts.severity then
- diagnostic = filter_to_severity_limit(opts.severity, diagnostic)
- elseif opts.severity_limit then
- diagnostic = filter_by_severity_limit(opts.severity_limit, diagnostic)
+ local predicate = function(d)
+ local severity = to_severity(opts.severity)
+ if severity then
+ return d.severity == severity
end
-
- for _, diag in ipairs(diagnostic) do
- insert_diag(bufnr, diag)
+ severity = to_severity(opts.severity_limit)
+ if severity then
+ return d.severity == severity
end
+ return true
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)
-
+ local items = util.diagnostics_to_items(diags, predicate)
+ local win_id = vim.api.nvim_get_current_win()
util.set_loclist(items, win_id)
if open_loclist then
vim.cmd [[lopen]]
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index d421a10011..cb9a7cbed5 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -30,6 +30,16 @@ local default_border = {
{" ", "NormalFloat"},
}
+
+local DiagnosticSeverity = protocol.DiagnosticSeverity
+local loclist_type_map = {
+ [DiagnosticSeverity.Error] = 'E',
+ [DiagnosticSeverity.Warning] = 'W',
+ [DiagnosticSeverity.Information] = 'I',
+ [DiagnosticSeverity.Hint] = 'I',
+}
+
+
--@private
-- Check the border given by opts or the default border for the additional
-- size it adds to a float.
@@ -1878,6 +1888,40 @@ function M.lookup_section(settings, section)
return settings
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._warn_once = warn_once
diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua
index 8c91c4ab2c..962028e7e1 100644
--- a/test/functional/plugin/lsp/diagnostic_spec.lua
+++ b/test/functional/plugin/lsp/diagnostic_spec.lua
@@ -86,6 +86,39 @@ describe('vim.lsp.diagnostic', function()
eq(2, #result[1])
eq('Diagnostic #1', result[1][1].message)
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()
eq(1, exec_lua [[
vim.lsp.diagnostic.save(