patch 8.2.3293: finding completions may cause an endless loop

Problem:    Finding completions may cause an endless loop.
Solution:   Use a better way to check coming back where the search started.
            (Andy Gozas, closes #8672, closes #8671)
This commit is contained in:
Andy Gozas
2021-08-05 16:23:27 +02:00
committed by Bram Moolenaar
parent bc67e5a0a4
commit 6a230c6b32
4 changed files with 82 additions and 1 deletions

View File

@ -2712,6 +2712,8 @@ ins_compl_get_exp(pos_T *ini)
char_u *dict = NULL;
int dict_f = 0;
int set_match_pos;
pos_T prev_pos = {0, 0, 0};
int looped_around = FALSE;
if (!compl_started)
{
@ -2964,6 +2966,7 @@ ins_compl_get_exp(pos_T *ini)
p_ws = FALSE;
else if (*e_cpt == '.')
p_ws = TRUE;
looped_around = FALSE;
for (;;)
{
int cont_s_ipos = FALSE;
@ -2991,8 +2994,31 @@ ins_compl_get_exp(pos_T *ini)
set_match_pos = FALSE;
}
else if (first_match_pos.lnum == last_match_pos.lnum
&& first_match_pos.col == last_match_pos.col)
&& first_match_pos.col == last_match_pos.col)
{
found_new_match = FAIL;
}
else if ((compl_direction == FORWARD)
&& (prev_pos.lnum > pos->lnum
|| (prev_pos.lnum == pos->lnum
&& prev_pos.col >= pos->col)))
{
if (looped_around)
found_new_match = FAIL;
else
looped_around = TRUE;
}
else if ((compl_direction != FORWARD)
&& (prev_pos.lnum < pos->lnum
|| (prev_pos.lnum == pos->lnum
&& prev_pos.col <= pos->col)))
{
if (looped_around)
found_new_match = FAIL;
else
looped_around = TRUE;
}
prev_pos = *pos;
if (found_new_match == FAIL)
{
if (ins_buf == curbuf)

View File

@ -162,6 +162,7 @@ NEW_TESTS = \
test_increment_dbcs \
test_indent \
test_ins_complete \
test_ins_complete_no_halt \
test_interrupt \
test_job_fails \
test_join \
@ -405,6 +406,7 @@ NEW_TESTS_RES = \
test_increment_dbcs.res \
test_indent.res \
test_ins_complete.res \
test_ins_complete_no_halt.res \
test_interrupt.res \
test_job_fails.res \
test_join.res \

View File

@ -0,0 +1,51 @@
" Test insert mode completion does not get stuck when looping around.
" In a separate file to avoid the settings to leak to other test cases.
set complete+=kspell
set completeopt+=menu
set completeopt+=menuone
set completeopt+=noselect
set completeopt+=noinsert
let g:autocompletion = v:true
func Test_ins_complete_no_halt()
function! OpenCompletion()
if pumvisible() && (g:autocompletion == v:true)
call feedkeys("\<C-e>\<C-n>", "i")
return
endif
if ((v:char >= 'a' && v:char <= 'z') || (v:char >= 'A' && v:char <= 'Z')) && (g:autocompletion == v:true)
call feedkeys("\<C-n>", "i")
redraw
endif
endfunction
autocmd InsertCharPre * noautocmd call OpenCompletion()
setlocal spell! spelllang=en_us
call feedkeys("iauto-complete-halt-test test test test test test test test test test test test test test test test test test test\<C-c>", "tx!")
call assert_equal(["auto-complete-halt-test test test test test test test test test test test test test test test test test test test"], getline(1, "$"))
endfunc
func Test_auto_complete_backwards_no_halt()
function! OpenCompletion()
if pumvisible() && (g:autocompletion == v:true)
call feedkeys("\<C-e>\<C-p>", "i")
return
endif
if ((v:char >= 'a' && v:char <= 'z') || (v:char >= 'A' && v:char <= 'Z')) && (g:autocompletion == v:true)
call feedkeys("\<C-p>", "i")
redraw
endif
endfunction
autocmd InsertCharPre * noautocmd call OpenCompletion()
setlocal spell! spelllang=en_us
call feedkeys("iauto-complete-halt-test test test test test test test test test test test test test test test test test test test\<C-c>", "tx!")
call assert_equal(["auto-complete-halt-test test test test test test test test test test test test test test test test test test test"], getline(1, "$"))
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -755,6 +755,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
3293,
/**/
3292,
/**/