feat(diagnostics)!: sort underline severity_sort (#30898)

feat(diagnostics)!: sort underline with severity_sort

BREAKING CHANGE: underline will be applied with a higher value than `vim.hl.priorities.diagnostics`
This commit is contained in:
Donatas 2024-10-27 18:36:39 +02:00 committed by GitHub
parent adf7c98d60
commit a9e725b26e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 69 additions and 24 deletions

View File

@ -445,10 +445,10 @@ Lua module: vim.diagnostic *diagnostic-api*
updated on |InsertLeave|)
• {severity_sort}? (`boolean|{reverse?:boolean}`, default: `false`)
Sort diagnostics by severity. This affects the
order in which signs and virtual text are
displayed. When true, higher severities are
displayed before lower severities (e.g. ERROR is
displayed before WARN). Options:
order in which signs, virtual text, and
highlights are displayed. When true, higher
severities are displayed before lower severities
(e.g. ERROR is displayed before WARN). Options:
• {reverse}? (boolean) Reverse sort order
• {jump}? (`vim.diagnostic.Opts.Jump`) Default values for
|vim.diagnostic.jump()|. See

View File

@ -55,6 +55,8 @@ DIAGNOSTICS
• |vim.diagnostic.config()| accepts a "jump" table to specify defaults for
|vim.diagnostic.jump()|.
• The "underline" diagnostics handler sorts diagnostics by severity when using
the "severity_sort" option.
EDITOR

View File

@ -71,9 +71,9 @@ local M = {}
--- (default: `false`)
--- @field update_in_insert? boolean
---
--- Sort diagnostics by severity. This affects the order in which signs and
--- virtual text are displayed. When true, higher severities are displayed
--- before lower severities (e.g. ERROR is displayed before WARN).
--- Sort diagnostics by severity. This affects the order in which signs,
--- virtual text, and highlights are displayed. When true, higher severities are
--- displayed before lower severities (e.g. ERROR is displayed before WARN).
--- Options:
--- - {reverse}? (boolean) Reverse sort order
--- (default: `false`)
@ -657,6 +657,28 @@ local function save_extmarks(namespace, bufnr)
api.nvim_buf_get_extmarks(bufnr, namespace, 0, -1, { details = true })
end
--- Create a function that converts a diagnostic severity to an extmark priority.
--- @param priority integer Base priority
--- @param opts vim.diagnostic.OptsResolved
--- @return fun(severity: vim.diagnostic.Severity): integer
local function severity_to_extmark_priority(priority, opts)
if opts.severity_sort then
if type(opts.severity_sort) == 'table' and opts.severity_sort.reverse then
return function(severity)
return priority + (severity - vim.diagnostic.severity.ERROR)
end
end
return function(severity)
return priority + (vim.diagnostic.severity.HINT - severity)
end
end
return function()
return priority
end
end
--- @type table<string,true>
local registered_autocmds = {}
@ -1352,22 +1374,7 @@ M.handlers.signs = {
-- 10 is the default sign priority when none is explicitly specified
local priority = opts.signs and opts.signs.priority or 10
local get_priority --- @type function
if opts.severity_sort then
if type(opts.severity_sort) == 'table' and opts.severity_sort.reverse then
get_priority = function(severity)
return priority + (severity - vim.diagnostic.severity.ERROR)
end
else
get_priority = function(severity)
return priority + (vim.diagnostic.severity.HINT - severity)
end
end
else
get_priority = function()
return priority
end
end
local get_priority = severity_to_extmark_priority(priority, opts)
local ns = M.get_namespace(namespace)
if not ns.user_data.sign_ns then
@ -1478,6 +1485,8 @@ M.handlers.underline = {
end
local underline_ns = ns.user_data.underline_ns
local get_priority = severity_to_extmark_priority(vim.hl.priorities.diagnostics, opts)
for _, diagnostic in ipairs(diagnostics) do
--- @type string?
local higroup = underline_highlight_map[assert(diagnostic.severity)]
@ -1504,7 +1513,7 @@ M.handlers.underline = {
higroup,
{ diagnostic.lnum, diagnostic.col },
{ diagnostic.end_lnum, diagnostic.end_col },
{ priority = vim.hl.priorities.diagnostics }
{ priority = get_priority(diagnostic.severity) }
)
end
save_extmarks(underline_ns, bufnr)

View File

@ -111,6 +111,19 @@ describe('vim.diagnostic', function()
{ details = true }
)
end
---@param ns integer
function _G.get_underline_extmarks(ns)
---@type integer
local underline_ns = vim.diagnostic.get_namespace(ns).user_data.underline_ns
return vim.api.nvim_buf_get_extmarks(
_G.diagnostic_bufnr,
underline_ns,
0,
-1,
{ details = true }
)
end
end)
exec_lua(function()
@ -1813,6 +1826,21 @@ describe('vim.diagnostic', function()
_G.make_info('Info', 4, 4, 4, 4),
})
function _G.get_highest_underline_hl(severity_sort)
vim.diagnostic.config({
underline = true,
severity_sort = severity_sort,
})
local extmarks = _G.get_underline_extmarks(_G.diagnostic_ns)
table.sort(extmarks, function(a, b)
return a[4].priority > b[4].priority
end)
return extmarks[1][4].hl_group
end
function _G.get_virt_text_and_signs(severity_sort)
vim.diagnostic.config({
severity_sort = severity_sort,
@ -1864,6 +1892,12 @@ describe('vim.diagnostic', function()
result = exec_lua [[return _G.get_virt_text_and_signs({ reverse = true })]]
eq({ 'Error', 'Warn', 'Info' }, result[1])
eq({ 'Info', 'Warn', 'Error' }, result[2])
local underline_hl = exec_lua [[return _G.get_highest_underline_hl(true)]]
eq('DiagnosticUnderlineError', underline_hl)
underline_hl = exec_lua [[return _G.get_highest_underline_hl({ reverse = true })]]
eq('DiagnosticUnderlineInfo', underline_hl)
end)
it('can show diagnostic sources in virtual text', function()