diff options
-rw-r--r-- | autoload/ale/completion.vim | 23 | ||||
-rw-r--r-- | test/test_ale_init_au_groups.vader | 25 | ||||
-rw-r--r-- | test/test_completion.vader | 108 |
3 files changed, 149 insertions, 7 deletions
diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index df8134a4..f3d74cf0 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -1,6 +1,10 @@ " Author: w0rp <devw0rp@gmail.com> " Description: Completion support for LSP linters +" A do-nothing function so we can load this autoload file in tests. +function! ale#completion#Nop() abort +endfunction + let s:timer_id = -1 function! s:GetRegex(map, filetype) abort @@ -98,6 +102,11 @@ function! ale#completion#OmniFunc(findstart, base) abort endif endfunction +" A wrapper function for feedkeys so we can test calls for it. +function! ale#completion#FeedKeys(string, mode) abort + call feedkeys(a:string, a:mode) +endfunction + function! ale#completion#Show(response, completion_parser) abort " Remember the old omnifunc value, if there is one. " If we don't store an old one, we'll just never reset the option. @@ -111,7 +120,7 @@ function! ale#completion#Show(response, completion_parser) abort let b:ale_completion_response = a:response let b:ale_completion_parser = a:completion_parser let &l:omnifunc = 'ale#completion#OmniFunc' - call feedkeys("\<C-x>\<C-o>", 'n') + call ale#completion#FeedKeys("\<C-x>\<C-o>", 'n') endfunction function! s:CompletionStillValid(request_id) abort @@ -237,10 +246,6 @@ endfunction function! ale#completion#GetCompletions() abort let [l:line, l:column] = getcurpos()[1:2] - if s:timer_pos != [l:line, l:column] - return - endif - let l:prefix = ale#completion#GetPrefix(&filetype, l:line, l:column) if empty(l:prefix) @@ -265,7 +270,13 @@ endfunction function! s:TimerHandler(...) abort let s:timer_id = -1 - call ale#completion#GetCompletions() + let [l:line, l:column] = getcurpos()[1:2] + + " When running the timer callback, we have to be sure that the cursor + " hasn't moved from where it was when we requested completions by typing. + if s:timer_pos == [l:line, l:column] + call ale#completion#GetCompletions() + endif endfunction function! ale#completion#Queue() abort diff --git a/test/test_ale_init_au_groups.vader b/test/test_ale_init_au_groups.vader index da77ccee..216e7cfb 100644 --- a/test/test_ale_init_au_groups.vader +++ b/test/test_ale_init_au_groups.vader @@ -40,11 +40,18 @@ Before: Save g:ale_lint_on_save Save g:ale_echo_cursor Save g:ale_fix_on_save + Save g:ale_completion_enabled After: delfunction CheckAutocmd Restore + if g:ale_completion_enabled + call ale#completion#Enable() + else + call ale#completion#Disable() + endif + call ALEInitAuGroups() Execute (g:ale_lint_on_text_changed = 0 should bind no events): @@ -185,3 +192,21 @@ Execute (g:ale_echo_cursor = 1 should bind cursor events): \ 'CursorMoved * call ale#cursor#EchoCursorWarningWithDelay()', \ 'InsertLeave * call ale#cursor#EchoCursorWarning()', \], CheckAutocmd('ALECursorGroup') + +Execute(Enabling completion should set up autocmd events correctly): + let g:ale_completion_enabled = 0 + call ale#completion#Enable() + + AssertEqual [ + \ 'CompleteDone * call ale#completion#Done()', + \ 'TextChangedI * call ale#completion#Queue()', + \], CheckAutocmd('ALECompletionGroup') + AssertEqual 1, g:ale_completion_enabled + +Execute(Disabling completion should remove autocmd events correctly): + let g:ale_completion_enabled = 1 + call ale#completion#Enable() + call ale#completion#Disable() + + AssertEqual [], CheckAutocmd('ALECompletionGroup') + AssertEqual 0, g:ale_completion_enabled diff --git a/test/test_completion.vader b/test/test_completion.vader index 65cef465..4331dd0d 100644 --- a/test/test_completion.vader +++ b/test/test_completion.vader @@ -1,10 +1,31 @@ Before: Save g:ale_completion_enabled + Save g:ale_completion_delay + Save &l:omnifunc + + let g:test_vars = { + \ 'feedkeys_calls': [], + \} + + call ale#completion#Nop() + + function! ale#completion#FeedKeys(string, mode) abort + call add(g:test_vars.feedkeys_calls, [a:string, a:mode]) + endfunction After: Restore - if !g:ale_completion_enabled + unlet! g:test_vars + unlet! b:ale_completion_info + unlet! b:ale_completion_response + unlet! b:ale_completion_parser + + runtime autoload/ale/completion.vim + + if g:ale_completion_enabled + call ale#completion#Enable() + else call ale#completion#Disable() endif @@ -100,3 +121,88 @@ Execute(Completion should be done after words in parens in TypeScript): Execute(Completion should not be done after parens in TypeScript): AssertEqual '', ale#completion#GetPrefix(&filetype, 3, 15) + +Execute(ale#completion#Show() should remember the omnifunc setting and replace it): + let &l:omnifunc = 'FooBar' + + call ale#completion#Show('Response', 'Parser') + + AssertEqual 'FooBar', b:ale_old_omnifunc + AssertEqual 'ale#completion#OmniFunc', &l:omnifunc + +Execute(ale#completion#Show() should make the correct feedkeys() call): + call ale#completion#Show('Response', 'Parser') + + AssertEqual [["\<C-x>\<C-o>", 'n']], g:test_vars.feedkeys_calls + +Execute(ale#completion#Show() should set up the response and parser): + call ale#completion#Show('Response', 'Parser') + + AssertEqual 'Response', b:ale_completion_response + AssertEqual 'Parser', b:ale_completion_parser + +Execute(ale#completion#Done() should restore old omnifunc values): + let b:ale_old_omnifunc = 'FooBar' + + call ale#completion#Done() + + " We reset the old omnifunc setting and remove the buffer variable. + AssertEqual 'FooBar', &l:omnifunc + Assert !has_key(b:, 'ale_old_omnifunc') + +Execute(The completion request_id should be reset when queuing again): + let b:ale_completion_info = {'request_id': 123} + + let g:ale_completion_delay = 0 + call ale#completion#Queue() + sleep 1m + + AssertEqual 0, b:ale_completion_info.request_id + +Execute(b:ale_completion_info should be set up correctly when requesting completions): + call setpos('.', [bufnr(''), 3, 14, 0]) + call ale#completion#GetCompletions() + + AssertEqual + \ { + \ 'request_id': 0, + \ 'conn_id': 0, + \ 'column': 14, + \ 'line': 3, + \ 'prefix': 'ab', + \ }, + \ b:ale_completion_info + +Execute(ale#completion#GetCompletions should be called when the cursor position stays the same): + let g:test_vars.get_completions_called = 0 + + " We just want to check if the function is called. + function! ale#completion#GetCompletions() + let g:test_vars.get_completions_called = 1 + endfunction + + let g:ale_completion_delay = 0 + call ale#completion#Queue() + sleep 1m + + Assert g:test_vars.get_completions_called + +Execute(ale#completion#GetCompletions should not be called when the cursor position changes): + call setpos('.', [bufnr(''), 1, 2, 0]) + + let g:test_vars.get_completions_called = 0 + + " We just want to check if the function is called. + function! ale#completion#GetCompletions() + let g:test_vars.get_completions_called = 1 + endfunction + + let g:ale_completion_delay = 0 + call ale#completion#Queue() + + " Change the cursor position before the callback is triggered. + call setpos('.', [bufnr(''), 2, 2, 0]) + + sleep 1m + + Assert !g:test_vars.get_completions_called |