fix(conceal): check for concealed lines on invalid row (#36084)

Problem:  May check for concealed lines on invalid line numbers.
Solution: Move checks after line number validation.
This commit is contained in:
luukvbaal
2025-10-09 15:44:11 +02:00
committed by GitHub
parent 645206e87f
commit ad8bce6674
4 changed files with 22 additions and 10 deletions

View File

@@ -865,6 +865,7 @@ static const uint32_t conceal_filter[kMTMetaCount] = {[kMTMetaConcealLines] = kM
/// @return whether "row" is concealed
bool decor_conceal_line(win_T *wp, int row, bool check_cursor)
{
assert(row >= 0);
if (wp->w_p_cole < 2
|| (!check_cursor && wp == curwin && row + 1 == wp->w_cursor.lnum
&& !conceal_cursor_line(wp))) {

View File

@@ -2449,10 +2449,10 @@ void cursor_up_inner(win_T *wp, linenr_T n, bool skip_conceal)
while (n--) {
// move up one line
lnum--;
n += skip_conceal && decor_conceal_line(wp, lnum - 1, true);
if (lnum <= 1) {
break;
}
n += skip_conceal && decor_conceal_line(wp, lnum - 1, true);
// If we entered a fold, move to the beginning, unless in
// Insert mode or when 'foldopen' contains "all": it will open
// in a moment.
@@ -2506,10 +2506,10 @@ void cursor_down_inner(win_T *wp, int n, bool skip_conceal)
} else {
lnum++;
}
n += skip_conceal && decor_conceal_line(wp, lnum - 1, true);
if (lnum >= line_count) {
break;
}
n += skip_conceal && decor_conceal_line(wp, lnum - 1, true);
}
lnum = MIN(lnum, line_count);
} else {

View File

@@ -331,10 +331,10 @@ void update_topline(win_T *wp)
// scrolled).
n = 0;
for (linenr_T lnum = wp->w_cursor.lnum; lnum < wp->w_topline + *so_ptr; lnum++) {
n += !decor_conceal_line(wp, lnum, false);
// stop at end of file or when we know we are far off
assert(wp->w_buffer != 0);
if (lnum >= wp->w_buffer->b_ml.ml_line_count || n >= halfheight) {
if (lnum >= wp->w_buffer->b_ml.ml_line_count
|| (n += !decor_conceal_line(wp, lnum, false)) >= halfheight) {
break;
}
hasFolding(wp, lnum, NULL, &lnum);
@@ -404,23 +404,23 @@ void update_topline(win_T *wp)
}
}
if (check_botline) {
int line_count = 0;
int n = 0;
if (win_lines_concealed(wp)) {
// Count the number of logical lines between the cursor and
// botline - p_so (approximation of how much will be
// scrolled).
for (linenr_T lnum = wp->w_cursor.lnum; lnum >= wp->w_botline - *so_ptr; lnum--) {
line_count += !decor_conceal_line(wp, lnum - 1, false);
// stop at end of file or when we know we are far off
if (lnum <= 0 || line_count > wp->w_view_height + 1) {
if (lnum <= 0
|| (n += !decor_conceal_line(wp, lnum - 1, false)) > wp->w_view_height + 1) {
break;
}
hasFolding(wp, lnum, &lnum, NULL);
}
} else {
line_count = wp->w_cursor.lnum - wp->w_botline + 1 + (int)(*so_ptr);
n = wp->w_cursor.lnum - wp->w_botline + 1 + (int)(*so_ptr);
}
if (line_count <= wp->w_view_height + 1) {
if (n <= wp->w_view_height + 1) {
scroll_cursor_bot(wp, scrolljump_value(wp), false);
} else {
scroll_cursor_halfway(wp, false, false);
@@ -513,7 +513,7 @@ void check_cursor_moved(win_T *wp)
|VALID_CHEIGHT|VALID_CROW|VALID_TOPLINE);
// Concealed line visibility toggled.
if (wp->w_p_cole >= 2 && !conceal_cursor_line(wp)
if (wp->w_valid_cursor.lnum > 0 && wp->w_p_cole >= 2 && !conceal_cursor_line(wp)
&& (decor_conceal_line(wp, wp->w_cursor.lnum - 1, true)
|| decor_conceal_line(wp, wp->w_valid_cursor.lnum - 1, true))) {
changed_window_setting(wp);

View File

@@ -3524,6 +3524,17 @@ describe('extmark decorations', function()
eq(5, n.fn.line('w0'))
end)
it('conceal_lines not checking on invalid row #36057', function()
exec_lua(function()
vim.fn.setline(1, { 'foo', 'bar', 'baz' })
vim.api.nvim_command('set conceallevel=3 scrolloff=3')
vim.api.nvim_open_win(0, true, { width = 1, height = 1, relative = 'editor', row = 0, col = 0 })
vim.api.nvim_buf_set_extmark(0, ns, 1, 0, { conceal_lines = '' })
vim.api.nvim__redraw({ flush = true })
end)
n.assert_alive()
end)
it('redraws the line from which a left gravity mark has moved #27369', function()
fn.setline(1, { 'aaa', 'bbb', 'ccc', 'ddd' })
api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_text = { { 'foo' } }, right_gravity = false })