ale/test/fix/test_ale_fix.vader

828 lines
20 KiB
Plaintext
Raw Normal View History

Before:
2017-05-30 20:32:51 +00:00
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
2017-11-22 14:55:08 +00:00
silent! cd /testplugin/test/fix
2017-05-30 20:32:51 +00:00
2017-05-19 14:24:21 +00:00
let g:ale_enabled = 0
2017-05-30 20:32:51 +00:00
let g:ale_echo_cursor = 0
let g:ale_run_synchronously = 1
unlet! g:ale_run_synchronously_callbacks
2017-10-23 22:09:40 +00:00
let g:ale_set_lists_synchronously = 1
let g:ale_fix_buffer_data = {}
let g:ale_fixers = {
\ 'testft': [],
\}
2017-10-23 22:09:40 +00:00
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
2017-10-23 22:09:40 +00:00
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 AddDollars(buffer, lines) abort
return map(a:lines, '''$'' . 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
2019-02-26 16:56:16 +00:00
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 RemoveLastLine(buffer, lines) abort
2017-05-19 08:53:28 +00:00
return ['a', 'b']
endfunction
2017-05-19 14:24:21 +00:00
function RemoveLastLineOneArg(buffer) abort
return ['a', 'b']
endfunction
2017-05-30 20:32:51 +00:00
function! TestCallback(buffer, output)
return [{'lnum': 1, 'col': 1, 'text': 'xxx'}]
endfunction
function! FirstChainCallback(buffer)
return {'command': 'echo echoline', 'chain_with': 'SecondChainCallback'}
endfunction
function! FirstChainCallbackSkipped(buffer)
2017-11-22 22:39:43 +00:00
let l:ChainWith = 'SecondChainCallback'
" Test with lambdas where support is available.
if has('lambda')
let l:ChainWith = {buffer, output -> SecondChainCallback(buffer, output)}
endif
return {'command': '', 'chain_with': l:ChainWith}
endfunction
function! FirstChainCallbackSecondSkipped(buffer)
return {'command': 'echo skipit', 'chain_with': 'SecondChainCallback'}
endfunction
function! SecondChainCallback(buffer, output)
let l:previous_line = empty(a:output)
\ ? 'emptydefault'
\ : join(split(a:output[0]))
if l:previous_line is# 'skipit'
return {'command': '', 'chain_with': 'ThirdChainCallback'}
endif
return {
\ 'command': 'echo ' . l:previous_line,
\ 'chain_with': 'ThirdChainCallback',
\}
endfunction
function! ThirdChainCallback(buffer, output, input)
let l:previous_line = empty(a:output)
\ ? 'thirddefault'
\ : join(split(a:output[0]))
return a:input + [l:previous_line]
endfunction
function! ChainWhereLastIsSkipped(buffer)
return {'command': 'echo echoline', 'chain_with': 'ChainEndSkipped'}
endfunction
function! ChainEndSkipped(buffer, output)
return {'command': ''}
endfunction
2017-11-22 12:01:21 +00:00
" echo will output a single blank line, and we should ingore it.
function! IgnoredEmptyOutput(buffer, output)
return {'command': has('win32') ? 'echo(' : 'echo'}
2017-11-22 12:01:21 +00:00
endfunction
function! EchoLineNoPipe(buffer, output)
return {'command': 'echo new line', 'read_buffer': 0}
endfunction
2017-05-30 20:32:51 +00:00
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
2017-10-23 22:09:40 +00:00
unlet! g:ale_set_lists_synchronously
unlet! g:ale_run_synchronously_callbacks
unlet! g:ale_emulate_job_failure
2017-05-20 15:00:05 +00:00
unlet! b:ale_fixers
unlet! b:ale_fix_on_save
2018-11-10 10:06:48 +00:00
unlet! b:ale_quitting
delfunction AddCarets
delfunction AddDollars
delfunction DoNothing
delfunction CatLine
delfunction CatLineOneArg
2019-02-26 16:56:16 +00:00
delfunction CatLineDeferred
delfunction ReplaceWithTempFile
delfunction CatWithTempFile
2017-05-19 08:53:28 +00:00
delfunction RemoveLastLine
delfunction RemoveLastLineOneArg
2017-05-30 20:32:51 +00:00
delfunction TestCallback
delfunction FirstChainCallback
delfunction FirstChainCallbackSkipped
delfunction FirstChainCallbackSecondSkipped
delfunction SecondChainCallback
delfunction ThirdChainCallback
delfunction ChainWhereLastIsSkipped
delfunction ChainEndSkipped
2017-05-30 20:32:51 +00:00
delfunction SetUpLinters
delfunction GetLastMessage
2017-11-22 12:01:21 +00:00
delfunction IgnoredEmptyOutput
delfunction EchoLineNoPipe
delfunction FixWithJSONPostProcessing
delfunction JSONPostProcessor
2017-10-23 22:09:40 +00:00
augroup VaderTest
autocmd!
augroup END
augroup! VaderTest
2017-10-23 22:09:40 +00:00
call ale#test#RestoreDirectory()
call ale#fix#registry#ResetToDefaults()
2017-05-30 20:32:51 +00:00
call ale#linter#Reset()
setlocal buftype=nofile
if exists('g:test_filename') && filereadable(g:test_filename)
call delete(g:test_filename)
2017-05-30 20:32:51 +00:00
endif
call setloclist(0, [])
let g:ale_fix_buffer_data = {}
" Clear the messages between tests.
echomsg ''
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 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(ALEFix should apply simple functions in a chain):
let g:ale_fixers.testft = ['AddCarets', 'AddDollars']
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', 'AddDollars']
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['*'] = ['AddDollars']
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 = {'*': ['AddDollars']}
ALEFix
call ale#test#FlushJobs()
Expect(The file should be changed):
$a
$b
$c
Execute(ALEFix should allow commands to be run):
2017-10-23 22:09:40 +00:00
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()
2017-10-23 22:09:40 +00:00
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 AddDollars
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):
2017-10-23 22:09:40 +00:00
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()
2017-10-23 22:09:40 +00:00
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):
2017-10-23 22:09:40 +00:00
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', 'AddDollars']
ALEFix
call ale#test#FlushJobs()
2017-10-23 22:09:40 +00:00
endif
Expect(The lines from the temporary file should be modified):
$x
Execute(ALEFix should send lines modified by functions to jobs):
2017-10-23 22:09:40 +00:00
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 = ['AddDollars', 'CatLine']
ALEFix
call ale#test#FlushJobs()
2017-10-23 22:09:40 +00:00
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', 'AddDollars']
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
2017-05-19 08:53:28 +00:00
Execute(ALEFix should be able to remove the last line for files):
let g:ale_fixers.testft = ['RemoveLastLine']
ALEFix
call ale#test#FlushJobs()
2017-05-19 08:53:28 +00:00
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
2017-05-20 15:00:05 +00:00
Execute(ALEFix should user buffer-local fixer settings):
let g:ale_fixers.testft = ['AddCarets', 'AddDollars']
let b:ale_fixers = {'testft': ['RemoveLastLine']}
ALEFix
call ale#test#FlushJobs()
2017-05-20 15:00:05 +00:00
Expect(There should be only two lines):
a
b
2017-05-30 20:32:51 +00:00
Execute(ALEFix should allow Lists to be used for buffer-local fixer settings):
let g:ale_fixers.testft = ['AddCarets', 'AddDollars']
let b:ale_fixers = ['RemoveLastLine']
ALEFix
call ale#test#FlushJobs()
Expect(There should be only two lines):
a
b
2017-05-30 20:32:51 +00:00
Given testft (A file with three lines):
a
b
c
2018-11-10 10:06:48 +00:00
Execute(ALEFix should fix files on the save event):
2017-05-30 20:32:51 +00:00
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)
2017-05-30 20:32:51 +00:00
let g:ale_fixers.testft = ['AddDollars']
" We have to set the buftype to empty so the file will be written.
setlocal buftype=
2017-05-30 20:32:51 +00:00
call SetUpLinters()
call ale#events#SaveEvent(bufnr(''))
call ale#test#FlushJobs()
2017-05-30 20:32:51 +00:00
" We should save the file.
AssertEqual ['$a', '$b', '$c'], readfile(g:test_filename)
Assert !&modified, 'The file was marked as ''modified'''
2017-05-30 20:32:51 +00:00
2017-10-23 22:09:40 +00:00
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,
2018-07-23 19:41:06 +00:00
\}], ale#test#GetLoclistWithoutModule()
2017-10-23 22:09:40 +00:00
endif
2017-05-30 20:32:51 +00:00
Expect(The buffer should be modified):
$a
$b
$c
2018-11-10 10:06:48 +00:00
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)
2018-11-10 10:06:48 +00:00
let g:ale_fixers.testft = ['AddDollars']
" 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)
2018-11-10 10:06:48 +00:00
Assert &modified, 'The was not marked as ''modified'''
" We should not run the linter.
AssertEqual [], ale#test#GetLoclistWithoutModule()
Expect(The buffer should not be modified):
a
b
c
2017-05-30 20:32:51 +00:00
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)
2017-05-30 20:32:51 +00:00
let g:ale_fixers.testft = []
call SetUpLinters()
call ale#events#SaveEvent(bufnr(''))
call ale#test#FlushJobs()
2017-05-30 20:32:51 +00:00
Assert !filereadable(g:test_filename), 'The file should not have been saved'
2017-05-30 20:32:51 +00:00
2017-10-23 22:09:40 +00:00
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,
2018-07-23 19:41:06 +00:00
\}], ale#test#GetLoclistWithoutModule()
2017-10-23 22:09:40 +00:00
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'
2017-10-23 22:09:40 +00:00
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,
2018-07-23 19:41:06 +00:00
\}], ale#test#GetLoclistWithoutModule()
2017-10-23 22:09:40 +00:00
endif
2017-05-30 20:32:51 +00:00
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,
\ },
\}, 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(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):
2017-10-23 22:09:40 +00:00
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()
2017-10-23 22:09:40 +00:00
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(Test fixing with chained callbacks):
let g:ale_fixers.testft = ['FirstChainCallback']
ALEFix
call ale#test#FlushJobs()
" The buffer shouldn't be piped in for earlier commands in the chain.
AssertEqual
\ [
\ string(ale#job#PrepareCommand(bufnr(''), 'echo echoline')),
\ string(ale#job#PrepareCommand(bufnr(''), 'echo echoline')),
\ ],
\ map(ale#history#Get(bufnr(''))[-2:-1], 'string(v:val.command)')
Expect(The echoed line should be added):
a
b
c
echoline
Execute(Test fixing with chained callback where the first command is skipped):
let g:ale_fixers.testft = ['FirstChainCallbackSkipped']
ALEFix
call ale#test#FlushJobs()
Expect(The default line should be added):
a
b
c
emptydefault
Execute(Test fixing with chained callback where the second command is skipped):
let g:ale_fixers.testft = ['FirstChainCallbackSecondSkipped']
ALEFix
call ale#test#FlushJobs()
Expect(The default line should be added):
a
b
c
thirddefault
Execute(Test fixing with chained callback where the final callback is skipped):
let g:ale_fixers.testft = ['ChainWhereLastIsSkipped']
ALEFix
call ale#test#FlushJobs()
Expect(The lines should be the same):
a
b
c
2017-11-22 12:01:21 +00:00
Execute(Empty output should be ignored):
let g:ale_fixers.testft = ['IgnoredEmptyOutput']
ALEFix
call ale#test#FlushJobs()
2017-11-22 12:01:21 +00:00
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)
2017-11-22 14:06:37 +00:00
" 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
2019-02-26 16:56:16 +00:00
Execute(ALEFix should support ale#command#Run):
let g:ale_fixers.testft = ['CatLineDeferred']
ALEFix
call ale#test#FlushJobs()
Expect(The extra line should be added):
a
b
c
d