aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua
diff options
context:
space:
mode:
authorpenglei <lambit@qq.com>2026-07-20 18:59:21 +0800
committerGitHub <noreply@github.com>2026-07-20 06:59:21 -0400
commit84fd9214cc71860e8bcbcdbdb4bd45bf00cabf50 (patch)
treef32085f84ce274c15e57fd3b20aa7afca1b57ad6 /runtime/lua
parent09a4cc8c50285fa5c7c094650f505de11f90dccc (diff)
downloadrneovim-84fd9214cc71860e8bcbcdbdb4bd45bf00cabf50.tar.gz
rneovim-84fd9214cc71860e8bcbcdbdb4bd45bf00cabf50.tar.bz2
rneovim-84fd9214cc71860e8bcbcdbdb4bd45bf00cabf50.zip
fix(diagnostic): skip out-of-range lnum in underline handler #40839
Problem: `vim.diagnostic.handlers.underline.show` throws `E565: Index out of bounds` when it tries to underline a diagnostic whose `lnum` is past the end of the buffer. This happens with stale diagnostics set on an unloaded buffer (e.g. via `bufadd()`) that are drawn only after the buffer is loaded: by then the file on disk can be shorter than the `lnum` the diagnostic carried. File pickers (snacks.nvim) that open files via `bufadd` + `:buffer` hit this whenever an LSP server has already emitted diagnostics for that URI. Solution: Skip diagnostics with an out-of-range `lnum` in the underline handler. Other handlers `M.virtual_text.show()`, `M.signs.show()`, have a similar condition.
Diffstat (limited to 'runtime/lua')
-rw-r--r--runtime/lua/vim/diagnostic/_handlers.lua41
1 files changed, 23 insertions, 18 deletions
diff --git a/runtime/lua/vim/diagnostic/_handlers.lua b/runtime/lua/vim/diagnostic/_handlers.lua
index 1490ceb76e..36233d9b85 100644
--- a/runtime/lua/vim/diagnostic/_handlers.lua
+++ b/runtime/lua/vim/diagnostic/_handlers.lua
@@ -265,29 +265,34 @@ function M.underline.show(namespace, bufnr, diagnostics, opts)
local underline_ns = ns.user_data.underline_ns
local get_priority = severity_to_extmark_priority(vim.hl.priorities.diagnostics, opts)
+ -- skip diagnostics with an out-of-range lnum.
+ local line_count = api.nvim_buf_line_count(bufnr)
+
for _, diagnostic0 in ipairs(diagnostics) do
- local higroups = { underline_highlight_map[diagnostic0.severity] }
+ if diagnostic0.lnum < line_count then
+ local higroups = { underline_highlight_map[diagnostic0.severity] }
- if diagnostic0._tags then
- if diagnostic0._tags.unnecessary then
- table.insert(higroups, 'DiagnosticUnnecessary')
- end
- if diagnostic0._tags.deprecated then
- table.insert(higroups, 'DiagnosticDeprecated')
+ if diagnostic0._tags then
+ if diagnostic0._tags.unnecessary then
+ table.insert(higroups, 'DiagnosticUnnecessary')
+ end
+ if diagnostic0._tags.deprecated then
+ table.insert(higroups, 'DiagnosticDeprecated')
+ end
end
- end
- local lines =
- api.nvim_buf_get_lines(diagnostic0.bufnr, diagnostic0.lnum, diagnostic0.lnum + 1, true)
+ local lines =
+ api.nvim_buf_get_lines(diagnostic0.bufnr, diagnostic0.lnum, diagnostic0.lnum + 1, true)
- vim.hl.range(
- bufnr,
- underline_ns,
- higroups,
- { diagnostic0.lnum, math.min(diagnostic0.col, #lines[1] - 1) },
- { diagnostic0.end_lnum, diagnostic0.end_col },
- { priority = get_priority(diagnostic0.severity) }
- )
+ vim.hl.range(
+ bufnr,
+ underline_ns,
+ higroups,
+ { diagnostic0.lnum, math.min(diagnostic0.col, #lines[1] - 1) },
+ { diagnostic0.end_lnum, diagnostic0.end_col },
+ { priority = get_priority(diagnostic0.severity) }
+ )
+ end
end
save_extmarks(underline_ns, bufnr)