fix(decorations): better approximation of botline #24794

Problem:
* The guessed botline might be smaller than the actual botline e.g. when
  there are folds and the user is typing in insert mode. This may result
  in incorrect treesitter highlights for injections.
* botline can be larger than the last line number of the buffer, which
  results in errors when placing extmarks.

Solution:
* Take a more conservative approximation. I am not sure if it is
  sufficient to guarantee correctness, but it seems to be good enough
  for the case mentioned above.
* Clamp it to the last line number.

Co-authored-by: Lewis Russell <me@lewisr.dev>
This commit is contained in:
Jaehwang Jung 2023-09-12 04:29:39 +09:00 committed by GitHub
parent f859d16aea
commit 65738202f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 17 additions and 11 deletions

View File

@ -2778,7 +2778,9 @@ nvim_set_decoration_provider({ns_id}, {*opts})
• on_buf: called for each buffer being redrawn (before window
callbacks) ["buf", bufnr, tick]
• on_win: called when starting to redraw a specific window.
["win", winid, bufnr, topline, botline_guess]
botline_guess is an approximation that does not exceed the
last line number. ["win", winid, bufnr, topline,
botline_guess]
• on_line: called for each buffer line being redrawn. (The
interaction with fold lines is subject to change) ["win",
winid, bufnr, row]

View File

@ -1777,7 +1777,9 @@ function vim.api.nvim_set_current_win(window) end
--- • on_buf: called for each buffer being redrawn (before window
--- callbacks) ["buf", bufnr, tick]
--- • on_win: called when starting to redraw a specific window.
--- ["win", winid, bufnr, topline, botline_guess]
--- botline_guess is an approximation that does not exceed the
--- last line number. ["win", winid, bufnr, topline,
--- botline_guess]
--- • on_line: called for each buffer line being redrawn. (The
--- interaction with fold lines is subject to change) ["win",
--- winid, bufnr, row]

View File

@ -322,7 +322,7 @@ function TSHighlighter._on_win(_, _win, buf, topline, botline)
if not self then
return false
end
self.tree:parse({ topline, botline })
self.tree:parse({ topline, botline + 1 })
self:reset_highlight_state()
self.redraw_count = self.redraw_count + 1
return true

View File

@ -1035,7 +1035,8 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start,
/// window callbacks)
/// ["buf", bufnr, tick]
/// - on_win: called when starting to redraw a
/// specific window.
/// specific window. botline_guess is an approximation
/// that does not exceed the last line number.
/// ["win", winid, bufnr, topline, botline_guess]
/// - on_line: called for each buffer line being redrawn.
/// (The interaction with fold lines is subject to change)

View File

@ -126,9 +126,10 @@ void decor_providers_invoke_win(win_T *wp, DecorProviders *providers,
{
kvi_init(*line_providers);
linenr_T knownmax = ((wp->w_valid & VALID_BOTLINE)
? wp->w_botline
: (wp->w_topline + wp->w_height_inner));
linenr_T knownmax = MIN(wp->w_buffer->b_ml.ml_line_count,
((wp->w_valid & VALID_BOTLINE)
? wp->w_botline
: MAX(wp->w_topline + wp->w_height_inner, wp->w_botline)));
for (size_t k = 0; k < kv_size(*providers); k++) {
DecorProvider *p = kv_A(*providers, k);
@ -138,7 +139,7 @@ void decor_providers_invoke_win(win_T *wp, DecorProviders *providers,
ADD_C(args, BUFFER_OBJ(wp->w_buffer->handle));
// TODO(bfredl): we are not using this, but should be first drawn line?
ADD_C(args, INTEGER_OBJ(wp->w_topline - 1));
ADD_C(args, INTEGER_OBJ(knownmax));
ADD_C(args, INTEGER_OBJ(knownmax - 1));
if (decor_provider_invoke(p, "win", p->redraw_win, args, true)) {
kvi_push(*line_providers, p);
}

View File

@ -103,7 +103,7 @@ describe('decorations providers', function()
]]}
check_trace {
{ "start", 4 };
{ "win", 1000, 1, 0, 8 };
{ "win", 1000, 1, 0, 6 };
{ "line", 1000, 1, 0 };
{ "line", 1000, 1, 1 };
{ "line", 1000, 1, 2 };
@ -128,7 +128,7 @@ describe('decorations providers', function()
check_trace {
{ "start", 5 };
{ "buf", 1, 5 };
{ "win", 1000, 1, 0, 8 };
{ "win", 1000, 1, 0, 6 };
{ "line", 1000, 1, 6 };
{ "end", 5 };
}
@ -195,7 +195,7 @@ describe('decorations providers', function()
check_trace {
{ "start", 5 };
{ "win", 1000, 1, 0, 5 };
{ "win", 1000, 1, 0, 3 };
{ "line", 1000, 1, 0 };
{ "line", 1000, 1, 1 };
{ "line", 1000, 1, 2 };