patch 9.1.0554: :bw leaves jumplist and tagstack data around

Commit: 
https://github.com/vim/vim/commit/4ff3a9b1e3ba45f9dbd0ea8c721f27d9315c4d93
Author: LemonBoy <thatle...@gmail.com>
Date:   Tue Jul 9 20:03:24 2024 +0200

    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 <thatle...@gmail.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt
index 9cf20300f..df56215ea 100644
--- a/runtime/doc/version9.txt
+++ b/runtime/doc/version9.txt
@@ -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 ~
diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt
index e264e5117..d3e5f6785 100644
--- a/runtime/doc/windows.txt
+++ b/runtime/doc/windows.txt
@@ -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
diff --git a/src/buffer.c b/src/buffer.c
index cbec9b980..28967342d 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -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
diff --git a/src/mark.c b/src/mark.c
index 22e3c6257..85f7b68e2 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -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.
diff --git a/src/proto/mark.pro b/src/proto/mark.pro
index cc45f0d3c..d398c3677 100644
--- a/src/proto/mark.pro
+++ b/src/proto/mark.pro
@@ -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 : */
diff --git a/src/proto/tag.pro b/src/proto/tag.pro
index 6de463e92..eec7c24ed 100644
--- a/src/proto/tag.pro
+++ b/src/proto/tag.pro
@@ -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 : */
diff --git a/src/tag.c b/src/tag.c
index d406fdec1..57f9fe016 100644
--- 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);
diff --git a/src/testdir/test_jumplist.vim b/src/testdir/test_jumplist.vim
index 8fbf39f55..0f43a8c6e 100644
--- a/src/testdir/test_jumplist.vim
+++ b/src/testdir/test_jumplist.vim
@@ -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
diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim
index 432906efb..71237855c 100644
--- a/src/testdir/test_tagjump.vim
+++ b/src/testdir/test_tagjump.vim
@@ -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
diff --git a/src/testdir/test_winfixbuf.vim b/src/testdir/test_winfixbuf.vim
index f800338cb..3cec4ed70 100644
--- a/src/testdir/test_winfixbuf.vim
+++ b/src/testdir/test_winfixbuf.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index 936a05c08..0de9c555d 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    554,
 /**/
     553,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1sRFMl-00DP7i-Qd%40256bit.org.

Raspunde prin e-mail lui