All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
6 Save g:ale_lint_on_save
8 Save g:ale_command_wrapper
9 Save g:ale_filename_mappings
11 silent! cd /testplugin/test/fix
13 unlet! b:ale_lint_on_save
15 let g:ale_echo_cursor = 0
16 let g:ale_command_wrapper = ''
17 let g:ale_run_synchronously = 1
18 let g:ale_set_lists_synchronously = 1
19 let g:ale_fix_buffer_data = {}
23 let g:ale_filename_mappings = {}
26 let g:post_success = 0
29 autocmd User ALEFixPre let g:pre_success = 1
30 autocmd User ALEFixPost let g:post_success = 1
34 let &shell = '/bin/bash'
37 call ale#test#SetDirectory('/testplugin/test')
38 call ale#test#SetFilename('test.txt')
39 call ale#linter#PreventLoading('testft')
41 function AddCarets(buffer, lines) abort
42 " map() is applied to the original lines here.
43 " This way, we can ensure that defensive copies are made.
44 return map(a:lines, '''^'' . v:val')
47 function Capitalize(buffer, lines) abort
48 return map(a:lines, 'toupper(v:val)')
51 function DoNothing(buffer, lines) abort
55 function CatLine(buffer, lines) abort
56 return {'command': 'cat - <(echo d)'}
59 function CatLineOneArg(buffer) abort
60 return {'command': 'cat - <(echo d)'}
63 function CatLineDeferred(buffer, lines) abort
64 return ale#command#Run(a:buffer, 'echo', {
65 \ -> ale#command#Run(a:buffer, 'echo', {-> {'command': 'cat - <(echo d)'}})
69 function ReplaceWithTempFile(buffer, lines) abort
70 return {'command': 'echo x > %t', 'read_temporary_file': 1}
73 function CatWithTempFile(buffer, lines) abort
74 return {'command': 'cat %t <(echo d)'}
77 function EchoFilename(buffer, lines) abort
78 return {'command': 'echo %s'}
81 function RemoveLastLine(buffer, lines) abort
85 function RemoveLastLineOneArg(buffer) abort
89 function! TestCallback(buffer, output)
90 return [{'lnum': 1, 'col': 1, 'text': 'xxx'}]
93 " echo will output a single blank line, and we should ignore it.
94 function! IgnoredEmptyOutput(buffer, output)
95 return {'command': has('win32') ? 'echo(' : 'echo'}
98 function! EchoLineNoPipe(buffer, output)
99 return {'command': 'echo new line', 'read_buffer': 0}
102 function! SetUpLinters()
103 call ale#linter#Define('testft', {
104 \ 'name': 'testlinter',
105 \ 'callback': 'TestCallback',
106 \ 'executable': 'true',
111 function GetLastMessage()
116 let l:lines = split(l:output, "\n")
118 return empty(l:lines) ? '' : l:lines[-1]
121 function! FixWithJSONPostProcessing(buffer) abort
122 let l:ProcessWith = 'JSONPostProcessor'
124 " Test with lambdas where support is available.
126 let l:ProcessWith = {buffer, output -> JSONPostProcessor(buffer, output)}
129 " Escaping needs to be handled specially for CMD on Windows.
130 let l:json_string = has('win32')
131 \ ? '{"output":["x","y","z"]}'
132 \ : ale#Escape('{"output": ["x", "y", "z"]}')
135 \ 'command': 'echo ' . l:json_string,
137 \ 'process_with': l:ProcessWith,
141 function! JSONPostProcessor(buffer, output) abort
142 return json_decode(a:output[0]).output
147 unlet! g:test_filename
148 unlet! g:ale_run_synchronously
149 unlet! g:ale_set_lists_synchronously
150 unlet! g:ale_run_synchronously_callbacks
151 unlet! g:ale_emulate_job_failure
153 unlet! b:ale_lint_on_save
154 unlet! b:ale_fix_on_save
155 unlet! b:ale_quitting
156 delfunction AddCarets
157 delfunction Capitalize
158 delfunction DoNothing
160 delfunction CatLineOneArg
161 delfunction CatLineDeferred
162 delfunction ReplaceWithTempFile
163 delfunction CatWithTempFile
164 delfunction EchoFilename
165 delfunction RemoveLastLine
166 delfunction RemoveLastLineOneArg
167 delfunction TestCallback
168 delfunction SetUpLinters
169 delfunction GetLastMessage
170 delfunction IgnoredEmptyOutput
171 delfunction EchoLineNoPipe
172 delfunction FixWithJSONPostProcessing
173 delfunction JSONPostProcessor
181 call ale#test#RestoreDirectory()
183 call ale#fix#registry#ResetToDefaults()
184 call ale#linter#Reset()
186 setlocal buftype=nofile
188 if exists('g:test_filename') && filereadable(g:test_filename)
189 call delete(g:test_filename)
192 call setloclist(0, [])
194 let g:ale_fix_buffer_data = {}
196 " Clear the messages between tests.
199 if !exists('g:ale_command_wrapper')
200 let g:ale_command_wrapper = ''
203 Given testft (A file with three lines):
208 Execute(ALEFix should complain when there are no functions to call):
210 call ale#test#FlushJobs()
211 AssertEqual 'No fixers have been defined. Try :ALEFixSuggest', GetLastMessage()
213 Execute(ALEFix should not complain when the command is run with a bang):
217 call ale#test#FlushJobs()
218 AssertEqual 'none', GetLastMessage()
220 Execute(ALEFix should apply simple functions):
221 let g:ale_fixers.testft = ['AddCarets']
223 call ale#test#FlushJobs()
225 Expect(The first function should be used):
230 Execute(Should apply filename mpapings):
231 " The command echos %s, and we'll map the current path so we can check
232 " that ALEFix applies filename mappings, end-to-end.
233 let g:ale_filename_mappings = {
235 \ [expand('%:p:h') . '/', '/some/fake/path/'],
239 call ale#fix#registry#Add('echo_filename', 'EchoFilename', [], 'echo filename')
240 let g:ale_fixers.testft = ['echo_filename']
242 call ale#test#FlushJobs()
243 " Remote trailing whitespace from the line.
244 call setline(1, substitute(getline(1), '[ \r]\+$', '', ''))
246 Expect(The mapped filename should be printed):
247 /some/fake/path/test.txt
249 Execute(ALEFix should apply simple functions in a chain):
250 let g:ale_fixers.testft = ['AddCarets', 'Capitalize']
252 call ale#test#FlushJobs()
254 Expect(Both functions should be used):
259 Execute(ALEFix should allow 0 to be returned to skip functions):
260 let g:ale_fixers.testft = ['DoNothing', 'Capitalize']
262 call ale#test#FlushJobs()
264 Expect(Only the second function should be applied):
269 Execute(The * fixers shouldn't be used if an empty list is set for fixers):
270 let g:ale_fixers.testft = []
271 let g:ale_fixers['*'] = ['Capitalize']
273 call ale#test#FlushJobs()
275 Expect(Nothing should be changed):
280 Execute(* fixers should be used if no filetype is matched):
281 let g:ale_fixers = {'*': ['Capitalize']}
283 call ale#test#FlushJobs()
285 Expect(The file should be changed):
290 Execute(ALEFix should allow commands to be run):
292 " Just skip this test on Windows, we can't run it.
293 call setline(1, ['a', 'b', 'c', 'd'])
295 let g:ale_fixers.testft = ['CatLine']
297 call ale#test#FlushJobs()
300 Expect(An extra line should be added):
306 Execute(ALEFix should use fixers passed in commandline when provided):
307 let g:ale_fixers.testft = ['RemoveLastLine']
308 ALEFix AddCarets Capitalize
309 call ale#test#FlushJobs()
311 Expect(Only fixers passed via command line should be run):
316 Execute(ALEFix should allow temporary files to be read):
318 " Just skip this test on Windows, we can't run it.
319 call setline(1, ['x'])
322 let g:ale_fixers.testft = ['ReplaceWithTempFile']
324 call ale#test#FlushJobs()
327 Expect(The line we wrote to the temporary file should be used here):
330 Execute(ALEFix should not read the temporary file when the option is not set):
332 " Just skip this test on Windows, we can't run it.
333 call setline(1, ['a', 'b', 'c', 'd'])
335 let g:ale_fixers.testft = ['CatWithTempFile']
337 call ale#test#FlushJobs()
340 Expect(An extra line should be added):
346 Execute(ALEFix should allow jobs and simple functions to be combined):
348 " Just skip this test on Windows, we can't run it.
349 call setline(1, ['X'])
352 let g:ale_fixers.testft = ['ReplaceWithTempFile', 'Capitalize']
354 call ale#test#FlushJobs()
357 Expect(The lines from the temporary file should be modified):
360 Execute(ALEFix should send lines modified by functions to jobs):
362 " Just skip this test on Windows, we can't run it.
363 call setline(1, ['A', 'B', 'C', 'd'])
365 let g:ale_fixers.testft = ['Capitalize', 'CatLine']
367 call ale#test#FlushJobs()
370 Expect(The lines should first be modified by the function, then the job):
376 Execute(ALEFix should skip commands when jobs fail to run):
377 let g:ale_emulate_job_failure = 1
378 let g:ale_fixers.testft = ['CatLine', 'Capitalize']
380 call ale#test#FlushJobs()
382 Expect(Only the second function should be applied):
387 Execute(ALEFix should handle strings for selecting a single function):
388 let g:ale_fixers.testft = 'AddCarets'
390 call ale#test#FlushJobs()
392 Expect(The first function should be used):
397 Execute(ALEFix should use functions from the registry):
398 call ale#fix#registry#Add('add_carets', 'AddCarets', [], 'Add some carets')
399 let g:ale_fixers.testft = ['add_carets']
401 call ale#test#FlushJobs()
403 Expect(The registry function should be used):
408 Execute(ALEFix should be able to remove the last line for files):
409 let g:ale_fixers.testft = ['RemoveLastLine']
411 call ale#test#FlushJobs()
413 Expect(There should be only two lines):
417 Execute(ALEFix should accept funcrefs):
418 let g:ale_fixers.testft = [function('RemoveLastLine')]
420 call ale#test#FlushJobs()
422 Expect(There should be only two lines):
426 Execute(ALEFix should accept lambdas):
428 " NeoVim 0.1.7 can't interpret lambdas correctly, so just set the lines
429 " to make the test pass.
430 call setline(1, ['a', 'b', 'c', 'd'])
432 let g:ale_fixers.testft = [{buffer, lines -> lines + ['d']}]
434 call ale#test#FlushJobs()
437 Expect(There should be an extra line):
443 Execute(ALEFix should user buffer-local fixer settings):
444 let g:ale_fixers.testft = ['AddCarets', 'Capitalize']
445 let b:ale_fixers = {'testft': ['RemoveLastLine']}
447 call ale#test#FlushJobs()
449 Expect(There should be only two lines):
453 Execute(ALEFix should allow Lists to be used for buffer-local fixer settings):
454 let g:ale_fixers.testft = ['AddCarets', 'Capitalize']
455 let b:ale_fixers = ['RemoveLastLine']
457 call ale#test#FlushJobs()
459 Expect(There should be only two lines):
463 Given testft (A file with three lines):
468 Execute(ALEFix should fix files on the save event):
469 let g:ale_fix_on_save = 1
470 let g:ale_lint_on_save = 1
471 let g:ale_enabled = 1
473 let g:test_filename = tempname()
474 execute 'noautocmd silent file ' . fnameescape(g:test_filename)
475 call writefile(getline(1, '$'), g:test_filename)
477 let g:ale_fixers.testft = ['Capitalize']
479 " We have to set the buftype to empty so the file will be written.
483 call ale#events#SaveEvent(bufnr(''))
484 call ale#test#FlushJobs()
486 " We should save the file.
487 AssertEqual ['A', 'B', 'C'], readfile(g:test_filename)
488 Assert !&modified, 'The file was marked as ''modified'''
491 " We should have run the linter.
493 \ 'bufnr': bufnr('%'),
502 \}], ale#test#GetLoclistWithoutNewerKeys()
505 Expect(The buffer should be modified):
510 Given testft (A file with three lines):
515 Execute(ALEFix should run the linters with b:ale_lint_on_save = 1):
516 let g:ale_fix_on_save = 0
517 let b:ale_fix_on_save = 1
518 let g:ale_lint_on_save = 1
519 let g:ale_enabled = 1
521 let g:test_filename = tempname()
522 execute 'noautocmd silent file ' . fnameescape(g:test_filename)
523 call writefile(getline(1, '$'), g:test_filename)
525 let g:ale_fixers.testft = ['Capitalize']
527 " We have to set the buftype to empty so the file will be written.
531 call ale#events#SaveEvent(bufnr(''))
532 call ale#test#FlushJobs()
534 " We should save the file.
535 AssertEqual ['A', 'B', 'C'], readfile(g:test_filename)
536 Assert !&modified, 'The file was marked as ''modified'''
539 " We should have run the linter.
541 \ 'bufnr': bufnr('%'),
550 \}], ale#test#GetLoclistWithoutNewerKeys()
553 Expect(The buffer should be modified):
558 Execute(ALEFix should not fix files on :wq):
559 let g:ale_fix_on_save = 1
560 let g:ale_lint_on_save = 1
561 let g:ale_enabled = 1
563 let g:test_filename = tempname()
564 execute 'noautocmd silent file ' . fnameescape(g:test_filename)
565 call writefile(getline(1, '$'), g:test_filename)
567 let g:ale_fixers.testft = ['Capitalize']
569 " We have to set the buftype to empty so the file will be written.
572 call ale#events#QuitEvent(bufnr(''))
575 call ale#events#SaveEvent(bufnr(''))
577 " We should save the file.
578 AssertEqual ['a', 'b', 'c'], readfile(g:test_filename)
579 Assert &modified, 'The was not marked as ''modified'''
581 " We should not run the linter.
582 AssertEqual [], ale#test#GetLoclistWithoutNewerKeys()
584 Expect(The buffer should not be modified):
589 Given testft (A file with three lines):
594 Execute(ALEFix should still lint with no linters to be applied):
595 let g:ale_fix_on_save = 1
596 let g:ale_lint_on_save = 1
597 let g:ale_enabled = 1
599 let g:test_filename = tempname()
600 execute 'noautocmd silent file ' . fnameescape(g:test_filename)
602 let g:ale_fixers.testft = []
605 call ale#events#SaveEvent(bufnr(''))
606 call ale#test#FlushJobs()
608 Assert !filereadable(g:test_filename), 'The file should not have been saved'
611 " We have run the linter.
613 \ 'bufnr': bufnr('%'),
622 \}], ale#test#GetLoclistWithoutNewerKeys()
625 Expect(The buffer should be the same):
630 Execute(ALEFix should still lint when nothing was fixed on save):
631 let g:ale_fix_on_save = 1
632 let g:ale_lint_on_save = 1
633 let g:ale_enabled = 1
635 let g:test_filename = tempname()
636 execute 'noautocmd silent file ' . fnameescape(g:test_filename)
638 let g:ale_fixers.testft = ['DoNothing']
641 call ale#events#SaveEvent(bufnr(''))
642 call ale#test#FlushJobs()
644 Assert !filereadable(g:test_filename), 'The file should not have been saved'
647 " We should have run the linter.
649 \ 'bufnr': bufnr('%'),
658 \}], ale#test#GetLoclistWithoutNewerKeys()
661 Expect(The buffer should be the same):
666 Execute(ALEFix should not lint the buffer on save if linting on save is disabled globally):
667 let g:ale_fix_on_save = 1
668 let g:ale_lint_on_save = 0
669 let g:ale_enabled = 1
671 let g:test_filename = tempname()
672 execute 'noautocmd silent file ' . fnameescape(g:test_filename)
674 let g:ale_fixers.testft = ['DoNothing']
677 call ale#events#SaveEvent(bufnr(''))
678 call ale#test#FlushJobs()
680 Assert !filereadable(g:test_filename), 'The file should not have been saved'
682 AssertEqual [], ale#test#GetLoclistWithoutNewerKeys()
684 Expect(The buffer should be the same):
689 Execute(ALEFix should not lint the buffer on save if linting on save is disabled locally):
690 let g:ale_fix_on_save = 1
691 let b:ale_lint_on_save = 0
692 let g:ale_enabled = 1
694 let g:test_filename = tempname()
695 execute 'noautocmd silent file ' . fnameescape(g:test_filename)
697 let g:ale_fixers.testft = ['DoNothing']
700 call ale#events#SaveEvent(bufnr(''))
701 call ale#test#FlushJobs()
703 Assert !filereadable(g:test_filename), 'The file should not have been saved'
705 AssertEqual [], ale#test#GetLoclistWithoutNewerKeys()
707 Expect(The buffer should be the same):
712 Given testft (A file with three lines):
717 Execute(ale#fix#InitBufferData() should set up the correct data):
718 let g:test_filename = tempname()
719 execute 'noautocmd silent file ' . fnameescape(g:test_filename)
721 call ale#fix#InitBufferData(bufnr(''), 'save_file')
725 \ 'temporary_directory_list': [],
727 \ 'lines_before': ['a', 'b', 'c'],
729 \ 'ignore_file_changed_errors': 0,
731 \}, g:ale_fix_buffer_data
733 call ale#fix#InitBufferData(bufnr(''), '!')
737 \ 'temporary_directory_list': [],
739 \ 'lines_before': ['a', 'b', 'c'],
741 \ 'ignore_file_changed_errors': 1,
743 \}, g:ale_fix_buffer_data
745 Execute(ALEFix simple functions should be able to accept one argument, the buffer):
746 let g:ale_fixers.testft = ['RemoveLastLineOneArg']
748 call ale#test#FlushJobs()
750 Expect(There should be only two lines):
754 Execute(ALEFix should modify a buffer that is not modifiable, if it becomes modifiable later):
755 let g:ale_fixers.testft = ['RemoveLastLineOneArg']
759 call ale#test#FlushJobs()
761 call ale#fix#ApplyQueuedFixes(bufnr(''))
763 Expect(There should be only two lines):
767 Execute(b:ale_fix_on_save = 1 should override g:ale_fix_on_save = 0):
768 let g:ale_fix_on_save = 0
769 let b:ale_fix_on_save = 1
771 let g:ale_fixers.testft = ['RemoveLastLineOneArg']
772 call ale#events#SaveEvent(bufnr(''))
774 Expect(There should be only two lines):
778 Execute(b:ale_fix_on_save = 0 should override g:ale_fix_on_save = 1):
779 let g:ale_fix_on_save = 1
780 let b:ale_fix_on_save = 0
782 let g:ale_fixers.testft = ['RemoveLastLineOneArg']
783 call ale#events#SaveEvent(bufnr(''))
785 Expect(The lines should be the same):
790 Execute(ALEFix functions returning jobs should be able to accept one argument):
792 " Just skip this test on Windows, we can't run it.
793 call setline(1, ['a', 'b', 'c', 'd'])
795 let g:ale_fixers.testft = ['CatLine']
797 call ale#test#FlushJobs()
800 Expect(An extra line should be added):
806 Execute(ALE should print a message telling you something isn't a valid fixer when you type some nonsense):
807 let g:ale_fixers.testft = ['CatLine', 'invalidname']
809 call ale#test#FlushJobs()
811 AssertEqual 'There is no fixer named `invalidname`. Check :ALEFixSuggest', GetLastMessage()
813 Execute(ALE should complain about invalid fixers with minuses in the name):
814 let g:ale_fixers.testft = ['foo-bar']
816 call ale#test#FlushJobs()
818 AssertEqual 'There is no fixer named `foo-bar`. Check :ALEFixSuggest', GetLastMessage()
820 Execute(ALE should tolerate valid fixers with minuses in the name):
821 let g:ale_fixers.testft = ['prettier-standard']
823 call ale#test#FlushJobs()
825 Execute(Empty output should be ignored):
826 let g:ale_fixers.testft = ['IgnoredEmptyOutput']
828 call ale#test#FlushJobs()
830 Expect(The lines should be the same):
835 Execute(A temporary file shouldn't be piped into the command when disabled):
836 let g:ale_fixers.testft = ['EchoLineNoPipe']
838 call ale#test#FlushJobs()
841 \ string(ale#job#PrepareCommand(bufnr(''), 'echo new line')),
842 \ string(ale#history#Get(bufnr(''))[-1].command)
844 " Remove trailing whitespace for Windows.
849 Expect(The new line should be used):
852 Execute(Post-processing should work):
853 let g:ale_fixers.testft = ['FixWithJSONPostProcessing']
855 call ale#test#FlushJobs()
857 Expect(The lines in the JSON should be used):
862 Execute(ALEFix should apply autocmds):
863 let g:ale_fixers.testft = ['AddCarets']
865 call ale#test#FlushJobs()
867 AssertEqual g:pre_success, 1
868 AssertEqual g:post_success, 1
870 Execute(ALEFix should support ale#command#Run):
872 " Just skip this test on Windows, we can't run it.
873 call setline(1, ['a', 'b', 'c', 'd'])
875 let g:ale_fixers.testft = ['CatLineDeferred']
877 call ale#test#FlushJobs()
880 Expect(The extra line should be added):