feat(diagnostic)!: filter diagnostics by severity before passing to handlers (#30070)

BREAKING CHANGE: This changes the list of diagnostics that are passed to
a diagnostic handler. If a handler is already filtering by severity
itself then this won't break anything, since the handler's filtering
will become a no-op. But handlers which depend on receiving the full
list of diagnostics may break.

Note that diagnostics are only filtered if the handler's configuration
has the `severity` option set. If `severity` is not set, the handler
still receives the full list of diagnostics.
This commit is contained in:
Gregory Anders 2025-01-11 12:54:43 -06:00 committed by GitHub
parent 9e0d40f7e4
commit a119aae4d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 11 additions and 16 deletions

View File

@ -93,6 +93,10 @@ The {opts} table passed to a handler is the full set of configuration options
values in the table are already resolved (i.e. if a user specifies a
function for a config option, the function has already been evaluated).
If a diagnostic handler is configured with a "severity" key then the list of
diagnostics passed to that handler will be filtered using the value of that
key (see example below).
Nvim provides these handlers by default: "virtual_text", "signs", and
"underline".
@ -119,6 +123,9 @@ with |vim.notify()|: >lua
vim.diagnostic.config({
["my/notify"] = {
log_level = vim.log.levels.INFO
-- This handler will only receive "error" diagnostics.
severity = vim.diagnostic.severity.ERROR,
}
})
<

View File

@ -68,6 +68,8 @@ DIAGNOSTICS
• The "underline" diagnostics handler sorts diagnostics by severity when using
the "severity_sort" option.
• Diagnostics are filtered by severity before being passed to a diagnostic
handler |diagnostic-handlers|.
EDITOR

View File

@ -1395,10 +1395,6 @@ M.handlers.signs = {
return
end
if opts.signs and opts.signs.severity then
diagnostics = filter_by_severity(opts.signs.severity, diagnostics)
end
-- 10 is the default sign priority when none is explicitly specified
local priority = opts.signs and opts.signs.priority or 10
local get_priority = severity_to_extmark_priority(priority, opts)
@ -1501,10 +1497,6 @@ M.handlers.underline = {
return
end
if opts.underline and opts.underline.severity then
diagnostics = filter_by_severity(opts.underline.severity, diagnostics)
end
local ns = M.get_namespace(namespace)
if not ns.user_data.underline_ns then
ns.user_data.underline_ns =
@ -1565,7 +1557,6 @@ M.handlers.virtual_text = {
return
end
local severity --- @type vim.diagnostic.SeverityFilter?
if opts.virtual_text then
if opts.virtual_text.format then
diagnostics = reformat_diagnostics(opts.virtual_text.format, diagnostics)
@ -1576,9 +1567,6 @@ M.handlers.virtual_text = {
then
diagnostics = prefix_source(diagnostics)
end
if opts.virtual_text.severity then
severity = opts.virtual_text.severity
end
end
local ns = M.get_namespace(namespace)
@ -1590,9 +1578,6 @@ M.handlers.virtual_text = {
local virt_text_ns = ns.user_data.virt_text_ns
local buffer_line_diagnostics = diagnostic_lines(diagnostics)
for line, line_diagnostics in pairs(buffer_line_diagnostics) do
if severity then
line_diagnostics = filter_by_severity(severity, line_diagnostics)
end
local virt_texts = M._get_virt_text_chunks(line_diagnostics, opts.virtual_text)
if virt_texts then
@ -1797,7 +1782,8 @@ function M.show(namespace, bufnr, diagnostics, opts)
for handler_name, handler in pairs(M.handlers) do
if handler.show and opts_res[handler_name] then
handler.show(namespace, bufnr, diagnostics, opts_res)
local filtered = filter_by_severity(opts_res[handler_name].severity, diagnostics)
handler.show(namespace, bufnr, filtered, opts_res)
end
end
end