Patch 8.0.1669
Problem:    :vimgrep may add entries to the wrong quickfix list.
Solution:   Use the list identifier. (Yegappan Lakshmanan)
Files:      src/quickfix.c, src/testdir/test_quickfix.vim


*** ../vim-8.0.1668/src/quickfix.c      2018-03-24 14:01:52.319933545 +0100
--- src/quickfix.c      2018-04-06 22:53:14.463745531 +0200
***************
*** 4160,4165 ****
--- 4160,4180 ----
  }
  
  /*
+  * Return the quickfix/location list number with the given identifier.
+  * Returns -1 if list is not found.
+  */
+     static int
+ qf_id2nr(qf_info_T *qi, int_u qfid)
+ {
+     int               qf_idx;
+ 
+     for (qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++)
+       if (qi->qf_lists[qf_idx].qf_id == qfid)
+           return qf_idx;
+     return -1;
+ }
+ 
+ /*
   * Return the vimgrep autocmd name.
   */
      static char_u *
***************
*** 4272,4311 ****
   */
      static int
  vgr_qflist_valid(
        qf_info_T   *qi,
!       int_u       save_qfid,
!       qfline_T    *cur_qf_start,
!       int         loclist_cmd,
        char_u      *title)
  {
!     if (loclist_cmd)
      {
!       /*
!        * Verify that the location list is still valid. An autocmd might
!        * have freed the location list.
!        */
!       if (!qflist_valid(curwin, save_qfid))
        {
            EMSG(_(e_loc_list_changed));
            return FALSE;
        }
      }
-     if (cur_qf_start != qi->qf_lists[qi->qf_curlist].qf_start)
-     {
-       int idx;
  
        /* Autocommands changed the quickfix list.  Find the one we were
         * using and restore it. */
!       for (idx = 0; idx < LISTCOUNT; ++idx)
!           if (cur_qf_start == qi->qf_lists[idx].qf_start)
!           {
!               qi->qf_curlist = idx;
!               break;
!           }
!       if (idx == LISTCOUNT)
!           /* List cannot be found, create a new one. */
!           qf_new_list(qi, title);
!     }
  
      return TRUE;
  }
--- 4287,4318 ----
   */
      static int
  vgr_qflist_valid(
+       win_T       *wp,
        qf_info_T   *qi,
!       int_u       qfid,
        char_u      *title)
  {
!     /* Verify that the quickfix/location list was not freed by an autocmd */
!     if (!qflist_valid(wp, qfid))
      {
!       if (wp != NULL)
        {
+           /* An autocmd has freed the location list. */
            EMSG(_(e_loc_list_changed));
            return FALSE;
        }
+       else
+       {
+           /* Quickfix list is not found, create a new one. */
+           qf_new_list(qi, title);
+           return TRUE;
+       }
      }
  
+     if (qi->qf_lists[qi->qf_curlist].qf_id != qfid)
        /* Autocommands changed the quickfix list.  Find the one we were
         * using and restore it. */
!       qi->qf_curlist = qf_id2nr(qi, qfid);
  
      return TRUE;
  }
***************
*** 4424,4433 ****
      char_u    *p;
      int               fi;
      qf_info_T *qi = &ql_info;
-     int               loclist_cmd = FALSE;
      int_u     save_qfid;
!     qfline_T  *cur_qf_start;
!     win_T     *wp;
      buf_T     *buf;
      int               duplicate_name = FALSE;
      int               using_dummy;
--- 4431,4438 ----
      char_u    *p;
      int               fi;
      qf_info_T *qi = &ql_info;
      int_u     save_qfid;
!     win_T     *wp = NULL;
      buf_T     *buf;
      int               duplicate_name = FALSE;
      int               using_dummy;
***************
*** 4461,4467 ****
        qi = ll_get_or_alloc_list(curwin);
        if (qi == NULL)
            return;
!       loclist_cmd = TRUE;
      }
  
      if (eap->addr_count > 0)
--- 4466,4472 ----
        qi = ll_get_or_alloc_list(curwin);
        if (qi == NULL)
            return;
!       wp = curwin;
      }
  
      if (eap->addr_count > 0)
***************
*** 4518,4527 ****
       * ":lcd %:p:h" changes the meaning of short path names. */
      mch_dirname(dirname_start, MAXPATHL);
  
!      /* Remember the current values of the quickfix list and qf_start, so that
!       * we can check for autocommands changing the current quickfix list. */
      save_qfid = qi->qf_lists[qi->qf_curlist].qf_id;
-     cur_qf_start = qi->qf_lists[qi->qf_curlist].qf_start;
  
      seconds = (time_t)0;
      for (fi = 0; fi < fcount && !got_int && tomatch > 0; ++fi)
--- 4523,4531 ----
       * ":lcd %:p:h" changes the meaning of short path names. */
      mch_dirname(dirname_start, MAXPATHL);
  
!      /* Remember the current quickfix list identifier, so that we can check 
for
!       * autocommands changing the current quickfix list. */
      save_qfid = qi->qf_lists[qi->qf_curlist].qf_id;
  
      seconds = (time_t)0;
      for (fi = 0; fi < fcount && !got_int && tomatch > 0; ++fi)
***************
*** 4549,4559 ****
            /* Use existing, loaded buffer. */
            using_dummy = FALSE;
  
!       /* Check whether the quickfix list is still valid */
!       if (!vgr_qflist_valid(qi, save_qfid, cur_qf_start, loclist_cmd,
!                   *eap->cmdlinep))
            goto theend;
!       cur_qf_start = qi->qf_lists[qi->qf_curlist].qf_start;
  
        if (buf == NULL)
        {
--- 4553,4563 ----
            /* Use existing, loaded buffer. */
            using_dummy = FALSE;
  
!       /* Check whether the quickfix list is still valid. When loading a
!        * buffer above, autocommands might have changed the quickfix list. */
!       if (!vgr_qflist_valid(wp, qi, save_qfid, *eap->cmdlinep))
            goto theend;
!       save_qfid = qi->qf_lists[qi->qf_curlist].qf_id;
  
        if (buf == NULL)
        {
***************
*** 4567,4574 ****
            found_match = vgr_match_buflines(qi, fname, buf, &regmatch,
                    tomatch, duplicate_name, flags);
  
-           cur_qf_start = qi->qf_lists[qi->qf_curlist].qf_start;
- 
            if (using_dummy)
            {
                if (found_match && first_match_buf == NULL)
--- 4571,4576 ----
***************
*** 4649,4655 ****
       * The QuickFixCmdPost autocmd may free the quickfix list. Check the list
       * is still valid.
       */
-     wp = loclist_cmd ? curwin : NULL;
      if (!qflist_valid(wp, save_qfid))
        goto theend;
  
--- 4651,4656 ----
***************
*** 4995,5015 ****
  }
  
  /*
-  * Return the quickfix/location list number with the given identifier.
-  * Returns -1 if list is not found.
-  */
-     static int
- qf_id2nr(qf_info_T *qi, int_u qfid)
- {
-     int               qf_idx;
- 
-     for (qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++)
-       if (qi->qf_lists[qf_idx].qf_id == qfid)
-           return qf_idx;
-     return -1;
- }
- 
- /*
   * Return the quickfix/location list window identifier in the current tabpage.
   */
      static int
--- 4996,5001 ----
*** ../vim-8.0.1668/src/testdir/test_quickfix.vim       2018-01-27 
11:52:08.717774798 +0100
--- src/testdir/test_quickfix.vim       2018-04-06 22:50:46.320572438 +0200
***************
*** 3111,3113 ****
--- 3111,3154 ----
    call assert_equal(3, winnr())
    close
  endfunc
+ 
+ " Tests for quickfix/location lists changed by autocommands when
+ " :vimgrep/:lvimgrep commands are running.
+ func Test_vimgrep_autocmd()
+   call setqflist([], 'f')
+   call writefile(['stars'], 'Xtest1.txt')
+   call writefile(['stars'], 'Xtest2.txt')
+ 
+   " Test 1:
+   " When searching for a pattern using :vimgrep, if the quickfix list is
+   " changed by an autocmd, the results should be added to the correct quickfix
+   " list.
+   autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
+   silent vimgrep stars Xtest*.txt
+   call assert_equal(1, getqflist({'nr' : 0}).nr)
+   call assert_equal(3, getqflist({'nr' : '$'}).nr)
+   call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
+   au! BufRead Xtest2.txt
+ 
+   " Test 2:
+   " When searching for a pattern using :vimgrep, if the quickfix list is
+   " freed, then a error should be given.
+   silent! %bwipe!
+   call setqflist([], 'f')
+   autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
+   call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
+   au! BufRead Xtest2.txt
+ 
+   " Test 3:
+   " When searching for a pattern using :lvimgrep, if the location list is
+   " freed, then the command should error out.
+   silent! %bwipe!
+   let g:save_winid = win_getid()
+   autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
+   call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
+   au! BufRead Xtest2.txt
+ 
+   call delete('Xtest1.txt')
+   call delete('Xtest2.txt')
+   call setqflist([], 'f')
+ endfunc
*** ../vim-8.0.1668/src/version.c       2018-04-06 22:26:17.985196787 +0200
--- src/version.c       2018-04-06 22:52:04.288136183 +0200
***************
*** 764,765 ****
--- 764,767 ----
  {   /* Add new patch number below this line */
+ /**/
+     1669,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
117. You are more comfortable typing in html.

 /// Bram Moolenaar -- b...@moolenaar.net -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
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.
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui