]> granicus.if.org Git - vim/commitdiff
patch 8.0.0904: cannot set a location list from text v8.0.0904
authorBram Moolenaar <Bram@vim.org>
Fri, 11 Aug 2017 18:25:26 +0000 (20:25 +0200)
committerBram Moolenaar <Bram@vim.org>
Fri, 11 Aug 2017 18:25:26 +0000 (20:25 +0200)
Problem:    Cannot set a location list from text.
Solution:   Add the "text" argument to setqflist(). (Yegappan Lakshmanan)

runtime/doc/eval.txt
src/quickfix.c
src/testdir/test_quickfix.vim
src/version.c

index 0289b9fcb9ef6675def9cfe8c3ee2e525a7379da..2705f2a5b8b5537eac03dadd52892430b986eaf9 100644 (file)
@@ -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}]])         *setqflist()*
                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
index 79cb4168d678b8ec665a0f9d03dfe18a107b2b1e..75b58af3b704f94fea9b5c6899d1ece1aae371cc 100644 (file)
@@ -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 *what, int action)
 
     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 *what, int action)
        }
     }
 
+    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);
 
index 41e5021548ca22c14ea26411af07f66eea132e63..3acbd12dffb78750df6b550ae4ced9557558d5e5 100644 (file)
@@ -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
index 3f8e89077d58e7b023a23504454544f5ff50de2a..f0e7062f751231acf97a89e7256956cbf0215f8a 100644 (file)
@@ -769,6 +769,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    904,
 /**/
     903,
 /**/