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 10:00:09 +00: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 let l:id = a:lsp_details.connection_id
if !ale#lsp#HasCapability(l:id, 'completion') if !ale#lsp#HasCapability(l:id, 'completion')
" Return at least an empty result to avoid OmniFunc timeout
call ale#completion#Show([])
return return
endif endif
@@ -945,9 +948,18 @@ function! ale#completion#OmniFunc(findstart, base) abort
else else
let l:result = ale#completion#GetCompletionResult() 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() while l:result is v:null && !complete_check()
sleep 2ms sleep 2ms
let l:result = ale#completion#GetCompletionResult() 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 endwhile
return l:result isnot v:null ? l:result : [] 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 Adjust this option as needed, depending on the complexity of your codebase
and your available processing power. 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* *ale-options.cursor_detail*
*g:ale_cursor_detail* *g:ale_cursor_detail*
cursor_detail cursor_detail
@@ -58,3 +58,10 @@ Execute(The omnifunc function should parse and return async responses):
AssertEqual ['foo'], ale#completion#OmniFunc(0, '') AssertEqual ['foo'], ale#completion#OmniFunc(0, '')
endif 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