# HG changeset patch # User Christian Brabandt # Date 1502476205 -7200 # Node ID ebd313aa5a6c4bb7d804095fd88efdbcfa35bd70 # Parent 005fcad44592ed56e309a8f48f4a6270013881de patch 8.0.0904: cannot set a location list from text commit https://github.com/vim/vim/commit/ae338338508ef42866204f90dca861ac555f4298 Author: Bram Moolenaar Date: Fri Aug 11 20:25:26 2017 +0200 patch 8.0.0904: cannot set a location list from text Problem: Cannot set a location list from text. Solution: Add the "text" argument to setqflist(). (Yegappan Lakshmanan) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -6973,10 +6973,12 @@ setpos({expr}, {list}) |winrestview()|. setqflist({list} [, {action}[, {what}]]) *setqflist()* - Create or replace or add to the quickfix list using the items - in {list}. Each item in {list} is a dictionary. - Non-dictionary items in {list} are ignored. Each dictionary - item can contain the following entries: + Create or replace or add to the quickfix list. + + When {what} is not present, use the items in {list}. Each + item must be a dictionary. Non-dictionary items in {list} are + ignored. Each dictionary item can contain the following + entries: bufnr buffer number; must be the number of a valid buffer @@ -7028,6 +7030,10 @@ setqflist({list} [, {action}[, {what}]]) argument is ignored. The following items can be specified in {what}: context any Vim type can be stored as a context + text use 'errorformat' to extract items from the + text and add the resulting entries to the + quickfix list {nr}. The value can be a string + with one line or a list with multiple lines. items list of quickfix entries. Same as the {list} argument. nr list number in the quickfix stack; zero diff --git a/src/quickfix.c b/src/quickfix.c --- a/src/quickfix.c +++ b/src/quickfix.c @@ -4885,7 +4885,7 @@ qf_add_entries( } static int -qf_set_properties(qf_info_T *qi, dict_T *what, int action) +qf_set_properties(qf_info_T *qi, dict_T *what, int action, char_u *title) { dictitem_T *di; int retval = FAIL; @@ -4929,7 +4929,7 @@ qf_set_properties(qf_info_T *qi, dict_T if (newlist) { - qf_new_list(qi, NULL); + qf_new_list(qi, title); qf_idx = qi->qf_curlist; } @@ -4957,6 +4957,23 @@ qf_set_properties(qf_info_T *qi, dict_T } } + if ((di = dict_find(what, (char_u *)"text", -1)) != NULL) + { + /* Only string and list values are supported */ + if ((di->di_tv.v_type == VAR_STRING && di->di_tv.vval.v_string != NULL) + || (di->di_tv.v_type == VAR_LIST + && di->di_tv.vval.v_list != NULL)) + { + if (action == 'r') + qf_free_items(qi, qf_idx); + if (qf_init_ext(qi, qf_idx, NULL, NULL, &di->di_tv, p_efm, + FALSE, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0) + retval = OK; + } + else + return FAIL; + } + if ((di = dict_find(what, (char_u *)"context", -1)) != NULL) { typval_T *ctx; @@ -5070,7 +5087,7 @@ set_errorlist( qf_free_stack(wp, qi); } else if (what != NULL) - retval = qf_set_properties(qi, what, action); + retval = qf_set_properties(qi, what, action, title); else retval = qf_add_entries(qi, qi->qf_curlist, list, title, action); diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -1862,6 +1862,11 @@ func Xproperty_tests(cchar) let l = g:Xgetlist({'items':1}) call assert_equal(0, len(l.items)) + " The following used to crash Vim with address sanitizer + call g:Xsetlist([], 'f') + call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]}) + call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum) + " Save and restore the quickfix stack call g:Xsetlist([], 'f') call assert_equal(0, g:Xgetlist({'nr':'$'}).nr) @@ -2284,8 +2289,135 @@ func Xchangedtick_tests(cchar) endfunc func Test_changedtick() - call Xchangedtick_tests('c') - call Xchangedtick_tests('l') + call Xchangedtick_tests('c') + call Xchangedtick_tests('l') +endfunc + +" Tests for parsing an expression using setqflist() +func Xsetexpr_tests(cchar) + call s:setup_commands(a:cchar) + + let t = ["File1:10:Line10", "File1:20:Line20"] + call g:Xsetlist([], ' ', {'text' : t}) + call g:Xsetlist([], 'a', {'text' : "File1:30:Line30"}) + + let l = g:Xgetlist() + call assert_equal(3, len(l)) + call assert_equal(20, l[1].lnum) + call assert_equal('Line30', l[2].text) + call g:Xsetlist([], 'r', {'text' : "File2:5:Line5"}) + let l = g:Xgetlist() + call assert_equal(1, len(l)) + call assert_equal('Line5', l[0].text) + call assert_equal(-1, g:Xsetlist([], 'a', {'text' : 10})) + + call g:Xsetlist([], 'f') + " Add entries to multiple lists + call g:Xsetlist([], 'a', {'nr' : 1, 'text' : ["File1:10:Line10"]}) + call g:Xsetlist([], 'a', {'nr' : 2, 'text' : ["File2:20:Line20"]}) + call g:Xsetlist([], 'a', {'nr' : 1, 'text' : ["File1:15:Line15"]}) + call g:Xsetlist([], 'a', {'nr' : 2, 'text' : ["File2:25:Line25"]}) + call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text) + call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text) +endfunc + +func Test_setexpr() + call Xsetexpr_tests('c') + call Xsetexpr_tests('l') +endfunc + +" Tests for per quickfix/location list directory stack +func Xmultidirstack_tests(cchar) + call s:setup_commands(a:cchar) + + call g:Xsetlist([], 'f') + Xexpr "" | Xexpr "" + + call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "Entering dir 'Xone/a'"}) + call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "Entering dir 'Xtwo/a'"}) + call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "one.txt:3:one one one"}) + call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "two.txt:5:two two two"}) + + let l1 = g:Xgetlist({'nr':1, 'items':1}) + let l2 = g:Xgetlist({'nr':2, 'items':1}) + call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr)) + call assert_equal(3, l1.items[1].lnum) + call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr)) + call assert_equal(5, l2.items[1].lnum) +endfunc + +func Test_multidirstack() + call mkdir('Xone/a', 'p') + call mkdir('Xtwo/a', 'p') + let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7'] + call writefile(lines, 'Xone/a/one.txt') + call writefile(lines, 'Xtwo/a/two.txt') + let save_efm = &efm + set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f' + + call Xmultidirstack_tests('c') + call Xmultidirstack_tests('l') + + let &efm = save_efm + call delete('Xone', 'rf') + call delete('Xtwo', 'rf') +endfunc + +" Tests for per quickfix/location list file stack +func Xmultifilestack_tests(cchar) + call s:setup_commands(a:cchar) + + call g:Xsetlist([], 'f') + Xexpr "" | Xexpr "" + + call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "[one.txt]"}) + call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "[two.txt]"}) + call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "(3,5) one one one"}) + call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "(5,9) two two two"}) + + let l1 = g:Xgetlist({'nr':1, 'items':1}) + let l2 = g:Xgetlist({'nr':2, 'items':1}) + call assert_equal('one.txt', bufname(l1.items[1].bufnr)) + call assert_equal(3, l1.items[1].lnum) + call assert_equal('two.txt', bufname(l2.items[1].bufnr)) + call assert_equal(5, l2.items[1].lnum) +endfunc + +func Test_multifilestack() + let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7'] + call writefile(lines, 'one.txt') + call writefile(lines, 'two.txt') + let save_efm = &efm + set efm=%+P[%f],(%l\\,%c)\ %m,%-Q + + call Xmultifilestack_tests('c') + call Xmultifilestack_tests('l') + + let &efm = save_efm + call delete('one.txt') + call delete('two.txt') +endfunc + +" Tests for per buffer 'efm' setting +func Test_perbuf_efm() + call writefile(["File1-10-Line10"], 'one.txt') + call writefile(["File2#20#Line20"], 'two.txt') + set efm=%f#%l#%m + new | only + new + setlocal efm=%f-%l-%m + cfile one.txt + wincmd w + caddfile two.txt + + let l = getqflist() + call assert_equal(10, l[0].lnum) + call assert_equal('Line20', l[1].text) + + set efm& + new | only + call delete('one.txt') + call delete('two.txt') endfunc " Open multiple help windows using ":lhelpgrep diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -770,6 +770,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 904, +/**/ 903, /**/ 902,