mirror of
https://github.com/neovim/neovim.git
synced 2025-09-05 19:08:15 +00:00
fix(diagnostics): avoid jumping to diagnostics in deleted ranges #35088
Problem: diagnostic extmark used for positioning continues to exist after deleting a range containing it, so it's possible to jump to a next/previous diagnositc, which isn't visible in any way, including not being shown via `open_float`. Solution: enable `invalidate` flag when setting an extmark to be able to filter out diagnostics based on `invalid` flag when looking for next/previous diagnostic to jump to.
This commit is contained in:

committed by
GitHub

parent
5151f635ca
commit
7a051a4c38
@@ -648,6 +648,7 @@ local sign_highlight_map = make_highlight_map('Sign')
|
||||
--- @return integer col
|
||||
--- @return integer end_lnum
|
||||
--- @return integer end_col
|
||||
--- @return boolean valid
|
||||
local function get_logical_pos(diagnostic)
|
||||
local ns = M.get_namespace(diagnostic.namespace)
|
||||
local extmark = api.nvim_buf_get_extmark_by_id(
|
||||
@@ -657,7 +658,7 @@ local function get_logical_pos(diagnostic)
|
||||
{ details = true }
|
||||
)
|
||||
|
||||
return extmark[1], extmark[2], extmark[3].end_row, extmark[3].end_col
|
||||
return extmark[1], extmark[2], extmark[3].end_row, extmark[3].end_col, not extmark[3].invalid
|
||||
end
|
||||
|
||||
--- @param diagnostics vim.Diagnostic[]
|
||||
@@ -669,13 +670,15 @@ local function diagnostic_lines(diagnostics)
|
||||
|
||||
local diagnostics_by_line = {} --- @type table<integer,vim.Diagnostic[]>
|
||||
for _, diagnostic in ipairs(diagnostics) do
|
||||
local lnum = get_logical_pos(diagnostic)
|
||||
local line_diagnostics = diagnostics_by_line[lnum]
|
||||
if not line_diagnostics then
|
||||
line_diagnostics = {}
|
||||
diagnostics_by_line[lnum] = line_diagnostics
|
||||
local lnum, _, _, _, valid = get_logical_pos(diagnostic)
|
||||
if valid then
|
||||
local line_diagnostics = diagnostics_by_line[lnum]
|
||||
if not line_diagnostics then
|
||||
line_diagnostics = {}
|
||||
diagnostics_by_line[lnum] = line_diagnostics
|
||||
end
|
||||
table.insert(line_diagnostics, diagnostic)
|
||||
end
|
||||
table.insert(line_diagnostics, diagnostic)
|
||||
end
|
||||
return diagnostics_by_line
|
||||
end
|
||||
@@ -1332,6 +1335,7 @@ function M.set(namespace, bufnr, diagnostics, opts)
|
||||
diagnostic._extmark_id = api.nvim_buf_set_extmark(bufnr, ns.user_data.location_ns, row, col, {
|
||||
end_row = end_row,
|
||||
end_col = end_col,
|
||||
invalidate = true,
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
@@ -1433,15 +1433,6 @@ describe('vim.diagnostic', function()
|
||||
|
||||
describe('after inserting text before diagnostic position', function()
|
||||
before_each(function()
|
||||
exec_lua(function()
|
||||
vim.api.nvim_set_current_buf(_G.diagnostic_bufnr)
|
||||
|
||||
vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
|
||||
_G.make_error('Diagnostic #1', 1, 4, 1, 7),
|
||||
_G.make_error('Diagnostic #2', 3, 0, 3, 3),
|
||||
})
|
||||
end)
|
||||
|
||||
api.nvim_buf_set_text(0, 3, 0, 3, 0, { 'new line', 'new ' })
|
||||
end)
|
||||
|
||||
@@ -1449,7 +1440,7 @@ describe('vim.diagnostic', function()
|
||||
eq(
|
||||
{ 5, 4 },
|
||||
exec_lua(function()
|
||||
vim.api.nvim_win_set_cursor(0, { 2, 4 })
|
||||
vim.api.nvim_win_set_cursor(0, { 3, 1 })
|
||||
vim.diagnostic.jump({ count = 1 })
|
||||
return vim.api.nvim_win_get_cursor(0)
|
||||
end)
|
||||
@@ -1471,8 +1462,6 @@ describe('vim.diagnostic', function()
|
||||
describe('if diagnostic is set after last character in line', function()
|
||||
before_each(function()
|
||||
exec_lua(function()
|
||||
vim.api.nvim_set_current_buf(_G.diagnostic_bufnr)
|
||||
|
||||
vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
|
||||
_G.make_error('Diagnostic #1', 2, 3, 3, 4),
|
||||
})
|
||||
@@ -1501,6 +1490,34 @@ describe('vim.diagnostic', function()
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('after entire text range with a diagnostic was deleted', function()
|
||||
before_each(function()
|
||||
api.nvim_buf_set_text(0, 1, 1, 1, 4, {})
|
||||
end)
|
||||
|
||||
it('does not find next diagnostic inside the deleted range', function()
|
||||
eq(
|
||||
{ 3, 0 },
|
||||
exec_lua(function()
|
||||
vim.api.nvim_win_set_cursor(0, { 1, 0 })
|
||||
vim.diagnostic.jump({ count = 1 })
|
||||
return vim.api.nvim_win_get_cursor(0)
|
||||
end)
|
||||
)
|
||||
end)
|
||||
|
||||
it('does not find previous diagnostic inside the deleted range', function()
|
||||
eq(
|
||||
{ 1, 0 },
|
||||
exec_lua(function()
|
||||
vim.api.nvim_win_set_cursor(0, { 3, 0 })
|
||||
vim.diagnostic.jump({ count = -1 })
|
||||
return vim.api.nvim_win_get_cursor(0)
|
||||
end)
|
||||
)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('get()', function()
|
||||
|
Reference in New Issue
Block a user