feat(diagnostic): format() can filter diagnostics by returning nil #32302

This commit is contained in:
Maria José Solano
2025-02-03 00:54:31 -08:00
committed by GitHub
parent 3a28930157
commit 445ecca398
4 changed files with 67 additions and 22 deletions

View File

@@ -376,6 +376,10 @@ Where possible, these patterns apply to _both_ Lua and the API:
- See |vim.lsp.inlay_hint.enable()| and |vim.lsp.inlay_hint.is_enabled()| - See |vim.lsp.inlay_hint.enable()| and |vim.lsp.inlay_hint.is_enabled()|
for a reference implementation of these "best practices". for a reference implementation of these "best practices".
- NOTE: open questions: https://github.com/neovim/neovim/issues/28603 - NOTE: open questions: https://github.com/neovim/neovim/issues/28603
- Transformation functions should also have a filter functionality when
appropriate. That is, when the function returns a nil value it "filters" its
input, otherwise the transformed value is used.
- Example: |vim.diagnostic.config.format()|
API DESIGN GUIDELINES *dev-api* API DESIGN GUIDELINES *dev-api*

View File

@@ -532,11 +532,13 @@ Lua module: vim.diagnostic *diagnostic-api*
the buffer. Otherwise, any truthy value means to the buffer. Otherwise, any truthy value means to
always show the diagnostic source. Overrides the always show the diagnostic source. Overrides the
setting from |vim.diagnostic.config()|. setting from |vim.diagnostic.config()|.
• {format}? (`fun(diagnostic:vim.Diagnostic): string`) A • {format}? (`fun(diagnostic:vim.Diagnostic): string?`) A
function that takes a diagnostic as input and function that takes a diagnostic as input and
returns a string. The return value is the text used returns a string or nil. If the return value is nil,
to display the diagnostic. Overrides the setting the diagnostic is not displayed by the handler. Else
from |vim.diagnostic.config()|. the output text is used to display the diagnostic.
Overrides the setting from
|vim.diagnostic.config()|.
• {prefix}? (`string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string)`) • {prefix}? (`string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string)`)
Prefix each diagnostic in the floating window: Prefix each diagnostic in the floating window:
• If a `function`, {i} is the index of the • If a `function`, {i} is the index of the
@@ -607,10 +609,11 @@ Lua module: vim.diagnostic *diagnostic-api*
Fields: ~ Fields: ~
• {current_line}? (`boolean`, default: `false`) Only show diagnostics • {current_line}? (`boolean`, default: `false`) Only show diagnostics
for the current line. for the current line.
• {format}? (`fun(diagnostic:vim.Diagnostic): string`) A function • {format}? (`fun(diagnostic:vim.Diagnostic): string?`) A
that takes a diagnostic as input and returns a function that takes a diagnostic as input and returns
string. The return value is the text used to display a string or nil. If the return value is nil, the
the diagnostic. diagnostic is not displayed by the handler. Else the
output text is used to display the diagnostic.
*vim.diagnostic.Opts.VirtualText* *vim.diagnostic.Opts.VirtualText*
@@ -635,9 +638,9 @@ Lua module: vim.diagnostic *diagnostic-api*
• {suffix}? (`string|(fun(diagnostic:vim.Diagnostic): string)`) • {suffix}? (`string|(fun(diagnostic:vim.Diagnostic): string)`)
Append diagnostic message with suffix. This can Append diagnostic message with suffix. This can
be used to render an LSP diagnostic error code. be used to render an LSP diagnostic error code.
• {format}? (`fun(diagnostic:vim.Diagnostic): string`) The • {format}? (`fun(diagnostic:vim.Diagnostic): string?`) If
return value is the text used to display the not nil, the return value is the text used to
diagnostic. Example: >lua display the diagnostic. Example: >lua
function(diagnostic) function(diagnostic)
if diagnostic.severity == vim.diagnostic.severity.ERROR then if diagnostic.severity == vim.diagnostic.severity.ERROR then
return string.format("E: %s", diagnostic.message) return string.format("E: %s", diagnostic.message)
@@ -645,6 +648,9 @@ Lua module: vim.diagnostic *diagnostic-api*
return diagnostic.message return diagnostic.message
end end
< <
If the return value is nil, the diagnostic is
not displayed by the handler.
• {hl_mode}? (`'replace'|'combine'|'blend'`) See • {hl_mode}? (`'replace'|'combine'|'blend'`) See
|nvim_buf_set_extmark()|. |nvim_buf_set_extmark()|.
• {virt_text}? (`[string,any][]`) See |nvim_buf_set_extmark()|. • {virt_text}? (`[string,any][]`) See |nvim_buf_set_extmark()|.

View File

@@ -150,10 +150,11 @@ end
--- Overrides the setting from |vim.diagnostic.config()|. --- Overrides the setting from |vim.diagnostic.config()|.
--- @field source? boolean|'if_many' --- @field source? boolean|'if_many'
--- ---
--- A function that takes a diagnostic as input and returns a string. --- A function that takes a diagnostic as input and returns a string or nil.
--- The return value is the text used to display the diagnostic. --- If the return value is nil, the diagnostic is not displayed by the handler.
--- Else the output text is used to display the diagnostic.
--- Overrides the setting from |vim.diagnostic.config()|. --- Overrides the setting from |vim.diagnostic.config()|.
--- @field format? fun(diagnostic:vim.Diagnostic): string --- @field format? fun(diagnostic:vim.Diagnostic): string?
--- ---
--- Prefix each diagnostic in the floating window: --- Prefix each diagnostic in the floating window:
--- - If a `function`, {i} is the index of the diagnostic being evaluated and --- - If a `function`, {i} is the index of the diagnostic being evaluated and
@@ -207,7 +208,7 @@ end
--- This can be used to render an LSP diagnostic error code. --- This can be used to render an LSP diagnostic error code.
--- @field suffix? string|(fun(diagnostic:vim.Diagnostic): string) --- @field suffix? string|(fun(diagnostic:vim.Diagnostic): string)
--- ---
--- The return value is the text used to display the diagnostic. Example: --- If not nil, the return value is the text used to display the diagnostic. Example:
--- ```lua --- ```lua
--- function(diagnostic) --- function(diagnostic)
--- if diagnostic.severity == vim.diagnostic.severity.ERROR then --- if diagnostic.severity == vim.diagnostic.severity.ERROR then
@@ -216,7 +217,8 @@ end
--- return diagnostic.message --- return diagnostic.message
--- end --- end
--- ``` --- ```
--- @field format? fun(diagnostic:vim.Diagnostic): string --- If the return value is nil, the diagnostic is not displayed by the handler.
--- @field format? fun(diagnostic:vim.Diagnostic): string?
--- ---
--- See |nvim_buf_set_extmark()|. --- See |nvim_buf_set_extmark()|.
--- @field hl_mode? 'replace'|'combine'|'blend' --- @field hl_mode? 'replace'|'combine'|'blend'
@@ -239,9 +241,10 @@ end
--- (default: `false`) --- (default: `false`)
--- @field current_line? boolean --- @field current_line? boolean
--- ---
--- A function that takes a diagnostic as input and returns a string. --- A function that takes a diagnostic as input and returns a string or nil.
--- The return value is the text used to display the diagnostic. --- If the return value is nil, the diagnostic is not displayed by the handler.
--- @field format? fun(diagnostic:vim.Diagnostic): string --- Else the output text is used to display the diagnostic.
--- @field format? fun(diagnostic:vim.Diagnostic): string?
--- @class vim.diagnostic.Opts.Signs --- @class vim.diagnostic.Opts.Signs
--- ---
@@ -503,15 +506,21 @@ local function prefix_source(diagnostics)
end, diagnostics) end, diagnostics)
end end
--- @param format fun(vim.Diagnostic): string?
--- @param diagnostics vim.Diagnostic[] --- @param diagnostics vim.Diagnostic[]
--- @return vim.Diagnostic[] --- @return vim.Diagnostic[]
local function reformat_diagnostics(format, diagnostics) local function reformat_diagnostics(format, diagnostics)
vim.validate('format', format, 'function') vim.validate('format', format, 'function')
vim.validate('diagnostics', diagnostics, vim.islist, 'a list of diagnostics') vim.validate('diagnostics', diagnostics, vim.islist, 'a list of diagnostics')
local formatted = vim.deepcopy(diagnostics, true) local formatted = {}
for _, diagnostic in ipairs(formatted) do for _, diagnostic in ipairs(diagnostics) do
diagnostic.message = format(diagnostic) local message = format(diagnostic)
if message ~= nil then
local formatted_diagnostic = vim.deepcopy(diagnostic, true)
formatted_diagnostic.message = message
table.insert(formatted, formatted_diagnostic)
end
end end
return formatted return formatted
end end

View File

@@ -2134,6 +2134,32 @@ describe('vim.diagnostic', function()
end) end)
) )
end) end)
it('can filter diagnostics by returning nil when formatting', function()
local result = exec_lua(function()
vim.diagnostic.config {
virtual_text = {
format = function(diagnostic)
if diagnostic.code == 'foo_err' then
return nil
end
return diagnostic.message
end,
},
}
vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
_G.make_error('An error here!', 0, 0, 0, 0, 'foo_server', 'foo_err'),
_G.make_error('An error there!', 1, 1, 1, 1, 'bar_server', 'bar_err'),
})
local extmarks = _G.get_virt_text_extmarks(_G.diagnostic_ns)
return extmarks
end)
eq(1, #result)
eq(' An error there!', result[1][4].virt_text[3][1])
end)
end) end)
describe('handlers.virtual_lines', function() describe('handlers.virtual_lines', function()