0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

patch 9.1.0554: :bw leaves jumplist and tagstack data around

Problem:  :bw leaves jumplist and tagstack data around
          (Paul "Joey" Clark)
Solution: Wipe jumplist and tagstack references to the wiped buffer
          (LemonBoy)

As documented the :bwipeout command brutally deletes all the references
to the buffer, so let's make it delete all the entries in the jump list
and tag stack referring to the wiped-out buffer.

fixes: #8201
closes: #15185

Signed-off-by: LemonBoy <thatlemon@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
LemonBoy
2024-07-09 20:03:24 +02:00
committed by Christian Brabandt
parent d33a518025
commit 4ff3a9b1e3
11 changed files with 72 additions and 20 deletions

View File

@@ -41579,6 +41579,7 @@ Changed~
- allow to specify a priority when defining a new sign |:sign-define|
- provide information about function arguments using the get(func, "arity")
function |get()-func|
- |:bwipe| also wipes jumplist and tagstack data
*added-9.2*
Added ~

View File

@@ -1,4 +1,4 @@
*windows.txt* For Vim version 9.1. Last change: 2024 Feb 20
*windows.txt* For Vim version 9.1. Last change: 2024 Jul 09
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1223,7 +1223,8 @@ list of buffers. |unlisted-buffer|
:bw[ipeout][!] N1 N2 ...
Like |:bdelete|, but really delete the buffer. Everything
related to the buffer is lost. All marks in this buffer
become invalid, option settings are lost, etc. Don't use this
become invalid, option settings are lost, the jumplist and
tagstack data will be purged, etc. Don't use this
unless you know what you are doing. Examples: >
:.+,$bwipeout " wipe out all buffers after the current
" one

View File

@@ -750,10 +750,15 @@ aucmd_abort:
*/
if (wipe_buf)
{
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)
mark_forget_file(wp, buf->b_fnum);
if (action == DOBUF_WIPE_REUSE)
{
// we can re-use this buffer number, store it

View File

@@ -129,6 +129,40 @@ setmark_pos(int c, pos_T *pos, int fnum)
return FAIL;
}
/*
* Delete every entry referring to file 'fnum' from both the jumplist and the
* tag stack.
*/
void
mark_forget_file(win_T *wp, int fnum)
{
int i;
for (i = 0; i < wp->w_jumplistlen; ++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;
}
for (i = 0; i < wp->w_tagstacklen; 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;
}
}
/*
* Set the previous context mark to the current position and add it to the
* jump list.

View File

@@ -28,4 +28,5 @@ void set_last_cursor(win_T *win);
void free_all_marks(void);
xfmark_T *get_namedfm(void);
void f_getmarklist(typval_T *argvars, typval_T *rettv);
void mark_forget_file(win_T *wp, int fnum);
/* vim: set ft=c : */

View File

@@ -14,4 +14,5 @@ int expand_tags(int tagnames, char_u *pat, int *num_file, char_u ***file);
int get_tags(list_T *list, char_u *pat, char_u *buf_fname);
void get_tagstack(win_T *wp, dict_T *retdict);
int set_tagstack(win_T *wp, dict_T *d, int action);
void tagstack_clear_entry(taggy_T *item);
/* vim: set ft=c : */

View File

@@ -144,7 +144,6 @@ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char_
#if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL)
static int add_llist_tags(char_u *tag, int num_matches, char_u **matches);
#endif
static void tagstack_clear_entry(taggy_T *item);
static char_u *tagmatchname = NULL; // name of last used tag
@@ -4233,7 +4232,7 @@ find_extra(char_u **pp)
/*
* Free a single entry in a tag stack
*/
static void
void
tagstack_clear_entry(taggy_T *item)
{
VIM_CLEAR(item->tagname);

View File

@@ -62,26 +62,16 @@ endfunc
func Test_jumplist_invalid()
new
clearjumps
" put some randome text
put ='a'
let prev = bufnr('%')
" Put some random text and fill the jump list.
call setline(1, ['foo', 'bar', 'baz'])
normal G
normal gg
setl nomodified bufhidden=wipe
e XXJumpListBuffer
let bnr = bufnr('%')
" 1) empty jumplist
let expected = [[
\ {'lnum': 2, 'bufnr': prev, 'col': 0, 'coladd': 0}], 1]
call assert_equal(expected, getjumplist())
" The jump list is empty as the buffer was wiped out.
call assert_equal([[], 0], getjumplist())
let jumps = execute(':jumps')
call assert_equal('>', jumps[-1:])
" now jump back
exe ":norm! \<c-o>"
let expected = [[
\ {'lnum': 2, 'bufnr': prev, 'col': 0, 'coladd': 0},
\ {'lnum': 1, 'bufnr': bnr, 'col': 0, 'coladd': 0}], 0]
call assert_equal(expected, getjumplist())
let jumps = execute(':jumps')
call assert_match('> 0 2 0 -invalid-', jumps)
endfunc
" Test for '' mark in an empty buffer

View File

@@ -958,6 +958,23 @@ func Test_tag_stack()
call settagstack(1, {'items' : []})
call assert_fails('pop', 'E73:')
" References to wiped buffer are deleted.
for i in range(10, 20)
edit Xtest
exe "tag var" .. i
endfor
edit Xtest
let t = gettagstack()
call assert_equal(11, t.length)
call assert_equal(12, t.curidx)
bwipe!
let t = gettagstack()
call assert_equal(0, t.length)
call assert_equal(1, t.curidx)
set tags&
%bwipe
endfunc

View File

@@ -2934,6 +2934,7 @@ func Test_tfirst()
\ "Xtags", 'D')
call writefile(["one", "two", "three"], "Xfile", 'D')
call writefile(["one"], "Xother", 'D')
tag one
edit Xother
set winfixbuf

View File

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