Hi,

On Thu, Jul 20, 2017 at 6:59 AM, Yegappan Lakshmanan
<yegapp...@gmail.com> wrote:
> Hi,
>
> I am investigating a memory leak reported by valgrind with
> this patch.
>

I am attaching an updated patch with the fix for this memory leak and
additional tests.

Once this patch is incorporated, output can be parsed using 'errorformat'
and resulting entries can be added to any quickfix/location list by
using setqflist().

- Yegappan

>
> On Wed, Jul 19, 2017 at 11:30 PM, Yegappan Lakshmanan
> <yegapp...@gmail.com> wrote:
>> Hi,
>>
>> I am attaching a patch to add support for parsing lines using 'errorformat'
>> and adding entries to any quickfix/location list in the stack using the
>> setqflist() function. This patch also includes additional tests.
>>
>> - Yegappan

-- 
-- 
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.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index add95bc3b..286c3dfcd 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -7006,6 +7006,9 @@ 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
+                   expr        evaluate expression and add the resulting
+                               entries to the quickfix list {nr}. Only string
+                               and list types are supported.
                    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
index 2adfc52ad..8b022e143 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -4943,7 +4943,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;
@@ -4987,7 +4987,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;
     }
 
@@ -5015,6 +5015,24 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int 
action)
        }
     }
 
+    if ((di = dict_find(what, (char_u *)"expr", -1)) != NULL)
+    {
+       /* Only string and list expressions 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;
@@ -5128,7 +5146,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
index 7b344eaad..7ebd35f1d 100644
--- 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,6 +2289,133 @@ 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([], ' ', {'expr' : t})
+  call g:Xsetlist([], 'a', {'expr' : "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', {'expr' : "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', {'expr' : 10}))
+
+  call g:Xsetlist([], 'f')
+  " Add entries to multiple lists
+  call g:Xsetlist([], 'a', {'nr' : 1, 'expr' : ["File1:10:Line10"]})
+  call g:Xsetlist([], 'a', {'nr' : 2, 'expr' : ["File2:20:Line20"]})
+  call g:Xsetlist([], 'a', {'nr' : 1, 'expr' : ["File1:15:Line15"]})
+  call g:Xsetlist([], 'a', {'nr' : 2, 'expr' : ["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, 'expr' : "Entering dir 'Xone/a'"})
+  call g:Xsetlist([], 'a', {'nr' : 2, 'expr' : "Entering dir 'Xtwo/a'"})
+  call g:Xsetlist([], 'a', {'nr' : 1, 'expr' : "one.txt:3:one one one"})
+  call g:Xsetlist([], 'a', {'nr' : 2, 'expr' : "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, 'expr' : "[one.txt]"})
+  call g:Xsetlist([], 'a', {'nr' : 2, 'expr' : "[two.txt]"})
+  call g:Xsetlist([], 'a', {'nr' : 1, 'expr' : "(3,5) one one one"})
+  call g:Xsetlist([], 'a', {'nr' : 2, 'expr' : "(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

Raspunde prin e-mail lui