neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit bc4bddbb214fa92e3689c0e4abb78d21d80223e0
parent 3c7b698d61c97c63858089e23879f1849e938769
Author: Sergei Slipchenko <faergeek@gmail.com>
Date:   Tue, 12 Aug 2025 02:34:29 +0400

fix: don't use logical diagnostic position in `get_prev` and `get_next` #35282

Problem: `vim.diagnostic.get_prev()` / `vim.diagnostic.get_next()` use
logical diagnostic positions and consider extmark validity.
`vim.diagnostic.get()` only uses original positions and doesn't care
about extmark validity. This results in inconsistency between these
APIs.

Solution: use original positions in `vim.diagnostic.get_prev()` and
`vim.diagnostic.get_next()` and don't consider extmark validity to match
previous behavior, which is consistent with `vim.diagnostic.get`.
Diffstat:
Mruntime/lua/vim/diagnostic.lua | 31+++++++++++++++++++++----------
1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua @@ -643,6 +643,7 @@ local underline_highlight_map = make_highlight_map('Underline') local floating_highlight_map = make_highlight_map('Floating') local sign_highlight_map = make_highlight_map('Sign') +--- Get a position based on an extmark referenced by `_extmark_id` field --- @param diagnostic vim.Diagnostic --- @return integer lnum --- @return integer col @@ -662,15 +663,24 @@ local function get_logical_pos(diagnostic) end --- @param diagnostics vim.Diagnostic[] +--- @param use_logical_pos boolean --- @return table<integer,vim.Diagnostic[]> -local function diagnostic_lines(diagnostics) +local function diagnostic_lines(diagnostics, use_logical_pos) if not diagnostics then return {} end local diagnostics_by_line = {} --- @type table<integer,vim.Diagnostic[]> for _, diagnostic in ipairs(diagnostics) do - local lnum, _, _, _, valid = get_logical_pos(diagnostic) + local lnum ---@type integer + local valid ---@type boolean + + if use_logical_pos then + lnum, _, _, _, valid = get_logical_pos(diagnostic) + else + lnum, valid = diagnostic.lnum, true + end + if valid then local line_diagnostics = diagnostics_by_line[lnum] if not line_diagnostics then @@ -1024,8 +1034,9 @@ end --- @param search_forward boolean --- @param opts vim.diagnostic.JumpOpts? +--- @param use_logical_pos boolean --- @return vim.Diagnostic? -local function next_diagnostic(search_forward, opts) +local function next_diagnostic(search_forward, opts, use_logical_pos) opts = opts or {} --- @cast opts vim.diagnostic.JumpOpts1 @@ -1058,12 +1069,12 @@ local function next_diagnostic(search_forward, opts) filter_highest(diagnostics) end - local line_diagnostics = diagnostic_lines(diagnostics) + local line_diagnostics = diagnostic_lines(diagnostics, use_logical_pos) --- @param diagnostic vim.Diagnostic --- @return integer local function col(diagnostic) - return select(2, get_logical_pos(diagnostic)) + return use_logical_pos and select(2, get_logical_pos(diagnostic)) or diagnostic.col end local line_count = api.nvim_buf_line_count(bufnr) @@ -1424,7 +1435,7 @@ end ---@param opts? vim.diagnostic.JumpOpts ---@return vim.Diagnostic? : Previous diagnostic function M.get_prev(opts) - return next_diagnostic(false, opts) + return next_diagnostic(false, opts, false) end --- Return the position of the previous diagnostic in the current buffer. @@ -1464,7 +1475,7 @@ end ---@param opts? vim.diagnostic.JumpOpts ---@return vim.Diagnostic? : Next diagnostic function M.get_next(opts) - return next_diagnostic(true, opts) + return next_diagnostic(true, opts, false) end --- Return the position of the next diagnostic in the current buffer. @@ -1582,7 +1593,7 @@ function M.jump(opts) local diag = nil while count ~= 0 do - local next = next_diagnostic(count > 0, opts) + local next = next_diagnostic(count > 0, opts, true) if not next then break end @@ -1814,7 +1825,7 @@ M.handlers.virtual_text = { api.nvim_clear_autocmds({ group = ns.user_data.virt_text_augroup, buffer = bufnr }) - local line_diagnostics = diagnostic_lines(diagnostics) + local line_diagnostics = diagnostic_lines(diagnostics, true) if opts.virtual_text.current_line ~= nil then api.nvim_create_autocmd('CursorMoved', { @@ -2067,7 +2078,7 @@ M.handlers.virtual_lines = { if opts.virtual_lines.current_line == true then -- Create a mapping from line -> diagnostics so that we can quickly get the -- diagnostics we need when the cursor line doesn't change. - local line_diagnostics = diagnostic_lines(diagnostics) + local line_diagnostics = diagnostic_lines(diagnostics, true) api.nvim_create_autocmd('CursorMoved', { buffer = bufnr, group = ns.user_data.virt_lines_augroup,