mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 9.0.1688: cannot store custom data in quickfix list
Problem: cannot store custom data in quickfix list Solution: add `user_data` field for the quickfix list closes: #11818 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Tom Praschan <13141438+tom-anders@users.noreply.github.com>
This commit is contained in:
committed by
Christian Brabandt
parent
7e0bae024d
commit
ca6ac99077
@@ -4002,6 +4002,9 @@ getqflist([{what}]) *getqflist()*
|
|||||||
text description of the error
|
text description of the error
|
||||||
type type of the error, 'E', '1', etc.
|
type type of the error, 'E', '1', etc.
|
||||||
valid |TRUE|: recognized error message
|
valid |TRUE|: recognized error message
|
||||||
|
user_data
|
||||||
|
custom data associated with the item, can be
|
||||||
|
any type.
|
||||||
|
|
||||||
When there is no error list or it's empty, an empty list is
|
When there is no error list or it's empty, an empty list is
|
||||||
returned. Quickfix list entries with a non-existing buffer
|
returned. Quickfix list entries with a non-existing buffer
|
||||||
@@ -8298,6 +8301,8 @@ setqflist({list} [, {action} [, {what}]]) *setqflist()*
|
|||||||
text description of the error
|
text description of the error
|
||||||
type single-character error type, 'E', 'W', etc.
|
type single-character error type, 'E', 'W', etc.
|
||||||
valid recognized error message
|
valid recognized error message
|
||||||
|
user_data custom data associated with the item, can be
|
||||||
|
any type.
|
||||||
|
|
||||||
The "col", "vcol", "nr", "type" and "text" entries are
|
The "col", "vcol", "nr", "type" and "text" entries are
|
||||||
optional. Either "lnum" or "pattern" entry can be used to
|
optional. Either "lnum" or "pattern" entry can be used to
|
||||||
|
@@ -43,6 +43,7 @@ struct qfline_S
|
|||||||
char_u qf_cleared; // set to TRUE if line has been deleted
|
char_u qf_cleared; // set to TRUE if line has been deleted
|
||||||
char_u qf_type; // type of the error (mostly 'E'); 1 for
|
char_u qf_type; // type of the error (mostly 'E'); 1 for
|
||||||
// :helpgrep
|
// :helpgrep
|
||||||
|
typval_T qf_user_data; // custom user data associated with this item
|
||||||
char_u qf_valid; // valid error message detected
|
char_u qf_valid; // valid error message detected
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -82,6 +83,7 @@ typedef struct qf_list_S
|
|||||||
int qf_count; // number of errors (0 means empty list)
|
int qf_count; // number of errors (0 means empty list)
|
||||||
int qf_index; // current index in the error list
|
int qf_index; // current index in the error list
|
||||||
int qf_nonevalid; // TRUE if not a single valid entry found
|
int qf_nonevalid; // TRUE if not a single valid entry found
|
||||||
|
int qf_has_user_data; // TRUE if at least one item has user_data attached
|
||||||
char_u *qf_title; // title derived from the command that created
|
char_u *qf_title; // title derived from the command that created
|
||||||
// the error list or set by setqflist
|
// the error list or set by setqflist
|
||||||
typval_T *qf_ctx; // context set by setqflist/setloclist
|
typval_T *qf_ctx; // context set by setqflist/setloclist
|
||||||
@@ -168,7 +170,7 @@ static efm_T *fmt_start = NULL; // cached across qf_parse_line() calls
|
|||||||
static callback_T qftf_cb;
|
static callback_T qftf_cb;
|
||||||
|
|
||||||
static void qf_new_list(qf_info_T *qi, char_u *qf_title);
|
static void qf_new_list(qf_info_T *qi, char_u *qf_title);
|
||||||
static int qf_add_entry(qf_list_T *qfl, char_u *dir, char_u *fname, char_u *module, int bufnum, char_u *mesg, long lnum, long end_lnum, int col, int end_col, int vis_col, char_u *pattern, int nr, int type, int valid);
|
static int qf_add_entry(qf_list_T *qfl, char_u *dir, char_u *fname, char_u *module, int bufnum, char_u *mesg, long lnum, long end_lnum, int col, int end_col, int vis_col, char_u *pattern, int nr, int type, typval_T *user_data, int valid);
|
||||||
static void qf_free(qf_list_T *qfl);
|
static void qf_free(qf_list_T *qfl);
|
||||||
static char_u *qf_types(int, int);
|
static char_u *qf_types(int, int);
|
||||||
static int qf_get_fnum(qf_list_T *qfl, char_u *, char_u *);
|
static int qf_get_fnum(qf_list_T *qfl, char_u *, char_u *);
|
||||||
@@ -951,6 +953,7 @@ typedef struct {
|
|||||||
char_u *pattern;
|
char_u *pattern;
|
||||||
int enr;
|
int enr;
|
||||||
int type;
|
int type;
|
||||||
|
typval_T *user_data;
|
||||||
int valid;
|
int valid;
|
||||||
} qffields_T;
|
} qffields_T;
|
||||||
|
|
||||||
@@ -1720,6 +1723,7 @@ qf_init_process_nextline(
|
|||||||
fields->pattern,
|
fields->pattern,
|
||||||
fields->enr,
|
fields->enr,
|
||||||
fields->type,
|
fields->type,
|
||||||
|
fields->user_data,
|
||||||
fields->valid);
|
fields->valid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1965,6 +1969,7 @@ qf_new_list(qf_info_T *qi, char_u *qf_title)
|
|||||||
qf_store_title(qfl, qf_title);
|
qf_store_title(qfl, qf_title);
|
||||||
qfl->qfl_type = qi->qfl_type;
|
qfl->qfl_type = qi->qfl_type;
|
||||||
qfl->qf_id = ++last_qf_id;
|
qfl->qf_id = ++last_qf_id;
|
||||||
|
qfl->qf_has_user_data = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2145,6 +2150,7 @@ qf_add_entry(
|
|||||||
char_u *pattern, // search pattern
|
char_u *pattern, // search pattern
|
||||||
int nr, // error number
|
int nr, // error number
|
||||||
int type, // type character
|
int type, // type character
|
||||||
|
typval_T *user_data, // custom user data or NULL
|
||||||
int valid) // valid entry
|
int valid) // valid entry
|
||||||
{
|
{
|
||||||
qfline_T *qfp;
|
qfline_T *qfp;
|
||||||
@@ -2173,6 +2179,13 @@ qf_add_entry(
|
|||||||
qfp->qf_col = col;
|
qfp->qf_col = col;
|
||||||
qfp->qf_end_col = end_col;
|
qfp->qf_end_col = end_col;
|
||||||
qfp->qf_viscol = vis_col;
|
qfp->qf_viscol = vis_col;
|
||||||
|
if (user_data == NULL || user_data->v_type == VAR_UNKNOWN)
|
||||||
|
qfp->qf_user_data.v_type = VAR_UNKNOWN;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
copy_tv(user_data, &qfp->qf_user_data);
|
||||||
|
qfl->qf_has_user_data = TRUE;
|
||||||
|
}
|
||||||
if (pattern == NULL || *pattern == NUL)
|
if (pattern == NULL || *pattern == NUL)
|
||||||
qfp->qf_pattern = NULL;
|
qfp->qf_pattern = NULL;
|
||||||
else if ((qfp->qf_pattern = vim_strsave(pattern)) == NULL)
|
else if ((qfp->qf_pattern = vim_strsave(pattern)) == NULL)
|
||||||
@@ -2335,6 +2348,7 @@ copy_loclist_entries(qf_list_T *from_qfl, qf_list_T *to_qfl)
|
|||||||
from_qfp->qf_pattern,
|
from_qfp->qf_pattern,
|
||||||
from_qfp->qf_nr,
|
from_qfp->qf_nr,
|
||||||
0,
|
0,
|
||||||
|
&from_qfp->qf_user_data,
|
||||||
from_qfp->qf_valid) == QF_FAIL)
|
from_qfp->qf_valid) == QF_FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
@@ -2360,6 +2374,7 @@ copy_loclist(qf_list_T *from_qfl, qf_list_T *to_qfl)
|
|||||||
// Some of the fields are populated by qf_add_entry()
|
// Some of the fields are populated by qf_add_entry()
|
||||||
to_qfl->qfl_type = from_qfl->qfl_type;
|
to_qfl->qfl_type = from_qfl->qfl_type;
|
||||||
to_qfl->qf_nonevalid = from_qfl->qf_nonevalid;
|
to_qfl->qf_nonevalid = from_qfl->qf_nonevalid;
|
||||||
|
to_qfl->qf_has_user_data = from_qfl->qf_has_user_data;
|
||||||
to_qfl->qf_count = 0;
|
to_qfl->qf_count = 0;
|
||||||
to_qfl->qf_index = 0;
|
to_qfl->qf_index = 0;
|
||||||
to_qfl->qf_start = NULL;
|
to_qfl->qf_start = NULL;
|
||||||
@@ -3957,6 +3972,7 @@ qf_free_items(qf_list_T *qfl)
|
|||||||
vim_free(qfp->qf_module);
|
vim_free(qfp->qf_module);
|
||||||
vim_free(qfp->qf_text);
|
vim_free(qfp->qf_text);
|
||||||
vim_free(qfp->qf_pattern);
|
vim_free(qfp->qf_pattern);
|
||||||
|
clear_tv(&qfp->qf_user_data);
|
||||||
stop = (qfp == qfpnext);
|
stop = (qfp == qfpnext);
|
||||||
vim_free(qfp);
|
vim_free(qfp);
|
||||||
if (stop)
|
if (stop)
|
||||||
@@ -6085,6 +6101,7 @@ vgr_match_buflines(
|
|||||||
NULL, // search pattern
|
NULL, // search pattern
|
||||||
0, // nr
|
0, // nr
|
||||||
0, // type
|
0, // type
|
||||||
|
NULL, // user_data
|
||||||
TRUE // valid
|
TRUE // valid
|
||||||
) == QF_FAIL)
|
) == QF_FAIL)
|
||||||
{
|
{
|
||||||
@@ -6131,6 +6148,7 @@ vgr_match_buflines(
|
|||||||
NULL, // search pattern
|
NULL, // search pattern
|
||||||
0, // nr
|
0, // nr
|
||||||
0, // type
|
0, // type
|
||||||
|
NULL, // user_data
|
||||||
TRUE // valid
|
TRUE // valid
|
||||||
) == QF_FAIL)
|
) == QF_FAIL)
|
||||||
{
|
{
|
||||||
@@ -6771,6 +6789,8 @@ get_qfline_items(qfline_T *qfp, list_T *list)
|
|||||||
|| dict_add_string(dict, "pattern", qfp->qf_pattern) == FAIL
|
|| dict_add_string(dict, "pattern", qfp->qf_pattern) == FAIL
|
||||||
|| dict_add_string(dict, "text", qfp->qf_text) == FAIL
|
|| dict_add_string(dict, "text", qfp->qf_text) == FAIL
|
||||||
|| dict_add_string(dict, "type", buf) == FAIL
|
|| dict_add_string(dict, "type", buf) == FAIL
|
||||||
|
|| (qfp->qf_user_data.v_type != VAR_UNKNOWN
|
||||||
|
&& dict_add_tv(dict, "user_data", &qfp->qf_user_data) == FAIL )
|
||||||
|| dict_add_number(dict, "valid", (long)qfp->qf_valid) == FAIL)
|
|| dict_add_number(dict, "valid", (long)qfp->qf_valid) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
@@ -7305,6 +7325,9 @@ qf_add_entry_from_dict(
|
|||||||
text = dict_get_string(d, "text", TRUE);
|
text = dict_get_string(d, "text", TRUE);
|
||||||
if (text == NULL)
|
if (text == NULL)
|
||||||
text = vim_strsave((char_u *)"");
|
text = vim_strsave((char_u *)"");
|
||||||
|
typval_T user_data;
|
||||||
|
user_data.v_type = VAR_UNKNOWN;
|
||||||
|
dict_get_tv(d, "user_data", &user_data);
|
||||||
|
|
||||||
valid = TRUE;
|
valid = TRUE;
|
||||||
if ((filename == NULL && bufnum == 0) || (lnum == 0 && pattern == NULL))
|
if ((filename == NULL && bufnum == 0) || (lnum == 0 && pattern == NULL))
|
||||||
@@ -7341,6 +7364,7 @@ qf_add_entry_from_dict(
|
|||||||
pattern, // search pattern
|
pattern, // search pattern
|
||||||
nr,
|
nr,
|
||||||
type == NULL ? NUL : *type,
|
type == NULL ? NUL : *type,
|
||||||
|
&user_data,
|
||||||
valid);
|
valid);
|
||||||
|
|
||||||
vim_free(filename);
|
vim_free(filename);
|
||||||
@@ -7348,6 +7372,7 @@ qf_add_entry_from_dict(
|
|||||||
vim_free(pattern);
|
vim_free(pattern);
|
||||||
vim_free(text);
|
vim_free(text);
|
||||||
vim_free(type);
|
vim_free(type);
|
||||||
|
clear_tv(&user_data);
|
||||||
|
|
||||||
if (valid)
|
if (valid)
|
||||||
*valid_entry = TRUE;
|
*valid_entry = TRUE;
|
||||||
@@ -7805,6 +7830,27 @@ set_errorlist(
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mark_quickfix_user_data(qf_info_T *qi, int copyID)
|
||||||
|
{
|
||||||
|
int abort = FALSE;
|
||||||
|
for (int i = 0; i < LISTCOUNT && !abort; ++i)
|
||||||
|
{
|
||||||
|
qf_list_T *qfl = &qi->qf_lists[i];
|
||||||
|
if (!qfl->qf_has_user_data)
|
||||||
|
continue;
|
||||||
|
qfline_T *qfp;
|
||||||
|
int j;
|
||||||
|
FOR_ALL_QFL_ITEMS(qfl, qfp, j)
|
||||||
|
{
|
||||||
|
typval_T* user_data = &qfp->qf_user_data;
|
||||||
|
if (user_data != NULL && user_data->v_type != VAR_NUMBER
|
||||||
|
&& user_data->v_type != VAR_STRING && user_data->v_type != VAR_FLOAT)
|
||||||
|
abort = abort || set_ref_in_item(user_data, copyID, NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return abort;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark the quickfix context and callback function as in use for all the lists
|
* Mark the quickfix context and callback function as in use for all the lists
|
||||||
* in a quickfix stack.
|
* in a quickfix stack.
|
||||||
@@ -7846,6 +7892,10 @@ set_ref_in_quickfix(int copyID)
|
|||||||
if (abort)
|
if (abort)
|
||||||
return abort;
|
return abort;
|
||||||
|
|
||||||
|
abort = mark_quickfix_user_data(&ql_info, copyID);
|
||||||
|
if (abort)
|
||||||
|
return abort;
|
||||||
|
|
||||||
abort = set_ref_in_callback(&qftf_cb, copyID);
|
abort = set_ref_in_callback(&qftf_cb, copyID);
|
||||||
if (abort)
|
if (abort)
|
||||||
return abort;
|
return abort;
|
||||||
@@ -7857,6 +7907,10 @@ set_ref_in_quickfix(int copyID)
|
|||||||
abort = mark_quickfix_ctx(win->w_llist, copyID);
|
abort = mark_quickfix_ctx(win->w_llist, copyID);
|
||||||
if (abort)
|
if (abort)
|
||||||
return abort;
|
return abort;
|
||||||
|
|
||||||
|
abort = mark_quickfix_user_data(win->w_llist, copyID);
|
||||||
|
if (abort)
|
||||||
|
return abort;
|
||||||
}
|
}
|
||||||
if (IS_LL_WINDOW(win) && (win->w_llist_ref->qf_refcount == 1))
|
if (IS_LL_WINDOW(win) && (win->w_llist_ref->qf_refcount == 1))
|
||||||
{
|
{
|
||||||
@@ -8225,6 +8279,7 @@ hgr_search_file(
|
|||||||
NULL, // search pattern
|
NULL, // search pattern
|
||||||
0, // nr
|
0, // nr
|
||||||
1, // type
|
1, // type
|
||||||
|
NULL, // user_data
|
||||||
TRUE // valid
|
TRUE // valid
|
||||||
) == QF_FAIL)
|
) == QF_FAIL)
|
||||||
{
|
{
|
||||||
|
@@ -1808,13 +1808,23 @@ func SetXlistTests(cchar, bnum)
|
|||||||
call s:setup_commands(a:cchar)
|
call s:setup_commands(a:cchar)
|
||||||
|
|
||||||
call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
|
call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
|
||||||
\ {'bufnr': a:bnum, 'lnum': 2, 'end_lnum': 3, 'col': 4, 'end_col': 5}])
|
\ {'bufnr': a:bnum, 'lnum': 2, 'end_lnum': 3, 'col': 4, 'end_col': 5, 'user_data': {'6': [7, 8]}}])
|
||||||
let l = g:Xgetlist()
|
let l = g:Xgetlist()
|
||||||
call assert_equal(2, len(l))
|
call assert_equal(2, len(l))
|
||||||
call assert_equal(2, l[1].lnum)
|
call assert_equal(2, l[1].lnum)
|
||||||
call assert_equal(3, l[1].end_lnum)
|
call assert_equal(3, l[1].end_lnum)
|
||||||
call assert_equal(4, l[1].col)
|
call assert_equal(4, l[1].col)
|
||||||
call assert_equal(5, l[1].end_col)
|
call assert_equal(5, l[1].end_col)
|
||||||
|
call assert_equal({'6': [7, 8]}, l[1].user_data)
|
||||||
|
|
||||||
|
" Test that user_data is garbage collected
|
||||||
|
call g:Xsetlist([{'user_data': ['high', 5]},
|
||||||
|
\ {'user_data': {'this': [7, 'eight'], 'is': ['a', 'dictionary']}}])
|
||||||
|
call test_garbagecollect_now()
|
||||||
|
let l = g:Xgetlist()
|
||||||
|
call assert_equal(2, len(l))
|
||||||
|
call assert_equal(['high', 5], l[0].user_data)
|
||||||
|
call assert_equal({'this': [7, 'eight'], 'is': ['a', 'dictionary']}, l[1].user_data)
|
||||||
|
|
||||||
Xnext
|
Xnext
|
||||||
call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a')
|
call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a')
|
||||||
|
@@ -695,6 +695,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1688,
|
||||||
/**/
|
/**/
|
||||||
1687,
|
1687,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user