Fix infinite autocompletion loop (#5130)
CI / Build (push) Has been cancelled
CI / Neovim 0.10 Windows (push) Has been cancelled
CI / Neovim 0.12 Windows (push) Has been cancelled
CI / Vim 8.2 Windows (push) Has been cancelled
CI / Vim 9.2 Windows (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Lua (push) Has been cancelled
CI / Neovim 0.10 Linux (push) Has been cancelled
CI / Neovim 0.12 Linux (push) Has been cancelled
CI / Vim 8.2 Linux (push) Has been cancelled
CI / Vim 9.2 Linux (push) Has been cancelled

* Check for timeout while waiting for language server result
* Return empty result if language server has no completion capabilities
* Add test for OmniFunc timeout
* Add documentation for timeout option
This commit is contained in:
Torben
2026-05-28 12:00:09 +02:00
committed by GitHub
parent 2a3af30fb6
commit 399c0ffd64
3 changed files with 33 additions and 0 deletions
+12
View File
@@ -764,6 +764,9 @@ function! s:OnReady(linter, lsp_details) abort
let l:id = a:lsp_details.connection_id
if !ale#lsp#HasCapability(l:id, 'completion')
" Return at least an empty result to avoid OmniFunc timeout
call ale#completion#Show([])
return
endif
@@ -945,9 +948,18 @@ function! ale#completion#OmniFunc(findstart, base) abort
else
let l:result = ale#completion#GetCompletionResult()
let l:timeout = get(g:, 'ale_completion_timeout', 3)
let l:timeout_start = reltime()
while l:result is v:null && !complete_check()
sleep 2ms
let l:result = ale#completion#GetCompletionResult()
if reltimefloat(reltime(l:timeout_start)) > l:timeout
" no-custom-checks
echoerr 'no result within timeout (' . l:timeout . 's)'
break
endif
endwhile
return l:result isnot v:null ? l:result : []
+14
View File
@@ -1143,6 +1143,20 @@ g:ale_completion_max_suggestions
Adjust this option as needed, depending on the complexity of your codebase
and your available processing power.
*ale-options.completion_timeout*
*g:ale_completion_timeout*
completion_timeout
g:ale_completion_timeout
Type: |Number|
Default: `3`
The maximum time in seconds ale#completion#OmniFunc() will wait for a
completion result from the language server.
When the timeout is exceeded ale#completion#OmniFunc() will print an error
message and return an empty result. Setting a higher value allows longer
response times, but it may also keep Vim unresponsible for a longer time.
*ale-options.cursor_detail*
*g:ale_cursor_detail*
cursor_detail
@@ -58,3 +58,10 @@ Execute(The omnifunc function should parse and return async responses):
AssertEqual ['foo'], ale#completion#OmniFunc(0, '')
endif
Execute (The omnifunc function should timeout with an error, if no result is returned):
" WARNING: This will lock the whole test-suite, if the timeout does not work!
let g:ale_completion_timeout = 0.2
AssertThrows call ale#completion#OmniFunc(0, '')
AssertEqual 'Vim(echoerr):no result within timeout (0.2s)', g:vader_exception