Mercurial > vim
comparison src/quickfix.c @ 13594:4d55eb79178b v8.0.1669
patch 8.0.1669: :vimgrep may add entries to the wrong quickfix list
commit https://github.com/vim/vim/commit/e1bb879f49665bb828197135b80aaf72cc190073
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Apr 6 22:58:23 2018 +0200
patch 8.0.1669: :vimgrep may add entries to the wrong quickfix list
Problem: :vimgrep may add entries to the wrong quickfix list.
Solution: Use the list identifier. (Yegappan Lakshmanan)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Fri, 06 Apr 2018 23:00:08 +0200 |
parents | 15c856a1617b |
children | 89223f5d5d12 |
comparison
equal
deleted
inserted
replaced
13593:1e1e371e8a4c | 13594:4d55eb79178b |
---|---|
4158 if (res > 0 && (eap->cmdidx == CMD_cfile || eap->cmdidx == CMD_lfile)) | 4158 if (res > 0 && (eap->cmdidx == CMD_cfile || eap->cmdidx == CMD_lfile)) |
4159 qf_jump(qi, 0, 0, eap->forceit); /* display first error */ | 4159 qf_jump(qi, 0, 0, eap->forceit); /* display first error */ |
4160 } | 4160 } |
4161 | 4161 |
4162 /* | 4162 /* |
4163 * Return the quickfix/location list number with the given identifier. | |
4164 * Returns -1 if list is not found. | |
4165 */ | |
4166 static int | |
4167 qf_id2nr(qf_info_T *qi, int_u qfid) | |
4168 { | |
4169 int qf_idx; | |
4170 | |
4171 for (qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++) | |
4172 if (qi->qf_lists[qf_idx].qf_id == qfid) | |
4173 return qf_idx; | |
4174 return -1; | |
4175 } | |
4176 | |
4177 /* | |
4163 * Return the vimgrep autocmd name. | 4178 * Return the vimgrep autocmd name. |
4164 */ | 4179 */ |
4165 static char_u * | 4180 static char_u * |
4166 vgr_get_auname(cmdidx_T cmdidx) | 4181 vgr_get_auname(cmdidx_T cmdidx) |
4167 { | 4182 { |
4270 * a quickfix list when vimgrep is running. If the list is not found, create a | 4285 * a quickfix list when vimgrep is running. If the list is not found, create a |
4271 * new list. | 4286 * new list. |
4272 */ | 4287 */ |
4273 static int | 4288 static int |
4274 vgr_qflist_valid( | 4289 vgr_qflist_valid( |
4290 win_T *wp, | |
4275 qf_info_T *qi, | 4291 qf_info_T *qi, |
4276 int_u save_qfid, | 4292 int_u qfid, |
4277 qfline_T *cur_qf_start, | |
4278 int loclist_cmd, | |
4279 char_u *title) | 4293 char_u *title) |
4280 { | 4294 { |
4281 if (loclist_cmd) | 4295 /* Verify that the quickfix/location list was not freed by an autocmd */ |
4282 { | 4296 if (!qflist_valid(wp, qfid)) |
4283 /* | 4297 { |
4284 * Verify that the location list is still valid. An autocmd might | 4298 if (wp != NULL) |
4285 * have freed the location list. | 4299 { |
4286 */ | 4300 /* An autocmd has freed the location list. */ |
4287 if (!qflist_valid(curwin, save_qfid)) | |
4288 { | |
4289 EMSG(_(e_loc_list_changed)); | 4301 EMSG(_(e_loc_list_changed)); |
4290 return FALSE; | 4302 return FALSE; |
4291 } | 4303 } |
4292 } | 4304 else |
4293 if (cur_qf_start != qi->qf_lists[qi->qf_curlist].qf_start) | 4305 { |
4294 { | 4306 /* Quickfix list is not found, create a new one. */ |
4295 int idx; | 4307 qf_new_list(qi, title); |
4296 | 4308 return TRUE; |
4309 } | |
4310 } | |
4311 | |
4312 if (qi->qf_lists[qi->qf_curlist].qf_id != qfid) | |
4297 /* Autocommands changed the quickfix list. Find the one we were | 4313 /* Autocommands changed the quickfix list. Find the one we were |
4298 * using and restore it. */ | 4314 * using and restore it. */ |
4299 for (idx = 0; idx < LISTCOUNT; ++idx) | 4315 qi->qf_curlist = qf_id2nr(qi, qfid); |
4300 if (cur_qf_start == qi->qf_lists[idx].qf_start) | |
4301 { | |
4302 qi->qf_curlist = idx; | |
4303 break; | |
4304 } | |
4305 if (idx == LISTCOUNT) | |
4306 /* List cannot be found, create a new one. */ | |
4307 qf_new_list(qi, title); | |
4308 } | |
4309 | 4316 |
4310 return TRUE; | 4317 return TRUE; |
4311 } | 4318 } |
4312 | 4319 |
4313 /* | 4320 /* |
4422 char_u *title; | 4429 char_u *title; |
4423 char_u *s; | 4430 char_u *s; |
4424 char_u *p; | 4431 char_u *p; |
4425 int fi; | 4432 int fi; |
4426 qf_info_T *qi = &ql_info; | 4433 qf_info_T *qi = &ql_info; |
4427 int loclist_cmd = FALSE; | |
4428 int_u save_qfid; | 4434 int_u save_qfid; |
4429 qfline_T *cur_qf_start; | 4435 win_T *wp = NULL; |
4430 win_T *wp; | |
4431 buf_T *buf; | 4436 buf_T *buf; |
4432 int duplicate_name = FALSE; | 4437 int duplicate_name = FALSE; |
4433 int using_dummy; | 4438 int using_dummy; |
4434 int redraw_for_dummy = FALSE; | 4439 int redraw_for_dummy = FALSE; |
4435 int found_match; | 4440 int found_match; |
4459 || eap->cmdidx == CMD_lvimgrepadd) | 4464 || eap->cmdidx == CMD_lvimgrepadd) |
4460 { | 4465 { |
4461 qi = ll_get_or_alloc_list(curwin); | 4466 qi = ll_get_or_alloc_list(curwin); |
4462 if (qi == NULL) | 4467 if (qi == NULL) |
4463 return; | 4468 return; |
4464 loclist_cmd = TRUE; | 4469 wp = curwin; |
4465 } | 4470 } |
4466 | 4471 |
4467 if (eap->addr_count > 0) | 4472 if (eap->addr_count > 0) |
4468 tomatch = eap->line2; | 4473 tomatch = eap->line2; |
4469 else | 4474 else |
4516 | 4521 |
4517 /* Remember the current directory, because a BufRead autocommand that does | 4522 /* Remember the current directory, because a BufRead autocommand that does |
4518 * ":lcd %:p:h" changes the meaning of short path names. */ | 4523 * ":lcd %:p:h" changes the meaning of short path names. */ |
4519 mch_dirname(dirname_start, MAXPATHL); | 4524 mch_dirname(dirname_start, MAXPATHL); |
4520 | 4525 |
4521 /* Remember the current values of the quickfix list and qf_start, so that | 4526 /* Remember the current quickfix list identifier, so that we can check for |
4522 * we can check for autocommands changing the current quickfix list. */ | 4527 * autocommands changing the current quickfix list. */ |
4523 save_qfid = qi->qf_lists[qi->qf_curlist].qf_id; | 4528 save_qfid = qi->qf_lists[qi->qf_curlist].qf_id; |
4524 cur_qf_start = qi->qf_lists[qi->qf_curlist].qf_start; | |
4525 | 4529 |
4526 seconds = (time_t)0; | 4530 seconds = (time_t)0; |
4527 for (fi = 0; fi < fcount && !got_int && tomatch > 0; ++fi) | 4531 for (fi = 0; fi < fcount && !got_int && tomatch > 0; ++fi) |
4528 { | 4532 { |
4529 fname = shorten_fname1(fnames[fi]); | 4533 fname = shorten_fname1(fnames[fi]); |
4547 } | 4551 } |
4548 else | 4552 else |
4549 /* Use existing, loaded buffer. */ | 4553 /* Use existing, loaded buffer. */ |
4550 using_dummy = FALSE; | 4554 using_dummy = FALSE; |
4551 | 4555 |
4552 /* Check whether the quickfix list is still valid */ | 4556 /* Check whether the quickfix list is still valid. When loading a |
4553 if (!vgr_qflist_valid(qi, save_qfid, cur_qf_start, loclist_cmd, | 4557 * buffer above, autocommands might have changed the quickfix list. */ |
4554 *eap->cmdlinep)) | 4558 if (!vgr_qflist_valid(wp, qi, save_qfid, *eap->cmdlinep)) |
4555 goto theend; | 4559 goto theend; |
4556 cur_qf_start = qi->qf_lists[qi->qf_curlist].qf_start; | 4560 save_qfid = qi->qf_lists[qi->qf_curlist].qf_id; |
4557 | 4561 |
4558 if (buf == NULL) | 4562 if (buf == NULL) |
4559 { | 4563 { |
4560 if (!got_int) | 4564 if (!got_int) |
4561 smsg((char_u *)_("Cannot open file \"%s\""), fname); | 4565 smsg((char_u *)_("Cannot open file \"%s\""), fname); |
4564 { | 4568 { |
4565 /* Try for a match in all lines of the buffer. | 4569 /* Try for a match in all lines of the buffer. |
4566 * For ":1vimgrep" look for first match only. */ | 4570 * For ":1vimgrep" look for first match only. */ |
4567 found_match = vgr_match_buflines(qi, fname, buf, ®match, | 4571 found_match = vgr_match_buflines(qi, fname, buf, ®match, |
4568 tomatch, duplicate_name, flags); | 4572 tomatch, duplicate_name, flags); |
4569 | |
4570 cur_qf_start = qi->qf_lists[qi->qf_curlist].qf_start; | |
4571 | 4573 |
4572 if (using_dummy) | 4574 if (using_dummy) |
4573 { | 4575 { |
4574 if (found_match && first_match_buf == NULL) | 4576 if (found_match && first_match_buf == NULL) |
4575 first_match_buf = buf; | 4577 first_match_buf = buf; |
4647 curbuf->b_fname, TRUE, curbuf); | 4649 curbuf->b_fname, TRUE, curbuf); |
4648 /* | 4650 /* |
4649 * The QuickFixCmdPost autocmd may free the quickfix list. Check the list | 4651 * The QuickFixCmdPost autocmd may free the quickfix list. Check the list |
4650 * is still valid. | 4652 * is still valid. |
4651 */ | 4653 */ |
4652 wp = loclist_cmd ? curwin : NULL; | |
4653 if (!qflist_valid(wp, save_qfid)) | 4654 if (!qflist_valid(wp, save_qfid)) |
4654 goto theend; | 4655 goto theend; |
4655 | 4656 |
4656 /* Jump to first match. */ | 4657 /* Jump to first match. */ |
4657 if (qi->qf_lists[qi->qf_curlist].qf_count > 0) | 4658 if (qi->qf_lists[qi->qf_curlist].qf_count > 0) |
4990 dict_add_list(retdict, "items", l); | 4991 dict_add_list(retdict, "items", l); |
4991 status = OK; | 4992 status = OK; |
4992 } | 4993 } |
4993 | 4994 |
4994 return status; | 4995 return status; |
4995 } | |
4996 | |
4997 /* | |
4998 * Return the quickfix/location list number with the given identifier. | |
4999 * Returns -1 if list is not found. | |
5000 */ | |
5001 static int | |
5002 qf_id2nr(qf_info_T *qi, int_u qfid) | |
5003 { | |
5004 int qf_idx; | |
5005 | |
5006 for (qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++) | |
5007 if (qi->qf_lists[qf_idx].qf_id == qfid) | |
5008 return qf_idx; | |
5009 return -1; | |
5010 } | 4996 } |
5011 | 4997 |
5012 /* | 4998 /* |
5013 * Return the quickfix/location list window identifier in the current tabpage. | 4999 * Return the quickfix/location list window identifier in the current tabpage. |
5014 */ | 5000 */ |