neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 1969f685af98c998c7eaa414982540d80d17d564
parent e7dfbf13439fd8b2c91df02607a0581fa7795cc0
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Fri,  8 Aug 2025 22:40:56 +0800

vim-patch:9.1.1610: completion: hang or E684 when 'tagfunc' calls complete() (#35243)

Problem:  completion: hang (after 9.1.1471) or E684 (after 9.1.1410)
          when 'tagfunc' calls complete().
Solution: Check if complete() has been called immediately after getting
          matches instead of in the next loop iteration (zeertzjq).

related: vim/vim#1668
related: neovim/neovim#34416
related: neovim/neovim#35163
closes: vim/vim#17929

https://github.com/vim/vim/commit/982cda69764ac0575125bc8786177e48f5fd9420
Diffstat:
Msrc/nvim/insexpand.c | 12++++++------
Mtest/old/testdir/test_ins_complete.vim | 29+++++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c @@ -4608,12 +4608,6 @@ static int ins_compl_get_exp(pos_T *ini) } } - // If complete() was called then compl_pattern has been reset. - // The following won't work then, bail out. - if (compl_pattern.data == NULL) { - break; - } - if (compl_autocomplete && type == CTRL_X_FUNCTION) { // LSP servers may sporadically take >1s to respond (e.g., while // loading modules), but other sources might already have matches. @@ -4627,6 +4621,12 @@ static int ins_compl_get_exp(pos_T *ini) // get the next set of completion matches found_new_match = get_next_completion_match(type, &st, &start_pos); + // If complete() was called then compl_pattern has been reset. + // The following won't work then, bail out. + if (compl_pattern.data == NULL) { + break; + } + if (may_advance_cpt_idx) { if (!advance_cpt_sources_index_safe()) { break; diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim @@ -3290,6 +3290,35 @@ func Test_tagfunc_wipes_out_buffer() bwipe! endfunc +func s:TagfuncComplete(t,f,o) + call complete(1, ['ddd', 'eee', 'fff']) + return [] +endfunc + +" 'tagfunc' calling complete() should not cause hang or E684. +func Test_tagfunc_calls_complete() + new + call setline(1, ['aaa', 'bbb', 'ccc']) + setlocal tagfunc=s:TagfuncComplete + setlocal completeopt=menu,noselect + + let v:errmsg = '' + + " This used to hang. + setlocal complete=.,t + call feedkeys("Go\<C-N>\<C-E>\<Esc>", 'tx') + call assert_equal('', getline('.')) + call assert_equal('', v:errmsg) + + " This used to cause E684. + setlocal complete=t,. + call feedkeys("cc\<C-N>\<C-E>\<Esc>", 'tx') + call assert_equal('', getline('.')) + call assert_equal('', v:errmsg) + + bwipe! +endfunc + func Test_ins_complete_popup_position() CheckScreendump