]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.0554: :bw leaves jumplist and tagstack data around v9.1.0554
authorLemonBoy <thatlemon@gmail.com>
Tue, 9 Jul 2024 18:03:24 +0000 (20:03 +0200)
committerChristian Brabandt <cb@256bit.org>
Tue, 9 Jul 2024 18:03:24 +0000 (20:03 +0200)
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>
runtime/doc/version9.txt
runtime/doc/windows.txt
src/buffer.c
src/mark.c
src/proto/mark.pro
src/proto/tag.pro
src/tag.c
src/testdir/test_jumplist.vim
src/testdir/test_tagjump.vim
src/testdir/test_winfixbuf.vim
src/version.c

index 9cf20300fa76bfc0ecbf5cb7ae795259c901812e..df56215ea8e642245d64fc6b34d2e548873b3289 100644 (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 ~
index e264e511707246fb91ebe6638bd9deff11ef9215..d3e5f6785861a7753889eaf637b1d9e8e2a60916 100644 (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
index cbec9b980c6b8d29e0c37a82f47c69b84b8eb2e7..28967342d02ea24988b159c4abbb09beb51bdc28 100644 (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
index 22e3c62575426089886dfe49befb6b9d77cd6d85..85f7b68e2f82e4565010d445457e192e0b9d7021 100644 (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.
index cc45f0d3c3a9e13bc558a9b2acbece95e38fa82e..d398c3677cb830c29ae2e793dc0b808a8918a568 100644 (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 : */
index 6de463e92c55296d83fb79513f93ac091b63e235..eec7c24ed482a56054c75e96329633b400463eb8 100644 (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 : */
index d406fdec1a3e43ebe8a8bc4f37f0800ac3e7100c..57f9fe016ab0ced723c6d614fbbcf030416858fa 100644 (file)
--- a/src/tag.c
+++ b/src/tag.c
@@ -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);
index 8fbf39f55b11e030286654db6e71fea68ee6dc7c..0f43a8c6ebb2dd75f19a5fbc4d952e17f45b4ece 100644 (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
index 432906efbfbf23bbcefcdcf0e1a823dc3ec23414..71237855c9bbdf7e6f8051c3aaa27acc9d650cd1 100644 (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
index f800338cbd2d8c3d205fa6c5dab4466e034438a3..3cec4ed70bb99d7af32b694a13fc29b1dffd8f77 100644 (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
index 936a05c08633d4060217b0f10613ab1fe62a6b4d..0de9c555dd4a41eb7f713d88d9073f304c85ff82 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    554,
 /**/
     553,
 /**/