mirror of
https://github.com/neovim/neovim.git
synced 2026-07-10 11:29:39 +00:00
fix(diagnostic): change default severity_sort order
This commit is contained in:
@@ -239,7 +239,9 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
|
||||
• severity_sort: (default false) Sort
|
||||
diagnostics by severity. This affects the
|
||||
order in which signs and virtual text are
|
||||
displayed. Options:
|
||||
displayed. When true, higher severities are
|
||||
displayed before lower severities (e.g.
|
||||
ERROR is displayed before WARN). Options:
|
||||
• reverse: (boolean) Reverse sort order
|
||||
{namespace} number|nil Update the options for the given
|
||||
namespace. When omitted, update the global
|
||||
|
||||
@@ -426,6 +426,70 @@ local function set_list(loclist, opts)
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
local function next_diagnostic(position, search_forward, bufnr, opts, namespace)
|
||||
position[1] = position[1] - 1
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
local wrap = vim.F.if_nil(opts.wrap, true)
|
||||
local line_count = vim.api.nvim_buf_line_count(bufnr)
|
||||
opts.namespace = namespace
|
||||
for i = 0, line_count do
|
||||
local offset = i * (search_forward and 1 or -1)
|
||||
local lnum = position[1] + offset
|
||||
if lnum < 0 or lnum >= line_count then
|
||||
if not wrap then
|
||||
return
|
||||
end
|
||||
lnum = (lnum + line_count) % line_count
|
||||
end
|
||||
opts.lnum = lnum
|
||||
local line_diagnostics = M.get(bufnr, opts)
|
||||
if line_diagnostics and not vim.tbl_isempty(line_diagnostics) then
|
||||
local sort_diagnostics, is_next
|
||||
if search_forward then
|
||||
sort_diagnostics = function(a, b) return a.col < b.col end
|
||||
is_next = function(diagnostic) return diagnostic.col > position[2] end
|
||||
else
|
||||
sort_diagnostics = function(a, b) return a.col > b.col end
|
||||
is_next = function(diagnostic) return diagnostic.col < position[2] end
|
||||
end
|
||||
table.sort(line_diagnostics, sort_diagnostics)
|
||||
if i == 0 then
|
||||
for _, v in pairs(line_diagnostics) do
|
||||
if is_next(v) then
|
||||
return v
|
||||
end
|
||||
end
|
||||
else
|
||||
return line_diagnostics[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
local function diagnostic_move_pos(opts, pos)
|
||||
opts = opts or {}
|
||||
|
||||
local enable_popup = vim.F.if_nil(opts.enable_popup, true)
|
||||
local win_id = opts.win_id or vim.api.nvim_get_current_win()
|
||||
|
||||
if not pos then
|
||||
vim.api.nvim_echo({{"No more valid diagnostics to move to", "WarningMsg"}}, true, {})
|
||||
return
|
||||
end
|
||||
|
||||
vim.api.nvim_win_set_cursor(win_id, {pos[1] + 1, pos[2]})
|
||||
|
||||
if enable_popup then
|
||||
-- This is a bit weird... I'm surprised that we need to wait til the next tick to do this.
|
||||
vim.schedule(function()
|
||||
M.show_position_diagnostics(opts.popup_opts, vim.api.nvim_win_get_buf(win_id))
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- }}}
|
||||
|
||||
-- Public API {{{
|
||||
@@ -452,7 +516,9 @@ end
|
||||
--- - update_in_insert: (default false) Update diagnostics in Insert mode (if false,
|
||||
--- diagnostics are updated on InsertLeave)
|
||||
--- - severity_sort: (default false) Sort diagnostics by severity. This affects the order in
|
||||
--- which signs and virtual text are displayed. Options:
|
||||
--- which signs and virtual text are displayed. When true, higher severities
|
||||
--- are displayed before lower severities (e.g. ERROR is displayed before WARN).
|
||||
--- Options:
|
||||
--- * reverse: (boolean) Reverse sort order
|
||||
---@param namespace number|nil Update the options for the given namespace. When omitted, update the
|
||||
--- global diagnostic options.
|
||||
@@ -594,70 +660,6 @@ function M.get(bufnr, opts)
|
||||
return diagnostics
|
||||
end
|
||||
|
||||
-- Diagnostic Movements {{{
|
||||
|
||||
local next_diagnostic = function(position, search_forward, bufnr, opts, namespace)
|
||||
position[1] = position[1] - 1
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
local wrap = vim.F.if_nil(opts.wrap, true)
|
||||
local line_count = vim.api.nvim_buf_line_count(bufnr)
|
||||
opts.namespace = namespace
|
||||
for i = 0, line_count do
|
||||
local offset = i * (search_forward and 1 or -1)
|
||||
local lnum = position[1] + offset
|
||||
if lnum < 0 or lnum >= line_count then
|
||||
if not wrap then
|
||||
return
|
||||
end
|
||||
lnum = (lnum + line_count) % line_count
|
||||
end
|
||||
opts.lnum = lnum
|
||||
local line_diagnostics = M.get(bufnr, opts)
|
||||
if line_diagnostics and not vim.tbl_isempty(line_diagnostics) then
|
||||
local sort_diagnostics, is_next
|
||||
if search_forward then
|
||||
sort_diagnostics = function(a, b) return a.col < b.col end
|
||||
is_next = function(diagnostic) return diagnostic.col > position[2] end
|
||||
else
|
||||
sort_diagnostics = function(a, b) return a.col > b.col end
|
||||
is_next = function(diagnostic) return diagnostic.col < position[2] end
|
||||
end
|
||||
table.sort(line_diagnostics, sort_diagnostics)
|
||||
if i == 0 then
|
||||
for _, v in pairs(line_diagnostics) do
|
||||
if is_next(v) then
|
||||
return v
|
||||
end
|
||||
end
|
||||
else
|
||||
return line_diagnostics[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
local function diagnostic_move_pos(opts, pos)
|
||||
opts = opts or {}
|
||||
|
||||
local enable_popup = vim.F.if_nil(opts.enable_popup, true)
|
||||
local win_id = opts.win_id or vim.api.nvim_get_current_win()
|
||||
|
||||
if not pos then
|
||||
vim.api.nvim_echo({{"No more valid diagnostics to move to", "WarningMsg"}}, true, {})
|
||||
return
|
||||
end
|
||||
|
||||
vim.api.nvim_win_set_cursor(win_id, {pos[1] + 1, pos[2]})
|
||||
|
||||
if enable_popup then
|
||||
-- This is a bit weird... I'm surprised that we need to wait til the next tick to do this.
|
||||
vim.schedule(function()
|
||||
M.show_position_diagnostics(opts.popup_opts, vim.api.nvim_win_get_buf(win_id))
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
--- Get the previous diagnostic closest to the cursor position.
|
||||
---
|
||||
---@param opts table See |vim.diagnostic.goto_next()|
|
||||
@@ -998,9 +1000,9 @@ function M.show(namespace, bufnr, diagnostics, opts)
|
||||
|
||||
if vim.F.if_nil(opts.severity_sort, false) then
|
||||
if type(opts.severity_sort) == "table" and opts.severity_sort.reverse then
|
||||
table.sort(diagnostics, function(a, b) return a.severity > b.severity end)
|
||||
else
|
||||
table.sort(diagnostics, function(a, b) return a.severity < b.severity end)
|
||||
else
|
||||
table.sort(diagnostics, function(a, b) return a.severity > b.severity end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
local log = require('vim.lsp.log')
|
||||
|
||||
---@brief lsp-diagnostic
|
||||
---
|
||||
---@class Diagnostic
|
||||
@@ -202,11 +200,9 @@ function M.on_publish_diagnostics(_, result, ctx, config)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vim.diagnostic.config(config, namespace)
|
||||
end
|
||||
|
||||
vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id))
|
||||
vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id), config)
|
||||
|
||||
-- Keep old autocmd for back compat. This should eventually be removed.
|
||||
vim.api.nvim_command("doautocmd <nomodeline> User LspDiagnosticsChanged")
|
||||
@@ -468,10 +464,7 @@ function M.set_signs(diagnostics, bufnr, client_id, _, opts)
|
||||
opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
|
||||
end
|
||||
|
||||
local ok = vim.diagnostic._set_signs(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id), opts)
|
||||
if not ok then
|
||||
log.debug("Failed to place signs:", diagnostics)
|
||||
end
|
||||
vim.diagnostic._set_signs(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id), opts)
|
||||
end
|
||||
|
||||
--- Set underline for given diagnostics
|
||||
|
||||
@@ -540,11 +540,11 @@ describe('vim.diagnostic', function()
|
||||
end)
|
||||
|
||||
it('allows sorting by severity', function()
|
||||
local result = exec_lua([[
|
||||
exec_lua [[
|
||||
vim.diagnostic.config({
|
||||
underline = true,
|
||||
virtual_text = false,
|
||||
severity_sort = false,
|
||||
underline = false,
|
||||
signs = true,
|
||||
virtual_text = true,
|
||||
})
|
||||
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
|
||||
@@ -553,31 +553,41 @@ describe('vim.diagnostic', function()
|
||||
make_info('Info', 4, 4, 4, 4),
|
||||
})
|
||||
|
||||
local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})
|
||||
function get_virt_text_and_signs(severity_sort)
|
||||
vim.diagnostic.config({
|
||||
severity_sort = severity_sort,
|
||||
})
|
||||
|
||||
local warn_highlight = extmarks[1][4].hl_group
|
||||
local virt_text = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})[1][4].virt_text
|
||||
|
||||
vim.diagnostic.config({
|
||||
severity_sort = true,
|
||||
})
|
||||
local virt_texts = {}
|
||||
for i = 2, #virt_text do
|
||||
table.insert(virt_texts, (string.gsub(virt_text[i][2], "DiagnosticVirtualText", "")))
|
||||
end
|
||||
|
||||
extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})
|
||||
local signs = {}
|
||||
for _, v in ipairs(vim.fn.sign_getplaced(diagnostic_bufnr, {group = "*"})[1].signs) do
|
||||
table.insert(signs, (string.gsub(v.name, "DiagnosticSign", "")))
|
||||
end
|
||||
|
||||
local err_highlight = extmarks[1][4].hl_group
|
||||
return {virt_texts, signs}
|
||||
end
|
||||
]]
|
||||
|
||||
vim.diagnostic.config({
|
||||
severity_sort = { reverse = true },
|
||||
})
|
||||
local result = exec_lua [[return get_virt_text_and_signs(false)]]
|
||||
|
||||
extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})
|
||||
-- Virt texts are defined lowest priority to highest, signs from
|
||||
-- highest to lowest
|
||||
eq({'Warn', 'Error', 'Info'}, result[1])
|
||||
eq({'Info', 'Error', 'Warn'}, result[2])
|
||||
|
||||
local info_highlight = extmarks[1][4].hl_group
|
||||
result = exec_lua [[return get_virt_text_and_signs(true)]]
|
||||
eq({'Info', 'Warn', 'Error'}, result[1])
|
||||
eq({'Error', 'Warn', 'Info'}, result[2])
|
||||
|
||||
return { warn_highlight, err_highlight, info_highlight }
|
||||
]])
|
||||
eq('DiagnosticUnderlineWarn', result[1])
|
||||
eq('DiagnosticUnderlineError', result[2])
|
||||
eq('DiagnosticUnderlineInfo', result[3])
|
||||
result = exec_lua [[return get_virt_text_and_signs({ reverse = true })]]
|
||||
eq({'Error', 'Warn', 'Info'}, result[1])
|
||||
eq({'Info', 'Warn', 'Error'}, result[2])
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user