summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-07-10 19:36:36 +0200
committerChristian Brabandt <cb@256bit.org>2024-07-10 19:36:36 +0200
commit2e7d89b39883b0cfd3e615b02bd55186e00fb7ce (patch)
tree6d9387c894a8a2d6c344335938b76951c5b152a0
parenta3a14d5469681676310d39c19e110a57cd8ac7c6 (diff)
patch 9.1.0556: :bwipe doesn't remove file from jumplist of other tabpagesv9.1.0556
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>
-rw-r--r--src/buffer.c5
-rw-r--r--src/mark.c14
-rw-r--r--src/testdir/test_jumplist.vim46
-rw-r--r--src/testdir/test_tagjump.vim40
-rw-r--r--src/version.c2
5 files changed, 95 insertions, 12 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 28967342d0..82957f986a 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -750,13 +750,14 @@ aucmd_abort:
*/
if (wipe_buf)
{
- win_T *wp;
+ tabpage_T *tp;
+ win_T *wp;
// Do not wipe out the buffer if it is used in a window.
if (buf->b_nwindows > 0)
return FALSE;
- FOR_ALL_WINDOWS(wp)
+ FOR_ALL_TAB_WINDOWS(tp, wp)
mark_forget_file(wp, buf->b_fnum);
if (action == DOBUF_WIPE_REUSE)
diff --git a/src/mark.c b/src/mark.c
index 85f7b68e2f..9f6a9ccf58 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -138,28 +138,26 @@ mark_forget_file(win_T *wp, int fnum)
{
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)
{
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)
--wp->w_jumplistidx;
--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)
{
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)
--wp->w_tagstackidx;
--wp->w_tagstacklen;
- --i;
+ mch_memmove(&wp->w_tagstack[i], &wp->w_tagstack[i + 1],
+ (wp->w_tagstacklen - i) * sizeof(wp->w_tagstack[i]));
}
}
diff --git a/src/testdir/test_jumplist.vim b/src/testdir/test_jumplist.vim
index 0f43a8c6eb..4b9fcee780 100644
--- a/src/testdir/test_jumplist.vim
+++ b/src/testdir/test_jumplist.vim
@@ -59,7 +59,7 @@ func Test_getjumplist()
call assert_equal(4, l[1])
endfunc
-func Test_jumplist_invalid()
+func Test_jumplist_wipe_buf()
new
clearjumps
" Put some random text and fill the jump list.
@@ -72,6 +72,50 @@ func Test_jumplist_invalid()
call assert_equal([[], 0], getjumplist())
let jumps = execute(':jumps')
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
" Test for '' mark in an empty buffer
diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim
index 71237855c9..c2419375a0 100644
--- a/src/testdir/test_tagjump.vim
+++ b/src/testdir/test_tagjump.vim
@@ -975,8 +975,46 @@ func Test_tag_stack()
call assert_equal(0, t.length)
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&
- %bwipe
endfunc
" Test for browsing multiple matching tags
diff --git a/src/version.c b/src/version.c
index 96691df617..8a392cac65 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 556,
+/**/
555,
/**/
554,