From d43151ea0bb194f7463cc8762919cd38546973c2 Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Sat, 18 Sep 2021 15:00:32 -0600 Subject: feat(diagnostic): add option to include diagnostic source Add an option to virtual text display and floating window previews to include diagnostic source in the diagnostic message. --- runtime/doc/diagnostic.txt | 7 ++++++ runtime/lua/vim/diagnostic.lua | 45 +++++++++++++++++++++++++++++++++++++- runtime/lua/vim/lsp/diagnostic.lua | 2 ++ 3 files changed, 53 insertions(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt index 59b73771a6..5845f11073 100644 --- a/runtime/doc/diagnostic.txt +++ b/runtime/doc/diagnostic.txt @@ -47,6 +47,7 @@ A diagnostic is a Lua table with the following keys: end_col: The final column of the diagnostic severity: The severity of the diagnostic |vim.diagnostic.severity| message: The diagnostic text + source: The source of the diagnostic Diagnostics use the same indexing as the rest of the Nvim API (i.e. 0-based rows and columns). |api-indexing| @@ -226,6 +227,9 @@ config({opts}, {namespace}) *vim.diagnostic.config()* • severity: Only show virtual text for diagnostics matching the given severity |diagnostic-severity| + • source: (string) Include the diagnostic + source in virtual text. One of "always" + or "if_many". • signs: (default true) Use signs for diagnostics. Options: @@ -532,6 +536,9 @@ show_position_diagnostics({opts}, {bufnr}, {position}) • severity: See |diagnostic-severity|. • show_header: (boolean, default true) Show "Diagnostics:" header + • source: (string) Include the diagnostic + source in the message. One of "always" or + "if_many". {bufnr} number|nil Buffer number. Defaults to the current buffer. {position} table|nil The (0,0)-indexed position. Defaults diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 0261475f72..26ee9ebca5 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -47,6 +47,35 @@ local function filter_by_severity(severity, diagnostics) return vim.tbl_filter(function(t) return t.severity <= min_severity and t.severity >= max_severity end, diagnostics) end +---@private +local function prefix_source(source, diagnostics) + vim.validate { source = {source, function(v) + return v == "always" or v == "if_many" + end, "Invalid value for option 'source'" } } + + if source == "if_many" then + local sources = {} + for _, d in pairs(diagnostics) do + if d.source then + sources[d.source] = true + end + end + if #vim.tbl_keys(sources) <= 1 then + return diagnostics + end + end + + return vim.tbl_map(function(d) + if not d.source then + return d + end + + local t = vim.deepcopy(d) + t.message = string.format("%s: %s", d.source, d.message) + return t + end, diagnostics) +end + ---@private local function resolve_optional_value(option, namespace, bufnr) local enabled_val = {} @@ -336,7 +365,9 @@ end ---@param diagnostics table: The diagnostics to display ---@return table {popup_bufnr, win_id} local function show_diagnostics(opts, diagnostics) - if vim.tbl_isempty(diagnostics) then return end + if vim.tbl_isempty(diagnostics) then + return + end local lines = {} local highlights = {} local show_header = vim.F.if_nil(opts.show_header, true) @@ -345,6 +376,10 @@ local function show_diagnostics(opts, diagnostics) table.insert(highlights, {0, "Bold"}) end + if opts.source then + diagnostics = prefix_source(opts.source, diagnostics) + end + for i, diagnostic in ipairs(diagnostics) do local prefix = string.format("%d. ", i) local hiname = floating_highlight_map[diagnostic.severity] @@ -487,6 +522,8 @@ end --- - virtual_text: (default true) Use virtual text for diagnostics. Options: --- * severity: Only show virtual text for diagnostics matching the given --- severity |diagnostic-severity| +--- * source: (string) Include the diagnostic source in virtual +--- text. One of "always" or "if_many". --- - signs: (default true) Use signs for diagnostics. Options: --- * severity: Only show signs for diagnostics matching the given severity --- |diagnostic-severity| @@ -826,6 +863,10 @@ function M._set_virtual_text(namespace, bufnr, diagnostics, opts) bufnr = get_bufnr(bufnr) opts = get_resolved_options({ virtual_text = opts }, namespace, bufnr).virtual_text + if opts and opts.source then + diagnostics = prefix_source(opts.source, diagnostics) + end + local buffer_line_diagnostics = diagnostic_lines(diagnostics) for line, line_diagnostics in pairs(buffer_line_diagnostics) do if opts and opts.severity then @@ -1007,6 +1048,8 @@ end --- - namespace: (number) Limit diagnostics to the given namespace --- - severity: See |diagnostic-severity|. --- - show_header: (boolean, default true) Show "Diagnostics:" header +--- - source: (string) Include the diagnostic source in +--- the message. One of "always" or "if_many". ---@param bufnr number|nil Buffer number. Defaults to the current buffer. ---@param position table|nil The (0,0)-indexed position. Defaults to the current cursor position. ---@return tuple ({popup_bufnr}, {win_id}) diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index a9d93ae65f..b4557b0e26 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -103,6 +103,7 @@ local function diagnostic_lsp_to_vim(diagnostics, bufnr, client_id) end_col = line_byte_from_position(buf_lines, _end.line, _end.character, offset_encoding), severity = severity_lsp_to_vim(diagnostic.severity), message = diagnostic.message, + source = diagnostic.source, user_data = { lsp = { code = diagnostic.code, @@ -132,6 +133,7 @@ local function diagnostic_vim_to_lsp(diagnostics) }, severity = severity_vim_to_lsp(diagnostic.severity), message = diagnostic.message, + source = diagnostic.source, }, diagnostic.user_data and (diagnostic.user_data.lsp or {}) or {}) end, diagnostics) end -- cgit From bc652f148f6bb03511e36a0d9c3e383bb22abcfa Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Mon, 20 Sep 2021 15:32:14 -0600 Subject: refactor(diagnostic): remove get_virt_text_chunks() This function isn't compatible with including diagnostic sources when "source" is "if_many" since it only has access to diagnostics for a single line. Rather than having an inconsistent or incomplete interface, make this function private. It is still exported as part of the module for backward compatibility with vim.lsp.diagnostics, but it can eventually be made into a local function. --- runtime/doc/deprecated.txt | 4 +++- runtime/doc/diagnostic.txt | 20 -------------------- runtime/lua/vim/diagnostic.lua | 16 ++++++++-------- runtime/lua/vim/lsp/diagnostic.lua | 2 +- 4 files changed, 12 insertions(+), 30 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index a0c291964e..a7ce4135af 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -75,7 +75,9 @@ For each of the functions below, use the corresponding function in *vim.lsp.diagnostic.get_prev()* *vim.lsp.diagnostic.get_prev_pos()* *vim.lsp.diagnostic.get_virtual_text_chunks_for_line()* - Use |vim.diagnostic.get_virt_text_chunks()| instead. + No replacement. Use options provided by + |vim.diagnostic.config()| to customize + virtual text. *vim.lsp.diagnostic.goto_next()* *vim.lsp.diagnostic.goto_prev()* *vim.lsp.diagnostic.redraw()* Use |vim.diagnostic.show()| instead. diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt index 5845f11073..c0ae6a5a1a 100644 --- a/runtime/doc/diagnostic.txt +++ b/runtime/doc/diagnostic.txt @@ -333,26 +333,6 @@ get_prev_pos({opts}) *vim.diagnostic.get_prev_pos()* Return: ~ table Previous diagnostic position as a (row, col) tuple. - *vim.diagnostic.get_virt_text_chunks()* -get_virt_text_chunks({line_diags}, {opts}) - Get virtual text chunks to display using - |nvim_buf_set_extmark()|. - - Parameters: ~ - {line_diags} table The diagnostics associated with the - line. - {opts} table|nil Configuration table with the - following keys: - • prefix: (string) Prefix to display before - virtual text on line. - • spacing: (number) Number of spaces to - insert before virtual text. - - Return: ~ - array of ({text}, {hl_group}) tuples. This can be passed - directly to the {virt_text} option of - |nvim_buf_set_extmark()|. - goto_next({opts}) *vim.diagnostic.goto_next()* Move to the next diagnostic. diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 26ee9ebca5..55bf212389 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -851,6 +851,8 @@ end ---@param opts table|nil Configuration table with the following keys: --- - prefix: (string) Prefix to display before virtual text on line. --- - spacing: (number) Number of spaces to insert before virtual text. +--- - source: (string) Include the diagnostic source in virtual text. One of "always" or +--- "if_many". ---@private function M._set_virtual_text(namespace, bufnr, diagnostics, opts) vim.validate { @@ -872,7 +874,7 @@ function M._set_virtual_text(namespace, bufnr, diagnostics, opts) if opts and opts.severity then line_diagnostics = filter_by_severity(opts.severity, line_diagnostics) end - local virt_texts = M.get_virt_text_chunks(line_diagnostics, opts) + local virt_texts = M._get_virt_text_chunks(line_diagnostics, opts) if virt_texts then vim.api.nvim_buf_set_extmark(bufnr, namespace, line, 0, { @@ -885,13 +887,11 @@ end --- Get virtual text chunks to display using |nvim_buf_set_extmark()|. --- ----@param line_diags table The diagnostics associated with the line. ----@param opts table|nil Configuration table with the following keys: ---- - prefix: (string) Prefix to display before virtual text on line. ---- - spacing: (number) Number of spaces to insert before virtual text. ----@return array of ({text}, {hl_group}) tuples. This can be passed directly to ---- the {virt_text} option of |nvim_buf_set_extmark()|. -function M.get_virt_text_chunks(line_diags, opts) +--- Exported for backward compatibility with +--- vim.lsp.diagnostic.get_virtual_text_chunks_for_line(). When that function is eventually removed, +--- this can be made local. +---@private +function M._get_virt_text_chunks(line_diags, opts) if #line_diags == 0 then return nil end diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index b4557b0e26..c6c08a15d3 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -529,7 +529,7 @@ end ---@return an array of [text, hl_group] arrays. This can be passed directly to --- the {virt_text} option of |nvim_buf_set_extmark()|. function M.get_virtual_text_chunks_for_line(bufnr, _, line_diags, opts) - return vim.diagnostic.get_virt_text_chunks(diagnostic_lsp_to_vim(line_diags, bufnr), opts) + return vim.diagnostic._get_virt_text_chunks(diagnostic_lsp_to_vim(line_diags, bufnr), opts) end --- Open a floating window with the diagnostics from {position} -- cgit