changeset 11412:84baca75b7f2 v8.0.0590

patch 8.0.0590: cannot add a context to locations commit https://github.com/vim/vim/commit/8f77c5a4ec756f3f866bd6b18feb6fca6f2a2e91 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Apr 30 14:21:00 2017 +0200 patch 8.0.0590: cannot add a context to locations Problem: Cannot add a context to locations. Solution: Add the "context" entry in location entries. (Yegappan Lakshmanan, closes #1012)
author Christian Brabandt <cb@256bit.org>
date Sun, 30 Apr 2017 14:30:04 +0200
parents ab53b2f7ffc3
children a3d6075a35ad
files src/eval.c src/proto/quickfix.pro src/quickfix.c src/testdir/test_quickfix.vim src/version.c
diffstat 5 files changed, 125 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -5327,6 +5327,10 @@ garbage_collect(int testing)
     abort = abort || set_ref_in_timer(copyID);
 #endif
 
+#ifdef FEAT_QUICKFIX
+    abort = abort || set_ref_in_quickfix(copyID);
+#endif
+
     if (!abort)
     {
 	/*
--- a/src/proto/quickfix.pro
+++ b/src/proto/quickfix.pro
@@ -29,6 +29,7 @@ void ex_vimgrep(exarg_T *eap);
 int get_errorlist(win_T *wp, int qf_idx, list_T *list);
 int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict);
 int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, dict_T *what);
+int set_ref_in_quickfix(int copyID);
 void ex_cbuffer(exarg_T *eap);
 void ex_cexpr(exarg_T *eap);
 void ex_helpgrep(exarg_T *eap);
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -57,6 +57,7 @@ typedef struct qf_list_S
     int		qf_nonevalid;	/* TRUE if not a single valid entry found */
     char_u	*qf_title;	/* title derived from the command that created
 				 * the error list */
+    typval_T	*qf_ctx;	/* context set by setqflist/setloclist */
 } qf_list_T;
 
 struct qf_info_S
@@ -1596,6 +1597,14 @@ copy_loclist(win_T *from, win_T *to)
 	    to_qfl->qf_title = vim_strsave(from_qfl->qf_title);
 	else
 	    to_qfl->qf_title = NULL;
+	if (from_qfl->qf_ctx != NULL)
+	{
+	    to_qfl->qf_ctx = alloc_tv();
+	    if (to_qfl->qf_ctx != NULL)
+		copy_tv(from_qfl->qf_ctx, to_qfl->qf_ctx);
+	}
+	else
+	    to_qfl->qf_ctx = NULL;
 
 	if (from_qfl->qf_count)
 	{
@@ -2749,6 +2758,8 @@ qf_free(qf_info_T *qi, int idx)
     }
     vim_free(qi->qf_lists[idx].qf_title);
     qi->qf_lists[idx].qf_title = NULL;
+    free_tv(qi->qf_lists[idx].qf_ctx);
+    qi->qf_lists[idx].qf_ctx = NULL;
     qi->qf_lists[idx].qf_index = 0;
     qi->qf_lists[idx].qf_start = NULL;
     qi->qf_lists[idx].qf_last = NULL;
@@ -4629,6 +4640,7 @@ enum {
     QF_GETLIST_ITEMS	= 0x2,
     QF_GETLIST_NR	= 0x4,
     QF_GETLIST_WINID	= 0x8,
+    QF_GETLIST_CONTEXT	= 0x10,
     QF_GETLIST_ALL	= 0xFF
 };
 
@@ -4681,6 +4693,9 @@ get_errorlist_properties(win_T *wp, dict
     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 (flags & QF_GETLIST_TITLE)
     {
 	char_u	*t;
@@ -4699,6 +4714,21 @@ get_errorlist_properties(win_T *wp, dict
 	    status = dict_add_nr_str(retdict, "winid", win->w_id, NULL);
     }
 
+    if ((status == OK) && (flags & QF_GETLIST_CONTEXT))
+    {
+	if (qi->qf_lists[qf_idx].qf_ctx != NULL)
+	{
+	    di = dictitem_alloc((char_u *)"context");
+	    if (di != NULL)
+	    {
+		copy_tv(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv);
+		dict_add(retdict, di);
+	    }
+	}
+	else
+	    status = dict_add_nr_str(retdict, "context", 0L, (char_u *)"");
+    }
+
     return status;
 }
 
@@ -4874,6 +4904,16 @@ qf_set_properties(qf_info_T *qi, dict_T 
 	}
     }
 
+    if ((di = dict_find(what, (char_u *)"context", -1)) != NULL)
+    {
+	typval_T	*ctx;
+	free_tv(qi->qf_lists[qi->qf_curlist].qf_ctx);
+	ctx =  alloc_tv();
+	if (ctx != NULL)
+	    copy_tv(&di->di_tv, ctx);
+	qi->qf_lists[qi->qf_curlist].qf_ctx = ctx;
+    }
+
     return retval;
 }
 
@@ -4981,6 +5021,52 @@ set_errorlist(
 
     return retval;
 }
+
+    static int
+mark_quickfix_ctx(qf_info_T *qi, int copyID)
+{
+    int		i;
+    int		abort = FALSE;
+    typval_T	*ctx;
+
+    for (i = 0; i < LISTCOUNT && !abort; ++i)
+    {
+	ctx = qi->qf_lists[i].qf_ctx;
+	if (ctx != NULL && ctx->v_type != VAR_NUMBER &&
+		ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT)
+	    abort = set_ref_in_item(ctx, copyID, NULL, NULL);
+    }
+
+    return abort;
+}
+
+/*
+ * Mark the context of the quickfix list and the location lists (if present) as
+ * "in use". So that garabage collection doesn't free the context.
+ */
+    int
+set_ref_in_quickfix(int copyID)
+{
+    int		abort = FALSE;
+    tabpage_T	*tp;
+    win_T	*win;
+
+    abort = mark_quickfix_ctx(&ql_info, copyID);
+    if (abort)
+	return abort;
+
+    FOR_ALL_TAB_WINDOWS(tp, win)
+    {
+	if (win->w_llist != NULL)
+	{
+	    abort = mark_quickfix_ctx(win->w_llist, copyID);
+	    if (abort)
+		return abort;
+	}
+    }
+
+    return abort;
+}
 #endif
 
 /*
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -1772,6 +1772,38 @@ func Xproperty_tests(cchar)
     if a:cchar == 'l'
 	call assert_equal({}, getloclist(99, {'title': 1}))
     endif
+
+    " Context related tests
+    call g:Xsetlist([], 'a', {'context':[1,2,3]})
+    call test_garbagecollect_now()
+    let d = g:Xgetlist({'context':1})
+    call assert_equal([1,2,3], d.context)
+    call g:Xsetlist([], 'a', {'context':{'color':'green'}})
+    let d = g:Xgetlist({'context':1})
+    call assert_equal({'color':'green'}, d.context)
+    call g:Xsetlist([], 'a', {'context':"Context info"})
+    let d = g:Xgetlist({'context':1})
+    call assert_equal("Context info", d.context)
+    call g:Xsetlist([], 'a', {'context':246})
+    let d = g:Xgetlist({'context':1})
+    call assert_equal(246, d.context)
+    if a:cchar == 'l'
+	" Test for copying context across two different location lists
+	new | only
+	let w1_id = win_getid()
+	let l = [1]
+	call setloclist(0, [], 'a', {'context':l})
+	new
+	let w2_id = win_getid()
+	call add(l, 2)
+	call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
+	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
+	unlet! l
+	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
+	only
+	call setloclist(0, [], 'f')
+	call assert_equal({}, getloclist(0, {'context':1}))
+    endif
 endfunc
 
 func Test_qf_property()
--- a/src/version.c
+++ b/src/version.c
@@ -765,6 +765,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    590,
+/**/
     589,
 /**/
     588,