From 28a4d72d1b751f2147f498442fcab97b6c5b86a1 Mon Sep 17 00:00:00 2001 From: Torben Date: Tue, 19 May 2026 12:48:17 +0200 Subject: [PATCH 1/6] Check for timeout while waiting for language server result --- autoload/ale/completion.vim | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index bd9fdf7203..133e77d394 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -945,8 +945,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() + if reltimefloat(reltime(l:timeout_start)) > l:timeout + " no-custom-checks + echoerr 'no result within timeout (' . l:timeout . 's)' + break + endif + sleep 2ms + let l:result = ale#completion#GetCompletionResult() endwhile From 0640ff0b9a583398015448e9c4e1265a374d48d6 Mon Sep 17 00:00:00 2001 From: Torben Date: Tue, 19 May 2026 13:02:52 +0200 Subject: [PATCH 2/6] Return empty result if language server has no completion capabilities --- autoload/ale/completion.vim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index 133e77d394..2d2c38bb68 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -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 From 6d4beb377d00c42f7ab09d19d564369bc5014252 Mon Sep 17 00:00:00 2001 From: Torben Date: Tue, 19 May 2026 16:58:41 +0200 Subject: [PATCH 3/6] Add test for OmniFunc timeout --- test/completion/test_omnifunc_completion.vader | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/completion/test_omnifunc_completion.vader b/test/completion/test_omnifunc_completion.vader index c9ecd205aa..164100b33e 100644 --- a/test/completion/test_omnifunc_completion.vader +++ b/test/completion/test_omnifunc_completion.vader @@ -58,3 +58,9 @@ Execute(The omnifunc function should parse and return async responses): AssertEqual ['foo'], ale#completion#OmniFunc(0, '') endif + +Execute(The omnifunc function should timeout, 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 + + AssertEqual v:null, ale#completion#OmniFunc(0, '') From 7d26aa166b353187330c41ba44d415ebaa500bb0 Mon Sep 17 00:00:00 2001 From: Torben Date: Wed, 20 May 2026 13:33:41 +0200 Subject: [PATCH 4/6] Fix test for OmniFunc timeout --- test/completion/test_omnifunc_completion.vader | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/completion/test_omnifunc_completion.vader b/test/completion/test_omnifunc_completion.vader index 164100b33e..8c0a339f82 100644 --- a/test/completion/test_omnifunc_completion.vader +++ b/test/completion/test_omnifunc_completion.vader @@ -59,8 +59,9 @@ Execute(The omnifunc function should parse and return async responses): AssertEqual ['foo'], ale#completion#OmniFunc(0, '') endif -Execute(The omnifunc function should timeout, if no result is returned): +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 - AssertEqual v:null, ale#completion#OmniFunc(0, '') + AssertThrows call ale#completion#OmniFunc(0, '') + AssertEqual 'Vim(echoerr):no result within timeout (0.2s)', g:vader_exception From e089f8cbfad17e4a294f1535119cee439d845dda Mon Sep 17 00:00:00 2001 From: Torben Date: Wed, 20 May 2026 13:53:29 +0200 Subject: [PATCH 5/6] Move timeout check at the end of loop --- autoload/ale/completion.vim | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index 2d2c38bb68..a435eb13f1 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -952,15 +952,14 @@ function! ale#completion#OmniFunc(findstart, base) abort 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 - - sleep 2ms - - let l:result = ale#completion#GetCompletionResult() endwhile return l:result isnot v:null ? l:result : [] From 50ec11a9cdba50e3441d4ddd8fe1d805e9b9459b Mon Sep 17 00:00:00 2001 From: Torben Date: Wed, 20 May 2026 17:04:52 +0200 Subject: [PATCH 6/6] Add documentation for timeout option --- doc/ale.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/ale.txt b/doc/ale.txt index 53453b54f7..99d1d621f6 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -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