aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaehwang Jung <tomtomjhj@gmail.com>2023-09-12 04:29:39 +0900
committerGitHub <noreply@github.com>2023-09-11 12:29:39 -0700
commit65738202f8be3ca63b75197d48f2c7a9324c035b (patch)
treeaf84592f43cac667a06c50d005f726a31492677c
parentf859d16aea0d58e572edc9aaf1de3542569e10a9 (diff)
downloadrneovim-65738202f8be3ca63b75197d48f2c7a9324c035b.tar.gz
rneovim-65738202f8be3ca63b75197d48f2c7a9324c035b.tar.bz2
rneovim-65738202f8be3ca63b75197d48f2c7a9324c035b.zip
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>
-rw-r--r--runtime/doc/api.txt4
-rw-r--r--runtime/lua/vim/_meta/api.lua4
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua2
-rw-r--r--src/nvim/api/extmark.c3
-rw-r--r--src/nvim/decoration_provider.c9
-rw-r--r--test/functional/ui/decorations_spec.lua6
6 files changed, 17 insertions, 11 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index c0bea52513..9cdfd8a563 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -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]
diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua
index 6c4e6c04d9..bfff16933a 100644
--- a/runtime/lua/vim/_meta/api.lua
+++ b/runtime/lua/vim/_meta/api.lua
@@ -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]
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index 56b075b723..8d4d6a9337 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -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
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index 6ec1fc4ee0..268fdded9a 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -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)
diff --git a/src/nvim/decoration_provider.c b/src/nvim/decoration_provider.c
index 8e5809c4e0..63c9772fb8 100644
--- a/src/nvim/decoration_provider.c
+++ b/src/nvim/decoration_provider.c
@@ -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);
}
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 62dbd57202..a75290b400 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -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 };