To: vim_dev@googlegroups.com Subject: Patch 8.0.1669 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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, ®match, 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 -- Bram@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 ///