# HG changeset patch # User Christian Brabandt # Date 1513116006 -3600 # Node ID 7c0e0e923537a0902df1ded27d4deba1d047ad37 # Parent 5f7d269284a304c5464ab829f67c5ffa0d09d939 patch 8.0.1389: getqflist() items are missing if not set commit https://github.com/vim/vim/commit/a6d4849c711379b773529afaed640455287ac934 Author: Bram Moolenaar Date: Tue Dec 12 22:45:31 2017 +0100 patch 8.0.1389: getqflist() items are missing if not set Problem: getqflist() items are missing if not set, that makes it more difficult to handle the values. Solution: When a value is not available return zero or another invalid value. (Yegappan Lakshmanan, closes #2430) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -4687,7 +4687,7 @@ getqflist([{what}]) *getqflist()* winid get the quickfix |window-ID| all all of the above quickfix properties Non-string items in {what} are ignored. To get the value of a - particular item, set it to one. + particular item, set it to zero. If "nr" is not present then the current quickfix list is used. If both "nr" and a non-zero "id" are specified, then the list specified by "id" is used. @@ -4697,17 +4697,21 @@ getqflist([{what}]) *getqflist()* When "lines" is specified, all the other items except "efm" are ignored. The returned dictionary contains the entry "items" with the list of entries. - In case of error processing {what}, an empty dictionary is - returned. The returned dictionary contains the following entries: - context context information stored with |setqflist()| - id quickfix list ID |quickfix-ID| - idx index of the current entry in the list - items quickfix list entries - nr quickfix list number - size number of entries in the quickfix list - title quickfix list title text + context context information stored with |setqflist()|. + If not present, set to "". + id quickfix list ID |quickfix-ID|. If not + present, set to 0. + idx index of the current entry in the list. If not + present, set to 0. + items quickfix list entries. If not present, set to + an empty list. + nr quickfix list number. If not present, set to 0 + size number of entries in the quickfix list. If not + present, set to 0. + title quickfix list title text. If not present, set + to "". winid quickfix |window-ID|. If not present, set to 0 Examples: > diff --git a/src/quickfix.c b/src/quickfix.c --- a/src/quickfix.c +++ b/src/quickfix.c @@ -4863,70 +4863,24 @@ qf_get_properties(win_T *wp, dict_T *wha if (wp != NULL) qi = GET_LOC_LIST(wp); - /* List is not present or is empty */ - if (qi == NULL || qi->qf_listcount == 0) - { - /* If querying for the size of the list, return 0 */ - if (((di = dict_find(what, (char_u *)"nr", -1)) != NULL) - && (di->di_tv.v_type == VAR_STRING) - && (STRCMP(di->di_tv.vval.v_string, "$") == 0)) - return dict_add_nr_str(retdict, "nr", 0, NULL); - return FAIL; - } - - qf_idx = qi->qf_curlist; /* default is the current list */ - if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL) - { - /* Use the specified quickfix/location list */ - if (di->di_tv.v_type == VAR_NUMBER) - { - /* for zero use the current list */ - if (di->di_tv.vval.v_number != 0) - { - qf_idx = di->di_tv.vval.v_number - 1; - if (qf_idx < 0 || qf_idx >= qi->qf_listcount) - return FAIL; - } - } - else if ((di->di_tv.v_type == VAR_STRING) - && (STRCMP(di->di_tv.vval.v_string, "$") == 0)) - /* Get the last quickfix list number */ - qf_idx = qi->qf_listcount - 1; - else - return FAIL; - flags |= QF_GETLIST_NR; - } - - if ((di = dict_find(what, (char_u *)"id", -1)) != NULL) - { - /* Look for a list with the specified id */ - if (di->di_tv.v_type == VAR_NUMBER) - { - /* For zero, use the current list or the list specifed by 'nr' */ - if (di->di_tv.vval.v_number != 0) - { - qf_idx = qf_id2nr(qi, di->di_tv.vval.v_number); - if (qf_idx == -1) - return FAIL; /* List not found */ - } - flags |= QF_GETLIST_ID; - } - else - return FAIL; - } - if (dict_find(what, (char_u *)"all", -1) != NULL) flags |= QF_GETLIST_ALL; if (dict_find(what, (char_u *)"title", -1) != NULL) flags |= QF_GETLIST_TITLE; + if (dict_find(what, (char_u *)"nr", -1) != NULL) + flags |= QF_GETLIST_NR; + if (dict_find(what, (char_u *)"winid", -1) != NULL) flags |= QF_GETLIST_WINID; if (dict_find(what, (char_u *)"context", -1) != NULL) flags |= QF_GETLIST_CONTEXT; + if (dict_find(what, (char_u *)"id", -1) != NULL) + flags |= QF_GETLIST_ID; + if (dict_find(what, (char_u *)"items", -1) != NULL) flags |= QF_GETLIST_ITEMS; @@ -4936,6 +4890,77 @@ qf_get_properties(win_T *wp, dict_T *wha if (dict_find(what, (char_u *)"size", -1) != NULL) flags |= QF_GETLIST_SIZE; + if (qi != NULL && qi->qf_listcount != 0) + { + qf_idx = qi->qf_curlist; /* default is the current list */ + if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL) + { + /* Use the specified quickfix/location list */ + if (di->di_tv.v_type == VAR_NUMBER) + { + /* for zero use the current list */ + if (di->di_tv.vval.v_number != 0) + { + qf_idx = di->di_tv.vval.v_number - 1; + if (qf_idx < 0 || qf_idx >= qi->qf_listcount) + qf_idx = -1; + } + } + else if ((di->di_tv.v_type == VAR_STRING) + && (STRCMP(di->di_tv.vval.v_string, "$") == 0)) + /* Get the last quickfix list number */ + qf_idx = qi->qf_listcount - 1; + else + qf_idx = -1; + flags |= QF_GETLIST_NR; + } + + if ((di = dict_find(what, (char_u *)"id", -1)) != NULL) + { + /* Look for a list with the specified id */ + if (di->di_tv.v_type == VAR_NUMBER) + { + /* + * For zero, use the current list or the list specifed by 'nr' + */ + if (di->di_tv.vval.v_number != 0) + qf_idx = qf_id2nr(qi, di->di_tv.vval.v_number); + flags |= QF_GETLIST_ID; + } + else + qf_idx = -1; + } + } + + /* List is not present or is empty */ + if (qi == NULL || qi->qf_listcount == 0 || qf_idx == -1) + { + if (flags & QF_GETLIST_TITLE) + status = dict_add_nr_str(retdict, "title", 0L, (char_u *)""); + if ((status == OK) && (flags & QF_GETLIST_ITEMS)) + { + list_T *l = list_alloc(); + if (l != NULL) + status = dict_add_list(retdict, "items", l); + else + status = FAIL; + } + if ((status == OK) && (flags & QF_GETLIST_NR)) + status = dict_add_nr_str(retdict, "nr", 0L, NULL); + if ((status == OK) && (flags & QF_GETLIST_WINID)) + status = dict_add_nr_str(retdict, "winid", 0L, NULL); + if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) + status = dict_add_nr_str(retdict, "context", 0L, (char_u *)""); + if ((status == OK) && (flags & QF_GETLIST_ID)) + status = dict_add_nr_str(retdict, "id", 0L, NULL); + if ((status == OK) && (flags & QF_GETLIST_IDX)) + status = dict_add_nr_str(retdict, "idx", 0L, NULL); + if ((status == OK) && (flags & QF_GETLIST_SIZE)) + status = dict_add_nr_str(retdict, "size", 0L, NULL); + + return status; + } + if (flags & QF_GETLIST_TITLE) { char_u *t; 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 @@ -1833,8 +1833,8 @@ func Xproperty_tests(cchar) call assert_equal(-1, s) call assert_equal({}, g:Xgetlist({'abc':1})) - call assert_equal({}, g:Xgetlist({'nr':99, 'title':1})) - call assert_equal({}, g:Xgetlist({'nr':[], 'title':1})) + call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title) + call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title) if a:cchar == 'l' call assert_equal({}, getloclist(99, {'title': 1})) @@ -1870,7 +1870,7 @@ func Xproperty_tests(cchar) call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context) only call setloclist(0, [], 'f') - call assert_equal({}, getloclist(0, {'context':1})) + call assert_equal('', getloclist(0, {'context':1}).context) endif " Test for changing the context of previous quickfix lists @@ -2383,8 +2383,8 @@ func XsizeTests(cchar) call g:Xsetlist([], 'f') call assert_equal(0, g:Xgetlist({'nr':'$'}).nr) - call assert_equal(1, len(g:Xgetlist({'nr':'$', 'all':1}))) - call assert_equal(0, len(g:Xgetlist({'nr':0}))) + call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title) + call assert_equal(0, g:Xgetlist({'nr':0}).nr) Xexpr "File1:10:Line1" Xexpr "File2:20:Line2" @@ -2754,7 +2754,7 @@ func Xqfid_tests(cchar) call s:setup_commands(a:cchar) call g:Xsetlist([], 'f') - call assert_equal({}, g:Xgetlist({'id':0})) + call assert_equal(0, g:Xgetlist({'id':0}).id) Xexpr '' let start_id = g:Xgetlist({'id' : 0}).id Xexpr '' | Xexpr '' @@ -2762,10 +2762,10 @@ func Xqfid_tests(cchar) call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id) call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id) call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id) - call assert_equal({}, g:Xgetlist({'id':0, 'nr':99})) + call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id) call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr) - call assert_equal({}, g:Xgetlist({'id':99, 'nr':0})) - call assert_equal({}, g:Xgetlist({'id':"abc", 'nr':0})) + call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id) + call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id) call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]}) call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context) @@ -2776,7 +2776,7 @@ func Xqfid_tests(cchar) let qfid = g:Xgetlist({'id':0, 'nr':0}) call g:Xsetlist([], 'f') - call assert_equal({}, g:Xgetlist({'id':qfid, 'nr':0})) + call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id) endfunc func Test_qf_id() @@ -2880,3 +2880,62 @@ func Test_qfjump() call Xqfjump_tests('c') call Xqfjump_tests('l') endfunc + +" Tests for the getqflist() and getloclist() functions when the list is not +" present or is empty +func Xgetlist_empty_tests(cchar) + call s:setup_commands(a:cchar) + + " Empty quickfix stack + call g:Xsetlist([], 'f') + call assert_equal('', g:Xgetlist({'context' : 0}).context) + call assert_equal(0, g:Xgetlist({'id' : 0}).id) + call assert_equal(0, g:Xgetlist({'idx' : 0}).idx) + call assert_equal([], g:Xgetlist({'items' : 0}).items) + call assert_equal(0, g:Xgetlist({'nr' : 0}).nr) + call assert_equal(0, g:Xgetlist({'size' : 0}).size) + call assert_equal('', g:Xgetlist({'title' : 0}).title) + call assert_equal(0, g:Xgetlist({'winid' : 0}).winid) + call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'all' : 0})) + + " Empty quickfix list + Xexpr "" + call assert_equal('', g:Xgetlist({'context' : 0}).context) + call assert_notequal(0, g:Xgetlist({'id' : 0}).id) + call assert_equal(0, g:Xgetlist({'idx' : 0}).idx) + call assert_equal([], g:Xgetlist({'items' : 0}).items) + call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr) + call assert_equal(0, g:Xgetlist({'size' : 0}).size) + call assert_notequal('', g:Xgetlist({'title' : 0}).title) + call assert_equal(0, g:Xgetlist({'winid' : 0}).winid) + + let qfid = g:Xgetlist({'id' : 0}).id + call g:Xsetlist([], 'f') + + " Non-existing quickfix identifier + call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context) + call assert_equal(0, g:Xgetlist({'id' : qfid}).id) + call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx) + call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items) + call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr) + call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size) + call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title) + call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid) + call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0})) + + " Non-existing quickfix list number + call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context) + call assert_equal(0, g:Xgetlist({'nr' : 5}).nr) + call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx) + call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items) + call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id) + call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size) + call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title) + call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid) + call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'nr' : 5, 'all' : 0})) +endfunc + +func Test_getqflist() + call Xgetlist_empty_tests('c') + call Xgetlist_empty_tests('l') +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -772,6 +772,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1389, +/**/ 1388, /**/ 1387,