commit 2767eac320ef3f422236cbc8ce2228b02e11bd31
parent 5d258854a7fb7df08139c54f5dca1f7f8a490c75
Author: Grzegorz Rozdzialik <voreny.gelio@gmail.com>
Date: Mon, 17 Nov 2025 18:37:59 +0100
feat(diagnostics): stack DiagnosticUnnecessary,DiagnosticDeprecated highlights #36590
Problem: unnecessary and deprecated diagnostics use their own highlight
groups (`DiagnosticUnnecessary` and `DiagnosticDeprecated`) which
override the typical severity-based highlight groups (like
`DiagnosticUnderlineWarn`).
This can be misleading, since diagnostics about unused variables which
are warnings or errors, are shown like comments, since then only the
`DiagnosticUnnecessary` highlight group is used. Users do not see the
more eye-catching red/yellow highlight.
Solution: Instead of overriding the highlight group to
`DiagnosticUnnecessary` or `DiagnosticDeprecated`, set them in addition
to the normal severity-based highlights.
Diffstat:
2 files changed, 42 insertions(+), 12 deletions(-)
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua
@@ -1734,29 +1734,30 @@ M.handlers.underline = {
local get_priority = severity_to_extmark_priority(vim.hl.priorities.diagnostics, opts)
for _, diagnostic in ipairs(diagnostics) do
- local higroup = underline_highlight_map[diagnostic.severity]
+ local higroups = { underline_highlight_map[diagnostic.severity] }
if diagnostic._tags then
- -- TODO(lewis6991): we should be able to stack these.
if diagnostic._tags.unnecessary then
- higroup = 'DiagnosticUnnecessary'
+ table.insert(higroups, 'DiagnosticUnnecessary')
end
if diagnostic._tags.deprecated then
- higroup = 'DiagnosticDeprecated'
+ table.insert(higroups, 'DiagnosticDeprecated')
end
end
local lines =
api.nvim_buf_get_lines(diagnostic.bufnr, diagnostic.lnum, diagnostic.lnum + 1, true)
- vim.hl.range(
- bufnr,
- underline_ns,
- higroup,
- { diagnostic.lnum, math.min(diagnostic.col, #lines[1] - 1) },
- { diagnostic.end_lnum, diagnostic.end_col },
- { priority = get_priority(diagnostic.severity) }
- )
+ for _, higroup in ipairs(higroups) do
+ vim.hl.range(
+ bufnr,
+ underline_ns,
+ higroup,
+ { diagnostic.lnum, math.min(diagnostic.col, #lines[1] - 1) },
+ { diagnostic.end_lnum, diagnostic.end_col },
+ { priority = get_priority(diagnostic.severity) }
+ )
+ end
end
save_extmarks(underline_ns, bufnr)
end)
diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua
@@ -2023,6 +2023,35 @@ describe('vim.diagnostic', function()
eq('DiagnosticUnderlineInfo', underline_hl)
end)
+ it(
+ 'shows deprecated and unnecessary highlights in addition to severity-based highlights',
+ function()
+ ---@type string[]
+ local result = exec_lua(function()
+ local diagnostic = _G.make_error('Some error', 0, 0, 0, 0, 'source x')
+ diagnostic._tags = {
+ deprecated = true,
+ unnecessary = true,
+ }
+
+ local diagnostics = { diagnostic }
+ vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
+
+ local extmarks = _G.get_underline_extmarks(_G.diagnostic_ns)
+ local hl_groups = vim.tbl_map(function(extmark)
+ return extmark[4].hl_group
+ end, extmarks)
+ return hl_groups
+ end)
+
+ eq({
+ 'DiagnosticDeprecated',
+ 'DiagnosticUnnecessary',
+ 'DiagnosticUnderlineError',
+ }, result)
+ end
+ )
+
it('can show diagnostic sources in virtual text', function()
local result = exec_lua(function()
local diagnostics = {