changeset 13026:7c0e0e923537 v8.0.1389

patch 8.0.1389: getqflist() items are missing if not set commit https://github.com/vim/vim/commit/a6d4849c711379b773529afaed640455287ac934 Author: Bram Moolenaar <Bram@vim.org> 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)
author Christian Brabandt <cb@256bit.org>
date Tue, 12 Dec 2017 23:00:06 +0100
parents 5f7d269284a3
children 4d0fa7ed1296
files runtime/doc/eval.txt src/quickfix.c src/testdir/test_quickfix.vim src/version.c
diffstat 4 files changed, 162 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- 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: >
--- 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;
--- 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
--- 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,