aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJames McCoy <jamessan@jamessan.com>2017-12-19 08:39:09 -0500
committerJames McCoy <jamessan@jamessan.com>2017-12-19 14:07:24 -0500
commit20708a07bfc1de2c56657123c41bb52919a728d8 (patch)
tree837ab6e11270171f8046e42b83117efdb767e19c /src
parent53a530b2f54e69adb52d32718edf36df7c0b1b5b (diff)
downloadrneovim-20708a07bfc1de2c56657123c41bb52919a728d8.tar.gz
rneovim-20708a07bfc1de2c56657123c41bb52919a728d8.tar.bz2
rneovim-20708a07bfc1de2c56657123c41bb52919a728d8.zip
vim-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 vim/vim#1012) https://github.com/vim/vim/commit/8f77c5a4ec756f3f866bd6b18feb6fca6f2a2e91
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval.c2
-rw-r--r--src/nvim/quickfix.c71
-rw-r--r--src/nvim/testdir/test_quickfix.vim32
3 files changed, 105 insertions, 0 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 1461ddb8f9..2355c8c813 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -5173,6 +5173,8 @@ bool garbage_collect(bool testing)
ABORTING(set_ref_list)(sub.additional_elements, copyID);
}
+ ABORTING(set_ref_in_quickfix)(copyID);
+
bool did_free = false;
if (!abort) {
// 2. Free lists and dictionaries that are not referenced.
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index d77cec4fd8..e7d11df833 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -85,6 +85,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 {
@@ -1409,6 +1410,13 @@ void copy_loclist(win_T *from, win_T *to)
else
to_qfl->qf_title = NULL;
+ if (from_qfl->qf_ctx != NULL) {
+ to_qfl->qf_ctx = xcalloc(1, sizeof(typval_T));
+ tv_copy(from_qfl->qf_ctx, to_qfl->qf_ctx);
+ } else {
+ to_qfl->qf_ctx = NULL;
+ }
+
if (from_qfl->qf_count) {
qfline_T *from_qfp;
qfline_T *prevp;
@@ -2410,6 +2418,8 @@ static void qf_free(qf_info_T *qi, int idx)
qi->qf_lists[idx].qf_start = NULL;
qi->qf_lists[idx].qf_ptr = NULL;
qi->qf_lists[idx].qf_title = NULL;
+ tv_free(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;
@@ -4060,6 +4070,7 @@ enum {
QF_GETLIST_ITEMS = 0x2,
QF_GETLIST_NR = 0x4,
QF_GETLIST_WINID = 0x8,
+ QF_GETLIST_CONTEXT = 0x10,
QF_GETLIST_ALL = 0xFF
};
@@ -4110,6 +4121,10 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
flags |= QF_GETLIST_WINID;
}
+ if (tv_dict_find(what, S_LEN("context")) != NULL) {
+ flags |= QF_GETLIST_CONTEXT;
+ }
+
if (flags & QF_GETLIST_TITLE) {
char_u *t = qi->qf_lists[qf_idx].qf_title;
if (t == NULL) {
@@ -4127,6 +4142,18 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
}
}
+ if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) {
+ if (qi->qf_lists[qf_idx].qf_ctx != NULL) {
+ di = tv_dict_item_alloc_len(S_LEN("context"));
+ if (di != NULL) {
+ tv_copy(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv);
+ tv_dict_add(retdict, di);
+ }
+ } else {
+ status = tv_dict_add_str(retdict, S_LEN("context"), "");
+ }
+ }
+
return status;
}
@@ -4276,6 +4303,14 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action)
}
}
+ if ((di = tv_dict_find(what, S_LEN("context"))) != NULL) {
+ tv_free(qi->qf_lists[qi->qf_curlist].qf_ctx);
+
+ typval_T *ctx = xcalloc(1, sizeof(typval_T));
+ tv_copy(&di->di_tv, ctx);
+ qi->qf_lists[qi->qf_curlist].qf_ctx = ctx;
+ }
+
return retval;
}
@@ -4362,6 +4397,42 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title,
return retval;
}
+static bool mark_quickfix_ctx(qf_info_T *qi, int copyID)
+{
+ bool abort = false;
+
+ for (int i = 0; i < LISTCOUNT && !abort; i++) {
+ typval_T *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.
+bool set_ref_in_quickfix(int copyID)
+{
+ bool 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;
+}
+
/*
* ":[range]cbuffer [bufnr]" command.
* ":[range]caddbuffer [bufnr]" command.
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index dd64e37ce3..1d17da31ed 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -1754,6 +1754,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()