mirror of
https://github.com/neovim/neovim.git
synced 2025-12-15 19:05:40 +00:00
fix(diagnostics): position diagnostics using extmarks #34014
Problem: Diagnostic positions are not being updated after text changes, which means `vim.diagnostic.open_float` and `vim.diagnostic.jump` will work with outdated positions when text is changed until diagnostics are updated again (if ever). Solution: Create extmarks in `vim.diagnostic.set` and use their positions for `vim.diagnostic.open_float` and `next_diagnostic` (used by `vim.diagnostic.jump`, `vim.diagnostic.get_next` and `vim.diagnostic.get_prev`).
This commit is contained in:
committed by
GitHub
parent
e4a100a1e1
commit
0a113013fb
@@ -1430,6 +1430,77 @@ describe('vim.diagnostic', function()
|
||||
eq(true, exec_lua('return _G.jumped'))
|
||||
end)
|
||||
end)
|
||||
|
||||
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)
|
||||
|
||||
it('finds next diagnostic at a logical location', function()
|
||||
eq(
|
||||
{ 5, 4 },
|
||||
exec_lua(function()
|
||||
vim.api.nvim_win_set_cursor(0, { 2, 4 })
|
||||
vim.diagnostic.jump({ count = 1 })
|
||||
return vim.api.nvim_win_get_cursor(0)
|
||||
end)
|
||||
)
|
||||
end)
|
||||
|
||||
it('finds previous diagnostic at a logical location', function()
|
||||
eq(
|
||||
{ 5, 4 },
|
||||
exec_lua(function()
|
||||
vim.api.nvim_win_set_cursor(0, { 6, 4 })
|
||||
vim.diagnostic.jump({ count = -1 })
|
||||
return vim.api.nvim_win_get_cursor(0)
|
||||
end)
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
||||
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),
|
||||
})
|
||||
end)
|
||||
end)
|
||||
|
||||
it('finds next diagnostic at the end of the line', function()
|
||||
eq(
|
||||
{ 3, 2 },
|
||||
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)
|
||||
|
||||
it('finds previous diagnostic at the end of the line', function()
|
||||
eq(
|
||||
{ 3, 2 },
|
||||
exec_lua(function()
|
||||
vim.api.nvim_win_set_cursor(0, { 4, 2 })
|
||||
vim.diagnostic.jump({ count = -1 })
|
||||
return vim.api.nvim_win_get_cursor(0)
|
||||
end)
|
||||
)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('get()', function()
|
||||
@@ -2924,7 +2995,7 @@ describe('vim.diagnostic', function()
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({
|
||||
header = false,
|
||||
scope = 'cursor',
|
||||
pos = { 0, first_line_len },
|
||||
pos = { 0, first_line_len - 1 },
|
||||
})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
@@ -2959,7 +3030,7 @@ describe('vim.diagnostic', function()
|
||||
vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
|
||||
vim.api.nvim_win_set_cursor(0, { 1, 1 })
|
||||
local float_bufnr, winnr =
|
||||
vim.diagnostic.open_float({ header = false, scope = 'cursor', pos = { 2, 1 } })
|
||||
vim.diagnostic.open_float({ header = false, scope = 'cursor', pos = { 2, 0 } })
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@@ -3564,6 +3635,88 @@ describe('vim.diagnostic', function()
|
||||
end)
|
||||
)
|
||||
end)
|
||||
|
||||
it('shows diagnostics at their logical locations after text changes before', 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 ' })
|
||||
|
||||
eq(
|
||||
{ 'Diagnostic #1' },
|
||||
exec_lua(function()
|
||||
vim.api.nvim_win_set_cursor(0, { 2, 4 })
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({ header = '', scope = 'cursor' })
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
end)
|
||||
)
|
||||
|
||||
eq(
|
||||
{ 'Diagnostic #2' },
|
||||
exec_lua(function()
|
||||
vim.api.nvim_win_set_cursor(0, { 5, 4 })
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({ header = '', scope = 'cursor' })
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
end)
|
||||
)
|
||||
end)
|
||||
|
||||
it('shows diagnostics at their logical locations after text changes inside', 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, 0, 1, 7),
|
||||
})
|
||||
end)
|
||||
|
||||
api.nvim_buf_set_text(0, 1, 4, 1, 4, { 'new ' })
|
||||
|
||||
eq(
|
||||
{ 'Diagnostic #1' },
|
||||
exec_lua(function()
|
||||
vim.api.nvim_win_set_cursor(0, { 2, 10 })
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({ header = '', scope = 'cursor' })
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
end)
|
||||
)
|
||||
end)
|
||||
|
||||
it(
|
||||
'shows diagnostics at the end of the line if diagnostic is set after last character in line',
|
||||
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),
|
||||
})
|
||||
end)
|
||||
|
||||
eq(
|
||||
{ 'Diagnostic #1' },
|
||||
exec_lua(function()
|
||||
vim.api.nvim_win_set_cursor(0, { 3, 2 })
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({ header = '', scope = 'cursor' })
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
end)
|
||||
)
|
||||
end
|
||||
)
|
||||
end)
|
||||
|
||||
describe('setloclist()', function()
|
||||
@@ -3840,9 +3993,9 @@ describe('vim.diagnostic', function()
|
||||
local list = vim.fn.getqflist()
|
||||
local new_diagnostics = vim.diagnostic.fromqflist(list)
|
||||
|
||||
-- Remove namespace since it isn't present in the return value of
|
||||
-- fromlist()
|
||||
-- Remove extra properties not present in the return value of fromlist()
|
||||
for _, v in ipairs(diagnostics) do
|
||||
v._extmark_id = nil
|
||||
v.namespace = nil
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user