0
0
mirror of https://github.com/vim/vim.git synced 2025-08-26 20:03:41 -04:00

patch 9.1.0556: :bwipe doesn't remove file from jumplist of other tabpages

Problem:  :bwipe doesn't remove file from jumplist and tagstack of other
          tabpages. Time complexity of mark_forget_file() is O(n^2) when
          removing all entries (after v9.1.0554)
Solution: Use FOR_ALL_TAB_WINDOWS().  Start the loops over the arrays
          from the end instead of the start (zeertzjq)

closes: #15199

Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
zeertzjq 2024-07-10 19:36:36 +02:00 committed by Christian Brabandt
parent a3a14d5469
commit 2e7d89b398
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
5 changed files with 95 additions and 12 deletions

View File

@ -750,13 +750,14 @@ aucmd_abort:
*/ */
if (wipe_buf) if (wipe_buf)
{ {
tabpage_T *tp;
win_T *wp; win_T *wp;
// Do not wipe out the buffer if it is used in a window. // Do not wipe out the buffer if it is used in a window.
if (buf->b_nwindows > 0) if (buf->b_nwindows > 0)
return FALSE; return FALSE;
FOR_ALL_WINDOWS(wp) FOR_ALL_TAB_WINDOWS(tp, wp)
mark_forget_file(wp, buf->b_fnum); mark_forget_file(wp, buf->b_fnum);
if (action == DOBUF_WIPE_REUSE) if (action == DOBUF_WIPE_REUSE)

View File

@ -138,28 +138,26 @@ mark_forget_file(win_T *wp, int fnum)
{ {
int i; int i;
for (i = 0; i < wp->w_jumplistlen; ++i) for (i = wp->w_jumplistlen - 1; i >= 0; --i)
if (wp->w_jumplist[i].fmark.fnum == fnum) if (wp->w_jumplist[i].fmark.fnum == fnum)
{ {
vim_free(wp->w_jumplist[i].fname); vim_free(wp->w_jumplist[i].fname);
mch_memmove(&wp->w_jumplist[i], &wp->w_jumplist[i + 1],
(wp->w_jumplistlen - i - 1) * sizeof(xfmark_T));
if (wp->w_jumplistidx > i) if (wp->w_jumplistidx > i)
--wp->w_jumplistidx; --wp->w_jumplistidx;
--wp->w_jumplistlen; --wp->w_jumplistlen;
--i; mch_memmove(&wp->w_jumplist[i], &wp->w_jumplist[i + 1],
(wp->w_jumplistlen - i) * sizeof(wp->w_jumplist[i]));
} }
for (i = 0; i < wp->w_tagstacklen; i++) for (i = wp->w_tagstacklen - 1; i >= 0; --i)
if (wp->w_tagstack[i].fmark.fnum == fnum) if (wp->w_tagstack[i].fmark.fnum == fnum)
{ {
tagstack_clear_entry(&wp->w_tagstack[i]); tagstack_clear_entry(&wp->w_tagstack[i]);
mch_memmove(&wp->w_tagstack[i], &wp->w_tagstack[i + 1],
(wp->w_tagstacklen - i - 1) * sizeof(taggy_T));
if (wp->w_tagstackidx > i) if (wp->w_tagstackidx > i)
--wp->w_tagstackidx; --wp->w_tagstackidx;
--wp->w_tagstacklen; --wp->w_tagstacklen;
--i; mch_memmove(&wp->w_tagstack[i], &wp->w_tagstack[i + 1],
(wp->w_tagstacklen - i) * sizeof(wp->w_tagstack[i]));
} }
} }

View File

@ -59,7 +59,7 @@ func Test_getjumplist()
call assert_equal(4, l[1]) call assert_equal(4, l[1])
endfunc endfunc
func Test_jumplist_invalid() func Test_jumplist_wipe_buf()
new new
clearjumps clearjumps
" Put some random text and fill the jump list. " Put some random text and fill the jump list.
@ -72,6 +72,50 @@ func Test_jumplist_invalid()
call assert_equal([[], 0], getjumplist()) call assert_equal([[], 0], getjumplist())
let jumps = execute(':jumps') let jumps = execute(':jumps')
call assert_equal('>', jumps[-1:]) call assert_equal('>', jumps[-1:])
" Put some random text and fill the jump list.
call setline(1, ['foo', 'bar', 'baz'])
setl bufhidden=hide
" References to wiped buffer are deleted with multiple tabpages.
let [w1, t1] = [win_getid(), tabpagenr()]
clearjumps
normal G
normal gg
enew
split XXJumpListBuffer
let [w2, t2] = [win_getid(), tabpagenr()]
clearjumps
normal G
normal gg
enew
tabnew XXJumpListBuffer
let [w3, t3] = [win_getid(), tabpagenr()]
clearjumps
normal G
normal gg
enew
split XXJumpListBuffer
let [w4, t4] = [win_getid(), tabpagenr()]
clearjumps
normal G
normal gg
enew
for [w, t] in [[w1, t1], [w2, t2], [w3, t3], [w4, t4]]
call assert_equal(2, len(getjumplist(w, t)[0]))
endfor
bwipe! XXJumpListBuffer
for [w, t] in [[w1, t1], [w2, t2], [w3, t3], [w4, t4]]
call assert_equal(0, len(getjumplist(w, t)[0]))
endfor
%bwipe!
endfunc endfunc
" Test for '' mark in an empty buffer " Test for '' mark in an empty buffer

View File

@ -975,8 +975,46 @@ func Test_tag_stack()
call assert_equal(0, t.length) call assert_equal(0, t.length)
call assert_equal(1, t.curidx) call assert_equal(1, t.curidx)
" References to wiped buffer are deleted with multiple tabpages.
let w1 = win_getid()
call settagstack(1, {'items' : []})
for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor
enew
new
let w2 = win_getid()
call settagstack(1, {'items' : []})
for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor
enew
tabnew
let w3 = win_getid()
call settagstack(1, {'items' : []})
for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor
enew
new
let w4 = win_getid()
call settagstack(1, {'items' : []})
for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor
enew
for w in [w1, w2, w3, w4]
let t = gettagstack(w)
call assert_equal(11, t.length)
call assert_equal(12, t.curidx)
endfor
bwipe! Xtest
for w in [w1, w2, w3, w4]
let t = gettagstack(w)
call assert_equal(0, t.length)
call assert_equal(1, t.curidx)
endfor
%bwipe!
set tags& set tags&
%bwipe
endfunc endfunc
" Test for browsing multiple matching tags " Test for browsing multiple matching tags

View File

@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
556,
/**/ /**/
555, 555,
/**/ /**/