# HG changeset patch # User Christian Brabandt # Date 1493555404 -7200 # Node ID 84baca75b7f20882d0b18974d9628d95c2fa45b5 # Parent ab53b2f7ffc38fa2722ca9536b7bd8f04f048d4a patch 8.0.0590: cannot add a context to locations commit https://github.com/vim/vim/commit/8f77c5a4ec756f3f866bd6b18feb6fca6f2a2e91 Author: Bram Moolenaar 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) diff --git a/src/eval.c b/src/eval.c --- 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) { /* diff --git a/src/proto/quickfix.pro b/src/proto/quickfix.pro --- 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); diff --git a/src/quickfix.c b/src/quickfix.c --- 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 /* 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 @@ -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() diff --git a/src/version.c b/src/version.c --- 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,