From 03da3697a40d56961250028ce60a49ea6e87728b Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sun, 12 Jan 2020 18:40:27 -0500 Subject: vim-patch:8.2.0112: illegal memory access when using 'cindent' Problem: Illegal memory access when using 'cindent'. Solution: Check for NUL byte. (Dominique Pelle, closes vim/vim#5470) https://github.com/vim/vim/commit/02ad46394e8f887b60fda994f8a5da2ac1937b23 --- src/nvim/indent_c.c | 3 +++ src/nvim/testdir/test_cindent.vim | 9 +++++++++ 2 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c index 1ca1f3dae5..67a7e58ed7 100644 --- a/src/nvim/indent_c.c +++ b/src/nvim/indent_c.c @@ -461,6 +461,9 @@ cin_iscase ( if (cin_starts_with(s, "case")) { for (s += 4; *s; ++s) { s = cin_skipcomment(s); + if (*s == NUL) { + break; + } if (*s == ':') { if (s[1] == ':') /* skip over "::" for C++ */ ++s; diff --git a/src/nvim/testdir/test_cindent.vim b/src/nvim/testdir/test_cindent.vim index d9795d9335..debc9da46d 100644 --- a/src/nvim/testdir/test_cindent.vim +++ b/src/nvim/testdir/test_cindent.vim @@ -118,4 +118,13 @@ b = something(); bw! endfunc +" this was going beyond the end of the line. +func Test_cindent_case() + new + call setline(1, "case x: // x") + set cindent + norm! f:a: + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab -- cgit From d811fab0ad3e679acc27a4ff8f399fcf04726aa9 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Wed, 15 Jan 2020 22:20:21 -0500 Subject: vim-patch:8.2.0120: virtcol() does not check arguments to be valid Problem: virtcol() does not check arguments to be valid, which may lead to a crash. Solution: Check the column to be valid. Do not decrement MAXCOL. (closes vim/vim#5480) https://github.com/vim/vim/commit/b3d33d8570bc49a7f90990572d7f9630a1bfae02 --- src/nvim/eval.c | 11 ++++++++++- src/nvim/testdir/test_marks.vim | 21 +++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 9916ee3bd3..797c61a482 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -16018,7 +16018,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) const char *const name = tv_get_string_chk(argvars); if (name != NULL) { if (list2fpos(&argvars[1], &pos, &fnum, &curswant) == OK) { - if (--pos.col < 0) { + if (pos.col != MAXCOL && --pos.col < 0) { pos.col = 0; } if (name[0] == '.' && name[1] == NUL) { @@ -19045,6 +19045,15 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, FunPtr fptr) fp = var2fpos(&argvars[0], FALSE, &fnum); if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count && fnum == curbuf->b_fnum) { + // Limit the column to a valid value, getvvcol() doesn't check. + if (fp->col < 0) { + fp->col = 0; + } else { + const size_t len = STRLEN(ml_get(fp->lnum)); + if (fp->col > (colnr_T)len) { + fp->col = (colnr_T)len; + } + } getvvcol(curwin, fp, NULL, NULL, &vcol); ++vcol; } diff --git a/src/nvim/testdir/test_marks.vim b/src/nvim/testdir/test_marks.vim index 272553c29f..06b9dc9dab 100644 --- a/src/nvim/testdir/test_marks.vim +++ b/src/nvim/testdir/test_marks.vim @@ -26,11 +26,11 @@ function! Test_Incr_Marks() endfunction func Test_setpos() - new one + new Xone let onebuf = bufnr('%') let onewin = win_getid() call setline(1, ['aaa', 'bbb', 'ccc']) - new two + new Xtwo let twobuf = bufnr('%') let twowin = win_getid() call setline(1, ['aaa', 'bbb', 'ccc']) @@ -63,7 +63,24 @@ func Test_setpos() call setpos("'N", [onebuf, 1, 3, 0]) call assert_equal([onebuf, 1, 3, 0], getpos("'N")) + " try invalid column and check virtcol() call win_gotoid(onewin) + call setpos("'a", [0, 1, 2, 0]) + call assert_equal([0, 1, 2, 0], getpos("'a")) + call setpos("'a", [0, 1, -5, 0]) + call assert_equal([0, 1, 2, 0], getpos("'a")) + call setpos("'a", [0, 1, 0, 0]) + call assert_equal([0, 1, 1, 0], getpos("'a")) + call setpos("'a", [0, 1, 4, 0]) + call assert_equal([0, 1, 4, 0], getpos("'a")) + call assert_equal(4, virtcol("'a")) + call setpos("'a", [0, 1, 5, 0]) + call assert_equal([0, 1, 5, 0], getpos("'a")) + call assert_equal(4, virtcol("'a")) + call setpos("'a", [0, 1, 21341234, 0]) + call assert_equal([0, 1, 21341234, 0], getpos("'a")) + call assert_equal(4, virtcol("'a")) + bwipe! call win_gotoid(twowin) bwipe! -- cgit From 1042338c0062ea091ea1e52b161fd25adcdc927f Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Thu, 16 Jan 2020 00:10:16 -0500 Subject: clang/'Logic error': zero-init struct --- src/nvim/ops.c | 2 +- src/nvim/spell.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 5da81dbff6..da2b81fd0a 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -1372,7 +1372,7 @@ int op_delete(oparg_T *oap) linenr_T lnum; char_u *ptr; char_u *newp, *oldp; - struct block_def bd; + struct block_def bd = { 0 }; linenr_T old_lcount = curbuf->b_ml.ml_line_count; if (curbuf->b_ml.ml_flags & ML_EMPTY) { // nothing to do diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 5feb7efda9..96ae75718d 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -6145,8 +6145,8 @@ static void spell_soundfold_sal(slang_T *slang, char_u *inword, char_u *res) static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res) { salitem_T *smp = (salitem_T *)slang->sl_sal.ga_data; - int word[MAXWLEN]; - int wres[MAXWLEN]; + int word[MAXWLEN] = { 0 }; + int wres[MAXWLEN] = { 0 }; int l; int *ws; int *pf; -- cgit From a7aa1fc87da0bd66b64afc39b5d6bf7c4c129986 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Thu, 16 Jan 2020 00:24:26 -0500 Subject: spell: spell_soundfold_sal() is dead code --- src/nvim/spell.c | 242 +------------------------------------------------------ 1 file changed, 1 insertion(+), 241 deletions(-) (limited to 'src') diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 96ae75718d..c75a53a777 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -5835,10 +5835,7 @@ void spell_soundfold(slang_T *slang, char_u *inword, bool folded, char_u *res) word = fword; } - if (has_mbyte) - spell_soundfold_wsal(slang, word, res); - else - spell_soundfold_sal(slang, word, res); + spell_soundfold_wsal(slang, word, res); } } @@ -5903,243 +5900,6 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res) res[ri] = NUL; } -static void spell_soundfold_sal(slang_T *slang, char_u *inword, char_u *res) -{ - salitem_T *smp; - char_u word[MAXWLEN]; - char_u *s = inword; - char_u *t; - char_u *pf; - int i, j, z; - int reslen; - int n, k = 0; - int z0; - int k0; - int n0; - int c; - int pri; - int p0 = -333; - int c0; - - // Remove accents, if wanted. We actually remove all non-word characters. - // But keep white space. We need a copy, the word may be changed here. - if (slang->sl_rem_accents) { - t = word; - while (*s != NUL) { - if (ascii_iswhite(*s)) { - *t++ = ' '; - s = skipwhite(s); - } else { - if (spell_iswordp_nmw(s, curwin)) - *t++ = *s; - ++s; - } - } - *t = NUL; - } else - STRLCPY(word, s, MAXWLEN); - - smp = (salitem_T *)slang->sl_sal.ga_data; - - // This comes from Aspell phonet.cpp. Converted from C++ to C. - // Changed to keep spaces. - i = reslen = z = 0; - while ((c = word[i]) != NUL) { - // Start with the first rule that has the character in the word. - n = slang->sl_sal_first[c]; - z0 = 0; - - if (n >= 0) { - // check all rules for the same letter - for (; (s = smp[n].sm_lead)[0] == c; ++n) { - // Quickly skip entries that don't match the word. Most - // entries are less then three chars, optimize for that. - k = smp[n].sm_leadlen; - if (k > 1) { - if (word[i + 1] != s[1]) - continue; - if (k > 2) { - for (j = 2; j < k; ++j) - if (word[i + j] != s[j]) - break; - if (j < k) - continue; - } - } - - if ((pf = smp[n].sm_oneof) != NULL) { - // Check for match with one of the chars in "sm_oneof". - while (*pf != NUL && *pf != word[i + k]) - ++pf; - if (*pf == NUL) - continue; - ++k; - } - s = smp[n].sm_rules; - pri = 5; // default priority - - p0 = *s; - k0 = k; - while (*s == '-' && k > 1) { - k--; - s++; - } - if (*s == '<') - s++; - if (ascii_isdigit(*s)) { - // determine priority - pri = *s - '0'; - s++; - } - if (*s == '^' && *(s + 1) == '^') - s++; - - if (*s == NUL - || (*s == '^' - && (i == 0 || !(word[i - 1] == ' ' - || spell_iswordp(word + i - 1, curwin))) - && (*(s + 1) != '$' - || (!spell_iswordp(word + i + k0, curwin)))) - || (*s == '$' && i > 0 - && spell_iswordp(word + i - 1, curwin) - && (!spell_iswordp(word + i + k0, curwin)))) { - // search for followup rules, if: - // followup and k > 1 and NO '-' in searchstring - c0 = word[i + k - 1]; - n0 = slang->sl_sal_first[c0]; - - if (slang->sl_followup && k > 1 && n0 >= 0 - && p0 != '-' && word[i + k] != NUL) { - // test follow-up rule for "word[i + k]" - for (; (s = smp[n0].sm_lead)[0] == c0; ++n0) { - // Quickly skip entries that don't match the word. - k0 = smp[n0].sm_leadlen; - if (k0 > 1) { - if (word[i + k] != s[1]) - continue; - if (k0 > 2) { - pf = word + i + k + 1; - for (j = 2; j < k0; ++j) - if (*pf++ != s[j]) - break; - if (j < k0) - continue; - } - } - k0 += k - 1; - - if ((pf = smp[n0].sm_oneof) != NULL) { - // Check for match with one of the chars in - // "sm_oneof". - while (*pf != NUL && *pf != word[i + k0]) - ++pf; - if (*pf == NUL) - continue; - ++k0; - } - - p0 = 5; - s = smp[n0].sm_rules; - while (*s == '-') { - // "k0" gets NOT reduced because - // "if (k0 == k)" - s++; - } - if (*s == '<') - s++; - if (ascii_isdigit(*s)) { - p0 = *s - '0'; - s++; - } - - if (*s == NUL - // *s == '^' cuts - || (*s == '$' - && !spell_iswordp(word + i + k0, - curwin))) { - if (k0 == k) - // this is just a piece of the string - continue; - - if (p0 < pri) - // priority too low - continue; - // rule fits; stop search - break; - } - } - - if (p0 >= pri && smp[n0].sm_lead[0] == c0) - continue; - } - - // replace string - s = smp[n].sm_to; - if (s == NULL) - s = (char_u *)""; - pf = smp[n].sm_rules; - p0 = (vim_strchr(pf, '<') != NULL) ? 1 : 0; - if (p0 == 1 && z == 0) { - // rule with '<' is used - if (reslen > 0 && *s != NUL && (res[reslen - 1] == c - || res[reslen - 1] == *s)) - reslen--; - z0 = 1; - z = 1; - k0 = 0; - while (*s != NUL && word[i + k0] != NUL) { - word[i + k0] = *s; - k0++; - s++; - } - if (k > k0) - STRMOVE(word + i + k0, word + i + k); - - // new "actual letter" - c = word[i]; - } else { - // no '<' rule used - i += k - 1; - z = 0; - while (*s != NUL && s[1] != NUL && reslen < MAXWLEN) { - if (reslen == 0 || res[reslen - 1] != *s) - res[reslen++] = *s; - s++; - } - // new "actual letter" - c = *s; - if (strstr((char *)pf, "^^") != NULL) { - if (c != NUL) - res[reslen++] = c; - STRMOVE(word, word + i + 1); - i = 0; - z0 = 1; - } - } - break; - } - } - } else if (ascii_iswhite(c)) { - c = ' '; - k = 1; - } - - if (z0 == 0) { - if (k && !p0 && reslen < MAXWLEN && c != NUL - && (!slang->sl_collapse || reslen == 0 - || res[reslen - 1] != c)) - // condense only double letters - res[reslen++] = c; - - i++; - z = 0; - k = 0; - } - } - - res[reslen] = NUL; -} - // Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]". // Multi-byte version of spell_soundfold(). static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res) -- cgit From 9a9bb9186a9f1596b1b501719b495a536065a4f3 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Fri, 17 Jan 2020 22:06:44 -0500 Subject: vim-patch:8.1.0716: get warning message when 'completefunc' returns nothing Problem: Get warning message when 'completefunc' returns nothing. Solution: Allow for returning v:none to suppress the warning message. (Yasuhiro Matsumoto, closes vim/vim#3789) https://github.com/vim/vim/commit/cee9bc2e3dc5c16a9d2a8d0e23aa0d5fdefa3a4a --- src/nvim/edit.c | 4 ++- src/nvim/testdir/test_ins_complete.vim | 61 ++++++++++++++++++++++++---------- 2 files changed, 47 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/nvim/edit.c b/src/nvim/edit.c index cdb4b127da..9bc00cf2aa 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -3747,6 +3747,8 @@ expand_by_function( case VAR_DICT: matchdict = rettv.vval.v_dict; break; + case VAR_SPECIAL: + FALLTHROUGH; default: // TODO(brammool): Give error message? tv_clear(&rettv); @@ -5210,7 +5212,7 @@ static int ins_complete(int c, bool enable_pum) } } - /* Show a message about what (completion) mode we're in. */ + // Show a message about what (completion) mode we're in. showmode(); if (!shortmess(SHM_COMPLETIONMENU)) { if (edit_submode_extra != NULL) { diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim index 52ec281d82..e77afb7a55 100644 --- a/src/nvim/testdir/test_ins_complete.vim +++ b/src/nvim/testdir/test_ins_complete.vim @@ -98,6 +98,15 @@ func Test_ins_complete() call delete('Xdir', 'rf') endfunc +func s:CompleteDone_CompleteFuncNone( findstart, base ) + throw 'skipped: Nvim does not support v:none' + if a:findstart + return 0 + endif + + return v:none +endfunc + function! s:CompleteDone_CompleteFuncDict( findstart, base ) if a:findstart return 0 @@ -117,6 +126,10 @@ function! s:CompleteDone_CompleteFuncDict( findstart, base ) \ } endfunction +func s:CompleteDone_CheckCompletedItemNone() + let s:called_completedone = 1 +endfunc + function! s:CompleteDone_CheckCompletedItemDict() call assert_equal( 'aword', v:completed_item[ 'word' ] ) call assert_equal( 'wrd', v:completed_item[ 'abbr' ] ) @@ -128,15 +141,29 @@ function! s:CompleteDone_CheckCompletedItemDict() let s:called_completedone = 1 endfunction -function Test_CompleteDoneDict() +func Test_CompleteDoneNone() + throw 'skipped: Nvim does not support v:none' + au CompleteDone * :call CompleteDone_CheckCompletedItemNone() + + set completefunc=CompleteDone_CompleteFuncNone + execute "normal a\\\" + set completefunc& + + call assert_true(s:called_completedone) + + let s:called_completedone = 0 + au! CompleteDone +endfunc + +func Test_CompleteDoneDict() au CompleteDone * :call CompleteDone_CheckCompletedItemDict() set completefunc=CompleteDone_CompleteFuncDict execute "normal a\\\" set completefunc& - call assert_equal( 'test', v:completed_item[ 'user_data' ] ) - call assert_true( s:called_completedone ) + call assert_equal('test', v:completed_item[ 'user_data' ]) + call assert_true(s:called_completedone) let s:called_completedone = 0 au! CompleteDone @@ -155,7 +182,7 @@ func Test_CompleteDone_undo() au! CompleteDone endfunc -function! s:CompleteDone_CompleteFuncDictNoUserData( findstart, base ) +func s:CompleteDone_CompleteFuncDictNoUserData(findstart, base) if a:findstart return 0 endif @@ -171,9 +198,9 @@ function! s:CompleteDone_CompleteFuncDictNoUserData( findstart, base ) \ } \ ] \ } -endfunction +endfunc -function! s:CompleteDone_CheckCompletedItemDictNoUserData() +func s:CompleteDone_CheckCompletedItemDictNoUserData() call assert_equal( 'aword', v:completed_item[ 'word' ] ) call assert_equal( 'wrd', v:completed_item[ 'abbr' ] ) call assert_equal( 'extra text', v:completed_item[ 'menu' ] ) @@ -182,31 +209,31 @@ function! s:CompleteDone_CheckCompletedItemDictNoUserData() call assert_equal( '', v:completed_item[ 'user_data' ] ) let s:called_completedone = 1 -endfunction +endfunc -function Test_CompleteDoneDictNoUserData() +func Test_CompleteDoneDictNoUserData() au CompleteDone * :call CompleteDone_CheckCompletedItemDictNoUserData() set completefunc=CompleteDone_CompleteFuncDictNoUserData execute "normal a\\\" set completefunc& - call assert_equal( '', v:completed_item[ 'user_data' ] ) - call assert_true( s:called_completedone ) + call assert_equal('', v:completed_item[ 'user_data' ]) + call assert_true(s:called_completedone) let s:called_completedone = 0 au! CompleteDone endfunc -function! s:CompleteDone_CompleteFuncList( findstart, base ) +func s:CompleteDone_CompleteFuncList(findstart, base) if a:findstart return 0 endif return [ 'aword' ] -endfunction +endfunc -function! s:CompleteDone_CheckCompletedItemList() +func s:CompleteDone_CheckCompletedItemList() call assert_equal( 'aword', v:completed_item[ 'word' ] ) call assert_equal( '', v:completed_item[ 'abbr' ] ) call assert_equal( '', v:completed_item[ 'menu' ] ) @@ -215,17 +242,17 @@ function! s:CompleteDone_CheckCompletedItemList() call assert_equal( '', v:completed_item[ 'user_data' ] ) let s:called_completedone = 1 -endfunction +endfunc -function Test_CompleteDoneList() +func Test_CompleteDoneList() au CompleteDone * :call CompleteDone_CheckCompletedItemList() set completefunc=CompleteDone_CompleteFuncList execute "normal a\\\" set completefunc& - call assert_equal( '', v:completed_item[ 'user_data' ] ) - call assert_true( s:called_completedone ) + call assert_equal('', v:completed_item[ 'user_data' ]) + call assert_true(s:called_completedone) let s:called_completedone = 0 au! CompleteDone -- cgit From 3d0c3148fbc3b66636bb9627db64331365ac1732 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Fri, 17 Jan 2020 23:14:47 -0500 Subject: vim-patch:8.1.1139: no test for what is fixed in patch 8.1.0716 Problem: No test for what is fixed in patch 8.1.0716. Solution: Add a test. (Yasuhiro Matsumoto, closes vim/vim#3797) https://github.com/vim/vim/commit/9845f36aa6ba28e0aa388bb635d4bb8ab56f1a47 --- src/nvim/testdir/test_ins_complete.vim | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim index e77afb7a55..4140d16a4c 100644 --- a/src/nvim/testdir/test_ins_complete.vim +++ b/src/nvim/testdir/test_ins_complete.vim @@ -144,12 +144,15 @@ endfunction func Test_CompleteDoneNone() throw 'skipped: Nvim does not support v:none' au CompleteDone * :call CompleteDone_CheckCompletedItemNone() + let oldline = join(map(range(&columns), 'nr2char(screenchar(&lines-1, v:val+1))'), '') set completefunc=CompleteDone_CompleteFuncNone execute "normal a\\\" set completefunc& + let newline = join(map(range(&columns), 'nr2char(screenchar(&lines-1, v:val+1))'), '') call assert_true(s:called_completedone) + call assert_equal(oldline, newline) let s:called_completedone = 0 au! CompleteDone -- cgit From ad35cbca76222deb33357b63a61a29945ef084f7 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Fri, 17 Jan 2020 23:31:18 -0500 Subject: vim-patch:8.2.0123: complete_info() does not work when CompleteDone is triggered Problem: complete_info() does not work when CompleteDone is triggered. Solution: Trigger CompleteDone before clearing the info. https://github.com/vim/vim/commit/17e04781f26c24769e202351c194ee252927eee1 --- src/nvim/edit.c | 16 +++++++++++++--- src/nvim/testdir/test_ins_complete.vim | 2 ++ 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 9bc00cf2aa..0c183add16 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -3385,6 +3385,7 @@ static bool ins_compl_prep(int c) { char_u *ptr; bool retval = false; + const int prev_mode = ctrl_x_mode; /* Forget any previous 'special' messages if this is actually * a ^X mode key - bar ^R, in which case we wait to see what it gives us. @@ -3593,6 +3594,18 @@ static bool ins_compl_prep(int c) auto_format(FALSE, TRUE); + { + const int new_mode = ctrl_x_mode; + + // Trigger the CompleteDone event to give scripts a chance to + // act upon the completion. Do this before clearing the info, + // and restore ctrl_x_mode, so that complete_info() can be + // used. + ctrl_x_mode = prev_mode; + ins_apply_autocmds(EVENT_COMPLETEDONE); + ctrl_x_mode = new_mode; + } + ins_compl_free(); compl_started = false; compl_matches = 0; @@ -3617,9 +3630,6 @@ static bool ins_compl_prep(int c) */ if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0))) do_c_expr_indent(); - /* Trigger the CompleteDone event to give scripts a chance to act - * upon the completion. */ - ins_apply_autocmds(EVENT_COMPLETEDONE); } } else if (ctrl_x_mode == CTRL_X_LOCAL_MSG) /* Trigger the CompleteDone event to give scripts a chance to act diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim index 4140d16a4c..e6d427db05 100644 --- a/src/nvim/testdir/test_ins_complete.vim +++ b/src/nvim/testdir/test_ins_complete.vim @@ -138,6 +138,8 @@ function! s:CompleteDone_CheckCompletedItemDict() call assert_equal( 'W', v:completed_item[ 'kind' ] ) call assert_equal( 'test', v:completed_item[ 'user_data' ] ) + call assert_equal('function', complete_info().mode) + let s:called_completedone = 1 endfunction -- cgit