mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 18:55:14 -07:00
vim-patch:9.1.0891: building the completion list array is inefficient
Problem: building the completion list array is inefficient
Solution: refactor and improve ins_compl_build_pum() func
(glepnir)
current time complexity is O(n^2). I guess garray is not used here to save memory and avoid efficiency
is caused by heap memory allocation. A simple way is to add an extra pointer as a single linked list
to store the matching compl_T, and traverse this single linked list to generate compl_match_array.
The time complexity is O(n x m). The worst case is m=n, but we can still get a little improvement.
Because the if condition does not need to be run at one time. This should be a good solution for now.
Later we may be able to complete it in O(lgn) time. But this requires more reconstruction. So this is
the first step.
closes: #16125
80b662009c
This commit is contained in:
parent
344923fe9a
commit
d512479115
@ -156,6 +156,7 @@ typedef struct compl_S compl_T;
|
||||
struct compl_S {
|
||||
compl_T *cp_next;
|
||||
compl_T *cp_prev;
|
||||
compl_T *cp_match_next; ///< matched next compl_T
|
||||
char *cp_str; ///< matched text
|
||||
char *(cp_text[CPT_COUNT]); ///< text for the menu
|
||||
typval_T cp_user_data;
|
||||
@ -789,6 +790,7 @@ static inline void free_cptext(char *const *const cptext)
|
||||
/// @param[in] cdir match direction. If 0, use "compl_direction".
|
||||
/// @param[in] flags_arg match flags (cp_flags)
|
||||
/// @param[in] adup accept this match even if it is already present.
|
||||
/// @param[in] user_hl list of extra highlight attributes for abbr kind.
|
||||
///
|
||||
/// If "cdir" is FORWARD, then the match is added after the current match.
|
||||
/// Otherwise, it is added before the current match.
|
||||
@ -798,7 +800,7 @@ static inline void free_cptext(char *const *const cptext)
|
||||
/// returned in case of error.
|
||||
static int ins_compl_add(char *const str, int len, char *const fname, char *const *const cptext,
|
||||
const bool cptext_allocated, typval_T *user_data, const Direction cdir,
|
||||
int flags_arg, const bool adup, int *extra_hl)
|
||||
int flags_arg, const bool adup, const int *user_hl)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
compl_T *match;
|
||||
@ -864,8 +866,8 @@ static int ins_compl_add(char *const str, int len, char *const fname, char *cons
|
||||
match->cp_fname = NULL;
|
||||
}
|
||||
match->cp_flags = flags;
|
||||
match->cp_user_abbr_hlattr = extra_hl ? extra_hl[0] : -1;
|
||||
match->cp_user_kind_hlattr = extra_hl ? extra_hl[1] : -1;
|
||||
match->cp_user_abbr_hlattr = user_hl ? user_hl[0] : -1;
|
||||
match->cp_user_kind_hlattr = user_hl ? user_hl[1] : -1;
|
||||
|
||||
if (cptext != NULL) {
|
||||
int i;
|
||||
@ -1173,7 +1175,7 @@ static int ins_compl_build_pum(void)
|
||||
unsigned cur_cot_flags = get_cot_flags();
|
||||
bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0;
|
||||
bool compl_fuzzy_match = (cur_cot_flags & kOptCotFlagFuzzy) != 0;
|
||||
|
||||
compl_T *match_head = NULL, *match_tail = NULL;
|
||||
do {
|
||||
// When 'completeopt' contains "fuzzy" and leader is not NULL or empty,
|
||||
// set the cp_score for later comparisons.
|
||||
@ -1186,6 +1188,12 @@ static int ins_compl_build_pum(void)
|
||||
|| ins_compl_equal(comp, compl_leader, (size_t)lead_len)
|
||||
|| (compl_fuzzy_match && comp->cp_score > 0))) {
|
||||
compl_match_arraysize++;
|
||||
if (match_head == NULL) {
|
||||
match_head = comp;
|
||||
} else {
|
||||
match_tail->cp_match_next = comp;
|
||||
}
|
||||
match_tail = comp;
|
||||
}
|
||||
comp = comp->cp_next;
|
||||
} while (comp != NULL && !is_first_match(comp));
|
||||
@ -1206,15 +1214,11 @@ static int ins_compl_build_pum(void)
|
||||
}
|
||||
|
||||
compl_T *shown_compl = NULL;
|
||||
bool did_find_shown_match = false;
|
||||
bool did_find_shown_match = match_head == match_tail ? true : false;
|
||||
int cur = -1;
|
||||
int i = 0;
|
||||
comp = compl_first_match;
|
||||
do {
|
||||
if (!match_at_original_text(comp)
|
||||
&& (compl_leader == NULL
|
||||
|| ins_compl_equal(comp, compl_leader, (size_t)lead_len)
|
||||
|| (compl_fuzzy_match && comp->cp_score > 0))) {
|
||||
comp = match_head;
|
||||
while (comp != NULL) {
|
||||
if (!shown_match_ok && !compl_fuzzy_match) {
|
||||
if (comp == compl_shown_match || did_find_shown_match) {
|
||||
// This item is the shown match or this is the
|
||||
@ -1275,7 +1279,6 @@ static int ins_compl_build_pum(void)
|
||||
} else {
|
||||
compl_match_array[i++].pum_extra = comp->cp_fname;
|
||||
}
|
||||
}
|
||||
|
||||
if (comp == compl_shown_match && !compl_fuzzy_match) {
|
||||
did_find_shown_match = true;
|
||||
@ -1293,8 +1296,10 @@ static int ins_compl_build_pum(void)
|
||||
shown_match_ok = true;
|
||||
}
|
||||
}
|
||||
comp = comp->cp_next;
|
||||
} while (comp != NULL && !is_first_match(comp));
|
||||
compl_T *match_next = comp->cp_match_next;
|
||||
comp->cp_match_next = NULL;
|
||||
comp = match_next;
|
||||
}
|
||||
|
||||
if (compl_fuzzy_match && compl_leader != NULL && lead_len > 0) {
|
||||
for (i = 0; i < compl_match_arraysize; i++) {
|
||||
@ -2574,7 +2579,7 @@ static int ins_compl_add_tv(typval_T *const tv, const Direction dir, bool fast)
|
||||
char *(cptext[CPT_COUNT]);
|
||||
char *user_abbr_hlname = NULL;
|
||||
char *user_kind_hlname = NULL;
|
||||
int extra_hl[2] = { -1, -1 };
|
||||
int user_hl[2] = { -1, -1 };
|
||||
typval_T user_data;
|
||||
|
||||
user_data.v_type = VAR_UNKNOWN;
|
||||
@ -2586,10 +2591,10 @@ static int ins_compl_add_tv(typval_T *const tv, const Direction dir, bool fast)
|
||||
cptext[CPT_INFO] = tv_dict_get_string(tv->vval.v_dict, "info", true);
|
||||
|
||||
user_abbr_hlname = tv_dict_get_string(tv->vval.v_dict, "abbr_hlgroup", false);
|
||||
extra_hl[0] = get_user_highlight_attr(user_abbr_hlname);
|
||||
user_hl[0] = get_user_highlight_attr(user_abbr_hlname);
|
||||
|
||||
user_kind_hlname = tv_dict_get_string(tv->vval.v_dict, "kind_hlgroup", false);
|
||||
extra_hl[1] = get_user_highlight_attr(user_kind_hlname);
|
||||
user_hl[1] = get_user_highlight_attr(user_kind_hlname);
|
||||
|
||||
tv_dict_get_tv(tv->vval.v_dict, "user_data", &user_data);
|
||||
|
||||
@ -2612,7 +2617,7 @@ static int ins_compl_add_tv(typval_T *const tv, const Direction dir, bool fast)
|
||||
return FAIL;
|
||||
}
|
||||
int status = ins_compl_add((char *)word, -1, NULL, cptext, true,
|
||||
&user_data, dir, flags, dup, extra_hl);
|
||||
&user_data, dir, flags, dup, user_hl);
|
||||
if (status != OK) {
|
||||
tv_clear(&user_data);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user