diff options
-rw-r--r-- | runtime/doc/lsp.txt | 24 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 86 | ||||
-rw-r--r-- | test/functional/plugin/lsp_spec.lua | 16 |
3 files changed, 92 insertions, 34 deletions
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 4c59e53343..c7baec0491 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -915,6 +915,21 @@ apply_text_edits({text_edits}, {bufnr}) apply_workspace_edit({workspace_edit}) TODO: Documentation + *vim.lsp.util.diagnostics_by_buf* +diagnostics_by_buf + A table containing diagnostics grouped by buf. + + {<bufnr>: {diagnostics}} + + {diagnostics} is an array of diagnostics. + + By default this is populated by the + `textDocument/publishDiagnostics` callback via + |vim.lsp.util.buf_diagnostics_save_positions|. + + It contains entries for active buffers. Once a buffer is + detached the entries for it are discarded. + buf_clear_diagnostics({bufnr}) *vim.lsp.util.buf_clear_diagnostics()* TODO: Documentation @@ -945,9 +960,14 @@ buf_diagnostics_count({kind}) buf_clear_references({bufnr}) *vim.lsp.util.buf_clear_references()* TODO: Documentation - *vim.lsp.util.buf_diagnostics_save_positions()* + *vim.lsp.util.buf_diagnostics_save()* buf_diagnostics_save_positions({bufnr}, {diagnostics}) - TODO: Documentation + Stores the diagnostics into |vim.lsp.util.diagnostics_by_buf| + + Parameters: ~ + {bufr} bufnr for which the diagnostics are for. + {diagnostics} Diagnostics[] received from the + langauge server. *vim.lsp.util.buf_diagnostics_underline()* buf_diagnostics_underline({bufnr}, {diagnostics}) diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 4c73bf8c5f..80e4399fe1 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -6,6 +6,31 @@ local list_extend = vim.list_extend local M = {} +--- Diagnostics received from the server via `textDocument/publishDiagnostics` +-- by buffer. +-- +-- {<bufnr>: {diagnostics}} +-- +-- This contains only entries for active buffers. Entries for detached buffers +-- are discarded. +-- +-- If you override the `textDocument/publishDiagnostic` callback, +-- this will be empty unless you call `buf_diagnostics_save_positions`. +-- +-- +-- Diagnostic is: +-- +-- { +-- range: Range +-- message: string +-- severity?: DiagnosticSeverity +-- code?: number | string +-- source?: string +-- tags?: DiagnosticTag[] +-- relatedInformation?: DiagnosticRelatedInformation[] +-- } +M.diagnostics_by_buf = {} + local split = vim.split local function split_lines(value) return split(value, '\n', true) @@ -635,8 +660,6 @@ local function highlight_range(bufnr, ns, hiname, start, finish) end do - local all_buffer_diagnostics = {} - local diagnostic_ns = api.nvim_create_namespace("vim_lsp_diagnostics") local reference_ns = api.nvim_create_namespace("vim_lsp_references") local sign_ns = 'vim_lsp_signs' @@ -692,13 +715,12 @@ do -- if #marks == 0 then -- return -- end - -- local buffer_diagnostics = all_buffer_diagnostics[bufnr] local lines = {"Diagnostics:"} local highlights = {{0, "Bold"}} - local buffer_diagnostics = all_buffer_diagnostics[bufnr] + local buffer_diagnostics = M.diagnostics_by_buf[bufnr] if not buffer_diagnostics then return end - local line_diagnostics = buffer_diagnostics[line] + local line_diagnostics = M.diagnostics_group_by_line(buffer_diagnostics[line]) if not line_diagnostics then return end for i, diagnostic in ipairs(line_diagnostics) do @@ -726,6 +748,8 @@ do return popup_bufnr, winnr end + --- Saves the diagnostics (Diagnostic[]) into diagnostics_by_buf + -- function M.buf_diagnostics_save_positions(bufnr, diagnostics) validate { bufnr = {bufnr, 'n', true}; @@ -734,28 +758,15 @@ do if not diagnostics then return end bufnr = bufnr == 0 and api.nvim_get_current_buf() or bufnr - if not all_buffer_diagnostics[bufnr] then + if not M.diagnostics_by_buf[bufnr] then -- Clean up our data when the buffer unloads. api.nvim_buf_attach(bufnr, false, { on_detach = function(b) - all_buffer_diagnostics[b] = nil + M.diagnostics_by_buf[b] = nil end }) end - all_buffer_diagnostics[bufnr] = {} - local buffer_diagnostics = all_buffer_diagnostics[bufnr] - - for _, diagnostic in ipairs(diagnostics) do - local start = diagnostic.range.start - -- local mark_id = api.nvim_buf_set_extmark(bufnr, diagnostic_ns, 0, start.line, 0, {}) - -- buffer_diagnostics[mark_id] = diagnostic - local line_diagnostics = buffer_diagnostics[start.line] - if not line_diagnostics then - line_diagnostics = {} - buffer_diagnostics[start.line] = line_diagnostics - end - table.insert(line_diagnostics, diagnostic) - end + M.diagnostics_by_buf[bufnr] = diagnostics end function M.buf_diagnostics_underline(bufnr, diagnostics) @@ -799,15 +810,26 @@ do end end - function M.buf_diagnostics_virtual_text(bufnr, diagnostics) - local buffer_line_diagnostics = all_buffer_diagnostics[bufnr] - if not buffer_line_diagnostics then - M.buf_diagnostics_save_positions(bufnr, diagnostics) + function M.diagnostics_group_by_line(diagnostics) + if not diagnostics then return end + local diagnostics_by_line = {} + for _, diagnostic in ipairs(diagnostics) do + local start = diagnostic.range.start + local line_diagnostics = diagnostics_by_line[start.line] + if not line_diagnostics then + line_diagnostics = {} + diagnostics_by_line[start.line] = line_diagnostics + end + table.insert(line_diagnostics, diagnostic) end - buffer_line_diagnostics = all_buffer_diagnostics[bufnr] - if not buffer_line_diagnostics then + return diagnostics_by_line + end + + function M.buf_diagnostics_virtual_text(bufnr, diagnostics) + if not diagnostics then return end + local buffer_line_diagnostics = M.diagnostics_group_by_line(diagnostics) for line, line_diags in pairs(buffer_line_diagnostics) do local virt_texts = {} for i = 1, #line_diags - 1 do @@ -821,12 +843,12 @@ do end function M.buf_diagnostics_count(kind) local bufnr = vim.api.nvim_get_current_buf() - local buffer_line_diagnostics = all_buffer_diagnostics[bufnr] - if not buffer_line_diagnostics then return end + local diagnostics = M.diagnostics_by_buf[bufnr] + if not diagnostics then return end local count = 0 - for _, line_diags in pairs(buffer_line_diagnostics) do - for _, diag in ipairs(line_diags) do - if protocol.DiagnosticSeverity[kind] == diag.severity then count = count + 1 end + for _, diagnostic in pairs(diagnostics) do + if protocol.DiagnosticSeverity[kind] == diagnostic.severity then + count = count + 1 end end return count diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index b21e344acd..a57443f909 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -845,4 +845,20 @@ describe('LSP', function() eq({}, exec_lua([[return vim.lsp.util.text_document_completion_list_to_complete_items(...)]], {}, prefix)) end) end) + describe('buf_diagnostics_save_positions', function() + it('stores the diagnostics in diagnostics_by_buf', function () + local diagnostics = { + { range = {}; message = "diag1" }, + { range = {}; message = "diag2" }, + } + exec_lua([[ + vim.lsp.util.buf_diagnostics_save_positions(...)]], 0, diagnostics) + eq(1, exec_lua [[ return #vim.lsp.util.diagnostics_by_buf ]]) + eq(diagnostics, exec_lua [[ + for _, diagnostics in pairs(vim.lsp.util.diagnostics_by_buf) do + return diagnostics + end + ]]) + end) + end) end) |