1
0
mirror of https://github.com/amix/vimrc synced 2025-07-04 23:15:01 +08:00

Update Ale.

This commit is contained in:
Kurtis Moxley
2022-05-19 21:16:38 +08:00
parent 0071859401
commit dd26bc4697
1324 changed files with 56041 additions and 437 deletions

View File

@ -0,0 +1,562 @@
Before:
Save g:ale_enabled
Save b:ale_enabled
Save g:ale_lint_on_text_changed
Save g:ale_completion_enabled
Save g:ale_completion_autoimport
Save g:ale_completion_max_suggestions
Save g:ale_linters
Save b:ale_linters
let g:ale_enabled = 0
let b:ale_enabled = 0
let g:ale_lint_on_text_changed = 'always'
let g:ale_completion_enabled = 0
let g:ale_completion_autoimport = 0
let g:ale_completion_max_suggestions = 50
let g:ale_linters = {'typescript': ['tsserver'], 'python': ['pyre']}
unlet! b:ale_linters
let g:server_started_value = 1
let g:request_id = 0
let g:LastCallback = v:null
let g:LastHandleCallback = v:null
let g:sent_message_list = []
let g:code_action_list = []
let g:execute_list = []
let g:ale_queue_call_list = []
runtime autoload/ale.vim
runtime autoload/ale/util.vim
runtime autoload/ale/code_action.vim
runtime autoload/ale/lsp.vim
runtime autoload/ale/lsp_linter.vim
function! ale#util#Execute(expr) abort
call add(g:execute_list, a:expr)
endfunction
function! ale#Queue(...) abort
call add(g:ale_queue_call_list, a:000)
endfunction
function! ale#lsp#RegisterCallback(id, Callback) abort
let g:LastHandleCallback = a:Callback
endfunction
function! ale#lsp#NotifyForChanges(id, buffer) abort
endfunction
function! ale#lsp#HasCapability(id, capability) abort
return 1
endfunction
function! ale#lsp#Send(id, message) abort
let g:request_id += 1
call add(g:sent_message_list, a:message)
return g:request_id
endfunction
function! ale#lsp_linter#StartLSP(buffer, linter, Callback) abort
let g:LastCallback = a:Callback
return g:server_started_value
endfunction
function! ale#code_action#HandleCodeAction(code_action, options) abort
Assert !get(a:options, 'should_save')
call add(g:code_action_list, a:code_action)
endfunction
function GetLastMessage()
return get(g:execute_list, -1, '')
endfunction
function CheckLintStates(conn_id, message)
" Check that we request more linter results after adding completions.
AssertEqual [[0, '']], g:ale_queue_call_list
let g:ale_enabled = 0
let g:ale_queue_call_list = []
call g:LastHandleCallback(a:conn_id, a:message)
AssertEqual [], g:ale_queue_call_list
let g:ale_enabled = 1
let g:ale_lint_on_text_changed = 1
let g:ale_queue_call_list = []
call g:LastHandleCallback(a:conn_id, a:message)
AssertEqual [[0, '']], g:ale_queue_call_list
let g:ale_lint_on_text_changed = 'normal'
let g:ale_queue_call_list = []
call g:LastHandleCallback(a:conn_id, a:message)
AssertEqual [[0, '']], g:ale_queue_call_list
let g:ale_lint_on_text_changed = 'insert'
let g:ale_queue_call_list = []
call g:LastHandleCallback(a:conn_id, a:message)
AssertEqual [[0, '']], g:ale_queue_call_list
let g:ale_queue_call_list = []
let g:ale_lint_on_text_changed = 'never'
call g:LastHandleCallback(a:conn_id, a:message)
AssertEqual [], g:ale_queue_call_list
let g:ale_lint_on_text_changed = '0'
call g:LastHandleCallback(a:conn_id, a:message)
AssertEqual [], g:ale_queue_call_list
let g:ale_lint_on_text_changed = 0
call g:LastHandleCallback(a:conn_id, a:message)
AssertEqual [], g:ale_queue_call_list
let g:ale_lint_on_text_changed = 'xxx'
call g:LastHandleCallback(a:conn_id, a:message)
AssertEqual [], g:ale_queue_call_list
endfunction
After:
call ale#linter#Reset()
Restore
delfunction GetLastMessage
delfunction CheckLintStates
unlet! g:LastCallback
unlet! g:LastHandleCallback
unlet! g:request_id
unlet! g:server_started_value
unlet! g:sent_message_list
unlet! g:code_action_list
unlet! g:ale_queue_call_list
unlet! g:execute_list
unlet! g:received_message
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
runtime autoload/ale.vim
runtime autoload/ale/util.vim
runtime autoload/ale/code_action.vim
runtime autoload/ale/lsp.vim
runtime autoload/ale/lsp_linter.vim
Given typescript(Some example TypeScript code):
let xyz = 123
let foo = missingword
let abc = 456
Execute(ALEImport should complain when there's no word at the cursor):
call setpos('.', [bufnr(''), 3, 1, 0])
ALEImport
AssertEqual 'echom ''Nothing to complete at cursor!''', GetLastMessage()
Execute(ALEImport should tell the user if no LSP is available):
let g:server_started_value = 0
call setpos('.', [bufnr(''), 2, 16, 0])
ALEImport
AssertEqual
\ 'echom ''No completion providers are available.''',
\ GetLastMessage()
Execute(ALEImport should request imports correctly for tsserver):
call setpos('.', [bufnr(''), 2, 16, 0])
ALEImport
AssertEqual
\ {
\ 'conn_id': 0,
\ 'request_id': 0,
\ 'source': 'ale-import',
\ 'column': 21,
\ 'line': 2,
\ 'line_length': 21,
\ 'prefix': 'missingword',
\ 'additional_edits_only': 1,
\ },
\ b:ale_completion_info
Assert g:LastCallback isnot v:null
call g:LastCallback(ale#linter#Get(&filetype)[0], {
\ 'connection_id': 347,
\ 'buffer': bufnr(''),
\})
AssertEqual
\ {
\ 'conn_id': 347,
\ 'request_id': 1,
\ 'source': 'ale-import',
\ 'column': 21,
\ 'line': 2,
\ 'line_length': 21,
\ 'prefix': 'missingword',
\ 'additional_edits_only': 1,
\ },
\ b:ale_completion_info
Assert g:LastHandleCallback isnot v:null
call g:LastHandleCallback(347, {
\ 'request_seq': 1,
\ 'command': 'completions',
\ 'body': [
\ {'name': 'missingwordIgnoreMe'},
\ {'name': 'missingword'},
\ ],
\})
AssertEqual
\ [
\ [0, 'ts@completions', {
\ 'file': expand('%:p'),
\ 'includeExternalModuleExports': 1,
\ 'offset': 21,
\ 'line': 2,
\ 'prefix': 'missingword',
\ }],
\ [0, 'ts@completionEntryDetails', {
\ 'file': expand('%:p'),
\ 'entryNames': [{'name': 'missingword'}],
\ 'offset': 21,
\ 'line': 2,
\ }]
\ ],
\ g:sent_message_list
AssertEqual 2, b:ale_completion_info.request_id
let g:ale_enabled = 1
let g:received_message = {
\ 'request_seq': 2,
\ 'command': 'completionEntryDetails',
\ 'body': [
\ {
\ 'name': 'missingword',
\ 'kind': 'className',
\ 'displayParts': [],
\ 'codeActions': [{
\ 'description': 'import { missingword } from "./Something";',
\ 'changes': [],
\ }],
\ },
\ ],
\}
call g:LastHandleCallback(347, g:received_message)
AssertEqual
\ [
\ {
\ 'description': 'import { missingword } from "./Something";',
\ 'changes': [],
\ },
\ ],
\ g:code_action_list
call CheckLintStates(347, g:received_message)
Execute(ALEImport should tell the user when no completions were found from tsserver):
call setpos('.', [bufnr(''), 2, 16, 0])
ALEImport
AssertEqual
\ {
\ 'conn_id': 0,
\ 'request_id': 0,
\ 'source': 'ale-import',
\ 'column': 21,
\ 'line': 2,
\ 'line_length': 21,
\ 'prefix': 'missingword',
\ 'additional_edits_only': 1,
\ },
\ b:ale_completion_info
Assert g:LastCallback isnot v:null
call g:LastCallback(ale#linter#Get(&filetype)[0], {
\ 'connection_id': 347,
\ 'buffer': bufnr(''),
\})
AssertEqual
\ {
\ 'conn_id': 347,
\ 'request_id': 1,
\ 'source': 'ale-import',
\ 'column': 21,
\ 'line': 2,
\ 'line_length': 21,
\ 'prefix': 'missingword',
\ 'additional_edits_only': 1,
\ },
\ b:ale_completion_info
Assert g:LastHandleCallback isnot v:null
call g:LastHandleCallback(347, {
\ 'request_seq': 1,
\ 'command': 'completions',
\ 'body': [
\ {'name': 'missingwordIgnoreMe'},
\ ],
\})
AssertEqual 'echom ''No possible imports found.''', GetLastMessage()
Given python(Some example Python code):
xyz = 123
foo = missingword
abc = 456
Execute(ALEImport should request imports correctly for language servers):
call setpos('.', [bufnr(''), 2, 12, 0])
ALEImport
AssertEqual
\ {
\ 'conn_id': 0,
\ 'request_id': 0,
\ 'source': 'ale-import',
\ 'column': 17,
\ 'line': 2,
\ 'line_length': 17,
\ 'prefix': 'missingword',
\ 'additional_edits_only': 1,
\ },
\ b:ale_completion_info
Assert g:LastCallback isnot v:null
call g:LastCallback(ale#linter#Get(&filetype)[0], {
\ 'connection_id': 347,
\ 'buffer': bufnr(''),
\})
AssertEqual
\ {
\ 'conn_id': 347,
\ 'request_id': 1,
\ 'source': 'ale-import',
\ 'column': 17,
\ 'line': 2,
\ 'line_length': 17,
\ 'prefix': 'missingword',
\ 'additional_edits_only': 1,
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
\ },
\ b:ale_completion_info
Assert g:LastHandleCallback isnot v:null
AssertEqual
\ [
\ [0, 'textDocument/completion', {
\ 'textDocument': {'uri': ale#path#ToFileURI(expand('%:p'))},
\ 'position': {'character': 16, 'line': 1}
\ }],
\ ],
\ g:sent_message_list
AssertEqual 1, b:ale_completion_info.request_id
let g:ale_enabled = 1
let g:received_message = {
\ 'id': 1,
\ 'jsonrpc': '2.0',
\ 'result': {
\ 'isIncomplete': v:false,
\ 'items': [
\ {
\ 'detail': 'Some other word we should ignore',
\ 'filterText': 'missingwordIgnoreMe',
\ 'insertText': 'missingwordIgnoreMe',
\ 'insertTextFormat': 1,
\ 'kind': 6,
\ 'label': ' missingwordIgnoreMe',
\ 'sortText': '3ee19999missingword',
\ 'additionalTextEdits': [
\ {
\ 'range': {
\ 'start': {'line': 1, 'character': 1},
\ 'end': {'line': 2, 'character': 1},
\ },
\ 'newText': 'from something import missingwordIgnoreMe',
\ },
\ ],
\ },
\ {
\ 'detail': 'Some word without text edits',
\ 'filterText': 'missingword',
\ 'insertText': 'missingword',
\ 'insertTextFormat': 1,
\ 'kind': 6,
\ 'label': ' missingword',
\ 'sortText': '3ee19999missingword',
\ },
\ {
\ 'detail': 'The word we should use',
\ 'filterText': 'missingword',
\ 'insertText': 'missingword',
\ 'insertTextFormat': 1,
\ 'kind': 6,
\ 'label': ' missingword',
\ 'sortText': '3ee19999missingword',
\ 'additionalTextEdits': [
\ {
\ 'range': {
\ 'start': {'line': 1, 'character': 1},
\ 'end': {'line': 2, 'character': 1},
\ },
\ 'newText': 'from something import missingword',
\ },
\ ],
\ },
\ {
\ 'detail': 'The other word we should not use',
\ 'filterText': 'missingword',
\ 'insertText': 'missingword',
\ 'insertTextFormat': 1,
\ 'kind': 6,
\ 'label': ' missingword',
\ 'sortText': '3ee19999missingword',
\ 'additionalTextEdits': [
\ {
\ 'range': {
\ 'start': {'line': 1, 'character': 1},
\ 'end': {'line': 2, 'character': 1},
\ },
\ 'newText': 'from something_else import missingword',
\ },
\ ],
\ },
\ ],
\ },
\}
call g:LastHandleCallback(347, g:received_message)
AssertEqual
\ [
\ {
\ 'description': 'completion',
\ 'changes': [
\ {
\ 'fileName': expand('%:p'),
\ 'textChanges': [
\ {
\ 'start': {'line': 2, 'offset': 2},
\ 'end': {'line': 3, 'offset': 2},
\ 'newText': 'from something import missingword',
\ },
\ ],
\ },
\ ],
\ },
\ ],
\ g:code_action_list
call CheckLintStates(347, g:received_message)
Execute(ALEImport should tell the user when no completions were found from a language server):
call setpos('.', [bufnr(''), 2, 12, 0])
ALEImport
AssertEqual
\ {
\ 'conn_id': 0,
\ 'request_id': 0,
\ 'source': 'ale-import',
\ 'column': 17,
\ 'line': 2,
\ 'line_length': 17,
\ 'prefix': 'missingword',
\ 'additional_edits_only': 1,
\ },
\ b:ale_completion_info
Assert g:LastCallback isnot v:null
call g:LastCallback(ale#linter#Get(&filetype)[0], {
\ 'connection_id': 347,
\ 'buffer': bufnr(''),
\})
AssertEqual
\ {
\ 'conn_id': 347,
\ 'request_id': 1,
\ 'source': 'ale-import',
\ 'column': 17,
\ 'line': 2,
\ 'line_length': 17,
\ 'prefix': 'missingword',
\ 'additional_edits_only': 1,
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
\ },
\ b:ale_completion_info
Assert g:LastHandleCallback isnot v:null
AssertEqual
\ [
\ [0, 'textDocument/completion', {
\ 'textDocument': {'uri': ale#path#ToFileURI(expand('%:p'))},
\ 'position': {'character': 16, 'line': 1}
\ }],
\ ],
\ g:sent_message_list
AssertEqual 1, b:ale_completion_info.request_id
let g:received_message = {
\ 'id': 1,
\ 'jsonrpc': '2.0',
\ 'result': {
\ 'isIncomplete': v:false,
\ 'items': [
\ {
\ 'detail': 'Some other word we should ignore',
\ 'filterText': 'missingwordIgnoreMe',
\ 'insertText': 'missingwordIgnoreMe',
\ 'insertTextFormat': 1,
\ 'kind': 6,
\ 'label': ' missingwordIgnoreMe',
\ 'sortText': '3ee19999missingword',
\ 'additionalTextEdits': [
\ {
\ 'range': {
\ 'start': {'line': 1, 'character': 1},
\ 'end': {'line': 2, 'character': 1},
\ },
\ 'newText': 'from something import missingwordIgnoreMe',
\ },
\ ],
\ },
\ {
\ 'detail': 'Some word without text edits',
\ 'filterText': 'missingword',
\ 'insertText': 'missingword',
\ 'insertTextFormat': 1,
\ 'kind': 6,
\ 'label': ' missingword',
\ 'sortText': '3ee19999missingword',
\ },
\ ],
\ },
\}
call g:LastHandleCallback(347, g:received_message)
AssertEqual 'echom ''No possible imports found.''', GetLastMessage()

View File

@ -0,0 +1,35 @@
Before:
let g:complete_post_triggered = 0
augroup VaderTest
autocmd!
autocmd User ALECompletePost let g:complete_post_triggered = 1
augroup END
After:
unlet! b:ale_completion_info
unlet! g:complete_post_triggered
augroup VaderTest
autocmd!
augroup END
augroup! VaderTest
Execute(ALECompletePost should not be triggered when completion is cancelled):
call ale#completion#HandleUserData({})
Assert !g:complete_post_triggered
Execute(ALECompletePost should not be triggered when tools other than ALE insert completions):
call ale#completion#HandleUserData({'user_data': ''})
call ale#completion#HandleUserData({'user_data': '{}'})
Assert !g:complete_post_triggered
Execute(ALECompletePost should be triggered when ALE inserts completions):
call ale#completion#HandleUserData({
\ 'user_data': json_encode({'_ale_completion_item': 1}),
\})
Assert g:complete_post_triggered

View File

@ -0,0 +1,486 @@
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 b:ale_linters = {
\ 'typescript': ['tsserver'],
\}
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 l: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, options) abort
Assert !get(a:options, 'should_save')
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
unlet! b:ale_linters
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,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,noinsert,preview', &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,noselect'
let b:ale_completion_info = {'source': 'ale-automatic'}
call ale#completion#AutomaticOmniFunc(0, '')
AssertEqual 'menu,noselect', b:ale_old_completeopt
AssertEqual 'menu,menuone,noinsert,noselect', &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,noinsert,preview', &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': 'other-source'}
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('ale-callback')
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(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': json_encode({}),
\})
AssertEqual g:handle_code_action_called, 0
call ale#completion#HandleUserData({
\ 'user_data': json_encode({
\ '_ale_completion_item': 1,
\ 'code_actions': [],
\ }),
\})
AssertEqual g:handle_code_action_called, 0
call ale#completion#HandleUserData({
\ 'user_data': json_encode({
\ '_ale_completion_item': 1,
\ 'code_actions': [
\ {'description': '', 'changes': []},
\ ],
\ }),
\})
AssertEqual g:handle_code_action_called, 1
let b:ale_completion_info = {'source': 'ale-automatic'}
call ale#completion#HandleUserData({
\ 'user_data': json_encode({
\ '_ale_completion_item': 1,
\ 'code_actions': [
\ {'description': '', 'changes': []},
\ ],
\ }),
\})
AssertEqual g:handle_code_action_called, 2
let b:ale_completion_info = {'source': 'ale-callback'}
call ale#completion#HandleUserData({
\ 'user_data': json_encode({
\ '_ale_completion_item': 1,
\ 'code_actions': [
\ {'description': '', 'changes': []},
\ ],
\ }),
\})
AssertEqual g:handle_code_action_called, 3
let b:ale_completion_info = {'source': 'ale-omnifunc'}
call ale#completion#HandleUserData({
\ 'user_data': json_encode({
\ '_ale_completion_item': 1,
\ 'code_actions': [
\ {'description': '', 'changes': []},
\ ],
\ }),
\})
AssertEqual g:handle_code_action_called, 4
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': json_encode({
\ '_ale_completion_item': 1,
\ 'code_actions': [
\ {'description': '', 'changes': []},
\ ],
\ }),
\})
AssertEqual g:handle_code_action_called, 0

View File

@ -0,0 +1,142 @@
Before:
Save g:ale_completion_excluded_words
let g:ale_completion_excluded_words = []
After:
Restore
unlet! b:ale_completion_excluded_words
unlet! b:suggestions
Execute(Prefix filtering should work for Lists of strings):
AssertEqual
\ ['FooBar', 'foo'],
\ ale#completion#Filter(bufnr(''), '', ['FooBar', 'FongBar', 'baz', 'foo'], 'foo', 0)
AssertEqual
\ ['FooBar', 'FongBar', 'baz', 'foo'],
\ ale#completion#Filter(bufnr(''), '', ['FooBar', 'FongBar', 'baz', 'foo'], '.', 0)
AssertEqual
\ ['FooBar', 'FongBar', 'baz', 'foo'],
\ ale#completion#Filter(bufnr(''), '', ['FooBar', 'FongBar', 'baz', 'foo'], '', 0)
Execute(Exact filtering should work):
AssertEqual
\ ['foo'],
\ ale#completion#Filter(bufnr(''), '', ['FooBar', 'FongBar', 'baz', 'foo'], 'foo', 1)
AssertEqual
\ ['FooBar', 'FongBar', 'baz', 'foo'],
\ ale#completion#Filter(bufnr(''), '', ['FooBar', 'FongBar', 'baz', 'foo'], '.', 1)
AssertEqual
\ ['Foo'],
\ ale#completion#Filter(bufnr(''), '', ['FooBar', 'FongBar', 'Foo', 'foo'], 'Foo', 1)
Execute(Prefix filtering should work for completion items):
AssertEqual
\ [{'word': 'FooBar'}, {'word': 'foo'}],
\ ale#completion#Filter(
\ bufnr(''),
\ '',
\ [
\ {'word': 'FooBar'},
\ {'word': 'FongBar'},
\ {'word': 'baz'},
\ {'word': 'foo'},
\ ],
\ 'foo',
\ 0,
\ )
AssertEqual
\ [
\ {'word': 'FooBar'},
\ {'word': 'FongBar'},
\ {'word': 'baz'},
\ {'word': 'foo'},
\ ],
\ ale#completion#Filter(
\ bufnr(''),
\ '',
\ [
\ {'word': 'FooBar'},
\ {'word': 'FongBar'},
\ {'word': 'baz'},
\ {'word': 'foo'},
\ ],
\ '.',
\ 0,
\ )
Execute(Excluding words from completion results should work):
let b:ale_completion_excluded_words = ['it', 'describe']
AssertEqual
\ [{'word': 'Italian'}],
\ ale#completion#Filter(
\ bufnr(''),
\ '',
\ [
\ {'word': 'Italian'},
\ {'word': 'it'},
\ ],
\ 'it',
\ 0,
\ )
AssertEqual
\ [{'word': 'Deutsch'}],
\ ale#completion#Filter(
\ bufnr(''),
\ '',
\ [
\ {'word': 'describe'},
\ {'word': 'Deutsch'},
\ ],
\ 'de',
\ 0,
\ )
AssertEqual
\ [{'word': 'Deutsch'}],
\ ale#completion#Filter(
\ bufnr(''),
\ '',
\ [
\ {'word': 'describe'},
\ {'word': 'Deutsch'},
\ ],
\ '.',
\ 0,
\ )
Execute(Excluding words from completion results should work with lists of Strings):
let b:ale_completion_excluded_words = ['it', 'describe']
AssertEqual
\ ['Italian'],
\ ale#completion#Filter(bufnr(''), '', ['Italian', 'it'], 'it', 0)
AssertEqual
\ ['Deutsch'],
\ ale#completion#Filter(bufnr(''), '', ['describe', 'Deutsch'], 'de', 0)
AssertEqual
\ ['Deutsch'],
\ ale#completion#Filter(bufnr(''), '', ['describe', 'Deutsch'], '.', 0)
AssertEqual
\ ['Deutsch'],
\ ale#completion#Filter(bufnr(''), '', ['Deutsch'], '', 0)
Execute(Filtering shouldn't modify the original list):
let b:ale_completion_excluded_words = ['it', 'describe']
let b:suggestions = [{'word': 'describe'}]
AssertEqual [], ale#completion#Filter(bufnr(''), '', b:suggestions, '.', 0)
AssertEqual b:suggestions, [{'word': 'describe'}]
AssertEqual [], ale#completion#Filter(bufnr(''), '', b:suggestions, 'de', 0)
AssertEqual b:suggestions, [{'word': 'describe'}]
Execute(Filtering should respect filetype triggers):
let b:suggestions = [{'word': 'describe'}]
AssertEqual b:suggestions, ale#completion#Filter(bufnr(''), '', b:suggestions, '.', 0)
AssertEqual b:suggestions, ale#completion#Filter(bufnr(''), 'rust', b:suggestions, '.', 0)
AssertEqual b:suggestions, ale#completion#Filter(bufnr(''), 'rust', b:suggestions, '::', 0)

View File

@ -0,0 +1,65 @@
Given typescript():
let abc = y.
let foo = ab
let foo = (ab)
let string1 = '
let string2 = "
Execute(Completion should be done after dots in TypeScript):
AssertEqual '.', ale#completion#GetPrefix(&filetype, 1, 13)
Execute(Completion should be done after words in TypeScript):
AssertEqual 'ab', ale#completion#GetPrefix(&filetype, 2, 13)
Execute(Completion should be done after words in parens in TypeScript):
AssertEqual 'ab', ale#completion#GetPrefix(&filetype, 3, 14)
Execute(Completion should not be done after parens in TypeScript):
AssertEqual '', ale#completion#GetPrefix(&filetype, 3, 15)
Execute(Completion should be done after strings in TypeScript):
AssertEqual '''', ale#completion#GetPrefix(&filetype, 4, 16)
AssertEqual '"', ale#completion#GetPrefix(&filetype, 5, 16)
Execute(Completion prefixes should work for other filetypes):
AssertEqual 'ab', ale#completion#GetPrefix('xxxyyyzzz', 3, 14)
Execute(Completion prefixes should work for other filetypes):
AssertEqual 'ab', ale#completion#GetPrefix('xxxyyyzzz', 3, 14)
Given rust():
let abc = y.
let abc = String::
let foo = (ab)
Execute(Completion should be done after dots in Rust):
AssertEqual '.', ale#completion#GetPrefix(&filetype, 1, 13)
Execute(Completion should be done after colons in Rust):
AssertEqual '::', ale#completion#GetPrefix(&filetype, 2, 19)
Execute(Completion should be done after words in parens in Rust):
AssertEqual 'ab', ale#completion#GetPrefix(&filetype, 3, 14)
Execute(Completion should not be done after parens in Rust):
AssertEqual '', ale#completion#GetPrefix(&filetype, 3, 15)
Given lisp():
(minus-name
(full-name)
Execute(Completion should be done for function names with minuses in Lisp):
AssertEqual 'minus-name', ale#completion#GetPrefix(&filetype, 1, 12)
Execute(Completion should not be done after parens in Lisp):
AssertEqual '', ale#completion#GetPrefix(&filetype, 2, 12)
Given clojure():
(minus-name
(full-name)
Execute(Completion should be done for function names with minuses in Clojure):
AssertEqual 'minus-name', ale#completion#GetPrefix(&filetype, 1, 12)
Execute(Completion should not be done after parens in Clojure):
AssertEqual '', ale#completion#GetPrefix(&filetype, 2, 12)

View File

@ -0,0 +1,307 @@
Before:
Save g:ale_completion_delay
Save g:ale_completion_max_suggestions
Save g:ale_completion_info
Save &l:omnifunc
Save &l:completeopt
let g:ale_completion_enabled = 1
call ale#test#SetDirectory('/testplugin/test/completion')
call ale#test#SetFilename('dummy.txt')
runtime autoload/ale/lsp.vim
let g:message_list = []
let g:capability_checked = ''
let g:conn_id = v:null
let g:Callback = ''
let g:init_callback_list = []
function! ale#lsp_linter#StartLSP(buffer, linter, Callback) abort
let g:conn_id = ale#lsp#Register('executable', '/foo/bar', {})
call ale#lsp#MarkDocumentAsOpen(g:conn_id, a:buffer)
let l:details = {
\ 'command': 'foobar',
\ 'buffer': a:buffer,
\ 'connection_id': g:conn_id,
\ 'project_root': '/foo/bar',
\}
call add(g:init_callback_list, {-> a:Callback(a:linter, l:details)})
endfunction
" Pretend we're in insert mode for most tests.
function! ale#util#Mode(...) abort
return 'i'
endfunction
function! ale#lsp#HasCapability(conn_id, capability) abort
let g:capability_checked = a:capability
return 1
endfunction
function! ale#lsp#RegisterCallback(conn_id, callback) abort
let g:Callback = a:callback
endfunction
" Replace the Send function for LSP, so we can monitor calls to it.
function! ale#lsp#Send(conn_id, message) abort
call add(g:message_list, a:message)
return 1
endfunction
After:
Restore
if g:conn_id isnot v:null
call ale#lsp#RemoveConnectionWithID(g:conn_id)
endif
unlet! g:message_list
unlet! g:capability_checked
unlet! g:init_callback_list
unlet! g:conn_id
unlet! g:Callback
unlet! b:ale_old_omnifunc
unlet! b:ale_old_completeopt
unlet! b:ale_completion_info
unlet! b:ale_complete_done_time
unlet! b:ale_linters
unlet! b:ale_tsserver_completion_names
" Reset the function.
function! ale#util#Mode(...) abort
return call('mode', a:000)
endfunction
call ale#test#RestoreDirectory()
call ale#linter#Reset()
" Stop any timers we left behind.
" This stops the tests from failing randomly.
call ale#completion#StopTimer()
runtime autoload/ale/completion.vim
runtime autoload/ale/lsp.vim
runtime autoload/ale/lsp_linter.vim
Given typescript(Some typescript file):
foo
somelongerline
bazxyzxyzxyz
Execute(The right message should be sent for the initial tsserver request):
runtime ale_linters/typescript/tsserver.vim
let b:ale_linters = ['tsserver']
" The cursor position needs to match what was saved before.
call setpos('.', [bufnr(''), 1, 3, 0])
call ale#completion#GetCompletions('ale-automatic')
" We shouldn't register the callback yet.
AssertEqual '''''', string(g:Callback)
AssertEqual 1, len(g:init_callback_list)
call map(g:init_callback_list, 'v:val()')
AssertEqual 'completion', g:capability_checked
" We should send the right callback.
AssertEqual
\ 'function(''ale#completion#HandleTSServerResponse'')',
\ string(g:Callback)
" We should send the right message.
AssertEqual
\ [[0, 'ts@completions', {
\ 'file': expand('%:p'),
\ 'line': 1,
\ 'offset': 3,
\ 'prefix': 'fo',
\ 'includeExternalModuleExports': g:ale_completion_autoimport,
\ }]],
\ g:message_list
" We should set up the completion info correctly.
AssertEqual
\ {
\ 'line_length': 3,
\ 'conn_id': g:conn_id,
\ 'column': 3,
\ 'request_id': 1,
\ 'line': 1,
\ 'prefix': 'fo',
\ 'source': 'ale-automatic',
\ },
\ get(b:, 'ale_completion_info', {})
Execute(The right message sent to the tsserver LSP when the first completion message is received):
" The cursor position needs to match what was saved before.
call setpos('.', [bufnr(''), 1, 1, 0])
let b:ale_completion_info = {
\ 'conn_id': 123,
\ 'prefix': 'f',
\ 'request_id': 4,
\ 'line': 1,
\ 'column': 1,
\}
" We should only show up to this many suggestions.
let g:ale_completion_max_suggestions = 3
" Handle the response for completions.
call ale#completion#HandleTSServerResponse(123, {
\ 'request_seq': 4,
\ 'command': 'completions',
\ 'body': [
\ {'name': 'Baz'},
\ {'name': 'dingDong'},
\ {'name': 'Foo', 'source': '/path/to/foo.ts'},
\ {'name': 'FooBar'},
\ {'name': 'frazzle'},
\ {'name': 'FFS'},
\ ],
\})
" We should save the names we got in the buffer, as TSServer doesn't return
" details for every name.
AssertEqual [{
\ 'word': 'Foo',
\ 'source': '/path/to/foo.ts',
\ }, {
\ 'word': 'FooBar',
\ 'source': '',
\ }, {
\ 'word': 'frazzle',
\ 'source': '',
\}],
\ get(b:, 'ale_tsserver_completion_names', [])
" The entry details messages should have been sent.
AssertEqual
\ [[
\ 0,
\ 'ts@completionEntryDetails',
\ {
\ 'file': expand('%:p'),
\ 'entryNames': [{
\ 'name': 'Foo',
\ 'source': '/path/to/foo.ts',
\ }, {
\ 'name': 'FooBar',
\ }, {
\ 'name': 'frazzle',
\ }],
\ 'offset': 1,
\ 'line': 1,
\ },
\ ]],
\ g:message_list
Given python(Some Python file):
foo
somelongerline
bazxyzxyzxyz
Execute(The right message should be sent for the initial LSP request):
runtime ale_linters/python/pylsp.vim
let b:ale_linters = ['pylsp']
" The cursor position needs to match what was saved before.
call setpos('.', [bufnr(''), 1, 5, 0])
call ale#completion#GetCompletions('ale-automatic')
" We shouldn't register the callback yet.
AssertEqual '''''', string(g:Callback)
AssertEqual 1, len(g:init_callback_list)
call map(g:init_callback_list, 'v:val()')
AssertEqual 'completion', g:capability_checked
" We should send the right callback.
AssertEqual
\ 'function(''ale#completion#HandleLSPResponse'')',
\ string(g:Callback)
" We should send the right message.
" The character index needs to be at most the index of the last character on
" the line, or integration with pylsp will be broken.
"
" We need to send the message for changing the document first.
AssertEqual
\ [
\ [1, 'textDocument/didChange', {
\ 'textDocument': {
\ 'uri': ale#path#ToFileURI(expand('%:p')),
\ 'version': g:ale_lsp_next_version_id - 1,
\ },
\ 'contentChanges': [{'text': join(getline(1, '$'), "\n") . "\n"}]
\ }],
\ [0, 'textDocument/completion', {
\ 'textDocument': {'uri': ale#path#ToFileURI(expand('%:p'))},
\ 'position': {'line': 0, 'character': 2},
\ }],
\ ],
\ g:message_list
" We should set up the completion info correctly.
AssertEqual
\ {
\ 'line_length': 3,
\ 'conn_id': g:conn_id,
\ 'column': 3,
\ 'request_id': 1,
\ 'line': 1,
\ 'prefix': 'fo',
\ 'source': 'ale-automatic',
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
\ },
\ get(b:, 'ale_completion_info', {})
Execute(Two completion requests shouldn't be sent in a row):
call ale#linter#PreventLoading('python')
call ale#linter#Define('python', {
\ 'name': 'foo',
\ 'lsp': 'stdio',
\ 'executable': 'foo',
\ 'command': 'foo',
\ 'project_root': {-> '/foo/bar'},
\})
call ale#linter#Define('python', {
\ 'name': 'bar',
\ 'lsp': 'stdio',
\ 'executable': 'foo',
\ 'command': 'foo',
\ 'project_root': {-> '/foo/bar'},
\})
let b:ale_linters = ['foo', 'bar']
" The cursor position needs to match what was saved before.
call setpos('.', [bufnr(''), 1, 5, 0])
call ale#completion#GetCompletions('ale-automatic')
" We shouldn't register the callback yet.
AssertEqual '''''', string(g:Callback)
AssertEqual 2, len(g:init_callback_list)
call map(g:init_callback_list, 'v:val()')
AssertEqual 'completion', g:capability_checked
" We should only send one completion message for two LSP servers.
AssertEqual
\ [
\ [1, 'textDocument/didChange', {
\ 'textDocument': {
\ 'uri': ale#path#ToFileURI(expand('%:p')),
\ 'version': g:ale_lsp_next_version_id - 1,
\ },
\ 'contentChanges': [{'text': join(getline(1, '$'), "\n") . "\n"}]
\ }],
\ [0, 'textDocument/completion', {
\ 'textDocument': {'uri': ale#path#ToFileURI(expand('%:p'))},
\ 'position': {'line': 0, 'character': 2},
\ }],
\ ],
\ g:message_list

View File

@ -0,0 +1,736 @@
Before:
Save g:ale_completion_autoimport
Save g:ale_completion_max_suggestions
let g:ale_completion_max_suggestions = 50
After:
Restore
unlet! b:ale_completion_info
Execute(Should handle Rust completion results correctly):
let g:ale_completion_autoimport = 0
AssertEqual
\ [
\ {'word': 'new', 'dup': 0, 'menu': 'pub fn new() -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'with_capacity', 'dup': 0, 'menu': 'pub fn with_capacity(capacity: usize) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from_utf8', 'dup': 0, 'menu': 'pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error>', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from_utf8_lossy', 'dup': 0, 'menu': 'pub fn from_utf8_lossy<''a>(v: &''a [u8]) -> Cow<''a, str>', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from_utf16', 'dup': 0, 'menu': 'pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error>', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from_utf16_lossy', 'dup': 0, 'menu': 'pub fn from_utf16_lossy(v: &[u16]) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from_raw_parts', 'dup': 0, 'menu': 'pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from_utf8_unchecked', 'dup': 0, 'menu': 'pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from_iter', 'dup': 0, 'menu': 'fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from_iter', 'dup': 0, 'menu': 'fn from_iter<I: IntoIterator<Item = &''a char>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from_iter', 'dup': 0, 'menu': 'fn from_iter<I: IntoIterator<Item = &''a str>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from_iter', 'dup': 0, 'menu': 'fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from_iter', 'dup': 0, 'menu': 'fn from_iter<I: IntoIterator<Item = Cow<''a, str>>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'Searcher', 'dup': 0, 'menu': 'type Searcher = <&''b str as Pattern<''a>>::Searcher;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'default', 'dup': 0, 'menu': 'fn default() -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'Output', 'dup': 0, 'menu': 'type Output = String;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'Output', 'dup': 0, 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'Output', 'dup': 0, 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'Output', 'dup': 0, 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'Output', 'dup': 0, 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'Output', 'dup': 0, 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'Output', 'dup': 0, 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'Target', 'dup': 0, 'menu': 'type Target = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'Err', 'dup': 0, 'menu': 'type Err = ParseError;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from_str', 'dup': 0, 'menu': 'fn from_str(s: &str) -> Result<String, ParseError>', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from', 'dup': 0, 'menu': 'fn from(s: &''a str) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from', 'dup': 0, 'menu': 'fn from(s: Box<str>) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from', 'dup': 0, 'menu': 'fn from(s: Cow<''a, str>) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'to_vec', 'dup': 0, 'menu': 'pub fn to_vec(&self) -> Vec<T> where T: Clone,', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\],
\ ale#completion#ParseLSPCompletions({
\ "jsonrpc":"2.0",
\ "id":65,
\ "result":[
\ {
\ "label":"new",
\ "kind":3,
\ "detail":"pub fn new() -> String"
\ },
\ {
\ "label":"with_capacity",
\ "kind":3,
\ "detail":"pub fn with_capacity(capacity: usize) -> String"
\ },
\ {
\ "label":"from_utf8",
\ "kind":3,
\ "detail":"pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error>"
\ },
\ {
\ "label":"from_utf8_lossy",
\ "kind":3,
\ "detail":"pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str>"
\ },
\ {
\ "label":"from_utf16",
\ "kind":3,
\ "detail":"pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error>"
\ },
\ {
\ "label":"from_utf16_lossy",
\ "kind":3,
\ "detail":"pub fn from_utf16_lossy(v: &[u16]) -> String"
\ },
\ {
\ "label":"from_raw_parts",
\ "kind":3,
\ "detail":"pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String"
\ },
\ {
\ "label":"from_utf8_unchecked",
\ "kind":3,
\ "detail":"pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String"
\ },
\ {
\ "label":"from_iter",
\ "kind":3,
\ "detail":"fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> String"
\ },
\ {
\ "label":"from_iter",
\ "kind":3,
\ "detail":"fn from_iter<I: IntoIterator<Item = &'a char>>(iter: I) -> String"
\ },
\ {
\ "label":"from_iter",
\ "kind":3,
\ "detail":"fn from_iter<I: IntoIterator<Item = &'a str>>(iter: I) -> String"
\ },
\ {
\ "label":"from_iter",
\ "kind":3,
\ "detail":"fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> String"
\ },
\ {
\ "label":"from_iter",
\ "kind":3,
\ "detail":"fn from_iter<I: IntoIterator<Item = Cow<'a, str>>>(iter: I) -> String"
\ },
\ {
\ "label":"Searcher",
\ "kind":8,
\ "detail":"type Searcher = <&'b str as Pattern<'a>>::Searcher;"
\ },
\ {
\ "label":"default",
\ "kind":3,
\ "detail":"fn default() -> String"
\ },
\ {
\ "label":"Output",
\ "kind":8,
\ "detail":"type Output = String;"
\ },
\ {
\ "label":"Output",
\ "kind":8,
\ "detail":"type Output = str;"
\ },
\ {
\ "label":"Output",
\ "kind":8,
\ "detail":"type Output = str;"
\ },
\ {
\ "label":"Output",
\ "kind":8,
\ "detail":"type Output = str;"
\ },
\ {
\ "label":"Output",
\ "kind":8,
\ "detail":"type Output = str;"
\ },
\ {
\ "label":"Output",
\ "kind":8,
\ "detail":"type Output = str;"
\ },
\ {
\ "label":"Output",
\ "kind":8,
\ "detail":"type Output = str;"
\ },
\ {
\ "label":"Target",
\ "kind":8,
\ "detail":"type Target = str;"
\ },
\ {
\ "label":"Err",
\ "kind":8,
\ "detail":"type Err = ParseError;"
\ },
\ {
\ "label":"from_str",
\ "kind":3,
\ "detail":"fn from_str(s: &str) -> Result<String, ParseError>"
\ },
\ {
\ "label":"from",
\ "kind":3,
\ "detail":"fn from(s: &'a str) -> String"
\ },
\ {
\ "label":"from",
\ "kind":3,
\ "detail":"fn from(s: Box<str>) -> String"
\ },
\ {
\ "label":"from",
\ "kind":3,
\ "detail":"fn from(s: Cow<'a, str>) -> String"
\ },
\ {
\ "label":"to_vec",
\ "kind":3,
\ "detail":"pub fn to_vec(&self) -> Vec<T>\nwhere\n T: Clone,"
\ }
\ ]
\ })
Execute(Should handle Python completion results correctly):
let g:ale_completion_autoimport = 0
let b:ale_completion_info = {
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
\}
AssertEqual
\ [
\ {'word': 'what', 'dup': 0, 'menu': 'example-python-project.bar.Bar', 'info': "what()\n\n", 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ ],
\ ale#completion#ParseLSPCompletions({
\ "jsonrpc":"2.0",
\ "id":6,
\ "result":{
\ "isIncomplete":v:false,
\ "items":[
\ {
\ "label":"what()",
\ "kind":3,
\ "detail":"example-python-project.bar.Bar",
\ "documentation":"what()\n\n",
\ "sortText":"awhat",
\ "insertText":"what"
\ },
\ {
\ "label":"__class__",
\ "kind":7,
\ "detail":"object",
\ "documentation":"type(object_or_name, bases, dict)\ntype(object) -> the object's type\ntype(name, bases, dict) -> a new type",
\ "sortText":"z__class__",
\ "insertText":"__class__"
\ },
\ {
\ "label":"__delattr__(name)",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Implement delattr(self, name).",
\ "sortText":"z__delattr__",
\ "insertText":"__delattr__"
\ },
\ {
\ "label":"__dir__()",
\ "kind":3,
\ "detail":"object",
\ "documentation":"__dir__() -> list\ndefault dir() implementation",
\ "sortText":"z__dir__",
\ "insertText":"__dir__"
\ },
\ {
\ "label":"__doc__",
\ "kind":18,
\ "detail":"object",
\ "documentation":"str(object='') -> str\nstr(bytes_or_buffer[, encoding[, errors]]) -> str\n\nCreate a new string object from the given object. If encoding or\nerrors is specified, then the object must expose a data buffer\nthat will be decoded using the given encoding and error handler.\nOtherwise, returns the result of object.__str__() (if defined)\nor repr(object).\nencoding defaults to sys.getdefaultencoding().\nerrors defaults to 'strict'.",
\ "sortText":"z__doc__",
\ "insertText":"__doc__"
\ },
\ {
\ "label":"__eq__(value)",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Return self==value.",
\ "sortText":"z__eq__",
\ "insertText":"__eq__"
\ },
\ {
\ "label":"__format__()",
\ "kind":3,
\ "detail":"object",
\ "documentation":"default object formatter",
\ "sortText":"z__format__",
\ "insertText":"__format__"
\ },
\ {
\ "label":"__ge__(value)",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Return self>=value.",
\ "sortText":"z__ge__",
\ "insertText":"__ge__"
\ },
\ {
\ "label":"__getattribute__(name)",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Return getattr(self, name).",
\ "sortText":"z__getattribute__",
\ "insertText":"__getattribute__"
\ },
\ {
\ "label":"__gt__(value)",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Return self>value.",
\ "sortText":"z__gt__",
\ "insertText":"__gt__"
\ },
\ {
\ "label":"__hash__()",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Return hash(self).",
\ "sortText":"z__hash__",
\ "insertText":"__hash__"
\ },
\ {
\ "label":"__init__(args, kwargs)",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Initialize self.\u00a0\u00a0See help(type(self)) for accurate signature.",
\ "sortText":"z__init__",
\ "insertText":"__init__"
\ },
\ {
\ "label":"__init_subclass__()",
\ "kind":3,
\ "detail":"object",
\ "documentation":"This method is called when a class is subclassed.\n\nThe default implementation does nothing. It may be\noverridden to extend subclasses.",
\ "sortText":"z__init_subclass__",
\ "insertText":"__init_subclass__"
\ },
\ {
\ "label":"__le__(value)",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Return self<=value.",
\ "sortText":"z__le__",
\ "insertText":"__le__"
\ },
\ {
\ "label":"__lt__(value)",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Return self<value.",
\ "sortText":"z__lt__",
\ "insertText":"__lt__"
\ },
\ {
\ "label":"__ne__(value)",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Return self!=value.",
\ "sortText":"z__ne__",
\ "insertText":"__ne__"
\ },
\ {
\ "label":"__new__(kwargs)",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Create and return a new object.\u00a0\u00a0See help(type) for accurate signature.",
\ "sortText":"z__new__",
\ "insertText":"__new__"
\ },
\ {
\ "label":"__reduce__()",
\ "kind":3,
\ "detail":"object",
\ "documentation":"helper for pickle",
\ "sortText":"z__reduce__",
\ "insertText":"__reduce__"
\ },
\ {
\ "label":"__reduce_ex__()",
\ "kind":3,
\ "detail":"object",
\ "documentation":"helper for pickle",
\ "sortText":"z__reduce_ex__",
\ "insertText":"__reduce_ex__"
\ },
\ {
\ "label":"__repr__()",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Return repr(self).",
\ "sortText":"z__repr__",
\ "insertText":"__repr__"
\ },
\ {
\ "label":"__setattr__(name, value)",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Implement setattr(self, name, value).",
\ "sortText":"z__setattr__",
\ "insertText":"__setattr__"
\ },
\ {
\ "label":"__sizeof__()",
\ "kind":3,
\ "detail":"object",
\ "documentation":"__sizeof__() -> int\nsize of object in memory, in bytes",
\ "sortText":"z__sizeof__",
\ "insertText":"__sizeof__"
\ },
\ {
\ "label":"__str__()",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Return str(self).",
\ "sortText":"z__str__",
\ "insertText":"__str__"
\ },
\ {
\ "label":"__subclasshook__()",
\ "kind":3,
\ "detail":"object",
\ "documentation":"Abstract classes can override this to customize issubclass().\n\nThis is invoked early on by abc.ABCMeta.__subclasscheck__().\nIt should return True, False or NotImplemented.\u00a0\u00a0If it returns\nNotImplemented, the normal algorithm is used.\u00a0\u00a0Otherwise, it\noverrides the normal algorithm (and the outcome is cached).",
\ "sortText":"z__subclasshook__",
\ "insertText":"__subclasshook__"
\ }
\ ]
\ }
\ })
Execute(Should handle extra Python completion results correctly):
let g:ale_completion_autoimport = 0
let b:ale_completion_info = {
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
\ 'prefix': 'mig',
\}
AssertEqual
\ [
\ {'word': 'migrations', 'dup': 0, 'menu': 'xxx', 'info': 'migrations', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'MigEngine', 'dup': 0, 'menu': 'xxx', 'info': 'mig engine', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ ],
\ ale#completion#ParseLSPCompletions({
\ 'jsonrpc': '2.0',
\ 'id': 6,
\ 'result': {
\ 'isIncomplete': v:false,
\ 'items': [
\ {
\ 'label': 'migrations',
\ 'kind': 3,
\ 'detail': 'xxx',
\ 'documentation': 'migrations',
\ },
\ {
\ 'label': 'MigEngine',
\ 'kind': 3,
\ 'detail': 'xxx',
\ 'documentation': 'mig engine',
\ },
\ {
\ 'label': 'ignore me',
\ 'kind': 3,
\ 'detail': 'nope',
\ 'documentation': 'nope',
\ },
\ ]
\ }
\ })
Execute(Should handle missing keys):
let g:ale_completion_autoimport = 0
AssertEqual
\ [
\ {'word': 'x', 'dup': 0, 'menu': '', 'info': '', 'kind': 'v', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ ],
\ ale#completion#ParseLSPCompletions({
\ 'jsonrpc': '2.0',
\ 'id': 6,
\ 'result': {
\ 'isIncomplete': v:false,
\ 'items': [
\ {
\ 'label': 'x',
\ },
\ ]
\ }
\ })
Execute(Should handle documentation in the markdown format):
let g:ale_completion_autoimport = 0
AssertEqual
\ [
\ {'word': 'migrations', 'dup': 0, 'menu': 'xxx', 'info': 'Markdown documentation', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ ],
\ ale#completion#ParseLSPCompletions({
\ 'jsonrpc': '2.0',
\ 'id': 6,
\ 'result': {
\ 'isIncomplete': v:false,
\ 'items': [
\ {
\ 'label': 'migrations',
\ 'kind': 3,
\ 'detail': 'xxx',
\ 'documentation': {
\ 'kind': 'markdown',
\ 'value': 'Markdown documentation',
\ },
\ },
\ ],
\ },
\ })
Execute(Should handle completion messages with textEdit objects):
let g:ale_completion_autoimport = 0
AssertEqual
\ [
\ {'word': 'next_callback', 'dup': 0, 'menu': 'PlayTimeCallback', 'info': '', 'kind': 'v', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ ],
\ ale#completion#ParseLSPCompletions({
\ 'id': 226,
\ 'jsonrpc': '2.0',
\ 'result': {
\ 'isIncomplete': v:false,
\ 'items': [
\ {
\ 'detail': 'PlayTimeCallback',
\ 'filterText': 'next_callback',
\ 'insertText': 'ignoreme',
\ 'insertTextFormat': 1,
\ 'kind': 6,
\ 'label': ' next_callback',
\ 'sortText': '3ee19999next_callback',
\ 'textEdit': {
\ 'newText': 'next_callback',
\ 'range': {
\ 'end': {'character': 13, 'line': 12},
\ 'start': {'character': 4, 'line': 12},
\ },
\ },
\ },
\ ],
\ },
\ })
Execute(Should handle completion messages with textEdit objects and no insertTextFormat key):
let g:ale_completion_autoimport = 0
AssertEqual
\ [
\ {'word': 'next_callback', 'dup': 0, 'menu': 'PlayTimeCallback', 'info': '', 'kind': 'v', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ ],
\ ale#completion#ParseLSPCompletions({
\ 'id': 226,
\ 'jsonrpc': '2.0',
\ 'result': {
\ 'isIncomplete': v:false,
\ 'items': [
\ {
\ 'detail': 'PlayTimeCallback',
\ 'filterText': 'next_callback',
\ 'insertText': 'ignoreme',
\ 'kind': 6,
\ 'label': ' next_callback',
\ 'sortText': '3ee19999next_callback',
\ 'textEdit': {
\ 'newText': 'next_callback',
\ 'range': {
\ 'end': {'character': 13, 'line': 12},
\ 'start': {'character': 4, 'line': 12},
\ },
\ },
\ },
\ ],
\ },
\ })
Execute(Should handle completion messages with the deprecated insertText attribute):
let g:ale_completion_autoimport = 0
AssertEqual
\ [
\ {'word': 'next_callback', 'dup': 0, 'menu': 'PlayTimeCallback', 'info': '', 'kind': 'v', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ ],
\ ale#completion#ParseLSPCompletions({
\ 'id': 226,
\ 'jsonrpc': '2.0',
\ 'result': {
\ 'isIncomplete': v:false,
\ 'items': [
\ {
\ 'detail': 'PlayTimeCallback',
\ 'filterText': 'next_callback',
\ 'insertText': 'next_callback',
\ 'insertTextFormat': 1,
\ 'kind': 6,
\ 'label': ' next_callback',
\ 'sortText': '3ee19999next_callback',
\ },
\ ],
\ },
\ })
Execute(Should handle completion messages with additionalTextEdits when ale_completion_autoimport is turned on):
let g:ale_completion_autoimport = 1
AssertEqual
\ [
\ {
\ 'word': 'next_callback',
\ 'dup': 1,
\ 'menu': 'PlayTimeCallback',
\ 'info': '',
\ 'kind': 'v',
\ 'icase': 1,
\ 'user_data': json_encode({
\ '_ale_completion_item': 1,
\ 'code_actions': [
\ {
\ 'description': 'completion',
\ 'changes': [
\ {
\ 'fileName': expand('#' . bufnr('') . ':p'),
\ 'textChanges': [
\ {
\ 'start': {
\ 'line': 11,
\ 'offset': 2,
\ },
\ 'end': {
\ 'line': 13,
\ 'offset': 4,
\ },
\ 'newText': 'from "module" import next_callback',
\ },
\ ],
\ },
\ ],
\ },
\ ],
\ }),
\ },
\ ],
\ ale#completion#ParseLSPCompletions({
\ 'id': 226,
\ 'jsonrpc': '2.0',
\ 'result': {
\ 'isIncomplete': v:false,
\ 'items': [
\ {
\ 'detail': 'PlayTimeCallback',
\ 'filterText': 'next_callback',
\ 'insertText': 'next_callback',
\ 'insertTextFormat': 1,
\ 'kind': 6,
\ 'label': ' next_callback',
\ 'sortText': '3ee19999next_callback',
\ 'additionalTextEdits': [
\ {
\ 'range': {
\ 'start': {
\ 'line': 10,
\ 'character': 1,
\ },
\ 'end': {
\ 'line': 12,
\ 'character': 3,
\ },
\ },
\ 'newText': 'from "module" import next_callback',
\ },
\ ],
\ },
\ ],
\ },
\ })
Execute(Should not handle completion messages with additionalTextEdits when ale_completion_autoimport is turned off):
let g:ale_completion_autoimport = 0
let b:ale_completion_info = {'line': 30}
AssertEqual
\ [],
\ ale#completion#ParseLSPCompletions({
\ 'id': 226,
\ 'jsonrpc': '2.0',
\ 'result': {
\ 'isIncomplete': v:false,
\ 'items': [
\ {
\ 'detail': 'PlayTimeCallback',
\ 'filterText': 'next_callback',
\ 'insertText': 'next_callback',
\ 'insertTextFormat': 1,
\ 'kind': 6,
\ 'label': ' next_callback',
\ 'sortText': '3ee19999next_callback',
\ 'additionalTextEdits': [
\ {
\ 'range': {
\ 'start': {
\ 'line': 10,
\ 'character': 1,
\ },
\ 'end': {
\ 'line': 12,
\ 'character': 3,
\ },
\ },
\ 'newText': 'from "module" import next_callback',
\ },
\ ],
\ },
\ ],
\ },
\ })
Execute(Should still handle completion messages with empty additionalTextEdits with ale_completion_autoimport turned off):
let g:ale_completion_autoimport = 0
AssertEqual
\ [
\ {
\ 'word': 'next_callback',
\ 'dup': 0,
\ 'menu': 'PlayTimeCallback',
\ 'info': '',
\ 'kind': 'v',
\ 'icase': 1,
\ 'user_data': json_encode({'_ale_completion_item': 1}),
\ }
\ ],
\ ale#completion#ParseLSPCompletions({
\ 'id': 226,
\ 'jsonrpc': '2.0',
\ 'result': {
\ 'isIncomplete': v:false,
\ 'items': [
\ {
\ 'detail': 'PlayTimeCallback',
\ 'filterText': 'next_callback',
\ 'insertText': 'next_callback',
\ 'insertTextFormat': 1,
\ 'kind': 6,
\ 'label': ' next_callback',
\ 'sortText': '3ee19999next_callback',
\ 'additionalTextEdits': [],
\ },
\ ],
\ },
\ })

View File

@ -0,0 +1,60 @@
Before:
unlet! b:ale_completion_info
unlet! b:ale_completion_result
let b:lsp_started = 0
runtime autoload/ale/lsp_linter.vim
function! ale#lsp_linter#StartLSP(buffer, linter, Callback) abort
return b:lsp_started
endfunction
function! SetCompletionResult(...) abort
let b:ale_completion_result = ['foo']
endfunction
function! SetCompletionResponse(...) abort
let b:ale_completion_result = ['foo']
endfunction
After:
unlet! b:ale_completion_info
unlet! b:ale_completion_result
unlet! b:lsp_started
delfunction SetCompletionResult
delfunction SetCompletionResponse
runtime autoload/ale/lsp_linter.vim
call ale#linter#Reset()
Given typescript():
let abc = y.
let foo = ab
let foo = (ab)
Execute(-3 should be returned when completion results cannot be requested):
AssertEqual -3, ale#completion#OmniFunc(1, '')
Execute(The start position should be returned when results can be requested):
let b:lsp_started = 1
call setpos('.', [bufnr(''), 3, 14, 0])
AssertEqual 11, ale#completion#OmniFunc(1, '')
Execute(The omnifunc function should return async results):
" Neovim 0.2.0 and 0.4.4 struggles at running these tests.
if !has('nvim')
call timer_start(0, function('SetCompletionResult'))
AssertEqual ['foo'], ale#completion#OmniFunc(0, '')
endif
Execute(The omnifunc function should parse and return async responses):
if !has('nvim')
call timer_start(0, function('SetCompletionResponse'))
AssertEqual ['foo'], ale#completion#OmniFunc(0, '')
endif

View File

@ -0,0 +1,47 @@
Before:
call ale#linter#Reset()
unlet! b:ale_linters
unlet! b:ale_completion_info
unlet! b:ale_completion_result
After:
call ale#linter#Reset()
unlet! b:ale_linters
unlet! b:ale_completion_info
unlet! b:ale_completion_result
Execute(ale#completion#GetCompletionResult() should return v:null when there are no results):
AssertEqual v:null, ale#completion#GetCompletionResult()
Execute(ale#completion#GetCompletionResult() should return a result computed previously):
let b:ale_completion_result = [1]
AssertEqual [1], ale#completion#GetCompletionResult()
Execute(ale#completion#GetCompletionPosition() should return 0 when there is no completion information):
AssertEqual 0, ale#completion#GetCompletionPosition()
Given python(Some Python file):
foo bar
Execute(ale#completion#GetCompletionPosition() should return the position in the file when information is available):
let b:ale_completion_info = {'line': 1, 'column': 6}
" This is the first character of 'bar'
AssertEqual 4, ale#completion#GetCompletionPosition()
Execute(ale#completion#GetCompletionPositionForDeoplete() should return the position on the given input string):
" This is the first character of 'bar'
AssertEqual 4, ale#completion#GetCompletionPositionForDeoplete('foo bar')
Execute(ale#completion#CanProvideCompletions should return 0 when no completion sources are available):
let b:ale_linters = ['flake8']
AssertEqual 0, ale#completion#CanProvideCompletions()
Execute(ale#completion#CanProvideCompletions should return 1 when at least one completion source is available):
runtime ale_linters/python/pylsp.vim
let b:ale_linters = ['pylsp']
AssertEqual 1, ale#completion#CanProvideCompletions()

View File

@ -0,0 +1,309 @@
Before:
Save g:ale_completion_tsserver_remove_warnings
let g:ale_completion_tsserver_remove_warnings = 0
After:
Restore
unlet! b:ale_tsserver_completion_names
Execute(TypeScript completions responses should be parsed correctly):
AssertEqual [],
\ ale#completion#ParseTSServerCompletions({
\ 'body': [],
\})
AssertEqual
\ [
\ {
\ 'word': 'foo',
\ 'source': '/path/to/foo.ts',
\ },
\ {
\ 'word': 'bar',
\ 'source': '',
\ },
\ {
\ 'word': 'baz',
\ 'source': '',
\ }
\ ],
\ ale#completion#ParseTSServerCompletions({
\ 'body': [
\ {'name': 'foo', 'source': '/path/to/foo.ts'},
\ {'name': 'bar'},
\ {'name': 'baz'},
\ ],
\})
Execute(TypeScript completions responses should include warnings):
AssertEqual
\ [
\ {
\ 'word': 'foo',
\ 'source': '/path/to/foo.ts',
\ },
\ {
\ 'word': 'bar',
\ 'source': '',
\ },
\ {
\ 'word': 'baz',
\ 'source': '',
\ }
\ ],
\ ale#completion#ParseTSServerCompletions({
\ 'body': [
\ {'name': 'foo', 'source': '/path/to/foo.ts'},
\ {'name': 'bar', 'kind': 'warning'},
\ {'name': 'baz'},
\ ],
\})
Execute(TypeScript completions responses should not include warnings if excluded):
let g:ale_completion_tsserver_remove_warnings = 1
AssertEqual
\ [
\ {
\ 'word': 'foo',
\ 'source': '/path/to/foo.ts',
\ },
\ {
\ 'word': 'baz',
\ 'source': '',
\ }
\ ],
\ ale#completion#ParseTSServerCompletions({
\ 'body': [
\ {'name': 'foo', 'source': '/path/to/foo.ts'},
\ {'name': 'bar', 'kind': 'warning'},
\ {'name': 'baz'},
\ ],
\})
Execute(TypeScript completion details responses should be parsed correctly):
AssertEqual
\ [
\ {
\ 'word': 'abc',
\ 'menu': '(property) Foo.abc: number',
\ 'info': '',
\ 'kind': 'v',
\ 'icase': 1,
\ 'user_data': json_encode({'_ale_completion_item': 1}),
\ 'dup': g:ale_completion_autoimport,
\ },
\ {
\ 'word': 'def',
\ 'menu': '(property) Foo.def: number',
\ 'info': 'foo bar baz',
\ 'kind': 'v',
\ 'icase': 1,
\ 'user_data': json_encode({'_ale_completion_item': 1}),
\ 'dup': g:ale_completion_autoimport,
\ },
\ {
\ 'word': 'ghi',
\ 'menu': '(class) Foo',
\ 'info': '',
\ 'kind': 'v',
\ 'icase': 1,
\ 'user_data': json_encode({'_ale_completion_item': 1}),
\ 'dup': g:ale_completion_autoimport,
\ },
\ ],
\ ale#completion#ParseTSServerCompletionEntryDetails({
\ 'body': [
\ {
\ 'name': 'abc',
\ 'kind': 'parameterName',
\ 'displayParts': [
\ {'text': '('},
\ {'text': 'property'},
\ {'text': ')'},
\ {'text': ' '},
\ {'text': 'Foo'},
\ {'text': '.'},
\ {'text': 'abc'},
\ {'text': ':'},
\ {'text': ' '},
\ {'text': 'number'},
\ ],
\ },
\ {
\ 'name': 'def',
\ 'kind': 'parameterName',
\ 'displayParts': [
\ {'text': '('},
\ {'text': 'property'},
\ {'text': ')'},
\ {'text': ' '},
\ {'text': 'Foo'},
\ {'text': '.'},
\ {'text': 'def'},
\ {'text': ':'},
\ {'text': ' '},
\ {'text': 'number'},
\ ],
\ 'documentation': [
\ {'text': 'foo'},
\ {'text': ' '},
\ {'text': 'bar'},
\ {'text': ' '},
\ {'text': 'baz'},
\ ],
\ },
\ {
\ 'name': 'ghi',
\ 'kind': 'className',
\ 'displayParts': [
\ {'text': '('},
\ {'text': 'class'},
\ {'text': ')'},
\ {'text': ' '},
\ {'text': 'Foo'},
\ ],
\ },
\ ],
\})
Execute(Entries without details should be included in the responses):
let b:ale_tsserver_completion_names = [{
\ 'word': 'xyz',
\ 'source': '/path/to/xyz.ts',
\ }]
AssertEqual
\ [
\ {
\ 'word': 'abc',
\ 'menu': 'import { def } from "./Foo"; (property) Foo.abc: number',
\ 'info': '',
\ 'kind': 'v',
\ 'icase': 1,
\ 'user_data': json_encode({
\ '_ale_completion_item': 1,
\ 'code_actions': [{
\ 'description': 'import { def } from "./Foo";',
\ 'changes': [],
\ }],
\ }),
\ 'dup': g:ale_completion_autoimport,
\ },
\ {
\ 'word': 'def',
\ 'menu': '(property) Foo.def: number',
\ 'info': 'foo bar baz',
\ 'kind': 'v',
\ 'icase': 1,
\ 'user_data': json_encode({'_ale_completion_item': 1}),
\ 'dup': g:ale_completion_autoimport,
\ },
\ {
\ 'word': 'xyz',
\ 'menu': '',
\ 'info': '',
\ 'kind': 'v',
\ 'user_data': json_encode({'_ale_completion_item': 1}),
\ 'icase': 1,
\ },
\ ],
\ ale#completion#ParseTSServerCompletionEntryDetails({
\ 'body': [
\ {
\ 'name': 'abc',
\ 'kind': 'parameterName',
\ 'displayParts': [
\ {'text': '('},
\ {'text': 'property'},
\ {'text': ')'},
\ {'text': ' '},
\ {'text': 'Foo'},
\ {'text': '.'},
\ {'text': 'abc'},
\ {'text': ':'},
\ {'text': ' '},
\ {'text': 'number'},
\ ],
\ 'codeActions': [{
\ 'description': 'import { def } from "./Foo";',
\ 'changes': [],
\ }],
\ },
\ {
\ 'name': 'def',
\ 'kind': 'parameterName',
\ 'displayParts': [
\ {'text': '('},
\ {'text': 'property'},
\ {'text': ')'},
\ {'text': ' '},
\ {'text': 'Foo'},
\ {'text': '.'},
\ {'text': 'def'},
\ {'text': ':'},
\ {'text': ' '},
\ {'text': 'number'},
\ ],
\ 'documentation': [
\ {'text': 'foo'},
\ {'text': ' '},
\ {'text': 'bar'},
\ {'text': ' '},
\ {'text': 'baz'},
\ ],
\ },
\ ],
\})
Execute(Default imports should be handled correctly):
AssertEqual
\ [
\ {
\ 'word': 'abcd',
\ 'menu': 'Import default ''abcd'' from module "./foo" (alias) const abcd: 3',
\ 'info': '',
\ 'kind': 't',
\ 'icase': 1,
\ 'user_data': json_encode({
\ '_ale_completion_item': 1,
\ 'code_actions': [{
\ 'description': 'Import default ''abcd'' from module "./foo"',
\ 'changes': [],
\ }],
\ }),
\ 'dup': g:ale_completion_autoimport,
\ },
\ ],
\ ale#completion#ParseTSServerCompletionEntryDetails({
\ 'body': [
\ {
\ 'name': 'default',
\ 'kind': 'alias',
\ 'displayParts': [
\ {'kind': 'punctuation', 'text': '('},
\ {'kind': 'text', 'text': 'alias'},
\ {'kind': 'punctuation', 'text': ')'},
\ {'kind': 'space', 'text': ' '},
\ {'kind': 'keyword', 'text': 'const'},
\ {'kind': 'space', 'text': ' '},
\ {'kind': 'localName', 'text': 'abcd'},
\ {'kind': 'punctuation', 'text': ':'},
\ {'kind': 'space', 'text': ' '},
\ {'kind': 'stringLiteral', 'text': '3'},
\ {'kind': 'lineBreak', 'text': '^@'},
\ {'kind': 'keyword', 'text': 'export'},
\ {'kind': 'space', 'text': ' '},
\ {'kind': 'keyword', 'text': 'default'},
\ {'kind': 'space', 'text': ' '},
\ {'kind': 'aliasName', 'text': 'abcd'}
\ ],
\ 'codeActions': [
\ {
\ 'description': 'Import default ''abcd'' from module "./foo"',
\ 'changes': [],
\ },
\ ],
\ },
\ ],
\ })

View File

@ -0,0 +1,884 @@
Before:
Save g:ale_fixers
Save &shell
Save g:ale_enabled
Save g:ale_fix_on_save
Save g:ale_lint_on_save
Save g:ale_echo_cursor
Save g:ale_command_wrapper
Save g:ale_filename_mappings
silent! cd /testplugin/test/fix
unlet! b:ale_lint_on_save
let g:ale_enabled = 0
let g:ale_echo_cursor = 0
let g:ale_command_wrapper = ''
let g:ale_run_synchronously = 1
let g:ale_set_lists_synchronously = 1
let g:ale_fix_buffer_data = {}
let g:ale_fixers = {
\ 'testft': [],
\}
let g:ale_filename_mappings = {}
let g:pre_success = 0
let g:post_success = 0
augroup VaderTest
autocmd!
autocmd User ALEFixPre let g:pre_success = 1
autocmd User ALEFixPost let g:post_success = 1
augroup END
if !has('win32')
let &shell = '/bin/bash'
endif
call ale#test#SetDirectory('/testplugin/test')
call ale#test#SetFilename('test.txt')
call ale#linter#PreventLoading('testft')
function AddCarets(buffer, lines) abort
" map() is applied to the original lines here.
" This way, we can ensure that defensive copies are made.
return map(a:lines, '''^'' . v:val')
endfunction
function Capitalize(buffer, lines) abort
return map(a:lines, 'toupper(v:val)')
endfunction
function DoNothing(buffer, lines) abort
return 0
endfunction
function CatLine(buffer, lines) abort
return {'command': 'cat - <(echo d)'}
endfunction
function CatLineOneArg(buffer) abort
return {'command': 'cat - <(echo d)'}
endfunction
function CatLineDeferred(buffer, lines) abort
return ale#command#Run(a:buffer, 'echo', {
\ -> ale#command#Run(a:buffer, 'echo', {-> {'command': 'cat - <(echo d)'}})
\})
endfunction
function ReplaceWithTempFile(buffer, lines) abort
return {'command': 'echo x > %t', 'read_temporary_file': 1}
endfunction
function CatWithTempFile(buffer, lines) abort
return {'command': 'cat %t <(echo d)'}
endfunction
function EchoFilename(buffer, lines) abort
return {'command': 'echo %s'}
endfunction
function RemoveLastLine(buffer, lines) abort
return ['a', 'b']
endfunction
function RemoveLastLineOneArg(buffer) abort
return ['a', 'b']
endfunction
function! TestCallback(buffer, output)
return [{'lnum': 1, 'col': 1, 'text': 'xxx'}]
endfunction
" echo will output a single blank line, and we should ingore it.
function! IgnoredEmptyOutput(buffer, output)
return {'command': has('win32') ? 'echo(' : 'echo'}
endfunction
function! EchoLineNoPipe(buffer, output)
return {'command': 'echo new line', 'read_buffer': 0}
endfunction
function! SetUpLinters()
call ale#linter#Define('testft', {
\ 'name': 'testlinter',
\ 'callback': 'TestCallback',
\ 'executable': 'true',
\ 'command': 'true',
\})
endfunction
function GetLastMessage()
redir => l:output
silent mess
redir END
let l:lines = split(l:output, "\n")
return empty(l:lines) ? '' : l:lines[-1]
endfunction
function! FixWithJSONPostProcessing(buffer) abort
let l:ProcessWith = 'JSONPostProcessor'
" Test with lambdas where support is available.
if has('lambda')
let l:ProcessWith = {buffer, output -> JSONPostProcessor(buffer, output)}
endif
" Escaping needs to be handled specially for CMD on Windows.
let l:json_string = has('win32')
\ ? '{"output":["x","y","z"]}'
\ : ale#Escape('{"output": ["x", "y", "z"]}')
return {
\ 'command': 'echo ' . l:json_string,
\ 'read_buffer': 0,
\ 'process_with': l:ProcessWith,
\}
endfunction
function! JSONPostProcessor(buffer, output) abort
return json_decode(a:output[0]).output
endfunction
After:
Restore
unlet! g:test_filename
unlet! g:ale_run_synchronously
unlet! g:ale_set_lists_synchronously
unlet! g:ale_run_synchronously_callbacks
unlet! g:ale_emulate_job_failure
unlet! b:ale_fixers
unlet! b:ale_lint_on_save
unlet! b:ale_fix_on_save
unlet! b:ale_quitting
delfunction AddCarets
delfunction Capitalize
delfunction DoNothing
delfunction CatLine
delfunction CatLineOneArg
delfunction CatLineDeferred
delfunction ReplaceWithTempFile
delfunction CatWithTempFile
delfunction EchoFilename
delfunction RemoveLastLine
delfunction RemoveLastLineOneArg
delfunction TestCallback
delfunction SetUpLinters
delfunction GetLastMessage
delfunction IgnoredEmptyOutput
delfunction EchoLineNoPipe
delfunction FixWithJSONPostProcessing
delfunction JSONPostProcessor
augroup VaderTest
autocmd!
augroup END
augroup! VaderTest
call ale#test#RestoreDirectory()
call ale#fix#registry#ResetToDefaults()
call ale#linter#Reset()
setlocal buftype=nofile
if exists('g:test_filename') && filereadable(g:test_filename)
call delete(g:test_filename)
endif
call setloclist(0, [])
let g:ale_fix_buffer_data = {}
" Clear the messages between tests.
echomsg ''
if !exists('g:ale_command_wrapper')
let g:ale_command_wrapper = ''
endif
Given testft (A file with three lines):
a
b
c
Execute(ALEFix should complain when there are no functions to call):
ALEFix
call ale#test#FlushJobs()
AssertEqual 'No fixers have been defined. Try :ALEFixSuggest', GetLastMessage()
Execute(ALEFix should not complain when the command is run with a bang):
echom 'none'
ALEFix!
call ale#test#FlushJobs()
AssertEqual 'none', GetLastMessage()
Execute(ALEFix should apply simple functions):
let g:ale_fixers.testft = ['AddCarets']
ALEFix
call ale#test#FlushJobs()
Expect(The first function should be used):
^a
^b
^c
Execute(Should apply filename mpapings):
" The command echos %s, and we'll map the current path so we can check
" that ALEFix applies filename mappings, end-to-end.
let g:ale_filename_mappings = {
\ 'echo_filename': [
\ [expand('%:p:h') . '/', '/some/fake/path/'],
\ ],
\}
call ale#fix#registry#Add('echo_filename', 'EchoFilename', [], 'echo filename')
let g:ale_fixers.testft = ['echo_filename']
ALEFix
call ale#test#FlushJobs()
" Remote trailing whitespace from the line.
call setline(1, substitute(getline(1), '[ \r]\+$', '', ''))
Expect(The mapped filename should be printed):
/some/fake/path/test.txt
Execute(ALEFix should apply simple functions in a chain):
let g:ale_fixers.testft = ['AddCarets', 'Capitalize']
ALEFix
call ale#test#FlushJobs()
Expect(Both functions should be used):
^A
^B
^C
Execute(ALEFix should allow 0 to be returned to skip functions):
let g:ale_fixers.testft = ['DoNothing', 'Capitalize']
ALEFix
call ale#test#FlushJobs()
Expect(Only the second function should be applied):
A
B
C
Execute(The * fixers shouldn't be used if an empty list is set for fixers):
let g:ale_fixers.testft = []
let g:ale_fixers['*'] = ['Capitalize']
ALEFix
call ale#test#FlushJobs()
Expect(Nothing should be changed):
a
b
c
Execute(* fixers should be used if no filetype is matched):
let g:ale_fixers = {'*': ['Capitalize']}
ALEFix
call ale#test#FlushJobs()
Expect(The file should be changed):
A
B
C
Execute(ALEFix should allow commands to be run):
if has('win32')
" Just skip this test on Windows, we can't run it.
call setline(1, ['a', 'b', 'c', 'd'])
else
let g:ale_fixers.testft = ['CatLine']
ALEFix
call ale#test#FlushJobs()
endif
Expect(An extra line should be added):
a
b
c
d
Execute(ALEFix should use fixers passed in commandline when provided):
let g:ale_fixers.testft = ['RemoveLastLine']
ALEFix AddCarets Capitalize
call ale#test#FlushJobs()
Expect(Only fixers passed via command line should be run):
^A
^B
^C
Execute(ALEFix should allow temporary files to be read):
if has('win32')
" Just skip this test on Windows, we can't run it.
call setline(1, ['x'])
2,3d
else
let g:ale_fixers.testft = ['ReplaceWithTempFile']
ALEFix
call ale#test#FlushJobs()
endif
Expect(The line we wrote to the temporary file should be used here):
x
Execute(ALEFix should not read the temporary file when the option is not set):
if has('win32')
" Just skip this test on Windows, we can't run it.
call setline(1, ['a', 'b', 'c', 'd'])
else
let g:ale_fixers.testft = ['CatWithTempFile']
ALEFix
call ale#test#FlushJobs()
endif
Expect(An extra line should be added):
a
b
c
d
Execute(ALEFix should allow jobs and simple functions to be combined):
if has('win32')
" Just skip this test on Windows, we can't run it.
call setline(1, ['X'])
2,3d
else
let g:ale_fixers.testft = ['ReplaceWithTempFile', 'Capitalize']
ALEFix
call ale#test#FlushJobs()
endif
Expect(The lines from the temporary file should be modified):
X
Execute(ALEFix should send lines modified by functions to jobs):
if has('win32')
" Just skip this test on Windows, we can't run it.
call setline(1, ['A', 'B', 'C', 'd'])
else
let g:ale_fixers.testft = ['Capitalize', 'CatLine']
ALEFix
call ale#test#FlushJobs()
endif
Expect(The lines should first be modified by the function, then the job):
A
B
C
d
Execute(ALEFix should skip commands when jobs fail to run):
let g:ale_emulate_job_failure = 1
let g:ale_fixers.testft = ['CatLine', 'Capitalize']
ALEFix
call ale#test#FlushJobs()
Expect(Only the second function should be applied):
A
B
C
Execute(ALEFix should handle strings for selecting a single function):
let g:ale_fixers.testft = 'AddCarets'
ALEFix
call ale#test#FlushJobs()
Expect(The first function should be used):
^a
^b
^c
Execute(ALEFix should use functions from the registry):
call ale#fix#registry#Add('add_carets', 'AddCarets', [], 'Add some carets')
let g:ale_fixers.testft = ['add_carets']
ALEFix
call ale#test#FlushJobs()
Expect(The registry function should be used):
^a
^b
^c
Execute(ALEFix should be able to remove the last line for files):
let g:ale_fixers.testft = ['RemoveLastLine']
ALEFix
call ale#test#FlushJobs()
Expect(There should be only two lines):
a
b
Execute(ALEFix should accept funcrefs):
let g:ale_fixers.testft = [function('RemoveLastLine')]
ALEFix
call ale#test#FlushJobs()
Expect(There should be only two lines):
a
b
Execute(ALEFix should accept lambdas):
if has('nvim')
" NeoVim 0.1.7 can't interpret lambdas correctly, so just set the lines
" to make the test pass.
call setline(1, ['a', 'b', 'c', 'd'])
else
let g:ale_fixers.testft = [{buffer, lines -> lines + ['d']}]
ALEFix
call ale#test#FlushJobs()
endif
Expect(There should be an extra line):
a
b
c
d
Execute(ALEFix should user buffer-local fixer settings):
let g:ale_fixers.testft = ['AddCarets', 'Capitalize']
let b:ale_fixers = {'testft': ['RemoveLastLine']}
ALEFix
call ale#test#FlushJobs()
Expect(There should be only two lines):
a
b
Execute(ALEFix should allow Lists to be used for buffer-local fixer settings):
let g:ale_fixers.testft = ['AddCarets', 'Capitalize']
let b:ale_fixers = ['RemoveLastLine']
ALEFix
call ale#test#FlushJobs()
Expect(There should be only two lines):
a
b
Given testft (A file with three lines):
a
b
c
Execute(ALEFix should fix files on the save event):
let g:ale_fix_on_save = 1
let g:ale_lint_on_save = 1
let g:ale_enabled = 1
let g:test_filename = tempname()
execute 'noautocmd silent file ' . fnameescape(g:test_filename)
call writefile(getline(1, '$'), g:test_filename)
let g:ale_fixers.testft = ['Capitalize']
" We have to set the buftype to empty so the file will be written.
setlocal buftype=
call SetUpLinters()
call ale#events#SaveEvent(bufnr(''))
call ale#test#FlushJobs()
" We should save the file.
AssertEqual ['A', 'B', 'C'], readfile(g:test_filename)
Assert !&modified, 'The file was marked as ''modified'''
if !has('win32')
" We should have run the linter.
AssertEqual [{
\ 'bufnr': bufnr('%'),
\ 'lnum': 1,
\ 'vcol': 0,
\ 'col': 1,
\ 'text': 'xxx',
\ 'type': 'E',
\ 'nr': -1,
\ 'pattern': '',
\ 'valid': 1,
\}], ale#test#GetLoclistWithoutNewerKeys()
endif
Expect(The buffer should be modified):
A
B
C
Given testft (A file with three lines):
a
b
c
Execute(ALEFix should run the linters with b:ale_lint_on_save = 1):
let g:ale_fix_on_save = 0
let b:ale_fix_on_save = 1
let g:ale_lint_on_save = 1
let g:ale_enabled = 1
let g:test_filename = tempname()
execute 'noautocmd silent file ' . fnameescape(g:test_filename)
call writefile(getline(1, '$'), g:test_filename)
let g:ale_fixers.testft = ['Capitalize']
" We have to set the buftype to empty so the file will be written.
setlocal buftype=
call SetUpLinters()
call ale#events#SaveEvent(bufnr(''))
call ale#test#FlushJobs()
" We should save the file.
AssertEqual ['A', 'B', 'C'], readfile(g:test_filename)
Assert !&modified, 'The file was marked as ''modified'''
if !has('win32')
" We should have run the linter.
AssertEqual [{
\ 'bufnr': bufnr('%'),
\ 'lnum': 1,
\ 'vcol': 0,
\ 'col': 1,
\ 'text': 'xxx',
\ 'type': 'E',
\ 'nr': -1,
\ 'pattern': '',
\ 'valid': 1,
\}], ale#test#GetLoclistWithoutNewerKeys()
endif
Expect(The buffer should be modified):
A
B
C
Execute(ALEFix should not fix files on :wq):
let g:ale_fix_on_save = 1
let g:ale_lint_on_save = 1
let g:ale_enabled = 1
let g:test_filename = tempname()
execute 'noautocmd silent file ' . fnameescape(g:test_filename)
call writefile(getline(1, '$'), g:test_filename)
let g:ale_fixers.testft = ['Capitalize']
" We have to set the buftype to empty so the file will be written.
setlocal buftype=
call ale#events#QuitEvent(bufnr(''))
call SetUpLinters()
call ale#events#SaveEvent(bufnr(''))
" We should save the file.
AssertEqual ['a', 'b', 'c'], readfile(g:test_filename)
Assert &modified, 'The was not marked as ''modified'''
" We should not run the linter.
AssertEqual [], ale#test#GetLoclistWithoutNewerKeys()
Expect(The buffer should not be modified):
a
b
c
Given testft (A file with three lines):
a
b
c
Execute(ALEFix should still lint with no linters to be applied):
let g:ale_fix_on_save = 1
let g:ale_lint_on_save = 1
let g:ale_enabled = 1
let g:test_filename = tempname()
execute 'noautocmd silent file ' . fnameescape(g:test_filename)
let g:ale_fixers.testft = []
call SetUpLinters()
call ale#events#SaveEvent(bufnr(''))
call ale#test#FlushJobs()
Assert !filereadable(g:test_filename), 'The file should not have been saved'
if !has('win32')
" We have run the linter.
AssertEqual [{
\ 'bufnr': bufnr('%'),
\ 'lnum': 1,
\ 'vcol': 0,
\ 'col': 1,
\ 'text': 'xxx',
\ 'type': 'E',
\ 'nr': -1,
\ 'pattern': '',
\ 'valid': 1,
\}], ale#test#GetLoclistWithoutNewerKeys()
endif
Expect(The buffer should be the same):
a
b
c
Execute(ALEFix should still lint when nothing was fixed on save):
let g:ale_fix_on_save = 1
let g:ale_lint_on_save = 1
let g:ale_enabled = 1
let g:test_filename = tempname()
execute 'noautocmd silent file ' . fnameescape(g:test_filename)
let g:ale_fixers.testft = ['DoNothing']
call SetUpLinters()
call ale#events#SaveEvent(bufnr(''))
call ale#test#FlushJobs()
Assert !filereadable(g:test_filename), 'The file should not have been saved'
if !has('win32')
" We should have run the linter.
AssertEqual [{
\ 'bufnr': bufnr('%'),
\ 'lnum': 1,
\ 'vcol': 0,
\ 'col': 1,
\ 'text': 'xxx',
\ 'type': 'E',
\ 'nr': -1,
\ 'pattern': '',
\ 'valid': 1,
\}], ale#test#GetLoclistWithoutNewerKeys()
endif
Expect(The buffer should be the same):
a
b
c
Execute(ALEFix should not lint the buffer on save if linting on save is disabled globally):
let g:ale_fix_on_save = 1
let g:ale_lint_on_save = 0
let g:ale_enabled = 1
let g:test_filename = tempname()
execute 'noautocmd silent file ' . fnameescape(g:test_filename)
let g:ale_fixers.testft = ['DoNothing']
call SetUpLinters()
call ale#events#SaveEvent(bufnr(''))
call ale#test#FlushJobs()
Assert !filereadable(g:test_filename), 'The file should not have been saved'
AssertEqual [], ale#test#GetLoclistWithoutNewerKeys()
Expect(The buffer should be the same):
a
b
c
Execute(ALEFix should not lint the buffer on save if linting on save is disabled locally):
let g:ale_fix_on_save = 1
let b:ale_lint_on_save = 0
let g:ale_enabled = 1
let g:test_filename = tempname()
execute 'noautocmd silent file ' . fnameescape(g:test_filename)
let g:ale_fixers.testft = ['DoNothing']
call SetUpLinters()
call ale#events#SaveEvent(bufnr(''))
call ale#test#FlushJobs()
Assert !filereadable(g:test_filename), 'The file should not have been saved'
AssertEqual [], ale#test#GetLoclistWithoutNewerKeys()
Expect(The buffer should be the same):
a
b
c
Given testft (A file with three lines):
a
b
c
Execute(ale#fix#InitBufferData() should set up the correct data):
let g:test_filename = tempname()
execute 'noautocmd silent file ' . fnameescape(g:test_filename)
call ale#fix#InitBufferData(bufnr(''), 'save_file')
AssertEqual {
\ bufnr(''): {
\ 'temporary_directory_list': [],
\ 'done': 0,
\ 'lines_before': ['a', 'b', 'c'],
\ 'should_save': 1,
\ 'ignore_file_changed_errors': 0,
\ },
\}, g:ale_fix_buffer_data
call ale#fix#InitBufferData(bufnr(''), '!')
AssertEqual {
\ bufnr(''): {
\ 'temporary_directory_list': [],
\ 'done': 0,
\ 'lines_before': ['a', 'b', 'c'],
\ 'should_save': 0,
\ 'ignore_file_changed_errors': 1,
\ },
\}, g:ale_fix_buffer_data
Execute(ALEFix simple functions should be able to accept one argument, the buffer):
let g:ale_fixers.testft = ['RemoveLastLineOneArg']
ALEFix
call ale#test#FlushJobs()
Expect(There should be only two lines):
a
b
Execute(ALEFix should modify a buffer that is not modifiable, if it becomes modifiable later):
let g:ale_fixers.testft = ['RemoveLastLineOneArg']
set nomodifiable
ALEFix
call ale#test#FlushJobs()
set modifiable
call ale#fix#ApplyQueuedFixes(bufnr(''))
Expect(There should be only two lines):
a
b
Execute(b:ale_fix_on_save = 1 should override g:ale_fix_on_save = 0):
let g:ale_fix_on_save = 0
let b:ale_fix_on_save = 1
let g:ale_fixers.testft = ['RemoveLastLineOneArg']
call ale#events#SaveEvent(bufnr(''))
Expect(There should be only two lines):
a
b
Execute(b:ale_fix_on_save = 0 should override g:ale_fix_on_save = 1):
let g:ale_fix_on_save = 1
let b:ale_fix_on_save = 0
let g:ale_fixers.testft = ['RemoveLastLineOneArg']
call ale#events#SaveEvent(bufnr(''))
Expect(The lines should be the same):
a
b
c
Execute(ALEFix functions returning jobs should be able to accept one argument):
if has('win32')
" Just skip this test on Windows, we can't run it.
call setline(1, ['a', 'b', 'c', 'd'])
else
let g:ale_fixers.testft = ['CatLine']
ALEFix
call ale#test#FlushJobs()
endif
Expect(An extra line should be added):
a
b
c
d
Execute(ALE should print a message telling you something isn't a valid fixer when you type some nonsense):
let g:ale_fixers.testft = ['CatLine', 'invalidname']
ALEFix
call ale#test#FlushJobs()
AssertEqual 'There is no fixer named `invalidname`. Check :ALEFixSuggest', GetLastMessage()
Execute(ALE should complain about invalid fixers with minuses in the name):
let g:ale_fixers.testft = ['foo-bar']
ALEFix
call ale#test#FlushJobs()
AssertEqual 'There is no fixer named `foo-bar`. Check :ALEFixSuggest', GetLastMessage()
Execute(ALE should tolerate valid fixers with minuses in the name):
let g:ale_fixers.testft = ['prettier-standard']
ALEFix
call ale#test#FlushJobs()
Execute(Empty output should be ignored):
let g:ale_fixers.testft = ['IgnoredEmptyOutput']
ALEFix
call ale#test#FlushJobs()
Expect(The lines should be the same):
a
b
c
Execute(A temporary file shouldn't be piped into the command when disabled):
let g:ale_fixers.testft = ['EchoLineNoPipe']
ALEFix
call ale#test#FlushJobs()
AssertEqual
\ string(ale#job#PrepareCommand(bufnr(''), 'echo new line')),
\ string(ale#history#Get(bufnr(''))[-1].command)
" Remove trailing whitespace for Windows.
if has('win32')
%s/[[:space:]]*$//g
endif
Expect(The new line should be used):
new line
Execute(Post-processing should work):
let g:ale_fixers.testft = ['FixWithJSONPostProcessing']
ALEFix
call ale#test#FlushJobs()
Expect(The lines in the JSON should be used):
x
y
z
Execute(ALEFix should apply autocmds):
let g:ale_fixers.testft = ['AddCarets']
ALEFix
call ale#test#FlushJobs()
AssertEqual g:pre_success, 1
AssertEqual g:post_success, 1
Execute(ALEFix should support ale#command#Run):
if has('win32')
" Just skip this test on Windows, we can't run it.
call setline(1, ['a', 'b', 'c', 'd'])
else
let g:ale_fixers.testft = ['CatLineDeferred']
ALEFix
call ale#test#FlushJobs()
endif
Expect(The extra line should be added):
a
b
c
d

View File

@ -0,0 +1,5 @@
Execute(prettier-eslint should be aliased):
AssertEqual 'ale#fixers#prettier_eslint#Fix', ale#fix#registry#GetFunc('prettier-eslint')
Execute(prettier-standard should be aliased):
AssertEqual 'ale#fixers#prettier_standard#Fix', ale#fix#registry#GetFunc('prettier-standard')

View File

@ -0,0 +1,23 @@
Execute (List of available fixers is empty):
call ale#fix#registry#Clear()
Then (List of applicable fixers for python file is empty):
AssertEqual [], ale#fix#registry#GetApplicableFixers('python')
Execute (Add ruby fixer):
call ale#fix#registry#Add('ruby_fixer', 'fixer_fun', ['ruby'], 'ruby fixer')
Then (List of applicable fixers for python file is still empty):
AssertEqual [], ale#fix#registry#GetApplicableFixers('python')
Execute (Add generic fixer):
call ale#fix#registry#Add('generic_fixer', 'fixer_fun', [], 'generic fixer')
Then (Generic fixer should be returned as applicable for python file):
AssertEqual ['generic_fixer'], ale#fix#registry#GetApplicableFixers('python')
Execute (Add python fixer):
call ale#fix#registry#Add('python_fixer', 'fixer_func', ['python'], 'python fixer')
Then (List of fixers should contain both generic and python fixers):
AssertEqual ['generic_fixer', 'python_fixer'], ale#fix#registry#GetApplicableFixers('python')

View File

@ -0,0 +1,14 @@
Before:
call ale#fix#registry#Clear()
call ale#test#SetFilename('test.js')
call ale#fix#registry#Add('prettier', '', ['javascript'], 'prettier')
call ale#fix#registry#Add('eslint', '', ['javascript'], 'eslint')
setfiletype javascript
Execute(completeFixers returns all of the applicable fixers without an arglead):
AssertEqual ['eslint', 'prettier'],
\ ale#fix#registry#CompleteFixers('', 'ALEFix ', 7)
Execute(completeFixers returns all of the applicable fixers without an arglead):
AssertEqual ['prettier'],
\ ale#fix#registry#CompleteFixers('pre', 'ALEFix ', 10)

View File

@ -0,0 +1,110 @@
Before:
Save g:ale_fixers
Save g:ale_fix_on_save
Save g:ale_fix_on_save_ignore
let g:ale_fix_on_save = 1
let g:ale_fixers = {'abc': ['a', 'b'], 'xyz': ['c', 'd']}
unlet! b:ale_fixers
unlet! b:ale_fix_on_save_ignore
function FixerA(buffer, lines) abort
return a:lines + ['a']
endfunction
function FixerB(buffer, lines) abort
return a:lines + ['b']
endfunction
function FixerC(buffer, lines) abort
return a:lines + ['c']
endfunction
function FixerD(buffer, lines) abort
return a:lines + ['d']
endfunction
set filetype=abc.xyz
let g:test_filename = tempname()
execute 'noautocmd silent file ' . fnameescape(g:test_filename)
call ale#fix#registry#Add('a', 'FixerA', ['abc'], '')
call ale#fix#registry#Add('b', 'FixerB', ['abc'], '')
call ale#fix#registry#Add('c', 'FixerC', ['xyz'], '')
call ale#fix#registry#Add('d', 'FixerD', ['xyz'], '')
After:
Restore
if exists('g:test_filename') && filereadable(g:test_filename)
call delete(g:test_filename)
endif
unlet! b:ale_fixers
unlet! b:ale_fix_on_save_ignore
unlet! g:test_filename
delfunction FixerA
delfunction FixerB
delfunction FixerC
delfunction FixerD
call ale#fix#registry#ResetToDefaults()
Given abc.xyz (An empty file):
Execute(Ignoring with a filetype in a global Dictionary should work):
let g:ale_fix_on_save_ignore = {'abc': ['b'], 'xyz': ['c']}
call ale#events#SaveEvent(bufnr(''))
AssertEqual ['', 'a', 'd'], getline(1, '$')
Execute(Ignoring with a filetype in a global List should work):
let g:ale_fix_on_save_ignore = ['b', 'c']
call ale#events#SaveEvent(bufnr(''))
AssertEqual ['', 'a', 'd'], getline(1, '$')
Execute(Ignoring with a filetype in a local Dictionary should work):
let g:ale_fix_on_save_ignore = {'abc': ['b'], 'xyz': ['c']}
" The local Dictionary should entirely replace the global one.
let b:ale_fix_on_save_ignore = {'abc': ['b']}
call ale#events#SaveEvent(bufnr(''))
AssertEqual ['', 'a', 'c', 'd'], getline(1, '$')
Execute(Ignoring with a filetype in a local List should work):
let g:ale_fix_on_save_ignore = {'abc': ['b'], 'xyz': ['c']}
" The local List should entirely replace the global Dictionary.
let b:ale_fix_on_save_ignore = ['b']
call ale#events#SaveEvent(bufnr(''))
AssertEqual ['', 'a', 'c', 'd'], getline(1, '$')
Execute(Ignoring functions by reference with a Dictionary should work):
let g:ale_fixers = {
\ 'abc': [function('FixerA'), function('FixerB')],
\ 'xyz': [function('FixerC'), function('FixerD')],
\}
let b:ale_fix_on_save_ignore = {
\ 'abc': [function('FixerB')],
\ 'xyz': [function('FixerC')],
\}
call ale#events#SaveEvent(bufnr(''))
AssertEqual ['', 'a', 'd'], getline(1, '$')
Execute(Ignoring functions by reference with a List should work):
let g:ale_fixers = {
\ 'abc': [function('FixerA'), function('FixerB')],
\ 'xyz': [function('FixerC'), function('FixerD')],
\}
let b:ale_fix_on_save_ignore = [function('FixerB'), function('FixerC')]
call ale#events#SaveEvent(bufnr(''))
AssertEqual ['', 'a', 'd'], getline(1, '$')

View File

@ -0,0 +1,102 @@
Before:
call ale#fix#registry#Clear()
let g:buffer = bufnr('')
function GetSuggestions()
silent ALEFixSuggest
if bufnr('') != g:buffer
let l:lines = getline(1, '$')
else
let l:lines = []
endif
return l:lines
endfunction
After:
if bufnr('') != g:buffer
:q!
endif
unlet! g:buffer
call ale#fix#registry#ResetToDefaults()
delfunction GetSuggestions
Execute(ALEFixSuggest should return something sensible with no suggestions):
AssertEqual
\ [
\ 'There is nothing in the registry to suggest.',
\ '',
\ 'Press q to close this window',
\ ],
\ GetSuggestions()
Execute(ALEFixSuggest should set the appropriate settings):
silent ALEFixSuggest
AssertEqual 'ale-fix-suggest', &filetype
Assert !&modified, 'The buffer was marked as modified'
Assert !&modifiable, 'The buffer was modifiable'
Execute(ALEFixSuggest output should be correct for only generic handlers):
call ale#fix#registry#Add('zed', 'XYZ', [], 'Zedify things.')
call ale#fix#registry#Add('alpha', 'XYZ', [], 'Alpha things.')
AssertEqual
\ [
\ 'Try the following generic fixers:',
\ '',
\ '''alpha'' - Alpha things.',
\ '''zed'' - Zedify things.',
\ '',
\ 'See :help ale-fix-configuration',
\ '',
\ 'Press q to close this window',
\ ],
\ GetSuggestions()
Execute(ALEFixSuggest output should be correct for only filetype handlers):
let &filetype = 'testft2.testft'
call ale#fix#registry#Add('zed', 'XYZ', ['testft2'], 'Zedify things.')
call ale#fix#registry#Add('alpha', 'XYZ', ['testft'], 'Alpha things.')
AssertEqual
\ [
\ 'Try the following fixers appropriate for the filetype:',
\ '',
\ '''alpha'' - Alpha things.',
\ '''zed'' - Zedify things.',
\ '',
\ 'See :help ale-fix-configuration',
\ '',
\ 'Press q to close this window',
\ ],
\ GetSuggestions()
Execute(ALEFixSuggest should suggest filetype and generic handlers):
let &filetype = 'testft2.testft'
call ale#fix#registry#Add('zed', 'XYZ', ['testft2'], 'Zedify things.', ['foobar'])
call ale#fix#registry#Add('alpha', 'XYZ', ['testft'], 'Alpha things.')
call ale#fix#registry#Add('generic', 'XYZ', [], 'Generic things.')
AssertEqual
\ [
\ 'Try the following fixers appropriate for the filetype:',
\ '',
\ '''alpha'' - Alpha things.',
\ '''zed'', ''foobar'' - Zedify things.',
\ '',
\ 'Try the following generic fixers:',
\ '',
\ '''generic'' - Generic things.',
\ '',
\ 'See :help ale-fix-configuration',
\ '',
\ 'Press q to close this window',
\ ],
\ GetSuggestions()

View File

@ -0,0 +1,47 @@
Before:
call ale#assert#SetUpFixerTest('swift', 'apple-swift-format')
After:
call ale#assert#TearDownFixerTest()
Execute(The swiftformat callback should return the correct default values):
call ale#test#SetFilename('../test-files/swift/dummy.swift')
let g:ale_swift_appleswiftformat_executable = 'xxxinvalid'
let g:ale_swift_appleswiftformat_use_swiftpm = 0
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_swift_appleswiftformat_executable)
\ . ' format --in-place %t',
\ },
\ ale#fixers#appleswiftformat#Fix(bufnr(''))
Execute(The swiftformat callback should return the correct default values and located configuration):
call ale#test#SetDirectory('/testplugin/test/test-files/swift/swift-package-project-with-config')
call ale#test#SetFilename('src/folder/dummy.swift')
let g:ale_swift_appleswiftformat_executable = 'xxxinvalid'
let g:ale_swift_appleswiftformat_use_swiftpm = 0
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_swift_appleswiftformat_executable)
\ . ' format --in-place %t --configuration ' . glob(g:dir . '/.swift-format'),
\ },
\ ale#fixers#appleswiftformat#Fix(bufnr(''))
call ale#test#RestoreDirectory()
Execute(The swiftformat callback should use swiftpm is use_swiftpm is set to 1):
call ale#test#SetFilename('../test-files/swift/swift-package-project/src/folder/dummy.swift')
let g:ale_swift_appleswiftformat_use_swiftpm = 1
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('swift')
\ . ' run swift-format format --in-place %t',
\ },
\ ale#fixers#appleswiftformat#Fix(bufnr(''))

View File

@ -0,0 +1,96 @@
Before:
Save g:ale_c_astyle_executable
Save g:ale_c_astyle_project_options
Save g:ale_cpp_astyle_project_options
" Use an invalid global executable, so we don't match it.
let g:ale_c_astyle_executable = 'xxxinvalid'
let g:ale_cpp_astyle_executable = 'invalidpp'
let g:ale_c_astyle_project_options = ''
let g:ale_cpp_astyle_project_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The astyle callback should return the correct default values):
" Because this file doesn't exist, no astylrc config
" exists near it. Therefore, project_options is empty.
call ale#test#SetFilename('../c_files/testfile.c')
let targetfile = bufname(bufnr('%'))
AssertEqual
\ {
\ 'command': ale#Escape(g:ale_c_astyle_executable)
\ . ' --stdin=' . ale#Escape(targetfile)
\ },
\ ale#fixers#astyle#Fix(bufnr(''))
Execute(The astyle callback should support cpp files):
" Because this file doesn't exist, no astylrc config
" exists near it. Therefore, project_options is empty.
call ale#test#SetFilename('../cpp_files/dummy.cpp')
set filetype=cpp " The test fails without this
let targetfile = bufname(bufnr('%'))
AssertEqual
\ {
\ 'command': ale#Escape(g:ale_cpp_astyle_executable)
\ . ' --stdin=' . ale#Escape(targetfile)
\ },
\ ale#fixers#astyle#Fix(bufnr(''))
Execute(The astyle callback should support cpp files with option file set):
call ale#test#SetFilename('../cpp_files/dummy.cpp')
let g:ale_cpp_astyle_project_options = '.astylerc_cpp'
let targetfile = bufname(bufnr('%'))
set filetype=cpp " The test fails without this
AssertEqual
\ {
\ 'command': ale#Escape('invalidpp')
\ . ' --project=' . g:ale_cpp_astyle_project_options
\ . ' --stdin=' . ale#Escape(targetfile)
\ },
\ ale#fixers#astyle#Fix(bufnr(''))
Execute(The astyle callback should return the correct default values with a specified option file):
call ale#test#SetFilename('../c_files/testfile.c')
let g:ale_c_astyle_project_options = '.astylerc_c'
let targetfile = bufname(bufnr('%'))
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' --project=' . g:ale_c_astyle_project_options
\ . ' --stdin=' . ale#Escape(targetfile)
\ },
\ ale#fixers#astyle#Fix(bufnr(''))
Execute(The astyle callback should find nearest default option file _astylrc):
call ale#test#SetFilename('../test-files/c/makefile_project/subdir/file.c')
let targetfile = bufname(bufnr('%'))
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' --project=_astylerc'
\ . ' --stdin=' . ale#Escape(targetfile)
\ },
\ ale#fixers#astyle#Fix(bufnr(''))
Execute(The astyle callback should find .astylrc in the same directory as src):
call ale#test#SetFilename('../test-files/cpp/dummy.cpp')
set filetype=cpp " The test fails without this
let targetfile = bufname(bufnr('%'))
AssertEqual
\ {
\ 'command': ale#Escape('invalidpp')
\ . ' --project=.astylerc'
\ . ' --stdin=' . ale#Escape(targetfile)
\ },
\ ale#fixers#astyle#Fix(bufnr(''))

View File

@ -0,0 +1,49 @@
Before:
Save g:ale_python_autoflake_executable
Save g:ale_python_autoflake_options
" Use an invalid global executable, so we don't match it.
let g:ale_python_autoflake_executable = 'xxxinvalid'
let g:ale_python_autoflake_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
let g:dir = getcwd()
let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
After:
Restore
unlet! b:bin_dir
call ale#test#RestoreDirectory()
Execute(The autoflake callback should return the correct default values):
AssertEqual
\ 0,
\ ale#fixers#autoflake#Fix(bufnr(''))
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
AssertEqual
\ {
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/autoflake'))
\ . ' --in-place '
\ . ' %t',
\ 'read_temporary_file': 1,
\ },
\ ale#fixers#autoflake#Fix(bufnr(''))
Execute(The autoflake callback should include options):
let g:ale_python_autoflake_options = '--some-option'
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
AssertEqual
\ {
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/autoflake'))
\ . ' --some-option'
\ . ' --in-place '
\ . ' %t',
\ 'read_temporary_file': 1,
\ },
\ ale#fixers#autoflake#Fix(bufnr(''))

View File

@ -0,0 +1,47 @@
Before:
Save g:ale_python_autoimport_executable
Save g:ale_python_autoimport_options
" Use an invalid global executable, so we don't match it.
let g:ale_python_autoimport_executable = 'xxxinvalid'
let g:ale_python_autoimport_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
After:
Restore
unlet! b:bin_dir
call ale#test#RestoreDirectory()
Execute(The autoimport callback should return the correct default values):
AssertEqual
\ 0,
\ ale#fixers#autoimport#Fix(bufnr(''))
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
AssertEqual
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/autoimport')) . ' -',
\ },
\ ale#fixers#autoimport#Fix(bufnr(''))
Execute(The autoimport callback should respect custom options):
let g:ale_python_autoimport_options = '--multi-line=3 --trailing-comma'
AssertEqual
\ 0,
\ ale#fixers#autoimport#Fix(bufnr(''))
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
AssertEqual
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/autoimport'))
\ . ' --multi-line=3 --trailing-comma -',
\ },
\ ale#fixers#autoimport#Fix(bufnr(''))

View File

@ -0,0 +1,37 @@
Before:
Save g:ale_python_autopep8_executable
Save g:ale_python_autopep8_options
" Use an invalid global executable, so we don't match it.
let g:ale_python_autopep8_executable = 'xxxinvalid'
let g:ale_python_autopep8_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
let g:dir = getcwd()
let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
After:
Restore
unlet! b:bin_dir
call ale#test#RestoreDirectory()
Execute(The autopep8 callback should return the correct default values):
AssertEqual
\ 0,
\ ale#fixers#autopep8#Fix(bufnr(''))
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
AssertEqual
\ {'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/autopep8')) . ' -'},
\ ale#fixers#autopep8#Fix(bufnr(''))
Execute(The autopep8 callback should include options):
let g:ale_python_autopep8_options = '--some-option'
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
AssertEqual
\ {'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/autopep8')) . ' --some-option -' },
\ ale#fixers#autopep8#Fix(bufnr(''))

View File

@ -0,0 +1,30 @@
Before:
Save g:ale_bib_bibclean_executable
Save g:ale_bib_bibclean_options
let g:ale_bib_bibclean_executable = 'xxxinvalid'
let g:ale_bib_bibclean_options = '-align-equals'
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The bibclean callback should return the correct default values):
call ale#test#SetFilename('../test-files/bib/dummy.bib')
AssertEqual
\ {'command': ale#Escape(g:ale_bib_bibclean_executable) . ' -align-equals'},
\ ale#fixers#bibclean#Fix(bufnr(''))
Execute(The bibclean callback should include custom bibclean options):
let g:ale_bib_bibclean_options = '-author -check-values'
call ale#test#SetFilename('../test-files/bib/dummy.bib')
AssertEqual
\ {
\ 'command': ale#Escape(g:ale_bib_bibclean_executable) . ' -author -check-values'
\ },
\ ale#fixers#bibclean#Fix(bufnr(''))

View File

@ -0,0 +1,67 @@
Before:
call ale#assert#SetUpFixerTest('python', 'black')
let g:dir = getcwd()
let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
After:
call ale#assert#TearDownFixerTest()
unlet! g:dir
unlet! b:bin_dir
Execute(The black callback should return the correct default values):
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
AssertEqual
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/black')) . ' -'},
\ ale#fixers#black#Fix(bufnr(''))
Execute(The black callback should include options):
let g:ale_python_black_options = '--some-option'
let g:ale_python_black_change_directory = 0
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
AssertEqual
\ {'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/black')) . ' --some-option -' },
\ ale#fixers#black#Fix(bufnr(''))
Execute(The black callback should include --pyi for .pyi files):
let g:ale_python_black_change_directory = 0
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.pyi')
AssertEqual
\ {'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/black')) . ' --pyi -' },
\ ale#fixers#black#Fix(bufnr(''))
Execute(The black callback should not concatenate options):
let g:ale_python_black_options = '--some-option'
let g:ale_python_black_change_directory = 0
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.pyi')
AssertEqual
\ {'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/black')) . ' --some-option --pyi -' },
\ ale#fixers#black#Fix(bufnr(''))
Execute(Pipenv is detected when python_black_auto_pipenv is set):
let g:ale_python_black_auto_pipenv = 1
let g:ale_python_black_change_directory = 0
call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')
AssertEqual
\ {'command': ale#Escape('pipenv') . ' run black -'},
\ ale#fixers#black#Fix(bufnr(''))
Execute(Poetry is detected when python_black_auto_poetry is set):
let g:ale_python_black_auto_poetry = 1
let g:ale_python_black_change_directory = 0
call ale#test#SetFilename('../test-files/python/poetry/whatever.py')
AssertEqual
\ {'command': ale#Escape('poetry') . ' run black -'},
\ ale#fixers#black#Fix(bufnr(''))

View File

@ -0,0 +1,39 @@
Before:
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
call ale#test#RestoreDirectory()
Execute(Long lines with basic function calls should be broken up correctly):
AssertEqual
\ [
\ 'def foo():',
\ ' some_variable = this_is_a_longer_function(',
\ 'first_argument,',
\ ' second_argument,',
\ ' third_with_function_call(',
\ 'foo,',
\ ' bar,',
\ '))',
\ ],
\ ale#fixers#generic_python#BreakUpLongLines(bufnr(''), [
\ 'def foo():',
\ ' some_variable = this_is_a_longer_function(first_argument, second_argument, third_with_function_call(foo, bar))',
\ ])
Execute(Longer lines should be permitted if a configuration file allows it):
call ale#test#SetFilename('../test-files/long-line/foo/bar.py')
AssertEqual
\ [
\ 'x = this_line_is_between_79_and_90_characters(first, second, third, fourth, fifth)',
\ 'y = this_line_is_longer_than_90_characters(',
\ 'much_longer_word,',
\ ' another_longer_word,',
\ ' a_third_long_word,',
\ ')'
\ ],
\ ale#fixers#generic_python#BreakUpLongLines(bufnr(''), [
\ 'x = this_line_is_between_79_and_90_characters(first, second, third, fourth, fifth)',
\ 'y = this_line_is_longer_than_90_characters(much_longer_word, another_longer_word, a_third_long_word)',
\ ])

View File

@ -0,0 +1,24 @@
Before:
Save g:ale_haskell_brittany_executable
" Use an invalid global executable, so we don't match it.
let g:ale_haskell_brittany_executable = 'xxxinvalid'
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The brittany callback should return the correct default values):
call ale#test#SetFilename('../haskell_files/testfile.hs')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' --write-mode inplace'
\ . ' %t',
\ },
\ ale#fixers#brittany#Fix(bufnr(''))

View File

@ -0,0 +1,21 @@
Before:
Save g:ale_proto_buf_format_executable
" Use an invalid global executable, so we don't match it.
let g:ale_proto_buf_format_executable = 'xxxinvalid'
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The buf-format callback should return the correct default values):
call ale#test#SetFilename('../test-files/proto/testfile.proto')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid') . ' format %t',
\ },
\ ale#fixers#buf_format#Fix(bufnr(''))

View File

@ -0,0 +1,29 @@
Before:
let g:ale_bazel_buildifier_options = ''
call ale#assert#SetUpFixerTest('bzl', 'buildifier')
After:
call ale#assert#TearDownFixerTest()
Execute(The buildifier callback should return the correct default values):
call ale#test#SetFilename('../test-files/bazel/WORKSPACE')
AssertFixer
\ {
\ 'command': ale#Escape(g:ale_bazel_buildifier_executable)
\ . ' -mode fix -lint fix -path '
\ . ale#Escape(ale#test#GetFilename('../test-files/bazel/WORKSPACE'))
\ . ' -'
\ }
Execute(The buildifier callback should include any additional options):
call ale#test#SetFilename('../test-files/bazel/WORKSPACE')
let g:ale_bazel_buildifier_options = '--some-option'
AssertFixer
\ {
\ 'command': ale#Escape(g:ale_bazel_buildifier_executable)
\ . ' -mode fix -lint fix -path '
\ . ale#Escape(ale#test#GetFilename('../test-files/bazel/WORKSPACE'))
\ . ' --some-option -'
\ }

View File

@ -0,0 +1,64 @@
Before:
Save g:ale_c_clangformat_executable
Save g:c_clangformat_style_option
Save g:c_clangformat_use_local_file
" Use an invalid global executable, so we don't match it.
let g:ale_c_clangformat_executable = 'xxxinvalid'
call ale#test#SetDirectory('/testplugin/test/fixers')
let g:dir = getcwd()
After:
Restore
call ale#test#RestoreDirectory()
Execute(The clang-format callback should return the correct default values):
call ale#test#SetFilename('../test-files/c/dummy.c')
AssertEqual
\ {
\ 'command': ale#Escape(g:ale_c_clangformat_executable)
\ . ' --assume-filename=' . ale#Escape(bufname(bufnr('')))
\ },
\ ale#fixers#clangformat#Fix(bufnr(''))
Execute(The clangformat callback should include any additional options):
call ale#test#SetFilename('../test-files/c/dummy.c')
let g:ale_c_clangformat_options = '--some-option'
AssertEqual
\ {
\ 'command': ale#Escape(g:ale_c_clangformat_executable)
\ . ' --assume-filename=' . ale#Escape(bufname(bufnr('')))
\ . ' --some-option',
\ },
\ ale#fixers#clangformat#Fix(bufnr(''))
Execute(The clangformat callback should include style options as well):
call ale#test#SetFilename('../test-files/c/dummy.c')
let g:ale_c_clangformat_options = '--some-option'
let g:ale_c_clangformat_style_option = '{BasedOnStyle: Microsoft, ColumnLimit:80,}'
AssertEqual
\ {
\ 'command': ale#Escape(g:ale_c_clangformat_executable)
\ . ' --assume-filename=' . ale#Escape(bufname(bufnr('')))
\ . ' --some-option' . " -style='{BasedOnStyle: Microsoft, ColumnLimit:80,}'",
\ },
\ ale#fixers#clangformat#Fix(bufnr(''))
Execute(The clangformat callback should use local file instead of style options):
call ale#test#SetFilename('../test-files/clangformat/with_clangformat/dummy.c')
let g:ale_c_clangformat_options = '--some-option'
let g:ale_c_clangformat_style_option = '{BasedOnStyle: Microsoft, ColumnLimit:80,}'
let g:ale_c_clangformat_use_local_file = 1
AssertEqual
\ {
\ 'command': ale#Escape(g:ale_c_clangformat_executable)
\ . ' --assume-filename=' . ale#Escape(bufname(bufnr('')))
\ . ' --some-option' . ' -style=file',
\ },
\ ale#fixers#clangformat#Fix(bufnr(''))

View File

@ -0,0 +1,47 @@
Before:
Save g:ale_c_build_dir
Save g:ale_c_clangtidy_executable
Save g:ale_c_clangtidy_checks
Save g:ale_c_clangtidy_extra_options
Save g:ale_cpp_clangtidy_executable
Save g:ale_cpp_clangtidy_checks
Save g:ale_cpp_clangtidy_extra_options
" Use an invalid global executable, so we don't match it.
let g:ale_c_clangtidy_executable = 'xxxinvalid'
let g:ale_c_clangtidy_checks = []
let g:ale_c_clangtidy_extra_options = ''
let g:ale_cpp_clangtidy_executable = 'xxxinvalidpp'
let g:ale_cpp_clangtidy_checks = []
let g:ale_cpp_clangtidy_extra_options = ''
let g:ale_c_build_dir = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The clangtidy callback should return the correct default values):
call ale#test#SetFilename('../test-files/c/dummy.c')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_c_clangtidy_executable)
\ . ' -fix -fix-errors %t'
\ },
\ ale#fixers#clangtidy#Fix(bufnr(''))
Execute(The clangtidy callback should include any additional options):
call ale#test#SetFilename('../test-files/c/dummy.c')
let g:ale_c_clangtidy_extra_options = '--some-option'
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_c_clangtidy_executable)
\ . ' -fix -fix-errors --some-option %t',
\ },
\ ale#fixers#clangtidy#Fix(bufnr(''))

View File

@ -0,0 +1,36 @@
Before:
Save g:ale_cmake_cmakeformat_executable
Save g:ale_cmake_cmakeformat_options
" Use an invalid global executable, so we don't match it.
let g:ale_cmake_cmakeformat_executable = 'xxxinvalid'
let g:ale_cmake_cmakeformat_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The cmakeformat callback should return the correct default values):
call ale#test#SetFilename('../cmake_files/CMakeList.txt')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' -'
\ },
\ ale#fixers#cmakeformat#Fix(bufnr(''))
Execute(The cmakeformat callback should include custom cmakeformat options):
let g:ale_cmake_cmakeformat_options = "-r '(a) -> a'"
call ale#test#SetFilename('../cmake_files/CMakeList.txt')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' ' . g:ale_cmake_cmakeformat_options
\ . ' -',
\ },
\ ale#fixers#cmakeformat#Fix(bufnr(''))

View File

@ -0,0 +1,33 @@
Before:
Save g:ale_crystal_format_executable
Save g:ale_crystal_format_options
" Use an invalid global executable, so we don't match it.
let g:ale_crystal_format_executable = 'xxxinvalid'
let g:ale_crystal_format_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The crystal format callback should return the correct default values):
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid') . ' tool format -',
\ },
\ ale#fixers#crystal#Fix(bufnr(''))
Execute(The crystal format callback should include custom options):
let g:ale_crystal_format_options = "-list=true"
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' tool format ' . g:ale_crystal_format_options
\ . ' -',
\ },
\ ale#fixers#crystal#Fix(bufnr(''))

View File

@ -0,0 +1,40 @@
Before:
Save g:ale_dart_format_executable
Save g:ale_dart_format_options
" Use an invalid global executable, so we don't match it.
let g:ale_dart_format_executable = 'xxxinvalid'
let g:ale_dart_format_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The dart format callback should return the correct default values):
call ale#test#SetFilename('../test-files/dart/testfile.dart')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' format'
\ . ' %t',
\ },
\ ale#fixers#dart_format#Fix(bufnr(''))
Execute(The dart format callback should include custom dart format options):
let g:ale_dart_format_options = "-l 80"
call ale#test#SetFilename('../test-files/dart/testfile.dart')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' format'
\ . ' ' . g:ale_dart_format_options
\ . ' %t',
\ },
\ ale#fixers#dart_format#Fix(bufnr(''))

View File

@ -0,0 +1,40 @@
Before:
Save g:ale_dart_dartfmt_executable
Save g:ale_dart_dartfmt_options
" Use an invalid global executable, so we don't match it.
let g:ale_dart_dartfmt_executable = 'xxxinvalid'
let g:ale_dart_dartfmt_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The dartfmt callback should return the correct default values):
call ale#test#SetFilename('../test-files/dart/testfile.dart')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' -w'
\ . ' %t',
\ },
\ ale#fixers#dartfmt#Fix(bufnr(''))
Execute(The dartfmt callback should include custom dartfmt options):
let g:ale_dart_dartfmt_options = "-l 80"
call ale#test#SetFilename('../test-files/dart/testfile.dart')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' -w'
\ . ' ' . g:ale_dart_dartfmt_options
\ . ' %t',
\ },
\ ale#fixers#dartfmt#Fix(bufnr(''))

View File

@ -0,0 +1,40 @@
Before:
Save g:ale_d_dfmt_executable
Save g:ale_d_dfmt_options
" Use an invalid global executable, so we don't match it.
let g:ale_d_dfmt_executable = 'xxxinvalid'
let g:ale_d_dfmt_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The dfmt callback should return the correct default values):
call ale#test#SetFilename('../test-files/d/test.d')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' -i'
\ . ' %t',
\ },
\ ale#fixers#dfmt#Fix(bufnr(''))
Execute(The dfmt callback should include custom dfmt options):
let g:ale_d_dfmt_options = "--space-after-cast"
call ale#test#SetFilename('../test-files/d/test.d')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' -i'
\ . ' ' . g:ale_d_dfmt_options
\ . ' %t',
\ },
\ ale#fixers#dfmt#Fix(bufnr(''))

View File

@ -0,0 +1,22 @@
Before:
Save g:ale_dhall_executable
Save g:ale_dhall_options
" Use an invalid global executable, so we dont match it.
let g:ale_dhall_executable = 'odd-dhall'
let g:ale_dhall_options = '--ascii'
call ale#assert#SetUpFixerTest('dhall', 'dhall-format')
After:
call ale#assert#TearDownFixerTest()
Execute(The dhall-format callback should return the correct options):
call ale#test#SetFilename('../dhall_files/testfile.dhall')
AssertFixer
\ {
\ 'command': ale#Escape('odd-dhall')
\ . ' --ascii'
\ . ' format'
\ }

View File

@ -0,0 +1,22 @@
Before:
Save g:ale_dhall_executable
Save g:ale_dhall_options
" Use an invalid global executable, so we dont match it.
let g:ale_dhall_executable = 'odd-dhall'
let g:ale_dhall_options = '--ascii'
let g:ale_dhall_freeze_options = '--all'
call ale#assert#SetUpFixerTest('dhall', 'dhall-freeze')
After:
call ale#assert#TearDownFixerTest()
Execute(The dhall-freeze callback should return the correct options):
AssertFixer
\ {
\ 'command': ale#Escape('odd-dhall')
\ . ' --ascii'
\ . ' freeze'
\ . ' --all'
\ }

View File

@ -0,0 +1,20 @@
Before:
Save g:ale_dhall_executable
Save g:ale_dhall_options
" Use an invalid global executable, so we dont match it.
let g:ale_dhall_executable = 'odd-dhall'
let g:ale_dhall_options = '--ascii'
call ale#assert#SetUpFixerTest('dhall', 'dhall-lint')
After:
call ale#assert#TearDownFixerTest()
Execute(The dhall-lint callback should return the correct options):
AssertFixer
\ {
\ 'command': ale#Escape('odd-dhall')
\ . ' --ascii'
\ . ' lint'
\ }

View File

@ -0,0 +1,41 @@
Before:
Save g:ale_cs_dotnet_format_executable
Save g:ale_cs_dotnet_format_options
" Use an invalid global executable, so we don't match it.
let g:ale_cs_dotnet_format_executable = 'xxxinvalid'
let g:ale_cs_dotnet_format_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The dotnet format callback should return the correct default values):
call ale#test#SetFilename('../test-files/cs/testfile.cs')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' format'
\ . ' --folder --include %t "$(dirname %t)"',
\ },
\ ale#fixers#dotnet_format#Fix(bufnr(''))
Execute(The dotnet format callback should include custom dotnet format options):
let g:ale_cs_dotnet_format_options = "-l 80"
call ale#test#SetFilename('../test-files/cs/testfile.cs')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' format'
\ . ' ' . g:ale_cs_dotnet_format_options
\ . ' --folder --include %t "$(dirname %t)"',
\ },
\ ale#fixers#dotnet_format#Fix(bufnr(''))

View File

@ -0,0 +1,44 @@
Before:
call ale#assert#SetUpFixerTest('typescript', 'dprint')
call ale#test#SetFilename('../test-files/dprint/blank.ts')
let g:ale_dprint_executable_override = 0
let g:ale_dprint_executable = 'dprint'
let g:ale_dprint_config = ''
After:
Restore
call ale#assert#TearDownFixerTest()
Execute(The dprint callback should return 0 for a non-existent executable):
let g:ale_dprint_executable = 'foo'
AssertFixer 0
Execute(The dprint callback should return the correct default values):
let g:ale_dprint_executable_override = 1
AssertFixer {
\ 'command': ale#Escape('dprint')
\ . ' fmt '
\ . ' --stdin %s'
\ }
Execute(The dprint callback should include config):
let g:ale_dprint_executable_override = 1
let g:ale_dprint_config = 'dprint.json'
AssertFixer {
\ 'command': ale#Escape('dprint')
\ . ' fmt '
\ . ' -c '
\ . ale#Escape((has('win32') ? 'C:\testplugin\test\test-files\dprint\dprint.json' : '/testplugin/test/test-files/dprint/dprint.json'))
\ . ' --stdin %s'
\ }
Execute(The dprint callback should include custom options):
let g:ale_dprint_executable_override = 1
let g:ale_dprint_options = '--verbose'
AssertFixer {
\ 'command': ale#Escape('dprint')
\ . ' fmt '
\ . '--verbose' . ' --stdin %s'
\ }

View File

@ -0,0 +1,74 @@
Before:
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
unlet! b:ale_elm_format_executable
unlet! b:ale_elm_format_use_global
unlet! b:ale_elm_format_options
call ale#test#RestoreDirectory()
Execute(The elm-format command should have default params):
call ale#test#SetFilename('../test-files/elm/src/subdir/testfile.elm')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command':
\ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/elm/node_modules/.bin/elm-format'))
\ . ' %t --yes',
\ },
\ ale#fixers#elm_format#Fix(bufnr(''))
Execute(The elm-format command should manage use_global = 1 param):
call ale#test#SetFilename('../test-files/elm/src/subdir/testfile.elm')
let b:ale_elm_format_use_global = 1
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command':
\ ale#Escape('elm-format')
\ . ' %t --yes',
\ },
\ ale#fixers#elm_format#Fix(bufnr(''))
Execute(The elm-format command should manage executable param):
call ale#test#SetFilename('../test-files/elm/src/subdir/testfile.elm')
let b:ale_elm_format_use_global = 1
let b:ale_elm_format_executable = 'elmformat'
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command':
\ ale#Escape('elmformat')
\ . ' %t --yes',
\ },
\ ale#fixers#elm_format#Fix(bufnr(''))
Execute(The elm-format command should manage empty options):
call ale#test#SetFilename('../test-files/elm/src/subdir/testfile.elm')
let b:ale_elm_format_options = ''
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command':
\ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/elm/node_modules/.bin/elm-format'))
\ . ' %t',
\ },
\ ale#fixers#elm_format#Fix(bufnr(''))
Execute(The elm-format command should manage custom options):
call ale#test#SetFilename('../test-files/elm/src/subdir/testfile.elm')
let b:ale_elm_format_options = '--param1 --param2'
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command':
\ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/elm/node_modules/.bin/elm-format'))
\ . ' %t --param1 --param2',
\ },
\ ale#fixers#elm_format#Fix(bufnr(''))

View File

@ -0,0 +1,55 @@
Before:
Save g:ale_eruby_erblint_executable
Save g:ale_eruby_erblint_options
" Use an invalid global executable, so we don't match it.
let g:ale_eruby_erblint_executable = 'xxxinvalid'
let g:ale_eruby_erblint_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The erblint callback should return the correct default values):
call ale#test#SetFilename('../test-files/eruby/dummy.html.erb')
AssertEqual
\ {
\ 'process_with': 'ale#fixers#erblint#PostProcess',
\ 'command': ale#Escape(g:ale_eruby_erblint_executable)
\ . ' --autocorrect --stdin %s',
\ },
\ ale#fixers#erblint#Fix(bufnr(''))
Execute(The erblint callback should include custom erblint options):
let g:ale_eruby_erblint_options = '--lint-all'
call ale#test#SetFilename('../test-files/ruby/with_config/dummy.rb')
AssertEqual
\ {
\ 'process_with': 'ale#fixers#erblint#PostProcess',
\ 'command': ale#Escape(g:ale_eruby_erblint_executable)
\ . ' --lint-all'
\ . ' --autocorrect --stdin %s',
\ },
\ ale#fixers#erblint#Fix(bufnr(''))
Execute(The erblint post-processor should remove diagnostics content):
AssertEqual
\ [
\ '<div>',
\ '',
\ '</div>',
\ ],
\ ale#fixers#erblint#PostProcess(bufnr(''), [
\ 'Linting 1 files with 11 autocorrectable linters...',
\ '',
\ '1 error(s) corrected in ERB files',
\ '================ /home/user/demo.html.erb ==================',
\ '<div>',
\ '',
\ '</div>',
\ ])

View File

@ -0,0 +1,25 @@
Before:
Save b:ale_elm_format_executable
Save b:ale_elm_format_options
let b:ale_elm_format_executable = 'erlfmt'
let b:ale_elm_format_options = ''
After:
Restore
Execute(The erlfmt command should handle empty options):
AssertEqual
\ {
\ 'command': ale#Escape('erlfmt') . ' %s'
\ },
\ ale#fixers#erlfmt#Fix(bufnr(''))
Execute(The erlfmt command should handle custom options):
let b:ale_erlang_erlfmt_options = '--insert-pragma'
AssertEqual
\ {
\ 'command': ale#Escape('erlfmt') . ' --insert-pragma %s'
\ },
\ ale#fixers#erlfmt#Fix(bufnr(''))

View File

@ -0,0 +1,339 @@
Before:
call ale#assert#SetUpFixerTest('javascript', 'eslint')
Save g:ale_command_wrapper
runtime autoload/ale/handlers/eslint.vim
let g:ale_command_wrapper = ''
After:
call ale#assert#TearDownFixerTest()
Execute(The executable path should be correct):
call ale#test#SetFilename('../test-files/eslint/react-app/subdir/testfile.js')
" eslint_d output with an older eslint version is used here.
GivenCommandOutput ['v4.4.1 (eslint_d v5.1.0)']
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'cwd': ale#path#Simplify(g:dir . '/../test-files/eslint/react-app'),
\ 'command': (has('win32') ? 'node.exe ' : '')
\ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/node_modules/eslint/bin/eslint.js'))
\ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/.eslintrc.js'))
\ . ' --fix %t',
\ }
Execute(The ESLint fixer shouldn't run if no configuration file can be found):
call ale#test#SetFilename('../no-configuration')
AssertFixerNotExecuted
Execute(The ESLint fixer should use a config file option if set for old versions):
call ale#test#SetFilename('../no-configuration')
let b:ale_javascript_eslint_options = '-c /foo.cfg'
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'cwd': '',
\ 'command': ale#Escape('eslint') . ' -c /foo.cfg --fix %t',
\ }
let b:ale_javascript_eslint_options = '--bar -c /foo.cfg'
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'cwd': '',
\ 'command': ale#Escape('eslint') . ' --bar -c /foo.cfg --fix %t',
\ }
let b:ale_javascript_eslint_options = '--config /foo.cfg'
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'cwd': '',
\ 'command': ale#Escape('eslint') . ' --config /foo.cfg --fix %t',
\ }
let b:ale_javascript_eslint_options = '--bar --config /foo.cfg'
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'cwd': '',
\ 'command': ale#Escape('eslint') . ' --bar --config /foo.cfg --fix %t',
\ }
Execute(The ESLint fixer should use a -c file option if set for eslint_d):
let b:ale_javascript_eslint_executable = '/bin/eslint_d'
GivenCommandOutput ['v3.19.0 (eslint_d v4.2.0)']
call ale#test#SetFilename('../no-configuration')
let b:ale_javascript_eslint_options = '-c /foo.cfg'
AssertFixer
\ {
\ 'process_with': 'ale#fixers#eslint#ProcessEslintDOutput',
\ 'cwd': '',
\ 'command': ale#Escape('/bin/eslint_d')
\ . ' -c /foo.cfg'
\ . ' --stdin-filename %s --stdin --fix-to-stdout'
\ }
let b:ale_javascript_eslint_options = '--bar -c /foo.cfg'
AssertFixer
\ {
\ 'process_with': 'ale#fixers#eslint#ProcessEslintDOutput',
\ 'cwd': '',
\ 'command': ale#Escape('/bin/eslint_d')
\ . ' --bar -c /foo.cfg'
\ . ' --stdin-filename %s --stdin --fix-to-stdout'
\ }
let b:ale_javascript_eslint_options = '--config /foo.cfg'
AssertFixer
\ {
\ 'process_with': 'ale#fixers#eslint#ProcessEslintDOutput',
\ 'cwd': '',
\ 'command': ale#Escape('/bin/eslint_d')
\ . ' --config /foo.cfg'
\ . ' --stdin-filename %s --stdin --fix-to-stdout'
\ }
let b:ale_javascript_eslint_options = '--bar --config /foo.cfg'
AssertFixer
\ {
\ 'process_with': 'ale#fixers#eslint#ProcessEslintDOutput',
\ 'cwd': '',
\ 'command': ale#Escape('/bin/eslint_d')
\ . ' --bar --config /foo.cfg'
\ . ' --stdin-filename %s --stdin --fix-to-stdout'
\ }
Execute(The ESLint fixer should use a config file option if set for new versions):
GivenCommandOutput ['4.9.0']
call ale#test#SetFilename('../no-configuration')
let b:ale_javascript_eslint_options = '-c /foo.cfg'
AssertFixer
\ {
\ 'process_with': 'ale#fixers#eslint#ProcessFixDryRunOutput',
\ 'cwd': '',
\ 'command': ale#Escape('eslint')
\ . ' -c /foo.cfg'
\ . ' --stdin-filename %s --stdin --fix-dry-run --format=json'
\ }
let b:ale_javascript_eslint_options = '--bar -c /foo.cfg'
AssertFixer
\ {
\ 'process_with': 'ale#fixers#eslint#ProcessFixDryRunOutput',
\ 'cwd': '',
\ 'command': ale#Escape('eslint')
\ . ' --bar -c /foo.cfg'
\ . ' --stdin-filename %s --stdin --fix-dry-run --format=json'
\ }
let b:ale_javascript_eslint_options = '--config /foo.cfg'
AssertFixer
\ {
\ 'process_with': 'ale#fixers#eslint#ProcessFixDryRunOutput',
\ 'cwd': '',
\ 'command': ale#Escape('eslint')
\ . ' --config /foo.cfg'
\ . ' --stdin-filename %s --stdin --fix-dry-run --format=json'
\ }
let b:ale_javascript_eslint_options = '--bar --config /foo.cfg'
AssertFixer
\ {
\ 'process_with': 'ale#fixers#eslint#ProcessFixDryRunOutput',
\ 'cwd': '',
\ 'command': ale#Escape('eslint')
\ . ' --bar --config /foo.cfg'
\ . ' --stdin-filename %s --stdin --fix-dry-run --format=json'
\ }
Execute(The lower priority configuration file in a nested directory should be preferred):
call ale#test#SetFilename('../test-files/eslint/react-app/subdir-with-config/testfile.js')
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'cwd': ale#path#Simplify(g:dir . '/../test-files/eslint/react-app'),
\ 'command': (has('win32') ? 'node.exe ' : '')
\ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/node_modules/eslint/bin/eslint.js'))
\ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/subdir-with-config/.eslintrc'))
\ . ' --fix %t',
\ }
Execute(--config in options should override configuration file detection for old versions):
call ale#test#SetFilename('../test-files/eslint/react-app/subdir-with-config/testfile.js')
let b:ale_javascript_eslint_options = '--config /foo.cfg'
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'cwd': ale#path#Simplify(g:dir . '/../test-files/eslint/react-app'),
\ 'command': (has('win32') ? 'node.exe ' : '')
\ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/node_modules/eslint/bin/eslint.js'))
\ . ' --config /foo.cfg'
\ . ' --fix %t',
\ }
let b:ale_javascript_eslint_options = '-c /foo.cfg'
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'cwd': ale#path#Simplify(g:dir . '/../test-files/eslint/react-app'),
\ 'command': (has('win32') ? 'node.exe ' : '')
\ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/node_modules/eslint/bin/eslint.js'))
\ . ' -c /foo.cfg'
\ . ' --fix %t',
\ }
Execute(package.json should be used as a last resort):
call ale#test#SetFilename('../test-files/eslint/react-app/subdir-with-package-json/testfile.js')
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'cwd': ale#path#Simplify(g:dir . '/../test-files/eslint/react-app'),
\ 'command': (has('win32') ? 'node.exe ' : '')
\ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/node_modules/eslint/bin/eslint.js'))
\ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/.eslintrc.js'))
\ . ' --fix %t',
\ }
call ale#test#SetFilename('../test-files/eslint/package.json')
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'cwd': ale#path#Simplify(g:dir . '/../test-files/eslint'),
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/node_modules/.bin/eslint'))
\ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/package.json'))
\ . ' --fix %t',
\ }
Execute(The version check should be correct):
call ale#test#SetFilename('../test-files/eslint/react-app/subdir-with-config/testfile.js')
" We should run the command to get the version the first time.
GivenCommandOutput ['4.9.0']
AssertFixer [
\ (has('win32') ? 'node.exe ' : '')
\ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/node_modules/eslint/bin/eslint.js'))
\ . ' --version',
\ {
\ 'cwd': ale#path#Simplify(g:dir . '/../test-files/eslint/react-app'),
\ 'command': (has('win32') ? 'node.exe ' : '')
\ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/node_modules/eslint/bin/eslint.js'))
\ . ' --stdin-filename %s --stdin --fix-dry-run --format=json',
\ 'process_with': 'ale#fixers#eslint#ProcessFixDryRunOutput',
\ },
\]
AssertFixer [
\ {
\ 'cwd': ale#path#Simplify(g:dir . '/../test-files/eslint/react-app'),
\ 'command': (has('win32') ? 'node.exe ' : '')
\ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/node_modules/eslint/bin/eslint.js'))
\ . ' --stdin-filename %s --stdin --fix-dry-run --format=json',
\ 'process_with': 'ale#fixers#eslint#ProcessFixDryRunOutput',
\ },
\]
Execute(--fix-dry-run should be used for 4.9.0 and up):
call ale#test#SetFilename('../test-files/eslint/react-app/subdir/testfile.js')
GivenCommandOutput ['4.9.0']
AssertFixer
\ {
\ 'cwd': ale#path#Simplify(g:dir . '/../test-files/eslint/react-app'),
\ 'command': (has('win32') ? 'node.exe ' : '')
\ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/node_modules/eslint/bin/eslint.js'))
\ . ' --stdin-filename %s --stdin --fix-dry-run --format=json',
\ 'process_with': 'ale#fixers#eslint#ProcessFixDryRunOutput',
\ }
Execute(--fix-to-stdout should be used for eslint_d):
call ale#test#SetFilename('../test-files/eslint/app-with-eslint-d/testfile.js')
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'cwd': ale#path#Simplify(g:dir . '/../test-files/eslint/app-with-eslint-d'),
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/app-with-eslint-d/node_modules/.bin/eslint_d'))
\ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/package.json'))
\ . ' --fix %t',
\ }
" The option should be used when eslint_d is new enough.
" We look at the ESLint version instead of the eslint_d version.
GivenCommandOutput ['v3.19.0 (eslint_d v4.2.0)']
AssertFixer
\ {
\ 'cwd': ale#path#Simplify(g:dir . '/../test-files/eslint/app-with-eslint-d'),
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/app-with-eslint-d/node_modules/.bin/eslint_d'))
\ . ' --stdin-filename %s --stdin --fix-to-stdout',
\ 'process_with': 'ale#fixers#eslint#ProcessEslintDOutput',
\ }
" The option should be used for new versions too.
GivenCommandOutput ['4.9.0']
AssertFixer
\ {
\ 'cwd': ale#path#Simplify(g:dir . '/../test-files/eslint/app-with-eslint-d'),
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/eslint/app-with-eslint-d/node_modules/.bin/eslint_d'))
\ . ' --stdin-filename %s --stdin --fix-to-stdout',
\ 'process_with': 'ale#fixers#eslint#ProcessEslintDOutput',
\ }
Execute(The --fix-dry-run post-processor should handle JSON output correctly):
AssertEqual
\ [],
\ ale#fixers#eslint#ProcessFixDryRunOutput(bufnr(''), [])
AssertEqual
\ [],
\ ale#fixers#eslint#ProcessFixDryRunOutput(bufnr(''), [''])
AssertEqual
\ [],
\ ale#fixers#eslint#ProcessFixDryRunOutput(bufnr(''), ['[{}]'])
AssertEqual
\ ['foo', 'bar'],
\ ale#fixers#eslint#ProcessFixDryRunOutput(bufnr(''), ['[{"output": "foo\nbar"}]'])
Execute(The eslint_d post-processor should permit regular JavaScript content):
AssertEqual
\ [
\ 'const x = ''Error: foo''',
\ 'const y = 3',
\ ],
\ ale#fixers#eslint#ProcessEslintDOutput(bufnr(''), [
\ 'const x = ''Error: foo''',
\ 'const y = 3',
\ ])
Execute(The eslint_d post-processor should handle error messages correctly):
AssertEqual
\ [],
\ ale#fixers#eslint#ProcessEslintDOutput(bufnr(''), [
\ 'Error: No ESLint configuration found.',
\ ])
Execute(The eslint_d post-processor should handle failing to connect properly):
AssertEqual
\ [],
\ ale#fixers#eslint#ProcessEslintDOutput(bufnr(''), [
\ 'Could not connect',
\ ])

View File

@ -0,0 +1,24 @@
Before:
call ale#assert#SetUpFixerTest('javascript', 'fecs')
runtime autoload/ale/handlers/fecs.vim
After:
call ale#assert#TearDownFixerTest()
Execute(The fecs fixer should respect to g:ale_javascript_fecs_executable):
let g:ale_javascript_fecs_executable = '../test-files/fecs/fecs'
let g:ale_javascript_fecs_use_global = 1
AssertEqual
\ {
\ 'command': ale#Escape(g:ale_javascript_fecs_executable) . ' format --replace=true %t',
\ 'read_temporary_file': 1,
\ },
\ ale#fixers#fecs#Fix(bufnr(''))
Execute(The fecs fixer should return 0 when executable not found):
let g:ale_javascript_fecs_executable = 'fecs-invalid'
let g:ale_javascript_fecs_use_global = 1
AssertEqual
\ 0,
\ ale#fixers#fecs#Fix(bufnr(''))

View File

@ -0,0 +1,40 @@
Before:
Save g:ale_fish_fish_indent_executable
Save g:ale_fish_fish_indent_options
" Use an invalid global executable, so we don't match it.
let g:ale_fish_fish_indent_executable = 'xxxinvalid'
let g:ale_fish_fish_indent_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The fish_indent callback should return the correct default values):
call ale#test#SetFilename('../test-files/fish/testfile.fish')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' -w '
\ . ' %t',
\ },
\ ale#fixers#fish_indent#Fix(bufnr(''))
Execute(The fish_indent callback should include custom fish_indent options):
let g:ale_fish_fish_indent_options = "-d"
call ale#test#SetFilename('../test-files/fish/testfile.fish')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' -w '
\ . ' -d'
\ . ' %t',
\ },
\ ale#fixers#fish_indent#Fix(bufnr(''))

View File

@ -0,0 +1,50 @@
Before:
Save g:ale_json_fixjson_executable
Save g:ale_json_fixjson_options
let g:ale_json_fixjson_executable = '/path/to/fixjson'
let g:ale_json_fixjson_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
Execute(The fixjson callback should return the correct default command):
AssertEqual
\ {
\ 'command': ale#Escape('/path/to/fixjson')
\ . ' --stdin-filename '
\ . ale#Escape(bufname(bufnr('')))
\ },
\ ale#fixers#fixjson#Fix(bufnr(''))
Execute(The fixjson callback should set the buffer name as file name):
call ale#test#SetFilename('../test-files/json/testfile.json')
AssertEqual
\ {
\ 'command': ale#Escape('/path/to/fixjson')
\ . ' --stdin-filename '
\ . ale#Escape(bufname(bufnr('')))
\ },
\ ale#fixers#fixjson#Fix(bufnr(''))
AssertNotEqual
\ stridx(
\ ale#fixers#fixjson#Fix(bufnr('')).command,
\ 'testfile.json',
\ ),
\ -1
Execute(The fixjson callback should include additional options):
let g:ale_json_fixjson_options = '-i 2'
AssertEqual
\ {
\ 'command': ale#Escape('/path/to/fixjson')
\ . ' --stdin-filename '
\ . ale#Escape(bufname(bufnr('')))
\ . ' -i 2'
\ },
\ ale#fixers#fixjson#Fix(bufnr(''))

View File

@ -0,0 +1,23 @@
Before:
Save g:ale_haskell_floskell_executable
" Use an invalid global executable, so we don't match it.
let g:ale_haskell_floskell_executable = 'xxxinvalid'
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The floskell callback should return the correct default values):
call ale#test#SetFilename('../haskell_files/testfile.hs')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' %t',
\ },
\ ale#fixers#floskell#Fix(bufnr(''))

View File

@ -0,0 +1,28 @@
Before:
call ale#assert#SetUpFixerTest('ada', 'gnatpp')
After:
" Reset fixers, variables, etc.
"
" Vader's 'Restore' command will be called here.
call ale#assert#TearDownFixerTest()
Execute(The default command should be correct):
call ale#test#SetFilename('../test-files/ada/testfile.adb')
AssertFixer
\ {
\ 'command': ale#Escape(g:ale_ada_gnatpp_executable) .' %t',
\ 'read_temporary_file': 1,
\ }
Execute(The version check should be correct):
call ale#test#SetFilename('../test-files/ada/testfile.adb')
let g:ale_ada_gnatpp_options = '--no-alignment'
AssertFixer
\ {
\ 'command': ale#Escape(g:ale_ada_gnatpp_executable)
\ . ' --no-alignment %t',
\ 'read_temporary_file': 1,
\ }

View File

@ -0,0 +1,50 @@
Before:
Save g:ale_go_gofmt_executable
Save g:ale_go_gofmt_options
Save g:ale_go_go111module
" Use an invalid global executable, so we don't match it.
let g:ale_go_gofmt_executable = 'xxxinvalid'
let g:ale_go_gofmt_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
unlet! b:ale_go_go111module
call ale#test#RestoreDirectory()
Execute(The gofmt callback should return the correct default values):
call ale#test#SetFilename('../test-files/go/testfile.go')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid'),
\ },
\ ale#fixers#gofmt#Fix(bufnr(''))
Execute(The gofmt callback should include custom gofmt options):
let g:ale_go_gofmt_options = "-r '(a) -> a'"
call ale#test#SetFilename('../test-files/go/testfile.go')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' ' . g:ale_go_gofmt_options,
\ },
\ ale#fixers#gofmt#Fix(bufnr(''))
Execute(The gofmt callback should support Go environment variables):
let g:ale_go_go111module = 'off'
call ale#test#SetFilename('../test-files/go/testfile.go')
AssertEqual
\ {
\ 'command': ale#Env('GO111MODULE', 'off')
\ . ale#Escape('xxxinvalid')
\ },
\ ale#fixers#gofmt#Fix(bufnr(''))

View File

@ -0,0 +1,27 @@
Before:
call ale#assert#SetUpFixerTest('go', 'gofumpt')
After:
call ale#assert#TearDownFixerTest()
Execute(The gofumpt callback should return the correct default values):
AssertFixer {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('gofumpt') . ' -w -- %t'
\}
Execute(The gofumpt callback should allow custom gofumpt executables):
let g:ale_go_gofumpt_executable = 'foo/bar'
AssertFixer {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('foo/bar') . ' -w -- %t'
\}
Execute(The gofumpt callback should allow custom gofumpt options):
let g:ale_go_gofumpt_options = '--foobar'
AssertFixer {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('gofumpt') . ' --foobar -w -- %t'
\}

View File

@ -0,0 +1,57 @@
Before:
Save g:ale_go_goimports_executable
Save g:ale_go_goimports_options
Save g:ale_go_go111module
" Use an invalid global executable, so we don't match it.
let g:ale_go_goimports_executable = 'xxxinvalid'
let g:ale_go_goimports_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
call ale#test#SetFilename('../test-files/go/testfile.go')
After:
Restore
unlet! b:ale_go_go111module
call ale#test#RestoreDirectory()
Execute(The goimports callback should return 0 when the executable isn't executable):
AssertEqual
\ 0,
\ ale#fixers#goimports#Fix(bufnr(''))
Execute(The goimports callback should the command when the executable test passes):
let g:ale_go_goimports_executable = has('win32') ? 'cmd' : 'echo'
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_go_goimports_executable) . ' -l -w -srcdir %s %t'
\ },
\ ale#fixers#goimports#Fix(bufnr(''))
Execute(The goimports callback should include extra options):
let g:ale_go_goimports_executable = has('win32') ? 'cmd' : 'echo'
let g:ale_go_goimports_options = '--xxx'
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_go_goimports_executable) . ' -l -w -srcdir %s --xxx %t'
\ },
\ ale#fixers#goimports#Fix(bufnr(''))
Execute(The goimports callback should support Go environment variables):
let g:ale_go_goimports_executable = has('win32') ? 'cmd' : 'echo'
let g:ale_go_go111module = 'on'
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Env('GO111MODULE', 'on')
\ . ale#Escape(g:ale_go_goimports_executable)
\ . ' -l -w -srcdir %s %t'
\ },
\ ale#fixers#goimports#Fix(bufnr(''))

View File

@ -0,0 +1,54 @@
Before:
Save g:ale_go_golines_executable
Save g:ale_go_golines_options
Save g:ale_go_go111module
" Use an invalid global executable, so we don't match it.
let g:ale_go_golines_executable = 'xxxinvalid'
let g:ale_go_golines_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
unlet! b:ale_go_go111module
call ale#test#RestoreDirectory()
Execute(The golines callback should return 0 when the executable isn't executable):
AssertEqual
\ 0,
\ ale#fixers#golines#Fix(bufnr(''))
Execute(The golines callback should return the correct default values):
let g:ale_go_golines_executable = has('win32') ? 'cmd' : 'echo'
AssertEqual
\ {
\ 'command': ale#Escape(g:ale_go_golines_executable),
\ },
\ ale#fixers#golines#Fix(bufnr(''))
Execute(The golines callback should include custom golines options):
let g:ale_go_golines_executable = has('win32') ? 'cmd' : 'echo'
let g:ale_go_golines_options = "--max-len --shorten-comments"
AssertEqual
\ {
\ 'command': ale#Escape(g:ale_go_golines_executable)
\ . ' ' . g:ale_go_golines_options,
\ },
\ ale#fixers#golines#Fix(bufnr(''))
Execute(The golines callback should support Go environment variables):
let g:ale_go_golines_executable = has('win32') ? 'cmd' : 'echo'
let g:ale_go_go111module = 'off'
AssertEqual
\ {
\ 'command': ale#Env('GO111MODULE', 'off')
\ . ale#Escape(g:ale_go_golines_executable)
\ },
\ ale#fixers#golines#Fix(bufnr(''))

View File

@ -0,0 +1,41 @@
Before:
Save g:ale_go_go_executable
Save g:ale_go_go111module
" Use an invalid global executable, so we don't match it.
let g:ale_go_go_executable = 'xxxinvalid'
let g:ale_go_go111module = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
unlet! b:ale_go_go111module
call ale#test#RestoreDirectory()
Execute(The gomod callback should return the correct default values):
call ale#test#SetFilename('../test-files/go/go.mod')
setl filetype=gomod
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' mod edit -fmt'
\ . ' %t',
\ },
\ ale#fixers#gomod#Fix(bufnr(''))
Execute(The gomod callback should support Go environment variables):
call ale#test#SetFilename('../test-files/go/go.mod')
setl filetype=gomod
let g:ale_go_go111module = 'on'
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Env('GO111MODULE', 'on')
\ . ale#Escape('xxxinvalid') . ' mod edit -fmt %t'
\ },
\ ale#fixers#gomod#Fix(bufnr(''))

View File

@ -0,0 +1,27 @@
Before:
Save g:ale_java_google_java_format_executable
" Use an invalid global executable, so we don't match it.
let g:ale_java_google_java_format_executable = 'xxxinvalid'
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The google-java-format callback should return 0 when the executable isn't executable):
AssertEqual
\ 0,
\ ale#fixers#google_java_format#Fix(bufnr(''))
Execute(The google-java-format callback should run the command when the executable test passes):
let g:ale_java_google_java_format_executable = has('win32') ? 'cmd' : 'echo'
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(ale_java_google_java_format_executable) . ' --replace %t'
\ },
\ ale#fixers#google_java_format#Fix(bufnr(''))

View File

@ -0,0 +1,37 @@
Before:
Save g:ale_hack_hackfmt_executable
Save g:ale_hack_hackfmt_options
" Use an invalid global executable, so we don't match it.
let g:ale_hack_hackfmt_executable = 'xxxinvalid'
let g:ale_hack_hackfmt_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The hackfmt callback should return the correct default values):
call ale#test#SetFilename('../hack_files/testfile.hack')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' -i %t',
\ },
\ ale#fixers#hackfmt#Fix(bufnr(''))
Execute(The hackfmt callback should include custom hackfmt options):
let g:ale_hack_hackfmt_options = "--some-option"
call ale#test#SetFilename('../hack_files/testfile.hack')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' -i --some-option %t',
\ },
\ ale#fixers#hackfmt#Fix(bufnr(''))

View File

@ -0,0 +1,24 @@
Before:
Save g:ale_haskell_hfmt_executable
" Use an invalid global executable, so we don't match it.
let g:ale_haskell_hfmt_executable = 'xxxinvalid'
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The hfmt callback should return the correct default values):
call ale#test#SetFilename('../haskell_files/testfile.hs')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' -w'
\ . ' %t',
\ },
\ ale#fixers#hfmt#Fix(bufnr(''))

View File

@ -0,0 +1,18 @@
Before:
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The hindent callback should return the correct default values):
call ale#test#SetFilename('../haskell_files/testfile.hs')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('hindent')
\ . ' %t',
\ },
\ ale#fixers#hindent#Fix(bufnr(''))

View File

@ -0,0 +1,20 @@
Before:
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The hlint callback should return the correct default values):
call ale#test#SetFilename('../haskell_files/testfile.hs')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('hlint')
\ . ' --refactor'
\ . ' --refactor-options="--inplace"'
\ . ' %t',
\ },
\ ale#fixers#hlint#Fix(bufnr(''))

View File

@ -0,0 +1,12 @@
Before:
call ale#assert#SetUpFixerTest('html', 'html-beautify', 'beautify')
After:
Restore
call ale#assert#TearDownFixerTest()
Execute(The html-beautify callback should return the correct default command):
AssertEqual
\ {'command': ale#Escape('html-beautify') . ' -'},
\ ale#fixers#html_beautify#Fix(bufnr(''))

View File

@ -0,0 +1,35 @@
Before:
Save g:ale_javascript_importjs_executable
" Use an invalid global executable, so we don't match it.
let g:ale_javascript_importjs_executable = 'xxxinvalid'
call ale#test#SetDirectory('/testplugin/test/fixers')
call ale#test#SetFilename('../test-files/javascript/test.js')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The importjs callback should return 0 when the executable isn't executable):
AssertEqual
\ 0,
\ ale#fixers#importjs#Fix(bufnr(''))
Execute(The importjs callback should run the command when the executable test passes):
let g:ale_javascript_importjs_executable = has('win32') ? 'cmd' : 'echo'
AssertEqual
\ {
\ 'process_with': 'ale#fixers#importjs#ProcessOutput',
\ 'command': ale#Escape(g:ale_javascript_importjs_executable) . ' fix %s'
\ },
\ ale#fixers#importjs#Fix(bufnr(''))
Execute(The ProcessOutput callback should return the expected output):
let g:testOutput = '{"messages":[],"fileContent":"one\ntwo","unresolvedImports":{}}'
AssertEqual
\ ['one', 'two'],
\ ale#fixers#importjs#ProcessOutput(bufnr(''), g:testOutput)

View File

@ -0,0 +1,70 @@
Before:
call ale#assert#SetUpFixerTest('python', 'isort')
let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
After:
call ale#assert#TearDownFixerTest()
unlet! g:dir
unlet! b:bin_dir
Execute(The isort callback should return the correct default values):
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
" --filename option exists only after 5.7.0
GivenCommandOutput ['VERSION 5.7.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/isort')) . ' --filename %s' . ' -',
\ }
Execute(The isort callback should respect custom options):
let g:ale_python_isort_options = '--multi-line=3 --trailing-comma'
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
" --filename option exists only after 5.7.0
GivenCommandOutput ['VERSION 5.7.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/isort'))
\ . ' --filename %s' . ' --multi-line=3 --trailing-comma -',
\ }
Execute(Pipenv is detected when python_isort_auto_pipenv is set):
let g:ale_python_isort_auto_pipenv = 1
call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')
GivenCommandOutput ['VERSION 5.7.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape('pipenv') . ' run isort' . ' --filename %s' . ' -'
\ }
Execute(Poetry is detected when python_isort_auto_poetry is set):
let g:ale_python_isort_auto_poetry = 1
call ale#test#SetFilename('../test-files/python/poetry/whatever.py')
GivenCommandOutput ['VERSION 5.7.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape('poetry') . ' run isort' . ' --filename %s' . ' -'
\ }
Execute(The isort callback should not use --filename for older versions):
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
" --filename option exists only after 5.7.0
GivenCommandOutput ['VERSION 5.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/isort')) . ' -',
\ }

View File

@ -0,0 +1,26 @@
Before:
Save g:ale_json_jq_executable
Save g:ale_json_jq_options
Save g:ale_json_jq_filters
After:
Restore
Execute(The jq fixer should use the options you set):
let g:ale_json_jq_executable = 'foo'
let g:ale_json_jq_options = '--bar'
let g:ale_json_jq_filters = '.baz'
AssertEqual
\ {'command': ale#Escape('foo') . ' .baz --bar'},
\ ale#fixers#jq#Fix(bufnr(''))
Execute(The jq fixer should return 0 when there are no filters):
let g:ale_json_jq_executable = 'jq'
let g:ale_json_jq_options = ''
let g:ale_json_jq_filters = ''
AssertEqual
\ 0,
\ ale#fixers#jq#Fix(bufnr(''))

View File

@ -0,0 +1,38 @@
Before:
Save g:ale_jsonnet_jsonnetfmt_executable
Save g:ale_jsonnet_jsonnetfmt_options
" Use an invalid global executable, so we don't match it.
let g:ale_jsonnet_jsonnetfmt_executable = 'xxxinvalid'
let g:ale_jsonnet_jsonnetfmt_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
call ale#assert#SetUpFixerTest('jsonnet', 'jsonnetfmt')
After:
call ale#test#RestoreDirectory()
call ale#assert#TearDownFixerTest()
Execute(The jsonnetfmt callback should return the correct default values):
call ale#test#SetFilename('../jsonnet_files/testfile.jsonnet')
AssertFixer {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_jsonnet_jsonnetfmt_executable)
\ . ' -i'
\ . ' %t',
\}
Execute(The jsonnetfmt callback should include custom options):
let g:ale_jsonnet_jsonnetfmt_options = '--pad-arrays'
call ale#test#SetFilename('../jsonnet_files/testfile.jsonnet')
AssertFixer {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_jsonnet_jsonnetfmt_executable)
\ . ' -i'
\ . ' ' . g:ale_jsonnet_jsonnetfmt_options
\ . ' %t',
\}

View File

@ -0,0 +1,42 @@
Before:
Save g:ale_kotlin_ktlint_executable
Save g:ale_kotlin_ktlint_options
Save g:ale_kotlin_ktlint_rulesets
" Use an invalid global executable, so we don't match it.
let g:ale_kotlin_ktlint_executable = 'xxxinvalid'
let g:ale_kotlin_ktlint_options = ''
let g:ale_kotlin_ktlint_rulesets = []
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The ktlint callback should return the correct default values):
call ale#test#SetFilename('../test-files/kotlin/testfile.kt')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' --stdin'
\ . ' --format',
\ },
\ ale#fixers#ktlint#Fix(bufnr(''))
Execute(The ktlint callback should include custom ktlint options):
let g:ale_kotlin_ktlint_options = "--android"
let g:ale_kotlin_ktlint_rulesets = ['/path/to/custom/ruleset.jar']
call ale#test#SetFilename('../test-files/kotlin/testfile.kt')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' ' . g:ale_kotlin_ktlint_options
\ . ' --ruleset /path/to/custom/ruleset.jar'
\ . ' --stdin'
\ . ' --format',
\ },
\ ale#fixers#ktlint#Fix(bufnr(''))

View File

@ -0,0 +1,36 @@
Before:
Save g:ale_tex_latexindent_executable
Save g:ale_tex_latexindent_options
" Use an invalid global executable, so we don't match it.
let g:ale_tex_latexindent_executable = 'xxxinvalid'
let g:ale_tex_latexindent_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The latexindent callback should return the correct default values):
call ale#test#SetFilename('../test-files/tex/testfile.tex')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' -l'
\ },
\ ale#fixers#latexindent#Fix(bufnr(''))
Execute(The latexindent callback should include custom gofmt options):
let g:ale_tex_latexindent_options = "-l '~/.indentconfig.yaml'"
call ale#test#SetFilename('../test-files/tex/testfile.tex')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' -l'
\ . ' ' . g:ale_tex_latexindent_options
\ },
\ ale#fixers#latexindent#Fix(bufnr(''))

View File

@ -0,0 +1,35 @@
Before:
Save g:ale_lua_lua_format_executable
Save g:ale_lua_lua_format_options
" Use an invalid global executable, so we don't match it.
let g:ale_lua_lua_format_executable = 'xxxinvalid'
let g:ale_lua_lua_format_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The lua_format callback should return the correct default values):
call ale#test#SetFilename('../test-files/lua/testfile.lua')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid') . ' -i',
\ },
\ ale#fixers#lua_format#Fix(bufnr(''))
Execute(The lua_format callback should include custom lua_format options):
let g:ale_lua_lua_format_options = "--no-chop-down-table"
call ale#test#SetFilename('../test-files/lua/testfile.lua')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' ' . g:ale_lua_lua_format_options
\ . ' -i',
\ },
\ ale#fixers#lua_format#Fix(bufnr(''))

View File

@ -0,0 +1,35 @@
Before:
Save g:ale_lua_luafmt_executable
Save g:ale_lua_luafmt_options
" Use an invalid global executable, so we don't match it.
let g:ale_lua_luafmt_executable = 'xxxinvalid'
let g:ale_lua_luafmt_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The luafmt callback should return the correct default values):
call ale#test#SetFilename('../test-files/lua/testfile.lua')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid') . ' --stdin',
\ },
\ ale#fixers#luafmt#Fix(bufnr(''))
Execute(The luafmt callback should include custom luafmt options):
let g:ale_lua_luafmt_options = "--skip-children"
call ale#test#SetFilename('../test-files/lua/testfile.lua')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' ' . g:ale_lua_luafmt_options
\ . ' --stdin',
\ },
\ ale#fixers#luafmt#Fix(bufnr(''))

View File

@ -0,0 +1,36 @@
Before:
Save g:ale_elixir_mix_executable
Save g:ale_elixir_mix_format_options
let g:ale_elixir_mix_executable = 'xxxinvalid'
let g:ale_elixir_mix_format_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The mix_format callback should return the correct default values):
call ale#test#SetFilename('../test-files/elixir/testfile.ex')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' format %t',
\ },
\ ale#fixers#mix_format#Fix(bufnr(''))
Execute(The mix_format callback should include the correct format options):
let g:ale_elixir_mix_format_options = 'invalid_options'
call ale#test#SetFilename('../test-files/elixir/testfile.ex')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' format invalid_options %t',
\ },
\ ale#fixers#mix_format#Fix(bufnr(''))

View File

@ -0,0 +1,23 @@
Before:
call ale#assert#SetUpFixerTest('nim', 'nimpretty')
After:
call ale#assert#TearDownFixerTest()
Execute(The nimpretty callback should return the correct default values):
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('nimpretty') . ' %t --maxLineLen:80'
\ },
\ ale#fixers#nimpretty#Fix(bufnr(''))
Execute(The nimpretty callback should include any additional options):
let g:ale_nim_nimpretty_options = '--some-option'
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('nimpretty') . ' %t --some-option'
\ },
\ ale#fixers#nimpretty#Fix(bufnr(''))

View File

@ -0,0 +1,24 @@
Before:
Save g:ale_nix_nixfmt_executable
Save g:ale_nix_nixfmt_options
After:
Restore
Execute(The nixfmt callback should return the correct default values):
AssertEqual
\ {
\ 'command': ale#Escape('nixfmt')
\ },
\ ale#fixers#nixfmt#Fix(bufnr(''))
Execute(The nixfmt executable and options should be configurable):
let g:ale_nix_nixfmt_executable = '/path/to/nixfmt'
let g:ale_nix_nixfmt_options = '--help'
AssertEqual
\ {
\ 'command': ale#Escape('/path/to/nixfmt')
\ . ' --help',
\ },
\ ale#fixers#nixfmt#Fix(bufnr(''))

View File

@ -0,0 +1,24 @@
Before:
Save g:ale_nix_nixpkgsfmt_executable
Save g:ale_nix_nixpkgsfmt_options
After:
Restore
Execute(The nixpkgs-fmt callback should return the correct default values):
AssertEqual
\ {
\ 'command': ale#Escape('nixpkgs-fmt')
\ },
\ ale#fixers#nixpkgsfmt#Fix(bufnr(''))
Execute(The nixpkgs-fmt executable and options should be configurable):
let g:ale_nix_nixpkgsfmt_executable = '/path/to/nixpkgs-fmt'
let g:ale_nix_nixpkgsfmt_options = '-h'
AssertEqual
\ {
\ 'command': ale#Escape('/path/to/nixpkgs-fmt')
\ . ' -h',
\ },
\ ale#fixers#nixpkgsfmt#Fix(bufnr(''))

View File

@ -0,0 +1,36 @@
Before:
Save g:ale_ocaml_ocamlformat_executable
Save g:ale_ocaml_ocamlformat_options
" Use an invalid global executable, so we don't match it.
let g:ale_ocaml_ocamlformat_executable = 'xxxinvalid'
let g:ale_ocaml_ocamlformat_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The ocamlformat callback should return the correct default values):
call ale#test#SetFilename('../test-files/ocaml/testfile.re')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' --name=%s -',
\ },
\ ale#fixers#ocamlformat#Fix(bufnr(''))
Execute(The ocamlformat callback should include custom ocamlformat options):
let g:ale_ocaml_ocamlformat_options = "-m 78"
call ale#test#SetFilename('../test-files/ocaml/testfile.re')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' ' . g:ale_ocaml_ocamlformat_options
\ . ' --name=%s -',
\ },
\ ale#fixers#ocamlformat#Fix(bufnr(''))

View File

@ -0,0 +1,34 @@
Before:
Save g:ale_ocaml_ocp_indent_executable
Save g:ale_ocaml_ocpindent_options
" Use an invalid global executable
let g:ale_ocaml_ocp_indent_executable = 'xxxinvalid'
let g:ale_ocaml_ocp_indent_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The ocp_indent callback should return the correct default values):
call ale#test#SetFilename('../test-files/ocaml/ocp_inden_testfile.re')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ },
\ ale#fixers#ocp_indent#Fix(bufnr(''))
Execute(The ocp_indent callback should include custom ocp_indent options):
let g:ale_ocaml_ocp_indent_config = "base=4, type=4"
call ale#test#SetFilename('../test-files/ocaml/ocp_inden_testfile.re')
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' --config=' . ale#Escape(g:ale_ocaml_ocp_indent_config)
\ },
\ ale#fixers#ocp_indent#Fix(bufnr(''))

View File

@ -0,0 +1,33 @@
Before:
Save g:ale_opa_fmt_executable
Save g:ale_opa_fmt_options
" Use an invalid global executable, so we don't match it.
let g:ale_opa_fmt_executable = 'xxxinvalid'
let g:ale_opa_fmt_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The opa fmt callback should return the correct default values):
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid') . ' fmt',
\ },
\ ale#fixers#opafmt#Fix(bufnr(''))
Execute(The opa fmt callback should include custom options):
let g:ale_opa_fmt_options = "--list"
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' fmt'
\ . ' ' . g:ale_opa_fmt_options
\ },
\ ale#fixers#opafmt#Fix(bufnr(''))

View File

@ -0,0 +1,24 @@
Before:
Save g:ale_haskell_ormolu_executable
Save g:ale_haskell_ormolu_options
After:
Restore
Execute(The ormolu callback should return the correct default values):
AssertEqual
\ {
\ 'command': ale#Escape('ormolu')
\ },
\ ale#fixers#ormolu#Fix(bufnr(''))
Execute(The ormolu executable and options should be configurable):
let g:ale_nix_nixpkgsfmt_executable = '/path/to/ormolu'
let g:ale_nix_nixpkgsfmt_options = '-h'
AssertEqual
\ {
\ 'command': ale#Escape('/path/to/ormolu')
\ . ' -h',
\ },
\ ale#fixers#nixpkgsfmt#Fix(bufnr(''))

View File

@ -0,0 +1,34 @@
Before:
Save g:ale_packer_fmt_executable
Save g:ale_packer_fmt_options
" Use an invalid global executable, so we don't match it.
let g:ale_packer_fmt_executable = 'xxxinvalid'
let g:ale_packer_fmt_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The packer fmt callback should return the correct default values):
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid') . ' fmt -',
\ },
\ ale#fixers#packer#Fix(bufnr(''))
Execute(The packer fmt callback should include custom options):
let g:ale_packer_fmt_options = "-list=true"
AssertEqual
\ {
\ 'command': ale#Escape('xxxinvalid')
\ . ' fmt'
\ . ' ' . g:ale_packer_fmt_options
\ . ' -',
\ },
\ ale#fixers#packer#Fix(bufnr(''))

View File

@ -0,0 +1,23 @@
Before:
Save g:ale_markdown_pandoc_executable
Save g:ale_markdown_pandoc_options
After:
Restore
Execute(The pandoc callback should return 'pandoc' as default command):
setlocal noexpandtab
Assert
\ ale#fixers#pandoc#Fix(bufnr('')).command =~# '^' . ale#Escape('pandoc'),
\ "Default command name is expected to be 'pandoc'"
Execute(The pandoc executable and options should be configurable):
let g:ale_markdown_pandoc_executable = 'foobar'
let g:ale_markdown_pandoc_options = '--some-option'
AssertEqual
\ {
\ 'command': ale#Escape('foobar')
\ . ' --some-option',
\ },
\ ale#fixers#pandoc#Fix(bufnr(''))

View File

@ -0,0 +1,40 @@
Before:
Save g:ale_perl_perltidy_executable
Save g:ale_perl_perltidy_options
" Use an invalid global executable, so we don't match it.
let g:ale_perl_perltidy_executable = 'xxxinvalid'
let g:ale_perl_perltidy_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The perltidy callback should return the correct default values):
call ale#test#SetFilename('../pl_files/testfile.pl')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' -b'
\ . ' %t',
\ },
\ ale#fixers#perltidy#Fix(bufnr(''))
Execute(The perltidy callback should include custom perltidy options):
let g:ale_perl_perltidy_options = "-r '(a) -> a'"
call ale#test#SetFilename('../pl_files/testfile.pl')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' -b'
\ . ' ' . g:ale_perl_perltidy_options
\ . ' %t',
\ },
\ ale#fixers#perltidy#Fix(bufnr(''))

View File

@ -0,0 +1,24 @@
Before:
Save g:ale_sql_pgformatter_executable
Save g:ale_sql_pgformatter_options
After:
Restore
Execute(The pgFormatter callback should return the correct default values):
AssertEqual
\ {
\ 'command': ale#Escape('pg_format')
\ },
\ ale#fixers#pgformatter#Fix(bufnr(''))
Execute(The pgFormatter executable and options should be configurable):
let g:ale_sql_pgformatter_executable = '/path/to/pg_format'
let g:ale_sql_pgformatter_options = '-n'
AssertEqual
\ {
\ 'command': ale#Escape('/path/to/pg_format')
\ . ' -n',
\ },
\ ale#fixers#pgformatter#Fix(bufnr(''))

View File

@ -0,0 +1,62 @@
Before:
Save g:ale_php_cs_fixer_executable
Save g:ale_php_cs_fixer_options
let g:ale_php_cs_fixer_executable = 'php-cs-fixer'
let g:ale_php_cs_fixer_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(project with php-cs-fixer should use local by default):
call ale#test#SetFilename('../test-files/php/project-with-php-cs-fixer/test.php')
AssertEqual
\ ale#path#Simplify(g:dir . '/../test-files/php/project-with-php-cs-fixer/vendor/bin/php-cs-fixer'),
\ ale#fixers#php_cs_fixer#GetExecutable(bufnr(''))
Execute(use-global should override local detection):
let g:ale_php_cs_fixer_use_global = 1
call ale#test#SetFilename('../test-files/php/project-with-php-cs-fixer/test.php')
AssertEqual
\ 'php-cs-fixer',
\ ale#fixers#php_cs_fixer#GetExecutable(bufnr(''))
Execute(project without php-cs-fixer should use global):
call ale#test#SetFilename('../test-files/php/project-without-php-cs-fixer/test.php')
AssertEqual
\ 'php-cs-fixer',
\ ale#fixers#php_cs_fixer#GetExecutable(bufnr(''))
Execute(The php-cs-fixer callback should return the correct default values):
call ale#test#SetFilename('../test-files/php/project-without-php-cs-fixer/foo/test.php')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('php-cs-fixer')
\ . ' ' . g:ale_php_cs_fixer_options
\ . ' fix %t'
\ },
\ ale#fixers#php_cs_fixer#Fix(bufnr(''))
Execute(The php-cs-fixer callback should include custom php-cs-fixer options):
let g:ale_php_cs_fixer_options = '--config="$HOME/.php_cs"'
call ale#test#SetFilename('../test-files/php/project-without-php-cs-fixer/test.php')
AssertEqual
\ {
\ 'command': ale#Escape(g:ale_php_cs_fixer_executable)
\ . ' --config="$HOME/.php_cs" fix %t',
\ 'read_temporary_file': 1,
\ },
\ ale#fixers#php_cs_fixer#Fix(bufnr(''))

View File

@ -0,0 +1,117 @@
Before:
Save g:ale_php_phpcbf_executable
Save g:ale_php_phpcbf_standard
Save g:ale_php_phpcbf_use_global
let g:ale_php_phpcbf_executable = 'phpcbf_test'
let g:ale_php_phpcbf_standard = ''
let g:ale_php_phpcbf_options = ''
let g:ale_php_phpcbf_use_global = 0
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(project with phpcbf should use local by default):
call ale#test#SetFilename('../test-files/php/project-with-phpcbf/foo/test.php')
AssertEqual
\ ale#path#Simplify(g:dir . '/../test-files/php/project-with-phpcbf/vendor/bin/phpcbf'),
\ ale#fixers#phpcbf#GetExecutable(bufnr(''))
Execute(use-global should override local detection):
let g:ale_php_phpcbf_use_global = 1
call ale#test#SetFilename('../test-files/php/project-with-phpcbf/foo/test.php')
AssertEqual
\ 'phpcbf_test',
\ ale#fixers#phpcbf#GetExecutable(bufnr(''))
Execute(project without phpcbf should use global):
call ale#test#SetFilename('../test-files/php/project-without-phpcbf/foo/test.php')
AssertEqual
\ 'phpcbf_test',
\ ale#fixers#phpcbf#GetExecutable(bufnr(''))
Execute(The phpcbf callback should return the correct default values):
call ale#test#SetFilename('../test-files/php/project-with-phpcbf/foo/test.php')
AssertEqual
\ {'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/php/project-with-phpcbf/vendor/bin/phpcbf')) . ' --stdin-path=%s -' },
\ ale#fixers#phpcbf#Fix(bufnr(''))
Execute(The phpcbf callback should include the phpcbf_standard option):
let g:ale_php_phpcbf_standard = 'phpcbf_ruleset.xml'
call ale#test#SetFilename('../test-files/php/project-with-phpcbf/foo/test.php')
AssertEqual
\ {'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/php/project-with-phpcbf/vendor/bin/phpcbf')) . ' --stdin-path=%s ' . '--standard=phpcbf_ruleset.xml' . ' -'},
\ ale#fixers#phpcbf#Fix(bufnr(''))
Execute(User provided options should be used):
let g:ale_php_phpcbf_options = '--my-user-provided-option my-value'
call ale#test#SetFilename('../test-files/php/project-with-phpcbf/foo/test.php')
AssertEqual
\ {'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/php/project-with-phpcbf/vendor/bin/phpcbf')) . ' --stdin-path=%s ' . ale#Pad('--my-user-provided-option my-value') . ' -'},
\ ale#fixers#phpcbf#Fix(bufnr(''))
Before:
Save g:ale_php_phpcbf_executable
Save g:ale_php_phpcbf_standard
Save g:ale_php_phpcbf_use_global
let g:ale_php_phpcbf_executable = 'phpcbf_test'
let g:ale_php_phpcbf_standard = ''
let g:ale_php_phpcbf_options = ''
let g:ale_php_phpcbf_use_global = 0
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(project with phpcbf should use local by default):
call ale#test#SetFilename('../test-files/php/project-with-phpcbf/foo/test.php')
AssertEqual
\ ale#path#Simplify(g:dir . '/../test-files/php/project-with-phpcbf/vendor/bin/phpcbf'),
\ ale#fixers#phpcbf#GetExecutable(bufnr(''))
Execute(use-global should override local detection):
let g:ale_php_phpcbf_use_global = 1
call ale#test#SetFilename('../test-files/php/project-with-phpcbf/foo/test.php')
AssertEqual
\ 'phpcbf_test',
\ ale#fixers#phpcbf#GetExecutable(bufnr(''))
Execute(project without phpcbf should use global):
call ale#test#SetFilename('../test-files/php/project-without-phpcbf/foo/test.php')
AssertEqual
\ 'phpcbf_test',
\ ale#fixers#phpcbf#GetExecutable(bufnr(''))
Execute(The phpcbf callback should return the correct default values):
call ale#test#SetFilename('../test-files/php/project-with-phpcbf/foo/test.php')
AssertEqual
\ {'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/php/project-with-phpcbf/vendor/bin/phpcbf')) . ' --stdin-path=%s -' },
\ ale#fixers#phpcbf#Fix(bufnr(''))
Execute(The phpcbf callback should include the phpcbf_standard option):
let g:ale_php_phpcbf_standard = 'phpcbf_ruleset.xml'
call ale#test#SetFilename('../test-files/php/project-with-phpcbf/foo/test.php')
AssertEqual
\ {'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/php/project-with-phpcbf/vendor/bin/phpcbf')) . ' --stdin-path=%s ' . '--standard=phpcbf_ruleset.xml' . ' -'},
\ ale#fixers#phpcbf#Fix(bufnr(''))

View File

@ -0,0 +1,97 @@
Before:
call ale#assert#SetUpFixerTest('javascript', 'prettier_eslint')
Save g:ale_command_wrapper
let g:ale_command_wrapper = ''
After:
call ale#assert#TearDownFixerTest()
Execute(The default command should be correct):
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'command':
\ ale#Escape('prettier-eslint')
\ . ' %t'
\ . ' --write'
\ }
Execute(Additional options should be used when set):
let b:ale_javascript_prettier_eslint_options = '--foobar'
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'command':
\ ale#Escape('prettier-eslint')
\ . ' %t'
\ . ' --foobar --write'
\ }
Execute(--eslint-config-path should be set for 4.2.0 and up):
call ale#test#SetFilename('../test-files/eslint/react-app/foo/bar.js')
GivenCommandOutput ['4.2.0']
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'command':
\ ale#Escape('prettier-eslint')
\ . ' %t'
\ . ' --eslint-config-path ' . ale#Escape(ale#test#GetFilename('../test-files/eslint/react-app/.eslintrc.js'))
\ . ' --write'
\ }
Execute(--eslint-config-path shouldn't be used for older versions):
call ale#test#SetFilename('../test-files/eslint/react-app/foo/bar.js')
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'command':
\ ale#Escape('prettier-eslint')
\ . ' %t'
\ . ' --write'
\ }
Execute(The version check should be correct):
AssertFixer [
\ ale#Escape('prettier-eslint') . ' --version',
\ {
\ 'read_temporary_file': 1,
\ 'command':
\ ale#Escape('prettier-eslint')
\ . ' %t'
\ . ' --write'
\ }
\]
Execute(The new --stdin-filepath option should be used when the version is new enough):
call ale#test#SetFilename('../test-files/eslint/react-app/foo/bar.js')
GivenCommandOutput ['4.4.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape('prettier-eslint')
\ . ' --eslint-config-path ' . ale#Escape(ale#test#GetFilename('../test-files/eslint/react-app/.eslintrc.js'))
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(The version number should be cached):
GivenCommandOutput ['4.4.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape('prettier-eslint')
\ . ' --stdin-filepath %s --stdin',
\ }
GivenCommandOutput []
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape('prettier-eslint')
\ . ' --stdin-filepath %s --stdin',
\ }

View File

@ -0,0 +1,337 @@
Before:
call ale#assert#SetUpFixerTest('javascript', 'prettier')
Save g:ale_command_wrapper
let g:ale_command_wrapper = ''
After:
call ale#assert#TearDownFixerTest()
Execute(The prettier callback should return the correct default values):
call ale#test#SetFilename('../test-files/prettier/testfile.js')
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' %t'
\ . ' --write',
\ }
Execute(The --config option should not be set automatically):
let g:ale_javascript_prettier_use_local_config = 1
call ale#test#SetFilename('../test-files/prettier/with_config/testfile.js')
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' %t'
\ . ' --write',
\ }
Execute(The prettier callback should include custom prettier options):
let g:ale_javascript_prettier_options = '--no-semi'
call ale#test#SetFilename('../test-files/prettier/with_config/testfile.js')
AssertFixer
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' %t'
\ . ' --no-semi'
\ . ' --write',
\ }
Execute(The version check should be correct):
call ale#test#SetFilename('../test-files/prettier/testfile.js')
AssertFixer [
\ ale#Escape('prettier') . ' --version',
\ {'read_temporary_file': 1, 'command': ale#Escape('prettier') . ' %t --write'}
\]
Execute(--stdin-filepath should be used when prettier is new enough):
let g:ale_javascript_prettier_options = '--no-semi'
call ale#test#SetFilename('../test-files/prettier/with_config/testfile.js')
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --no-semi'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(The version number should be cached):
call ale#test#SetFilename('../test-files/prettier/with_config/testfile.js')
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --stdin-filepath %s --stdin',
\ }
GivenCommandOutput []
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser to `babylon` by default, < 1.16.0):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=javascript
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser babylon'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser to `babel` by default, >= 1.16.0):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=javascript
GivenCommandOutput ['1.16.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser babel'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser based on filetype, TypeScript):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=typescript
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser typescript'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser based on filetype, CSS):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=css
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser css'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser based on filetype, LESS):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=less
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser less'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser based on filetype, SCSS):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=scss
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser scss'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser based on filetype, JSON):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=json
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser json'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser based on filetype, JSON5):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=json5
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser json5'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser based on filetype, GraphQL):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=graphql
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser graphql'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser based on filetype, Markdown):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=markdown
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser markdown'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser based on filetype, Vue):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=vue
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser vue'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser based on filetype, YAML):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=yaml
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser yaml'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser based on filetype, HTML):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=html
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser html'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser based on filetype, Ruby):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=ruby
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser ruby'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser based on first filetype of multiple filetypes):
call ale#test#SetFilename('../test-files/prettier/testfile')
set filetype=css.scss
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser css'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Should set --parser for experimental language, Handlebars):
call ale#test#SetFilename('../test-files/prettier/testfile.hbs')
set filetype=html.handlebars
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': '%s:h',
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --parser glimmer'
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(Changes to directory where .prettierignore is found):
call ale#test#SetFilename('../test-files/prettier/with_prettierignore/src/testfile.js')
GivenCommandOutput ['1.6.0']
AssertFixer
\ {
\ 'cwd': expand('%:p:h:h'),
\ 'command': ale#Escape(g:ale_javascript_prettier_executable)
\ . ' --stdin-filepath %s --stdin',
\ }
Execute(The prettier_d post-processor should permit regular JavaScript content):
AssertEqual
\ [
\ 'const x = ''Error: foo''',
\ 'const y = 3',
\ ],
\ ale#fixers#prettier#ProcessPrettierDOutput(bufnr(''), [
\ 'const x = ''Error: foo''',
\ 'const y = 3',
\ ])
Execute(The prettier_d post-processor should handle error messages correctly):
AssertEqual
\ [],
\ ale#fixers#prettier#ProcessPrettierDOutput(bufnr(''), [
\ 'SyntaxError: Unexpected token, expected "," (36:28)',
\ ])

View File

@ -0,0 +1,15 @@
Before:
call ale#assert#SetUpFixerTest('javascript', 'prettier_standard')
After:
call ale#assert#TearDownFixerTest()
Execute(The prettier callback should return the correct default values):
call ale#test#SetFilename('../test-files/prettier/testfile.js')
AssertFixer
\ {
\ 'command': ale#Escape(g:ale_javascript_prettier_standard_executable)
\ . ' --stdin'
\ . ' --stdin-filepath=%s ',
\ }

View File

@ -0,0 +1,28 @@
Before:
call ale#assert#SetUpFixerTest('proto', 'protolint')
call ale#test#SetFilename('test.proto')
After:
call ale#assert#TearDownFixerTest()
Execute(The default command should be correct):
AssertFixer
\ {
\ 'command': ale#Escape('protolint')
\ . ' -fix'
\ . ' %t',
\ 'read_temporary_file': 1,
\ }
Execute(The callback should include any additional options):
let b:ale_proto_protolint_executable = '/tmp/protolint'
let b:ale_proto_protolint_config = '/tmp/protolint.yaml'
AssertFixer
\ {
\ 'command': ale#Escape('/tmp/protolint')
\ . ' -config_path=' . ale#Escape('/tmp/protolint.yaml')
\ . ' -fix'
\ . ' %t',
\ 'read_temporary_file': 1,
\ }

View File

@ -0,0 +1,38 @@
Before:
Save g:ale_pascal_ptop_executable
Save g:ale_pascal_ptop_options
" Use an invalid global executable, so we don't match it.
let g:ale_pascal_ptop_executable = 'xxxinvalid'
let g:ale_pascal_ptop_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The ptop callback should return the correct default values):
call ale#test#SetFilename('../test-files/pascal/test.pas')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' %s %t',
\ },
\ ale#fixers#ptop#Fix(bufnr(''))
Execute(The ptop callback should include custom ptop options):
let g:ale_pascal_ptop_options = "-i 2"
call ale#test#SetFilename('../test-files/pascal/test.pas')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' ' . g:ale_pascal_ptop_options
\ . ' %s %t',
\ },
\ ale#fixers#ptop#Fix(bufnr(''))

View File

@ -0,0 +1,24 @@
Before:
Save g:ale_puppet_puppetlint_executable
Save g:ale_puppet_puppetlint_options
" Use an invalid global executable, so we don't match it.
let g:ale_puppet_puppetlint_executable = 'xxxinvalid'
let g:ale_puppet_puppetlint_options = '--invalid'
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The puppetlint callback should return the correct default values):
silent execute 'file ' . fnameescape(g:dir . '/../test-files/puppet/dummy.pp')
AssertEqual
\ {'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_puppet_puppetlint_executable)
\ . ' ' . g:ale_puppet_puppetlint_options
\ . ' --fix %t' },
\ ale#fixers#puppetlint#Fix(bufnr(''))

View File

@ -0,0 +1,20 @@
Before:
Save g:ale_purescript_tidy_executable
Save g:ale_purescript_tidy_options
" Use an invalid global executable, so we dont match it.
let g:ale_purescript_tidy_executable = 'odd-purs-tidy'
let g:ale_purescript_tidy_options = '--indent 3'
call ale#assert#SetUpFixerTest('purescript', 'purs-tidy')
After:
call ale#assert#TearDownFixerTest()
Execute(The purs-tidy callback should return the correct custom options):
AssertFixer
\ {
\ 'command': ale#Escape('odd-purs-tidy')
\ . ' format'
\ . ' --indent 3'
\ }

View File

@ -0,0 +1,24 @@
Before:
Save g:ale_purescript_purty_executable
" Use an invalid global executable, so we don't match it.
let g:ale_purescript_purty_executable = 'my-special-purty'
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The purty callback should return the correct options):
call ale#test#SetFilename('../purescript_files/testfile.purs')
AssertEqual
\ {
\ 'command': ale#Escape('my-special-purty')
\ . ' --write'
\ . ' %t',
\ 'read_temporary_file': 1,
\ },
\ ale#fixers#purty#Fix(bufnr(''))

View File

@ -0,0 +1,167 @@
Before:
Save g:ale_fixers
After:
Restore
Given python(Some Python without blank lines):
def foo():
""" This is a simple test docstring """
return 1
def bar():
'''This is another simple test docstring'''
return 1
return 4
def bar():
"""
This is a multi-line
docstring
"""
if x:
pass
for l in x:
pass
for l in x:
pass
break
continue
elif x:
pass
while x:
pass
while x:
pass
else:
pass
if x:
pass
elif x:
pass
else:
pass
Execute(Blank lines should be added appropriately):
let g:ale_fixers = {'python': ['add_blank_lines_for_python_control_statements']}
ALEFix
Expect python(Newlines should be added):
def foo():
""" This is a simple test docstring """
return 1
def bar():
'''This is another simple test docstring'''
return 1
return 4
def bar():
"""
This is a multi-line
docstring
"""
if x:
pass
for l in x:
pass
for l in x:
pass
break
continue
elif x:
pass
while x:
pass
while x:
pass
else:
pass
if x:
pass
elif x:
pass
else:
pass
Given python(A file with a main block):
import os
def main():
print('hello')
if __name__ == '__main__':
main()
Execute(Fix the file):
let g:ale_fixers = {'python': ['add_blank_lines_for_python_control_statements']}
ALEFix
Expect python(extra newlines shouldn't be added to the main block):
import os
def main():
print('hello')
if __name__ == '__main__':
main()
Given python(A file with variables/docstring that start with a control statement):
def some():
"""
This is a docstring that contains an
break control statement and also contains a
return something funny.
"""
continue_some_var = True
forward_something = False
if (
continue_some_var and
forwarded_something
):
return True
Execute(Fix the file):
let g:ale_fixers = {'python': ['add_blank_lines_for_python_control_statements']}
ALEFix
Expect python(Extra new lines are not added to the file):
def some():
"""
This is a docstring that contains an
break control statement and also contains a
return something funny.
"""
continue_some_var = True
forward_something = False
if (
continue_some_var and
forwarded_something
):
return True

View File

@ -0,0 +1,12 @@
Before:
Save g:ale_qml_qmlfmt_executable
After:
Restore
Execute(The qmlfmt fixer should use the options you set):
let g:ale_qml_qmlfmt_executable = 'foo-exe'
AssertEqual
\ {'command': ale#Escape('foo-exe')},
\ ale#fixers#qmlfmt#Fix(bufnr(''))

View File

@ -0,0 +1,41 @@
Before:
Save g:ale_reasonml_refmt_executable
Save g:ale_reasonml_refmt_options
" Use an invalid global executable, so we don't match it.
let g:ale_reasonml_refmt_executable = 'xxxinvalid'
let g:ale_reasonml_refmt_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The refmt callback should return the correct default values):
call ale#test#SetFilename('../test-files/reasonml/testfile.re')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' --in-place'
\ . ' %t',
\ },
\ ale#fixers#refmt#Fix(bufnr(''))
Execute(The refmt callback should include custom refmt options):
let g:ale_reasonml_refmt_options = "-w 80"
call ale#test#SetFilename('../test-files/reasonml/testfile.re')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
\ . ' ' . g:ale_reasonml_refmt_options
\ . ' --in-place'
\ . ' %t',
\ },
\ ale#fixers#refmt#Fix(bufnr(''))

View File

@ -0,0 +1,24 @@
Before:
Save g:ale_markdown_remark_lint_executable
Save g:ale_markdown_remark_lint_options
After:
Restore
Execute(The remark callback should return the correct default values):
AssertEqual
\ {
\ 'command': ale#Escape('remark')
\ },
\ ale#fixers#remark_lint#Fix(bufnr(''))
Execute(The remark executable and options should be configurable):
let g:ale_markdown_remark_lint_executable = '/path/to/remark'
let g:ale_markdown_remark_lint_options = '-h'
AssertEqual
\ {
\ 'command': ale#Escape('/path/to/remark')
\ . ' -h',
\ },
\ ale#fixers#remark_lint#Fix(bufnr(''))

View File

@ -0,0 +1,46 @@
Before:
Save g:ale_python_reorder_python_imports_executable
Save g:ale_python_reorder_python_imports_options
" Use an invalid global executable, so we don't match it.
let g:ale_python_reorder_python_imports_executable = 'xxxinvalid'
let g:ale_python_reorder_python_imports_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
After:
Restore
unlet! b:bin_dir
call ale#test#RestoreDirectory()
Execute(The reorder_python_imports callback should return the correct default values):
AssertEqual
\ 0,
\ ale#fixers#reorder_python_imports#Fix(bufnr(''))
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
AssertEqual
\ {
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/'
\ . b:bin_dir . '/reorder-python-imports')) . ' -',
\ },
\ ale#fixers#reorder_python_imports#Fix(bufnr(''))
Execute(The reorder_python_imports callback should respect custom options):
let g:ale_python_reorder_python_imports_options = '--py3-plus'
AssertEqual
\ 0,
\ ale#fixers#reorder_python_imports#Fix(bufnr(''))
silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
AssertEqual
\ {
\ 'command': ale#Escape(ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/'
\ . b:bin_dir . '/reorder-python-imports')) . ' --py3-plus -',
\ },
\ ale#fixers#reorder_python_imports#Fix(bufnr(''))

View File

@ -0,0 +1,89 @@
Before:
Save g:ale_ruby_rubocop_executable
Save g:ale_ruby_rubocop_options
" Use an invalid global executable, so we don't match it.
let g:ale_ruby_rubocop_executable = 'xxxinvalid'
let g:ale_ruby_rubocop_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The rubocop callback should return the correct default values):
call ale#test#SetFilename('../test-files/ruby/dummy.rb')
AssertEqual
\ {
\ 'process_with': 'ale#fixers#rubocop#PostProcess',
\ 'command': ale#Escape(g:ale_ruby_rubocop_executable)
\ . ' --auto-correct --force-exclusion --stdin %s',
\ },
\ ale#fixers#rubocop#Fix(bufnr(''))
Execute(The rubocop callback should include custom rubocop options):
let g:ale_ruby_rubocop_options = '--except Lint/Debugger'
call ale#test#SetFilename('../test-files/ruby/with_config/dummy.rb')
AssertEqual
\ {
\ 'process_with': 'ale#fixers#rubocop#PostProcess',
\ 'command': ale#Escape(g:ale_ruby_rubocop_executable)
\ . ' --except Lint/Debugger'
\ . ' --auto-correct --force-exclusion --stdin %s',
\ },
\ ale#fixers#rubocop#Fix(bufnr(''))
Execute(The rubocop callback should use auto-correct-all option when set):
let g:ale_ruby_rubocop_auto_correct_all = 1
call ale#test#SetFilename('../test-files/ruby/with_config/dummy.rb')
AssertEqual
\ {
\ 'process_with': 'ale#fixers#rubocop#PostProcess',
\ 'command': ale#Escape(g:ale_ruby_rubocop_executable)
\ . ' --auto-correct-all --force-exclusion --stdin %s'
\ },
\ ale#fixers#rubocop#Fix(bufnr(''))
Execute(The rubocop post-processor should remove diagnostics content):
AssertEqual
\ [
\ 'class MyModel < ApplicationRecord',
\ ' # rubocop:disable Rails/InverseOf',
\ ' has_one :something',
\ ' # rubocop:enable Rails/InverseOf',
\ 'end',
\ '',
\ 'array = [1, 2, 3,',
\ ' 4, 5, 6]',
\ 'array = [''run'',',
\ ' ''forrest'',',
\ ' ''run'']',
\ ],
\ ale#fixers#rubocop#PostProcess(bufnr(''), [
\ 'Inspecting 1 file',
\ 'C',
\ '',
\ 'Offenses:',
\ 'app/models/my_model.rb:8:3: C: [Corrected] Layout/ArrayAlignment: ',
\ '4, 5, 6]',
\ '^',
\ '',
\ '1 file inspected, 3 offenses detected, 3 offenses corrected',
\ '====================',
\ 'class MyModel < ApplicationRecord',
\ ' # rubocop:disable Rails/InverseOf',
\ ' has_one :something',
\ ' # rubocop:enable Rails/InverseOf',
\ 'end',
\ '',
\ 'array = [1, 2, 3,',
\ ' 4, 5, 6]',
\ 'array = [''run'',',
\ ' ''forrest'',',
\ ' ''run'']',
\ ])

View File

@ -0,0 +1,30 @@
Before:
Save g:ale_ruby_rufo_executable
" Use an invalid global executable, so we don't match it.
let g:ale_ruby_rufo_executable = 'xxxinvalid'
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The rufo command should contain `bundle exec` when executable is `bundle`):
let g:ale_ruby_rufo_executable = 'bundle'
call ale#test#SetFilename('../test-files/ruby/dummy.rb')
AssertEqual
\ ale#Escape('bundle') . ' exec rufo %t',
\ ale#fixers#rufo#GetCommand(bufnr(''))
Execute(The rufo callback should return the correct default values):
call ale#test#SetFilename('../test-files/ruby/dummy.rb')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid') . ' %t'
\ },
\ ale#fixers#rufo#Fix(bufnr(''))

View File

@ -0,0 +1,16 @@
Before:
call ale#assert#SetUpFixerTest('rust', 'rustfmt')
After:
call ale#assert#TearDownFixerTest()
Execute(The rustfmt callback should return the correct default values):
call ale#test#SetFilename('../test-files/rust/testfile.rs')
AssertFixer {'command': ale#Escape('rustfmt')}
Execute(The rustfmt callback should include custom rustfmt options):
let g:ale_rust_rustfmt_options = "--skip-children"
call ale#test#SetFilename('../test-files/rust/testfile.rs')
AssertFixer {'command': ale#Escape('rustfmt') . ' ' . g:ale_rust_rustfmt_options}

View File

@ -0,0 +1,66 @@
Before:
Save g:ale_scala_scalafmt_executable
Save g:ale_scala_scalafmt_options
" Use an invalid global executable, so we don't match it.
let g:ale_scala_scalafmt_executable = 'xxxinvalid'
let g:ale_scala_scalafmt_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The scalafmt callback should return the correct default values):
call ale#test#SetFilename('../test-files/scala/dummy.scala')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_scala_scalafmt_executable)
\ . ' %t',
\ },
\ ale#fixers#scalafmt#Fix(bufnr(''))
Execute(The scalafmt callback should use ng with scalafmt automatically):
let g:ale_scala_scalafmt_executable = 'ng'
call ale#test#SetFilename('../test-files/scala/dummy.scala')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('ng')
\ . ' scalafmt'
\ . ' %t',
\ },
\ ale#fixers#scalafmt#Fix(bufnr(''))
Execute(The scalafmt callback should include custom scalafmt options):
let g:ale_scala_scalafmt_options = '--diff'
call ale#test#SetFilename('../test-files/scala/dummy.scala')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_scala_scalafmt_executable)
\ . ' --diff'
\ . ' %t',
\ },
\ ale#fixers#scalafmt#Fix(bufnr(''))
Execute(The scalafmt callback should include custom scalafmt options and use ng with scalafmt):
let g:ale_scala_scalafmt_options = '--diff'
let g:ale_scala_scalafmt_executable = 'ng'
call ale#test#SetFilename('../test-files/scala/dummy.scala')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('ng')
\ . ' scalafmt'
\ . ' --diff'
\ . ' %t',
\ },
\ ale#fixers#scalafmt#Fix(bufnr(''))

View File

@ -0,0 +1,59 @@
Before:
Save g:ale_sh_shfmt_executable
Save g:ale_sh_shfmt_options
Save &l:expandtab
Save &l:shiftwidth
Save &l:tabstop
After:
Restore
Execute(The shfmt callback should return 'shfmt' as default command):
setlocal noexpandtab
Assert
\ ale#fixers#shfmt#Fix(bufnr('')).command =~# '^' . ale#Escape('shfmt'),
\ "Default command name is expected to be 'shfmt'"
Execute(The shfmt callback should return the command with no option as default when noexpandtab is set):
let g:ale_sh_shfmt_executable = 'shfmt'
let g:ale_sh_shfmt_options = ''
setlocal noexpandtab
AssertEqual
\ {
\ 'command': ale#Escape('shfmt'),
\ },
\ ale#fixers#shfmt#Fix(bufnr(''))
Execute(The shfmt callback should return the command specifying indent width by looking shiftwidth as default):
let g:ale_sh_shfmt_executable = 'shfmt'
let g:ale_sh_shfmt_options = ''
setlocal expandtab
setlocal shiftwidth=4
AssertEqual
\ {
\ 'command': ale#Escape('shfmt') . ' -i 4',
\ },
\ ale#fixers#shfmt#Fix(bufnr(''))
Execute(The shfmt callback should return the command specifying indent width by looking tabstop when shiftwidth is 0 as default):
let g:ale_sh_shfmt_executable = 'shfmt'
let g:ale_sh_shfmt_options = ''
setlocal expandtab
setlocal shiftwidth=0
setlocal tabstop=8
AssertEqual
\ {
\ 'command': ale#Escape('shfmt') . ' -i 8',
\ },
\ ale#fixers#shfmt#Fix(bufnr(''))
Execute(The shfmt executable and options should be configurable):
let g:ale_sh_shfmt_executable = 'foobar'
let g:ale_sh_shfmt_options = '--some-option'
AssertEqual
\ {
\ 'command': ale#Escape('foobar')
\ . ' --some-option',
\ },
\ ale#fixers#shfmt#Fix(bufnr(''))

View File

@ -0,0 +1,38 @@
Before:
Save g:ale_ruby_sorbet_executable
Save g:ale_ruby_sorbet_options
" Use an invalid global executable, so we don't match it.
let g:ale_ruby_sorbet_executable = 'xxxinvalid'
let g:ale_ruby_sorbet_options = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
After:
Restore
call ale#test#RestoreDirectory()
Execute(The sorbet callback should return the correct default values):
call ale#test#SetFilename('../test-files/ruby/dummy.rb')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_ruby_sorbet_executable)
\ . ' tc --autocorrect --file %t',
\ },
\ ale#fixers#sorbet#Fix(bufnr(''))
Execute(The sorbet callback should include custom sorbet options):
let g:ale_ruby_sorbet_options = '--enable-experimental-lsp-hover'
call ale#test#SetFilename('../test-files/ruby/with_config/dummy.rb')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_ruby_sorbet_executable)
\ . ' tc --enable-experimental-lsp-hover'
\ . ' --autocorrect --file %t',
\ },
\ ale#fixers#sorbet#Fix(bufnr(''))

Some files were not shown because too many files have changed in this diff Show More