3e8c8d3ccb
This commit adds support for renaming symbols in tsserver and with LSP tools, and for organising imports with tsserver. Completion results for symbols that can be imported are now suggested if enabled for tsserver completion done via ALE.
440 lines
13 KiB
Text
440 lines
13 KiB
Text
Before:
|
|
Save g:ale_completion_enabled
|
|
Save g:ale_completion_delay
|
|
Save g:ale_completion_max_suggestions
|
|
Save &l:omnifunc
|
|
Save &l:completeopt
|
|
|
|
unlet! b:ale_completion_enabled
|
|
let g:ale_completion_enabled = 1
|
|
let g:get_completions_called = 0
|
|
let g:feedkeys_calls = []
|
|
let g:fake_mode = 'i'
|
|
|
|
let &l:completeopt = 'menu,menuone,preview,noselect,noinsert'
|
|
|
|
runtime autoload/ale/util.vim
|
|
|
|
function! ale#util#FeedKeys(string) abort
|
|
call add(g:feedkeys_calls, [a:string])
|
|
endfunction
|
|
|
|
" Pretend we're in insert mode for most tests.
|
|
function! ale#util#Mode(...) abort
|
|
return g:fake_mode
|
|
endfunction
|
|
|
|
function! CheckCompletionCalled(expect_success) abort
|
|
let g:get_completions_called = 0
|
|
|
|
" We just want to check if the function is called.
|
|
function! ale#completion#GetCompletions(source)
|
|
let g:get_completions_called = 1
|
|
endfunction
|
|
|
|
let g:ale_completion_delay = 0
|
|
|
|
" Run this check a few times, as it can fail randomly.
|
|
for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1)
|
|
call ale#completion#Queue()
|
|
sleep 1m
|
|
|
|
if g:get_completions_called is a:expect_success
|
|
break
|
|
endif
|
|
endfor
|
|
|
|
AssertEqual a:expect_success, g:get_completions_called
|
|
endfunction
|
|
|
|
let g:handle_code_action_called = 0
|
|
function! MockHandleCodeAction() abort
|
|
" delfunction! ale#code_action#HandleCodeAction
|
|
function! ale#code_action#HandleCodeAction(action) abort
|
|
let g:handle_code_action_called += 1
|
|
endfunction
|
|
endfunction
|
|
|
|
After:
|
|
Restore
|
|
|
|
unlet! b:ale_completion_enabled
|
|
unlet! g:output
|
|
unlet! g:fake_mode
|
|
unlet! g:get_completions_called
|
|
unlet! g:handle_code_action_called
|
|
unlet! b:ale_old_omnifunc
|
|
unlet! b:ale_old_completeopt
|
|
unlet! b:ale_completion_info
|
|
unlet! b:ale_completion_result
|
|
unlet! b:ale_complete_done_time
|
|
|
|
delfunction CheckCompletionCalled
|
|
delfunction ale#code_action#HandleCodeAction
|
|
delfunction MockHandleCodeAction
|
|
|
|
if exists('*CompleteCallback')
|
|
delfunction CompleteCallback
|
|
endif
|
|
|
|
" Stop any timers we left behind.
|
|
" This stops the tests from failing randomly.
|
|
call ale#completion#StopTimer()
|
|
|
|
" Reset the function. The runtime command below should fix this, but doesn't
|
|
" seem to fix it.
|
|
function! ale#util#Mode(...) abort
|
|
return call('mode', a:000)
|
|
endfunction
|
|
|
|
runtime autoload/ale/completion.vim
|
|
runtime autoload/ale/code_action.vim
|
|
runtime autoload/ale/util.vim
|
|
|
|
Execute(ale#completion#GetCompletions should be called when the cursor position stays the same):
|
|
call CheckCompletionCalled(1)
|
|
|
|
Execute(ale#completion#GetCompletions should not be called if the global setting is disabled):
|
|
let g:ale_completion_enabled = 0
|
|
call CheckCompletionCalled(0)
|
|
|
|
Execute(ale#completion#GetCompletions should not be called if the buffer setting is disabled):
|
|
let b:ale_completion_enabled = 0
|
|
call CheckCompletionCalled(0)
|
|
|
|
Given typescript():
|
|
let abc = y.
|
|
let foo = ab
|
|
let foo = (ab)
|
|
|
|
Execute(ale#completion#GetCompletions should not be called when the cursor position changes):
|
|
call setpos('.', [bufnr(''), 1, 2, 0])
|
|
|
|
" We just want to check if the function is called.
|
|
function! ale#completion#GetCompletions(source)
|
|
let g: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:get_completions_called
|
|
|
|
Execute(ale#completion#GetCompletions should not be called if you switch to normal mode):
|
|
let &l:completeopt = 'menu,preview'
|
|
let g:fake_mode = 'n'
|
|
|
|
" We just want to check if the function is called.
|
|
function! ale#completion#GetCompletions(source)
|
|
let g:get_completions_called = 1
|
|
endfunction
|
|
|
|
let g:ale_completion_delay = 0
|
|
call ale#completion#Queue()
|
|
|
|
sleep 1m
|
|
|
|
Assert !g:get_completions_called
|
|
|
|
Execute(Completion should not be done shortly after the CompleteDone function):
|
|
call CheckCompletionCalled(1)
|
|
call ale#completion#Done()
|
|
call CheckCompletionCalled(0)
|
|
|
|
Execute(ale#completion#Show() should remember the omnifunc setting and replace it):
|
|
let &l:omnifunc = 'FooBar'
|
|
|
|
let b:ale_completion_info = {'source': 'ale-automatic'}
|
|
call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}])
|
|
|
|
AssertEqual 'FooBar', b:ale_old_omnifunc
|
|
AssertEqual 'ale#completion#AutomaticOmniFunc', &l:omnifunc
|
|
|
|
AssertEqual [], g:feedkeys_calls
|
|
sleep 1ms
|
|
AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls
|
|
|
|
Execute(ale#completion#Show() should remember the completeopt setting and replace it):
|
|
let &l:completeopt = 'menu'
|
|
|
|
let b:ale_completion_info = {'source': 'ale-automatic'}
|
|
call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}])
|
|
|
|
AssertEqual 'menu', b:ale_old_completeopt
|
|
AssertEqual 'menu,menuone,noselect,noinsert', &l:completeopt
|
|
|
|
AssertEqual [], g:feedkeys_calls
|
|
sleep 1ms
|
|
AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls
|
|
|
|
Execute(ale#completion#Show() should set the preview option if it's set):
|
|
let &l:completeopt = 'menu,preview'
|
|
|
|
let b:ale_completion_info = {'source': 'ale-automatic'}
|
|
call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}])
|
|
|
|
AssertEqual 'menu,preview', b:ale_old_completeopt
|
|
AssertEqual 'menu,menuone,preview,noselect,noinsert', &l:completeopt
|
|
|
|
AssertEqual [], g:feedkeys_calls
|
|
sleep 1ms
|
|
AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls
|
|
|
|
Execute(ale#completion#Show() should not replace the completeopt setting for manual completion):
|
|
let b:ale_completion_info = {'source': 'ale-manual'}
|
|
|
|
let &l:completeopt = 'menu,preview'
|
|
|
|
call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}])
|
|
|
|
Assert !exists('b:ale_old_completeopt')
|
|
|
|
AssertEqual [], g:feedkeys_calls
|
|
sleep 1ms
|
|
AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls
|
|
|
|
Execute(ale#completion#AutomaticOmniFunc() should also remember the completeopt setting and replace it):
|
|
let &l:completeopt = 'menu'
|
|
|
|
let b:ale_completion_info = {'source': 'ale-automatic'}
|
|
call ale#completion#AutomaticOmniFunc(0, '')
|
|
|
|
AssertEqual 'menu', b:ale_old_completeopt
|
|
AssertEqual 'menu,menuone,noselect,noinsert', &l:completeopt
|
|
|
|
Execute(ale#completion#AutomaticOmniFunc() should set the preview option if it's set):
|
|
let &l:completeopt = 'menu,preview'
|
|
|
|
let b:ale_completion_info = {'source': 'ale-automatic'}
|
|
call ale#completion#AutomaticOmniFunc(0, '')
|
|
|
|
AssertEqual 'menu,preview', b:ale_old_completeopt
|
|
AssertEqual 'menu,menuone,preview,noselect,noinsert', &l:completeopt
|
|
|
|
Execute(ale#completion#Show() should make the correct feedkeys() call for automatic completion):
|
|
let b:ale_completion_info = {'source': 'ale-automatic'}
|
|
call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}])
|
|
|
|
AssertEqual [], g:feedkeys_calls
|
|
sleep 1ms
|
|
AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls
|
|
|
|
Execute(ale#completion#Show() should make the correct feedkeys() call for manual completion):
|
|
let b:ale_completion_info = {'source': 'ale-automatic'}
|
|
call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}])
|
|
|
|
AssertEqual [], g:feedkeys_calls
|
|
sleep 1ms
|
|
AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls
|
|
|
|
Execute(ale#completion#Show() should not call feedkeys() for other sources):
|
|
let b:ale_completion_info = {'source': 'deoplete'}
|
|
call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}])
|
|
|
|
sleep 1ms
|
|
AssertEqual [], g:feedkeys_calls
|
|
|
|
Execute(ale#completion#Show() shouldn't do anything if you switch back to normal mode):
|
|
let &l:completeopt = 'menu,preview'
|
|
let g:fake_mode = 'n'
|
|
|
|
call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}])
|
|
|
|
AssertEqual 'menu,preview', &l:completeopt
|
|
Assert !exists('b:ale_old_omnifunc')
|
|
Assert !exists('b:ale_old_completeopt')
|
|
Assert !exists('b:ale_completion_result')
|
|
AssertEqual [], g:feedkeys_calls
|
|
|
|
Execute(ale#completion#Show() should save the result it is given):
|
|
call ale#completion#Show([])
|
|
|
|
AssertEqual [], b:ale_completion_result
|
|
|
|
call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}])
|
|
|
|
AssertEqual [{'word': 'x', 'kind': 'v', 'icase': 1}], b:ale_completion_result
|
|
|
|
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(ale#completion#Done() should restore the old completeopt setting):
|
|
let b:ale_old_completeopt = 'menu'
|
|
|
|
call ale#completion#Done()
|
|
|
|
AssertEqual 'menu', &l:completeopt
|
|
Assert !has_key(b:, 'ale_old_completeopt')
|
|
|
|
Execute(ale#completion#Done() should leave settings alone when none were remembered):
|
|
let &l:omnifunc = 'BazBoz'
|
|
let &l:completeopt = 'menu'
|
|
|
|
call ale#completion#Done()
|
|
|
|
AssertEqual 'BazBoz', &l:omnifunc
|
|
AssertEqual 'menu', &l:completeopt
|
|
|
|
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 automatically):
|
|
let b:ale_completion_result = []
|
|
call setpos('.', [bufnr(''), 3, 14, 0])
|
|
call ale#completion#GetCompletions('ale-automatic')
|
|
|
|
AssertEqual
|
|
\ {
|
|
\ 'request_id': 0,
|
|
\ 'conn_id': 0,
|
|
\ 'column': 14,
|
|
\ 'line_length': 14,
|
|
\ 'line': 3,
|
|
\ 'prefix': 'ab',
|
|
\ 'source': 'ale-automatic',
|
|
\ },
|
|
\ b:ale_completion_info
|
|
Assert !exists('b:ale_completion_result')
|
|
|
|
Execute(b:ale_completion_info should be set up correctly when requesting completions manually):
|
|
let b:ale_completion_result = []
|
|
call setpos('.', [bufnr(''), 3, 14, 0])
|
|
ALEComplete
|
|
|
|
AssertEqual
|
|
\ {
|
|
\ 'request_id': 0,
|
|
\ 'conn_id': 0,
|
|
\ 'column': 14,
|
|
\ 'line_length': 14,
|
|
\ 'line': 3,
|
|
\ 'prefix': 'ab',
|
|
\ 'source': 'ale-manual',
|
|
\ },
|
|
\ b:ale_completion_info
|
|
Assert !exists('b:ale_completion_result')
|
|
|
|
Execute(b:ale_completion_info should be set up correctly for other sources):
|
|
let b:ale_completion_result = []
|
|
call setpos('.', [bufnr(''), 3, 14, 0])
|
|
call ale#completion#GetCompletions('deoplete')
|
|
|
|
AssertEqual
|
|
\ {
|
|
\ 'request_id': 0,
|
|
\ 'conn_id': 0,
|
|
\ 'column': 14,
|
|
\ 'line_length': 14,
|
|
\ 'line': 3,
|
|
\ 'prefix': 'ab',
|
|
\ 'source': 'deoplete',
|
|
\ },
|
|
\ b:ale_completion_info
|
|
Assert !exists('b:ale_completion_result')
|
|
|
|
Execute(b:ale_completion_info should be set up correctly when requesting completions via callback):
|
|
let b:ale_completion_result = []
|
|
call setpos('.', [bufnr(''), 3, 14, 0])
|
|
|
|
function! CompleteCallback() abort
|
|
echo 'Called'
|
|
endfunction
|
|
|
|
|
|
call ale#completion#GetCompletions('ale-callback', {'callback': funcref('CompleteCallback')})
|
|
|
|
AssertEqual
|
|
\ {
|
|
\ 'request_id': 0,
|
|
\ 'conn_id': 0,
|
|
\ 'column': 14,
|
|
\ 'line_length': 14,
|
|
\ 'line': 3,
|
|
\ 'prefix': 'ab',
|
|
\ 'source': 'ale-callback',
|
|
\ },
|
|
\ b:ale_completion_info
|
|
Assert !exists('b:ale_completion_result')
|
|
|
|
Execute(The correct keybinds should be configured):
|
|
redir => g:output
|
|
silent map <Plug>(ale_show_completion_menu)
|
|
redir END
|
|
|
|
AssertEqual
|
|
\ [
|
|
\ 'n <Plug>(ale_show_completion_menu) * :call ale#completion#RestoreCompletionOptions()<CR>',
|
|
\ 'o <Plug>(ale_show_completion_menu) * <Nop>',
|
|
\ 'v <Plug>(ale_show_completion_menu) * <Nop>',
|
|
\ ],
|
|
\ sort(split(g:output, "\n"))
|
|
|
|
Execute(Running the normal mode <Plug> keybind should reset the settings):
|
|
let b:ale_old_omnifunc = 'FooBar'
|
|
let b:ale_old_completeopt = 'menu'
|
|
|
|
" We can't run the keybind, but we can call the function.
|
|
call ale#completion#RestoreCompletionOptions()
|
|
|
|
AssertEqual 'FooBar', &l:omnifunc
|
|
AssertEqual 'menu', &l:completeopt
|
|
Assert !has_key(b:, 'ale_old_omnifunc')
|
|
Assert !has_key(b:, 'ale_old_completeopt')
|
|
|
|
Execute(HandleUserData should call ale#code_action#HandleCodeAction):
|
|
let b:ale_completion_info = {'source': 'ale-manual'}
|
|
call MockHandleCodeAction()
|
|
|
|
call ale#completion#HandleUserData({})
|
|
AssertEqual g:handle_code_action_called, 0
|
|
|
|
call ale#completion#HandleUserData({
|
|
\ 'user_data': ''
|
|
\})
|
|
AssertEqual g:handle_code_action_called, 0
|
|
|
|
call ale#completion#HandleUserData({
|
|
\ 'user_data': '{}'
|
|
\})
|
|
AssertEqual g:handle_code_action_called, 0
|
|
|
|
call ale#completion#HandleUserData({
|
|
\ 'user_data': '{"codeActions": []}'
|
|
\})
|
|
AssertEqual g:handle_code_action_called, 0
|
|
|
|
call ale#completion#HandleUserData({
|
|
\ 'user_data': '{"codeActions": [{"description":"", "changes": []}]}'
|
|
\})
|
|
AssertEqual g:handle_code_action_called, 1
|
|
|
|
let b:ale_completion_info = {'source': 'ale-automatic'}
|
|
call ale#completion#HandleUserData({
|
|
\ 'user_data': '{"codeActions": [{"description":"", "changes": []}]}'
|
|
\})
|
|
AssertEqual g:handle_code_action_called, 2
|
|
|
|
Execute(ale#code_action#HandleCodeAction should not be called when when source is not ALE):
|
|
call MockHandleCodeAction()
|
|
let b:ale_completion_info = {'source': 'syntastic'}
|
|
call ale#completion#HandleUserData({
|
|
\ 'user_data': '{"codeActions": [{"description":"", "changes": []}]}'
|
|
\})
|
|
AssertEqual g:handle_code_action_called, 0
|