Mercurial > vim
changeset 35627:256723b12b48 v9.1.0556
patch 9.1.0556: :bwipe doesn't remove file from jumplist of other tabpages
Commit: https://github.com/vim/vim/commit/2e7d89b39883b0cfd3e615b02bd55186e00fb7ce
Author: zeertzjq <zeertzjq@outlook.com>
Date: Wed Jul 10 19:36:36 2024 +0200
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>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Wed, 10 Jul 2024 20:15:02 +0200 |
parents | 35f452cbbe0c |
children | f45ef74af0d2 |
files | src/buffer.c src/mark.c src/testdir/test_jumplist.vim src/testdir/test_tagjump.vim src/version.c |
diffstat | 5 files changed, 95 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- 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)
--- 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])); } }
--- 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
--- 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