diff options
author | toastal <toastal@protonmail.com> | 2020-09-08 10:08:00 +0700 |
---|---|---|
committer | toastal <toastal@protonmail.com> | 2020-09-08 10:08:00 +0700 |
commit | f07ecbc579a216a0fff18bdc010fe1a4de91fa39 (patch) | |
tree | 13c59e33534ae7b7a79fdf0edaa180222f0ec86b /test | |
parent | 167e2e77506c55831921ee40dc30c92f7f2aaae8 (diff) | |
parent | b4b75126f9eae30da8f5e0cb9ec100feb38c1cb6 (diff) | |
download | ale-f07ecbc579a216a0fff18bdc010fe1a4de91fa39.zip |
merge master -- apparently someone else added dhall?
Diffstat (limited to 'test')
100 files changed, 2347 insertions, 1179 deletions
diff --git a/test/command_callback/test_ada_gcc_command_callbacks.vader b/test/command_callback/test_ada_gcc_command_callbacks.vader index de6e355e..906b31a4 100644 --- a/test/command_callback/test_ada_gcc_command_callbacks.vader +++ b/test/command_callback/test_ada_gcc_command_callbacks.vader @@ -18,11 +18,10 @@ After: call ale#assert#TearDownLinterTest() Execute(The executable should be configurable): - AssertLinter 'gcc', \ ale#Escape('gcc') . ' -x ada -c -gnatc' \ . ' -o ' . b:out_file - \ . ' -I ' . ale#Escape(getcwd()) + \ . ' -I %s:h' \ . ' -gnatwa -gnatq %t' let b:ale_ada_gcc_executable = 'foo' @@ -30,15 +29,14 @@ Execute(The executable should be configurable): AssertLinter 'foo', \ ale#Escape('foo') . ' -x ada -c -gnatc' \ . ' -o ' . b:out_file - \ . ' -I ' . ale#Escape(getcwd()) + \ . ' -I %s:h' \ . ' -gnatwa -gnatq %t' Execute(The options should be configurable): - let g:ale_ada_gcc_options = '--foo --bar' AssertLinter 'gcc', \ ale#Escape('gcc') . ' -x ada -c -gnatc' \ . ' -o ' . b:out_file - \ . ' -I ' . ale#Escape(getcwd()) + \ . ' -I %s:h' \ . ' --foo --bar %t' diff --git a/test/command_callback/test_asm_gcc_command_callbacks.vader b/test/command_callback/test_asm_gcc_command_callbacks.vader index 42606ec0..5976b5f2 100644 --- a/test/command_callback/test_asm_gcc_command_callbacks.vader +++ b/test/command_callback/test_asm_gcc_command_callbacks.vader @@ -3,7 +3,7 @@ Before: call ale#test#SetFilename('test.cpp') let b:command_tail = ' -x assembler' \ . ' -o ' . (has('win32') ? 'nul': '/dev/null') - \ . '-iquote ' . ale#Escape(g:dir) + \ . '-iquote %s:h' \ . ' -Wall -' After: diff --git a/test/command_callback/test_c_cc_command_callbacks.vader b/test/command_callback/test_c_cc_command_callbacks.vader new file mode 100644 index 00000000..c8c2de7d --- /dev/null +++ b/test/command_callback/test_c_cc_command_callbacks.vader @@ -0,0 +1,55 @@ +Before: + Save g:ale_c_parse_makefile + Save g:ale_history_enabled + + let g:ale_c_parse_makefile = 0 + let g:ale_history_enabled = 0 + + let g:get_cflags_return_value = '' + let g:executable_map = {} + + runtime autoload/ale/c.vim + runtime autoload/ale/engine.vim + + function! ale#engine#IsExecutable(buffer, executable) abort + return has_key(g:executable_map, a:executable) + endfunction + + function! ale#c#GetCFlags(buffer, output) abort + return g:get_cflags_return_value + endfunction + + call ale#assert#SetUpLinterTest('c', 'cc') + + let b:command_tail = ' -S -x c' + \ . ' -o ' . (has('win32') ? 'nul': '/dev/null') + \ . ' -iquote %s:h' + \ . ' -std=c11 -Wall -' + +After: + unlet! g:get_cflags_return_value + unlet! g:executable_map + unlet! b:command_tail + + runtime autoload/ale/c.vim + runtime autoload/ale/engine.vim + + call ale#assert#TearDownLinterTest() + +Execute(clang should be used instead of gcc, if available): + let g:executable_map = {'clang': 1} + + AssertLinter 'clang', [ale#Escape('clang') . b:command_tail] + +Execute(The executable should be configurable): + AssertLinter 'gcc', [ale#Escape('gcc') . b:command_tail] + + let b:ale_c_cc_executable = 'foobar' + + AssertLinter 'foobar', [ale#Escape('foobar') . b:command_tail] + +Execute(The -std flag should be replaced by parsed C flags): + let b:command_tail = substitute(b:command_tail, 'c11', 'c99 ', '') + let g:get_cflags_return_value = '-std=c99' + + AssertLinter 'gcc', ale#Escape('gcc') . b:command_tail diff --git a/test/command_callback/test_c_clang_command_callbacks.vader b/test/command_callback/test_c_clang_command_callbacks.vader deleted file mode 100644 index b8c02e4d..00000000 --- a/test/command_callback/test_c_clang_command_callbacks.vader +++ /dev/null @@ -1,20 +0,0 @@ -Before: - Save g:ale_c_parse_makefile - let g:ale_c_parse_makefile = 0 - - call ale#assert#SetUpLinterTest('c', 'clang') - let b:command_tail = ' -S -x c -fsyntax-only -iquote' - \ . ' ' . ale#Escape(getcwd()) - \ . ' -std=c11 -Wall -' - -After: - unlet! b:command_tail - - call ale#assert#TearDownLinterTest() - -Execute(The executable should be configurable): - AssertLinter 'clang', [ale#Escape('clang') . b:command_tail] - - let b:ale_c_clang_executable = 'foobar' - - AssertLinter 'foobar', [ale#Escape('foobar') . b:command_tail] diff --git a/test/command_callback/test_c_gcc_command_callbacks.vader b/test/command_callback/test_c_gcc_command_callbacks.vader deleted file mode 100644 index 2dbb8b7c..00000000 --- a/test/command_callback/test_c_gcc_command_callbacks.vader +++ /dev/null @@ -1,22 +0,0 @@ -Before: - Save g:ale_c_parse_makefile - let g:ale_c_parse_makefile = 0 - - call ale#assert#SetUpLinterTest('c', 'gcc') - - let b:command_tail = ' -S -x c' - \ . ' -o ' . (has('win32') ? 'nul': '/dev/null') - \ . ' -iquote ' . ale#Escape(getcwd()) - \ . ' -std=c11 -Wall -' - -After: - call ale#assert#TearDownLinterTest() - - unlet! b:command_tail - -Execute(The executable should be configurable): - AssertLinter 'gcc', [ale#Escape('gcc') . b:command_tail] - - let b:ale_c_gcc_executable = 'foobar' - - AssertLinter 'foobar', [ale#Escape('foobar') . b:command_tail] diff --git a/test/command_callback/test_c_import_paths.vader b/test/command_callback/test_c_import_paths.vader index e6102998..3c2bd79b 100644 --- a/test/command_callback/test_c_import_paths.vader +++ b/test/command_callback/test_c_import_paths.vader @@ -7,6 +7,7 @@ Before: Save g:__ale_c_project_filenames let g:original_project_filenames = g:__ale_c_project_filenames + let g:executable_map = {} " Remove the .git/HEAD dir for C import paths for these tests. " The tests run inside of a git repo. @@ -18,106 +19,67 @@ Before: let g:ale_c_parse_compile_commands = 0 let g:ale_c_parse_makefile = 0 + runtime autoload/ale/engine.vim + + function! ale#engine#IsExecutable(buffer, executable) abort + return has_key(g:executable_map, a:executable) + endfunction + After: Restore unlet! g:original_project_filenames + unlet! g:executable_map + + runtime autoload/ale/engine.vim call ale#assert#TearDownLinterTest() -Execute(The C GCC handler should include 'include' directories for projects with a Makefile): - call ale#assert#SetUpLinterTest('c', 'gcc') +Execute(The C cc linter should include 'include' directories for projects with a Makefile): + call ale#assert#SetUpLinterTest('c', 'cc') call ale#test#SetFilename('../test_c_projects/makefile_project/subdir/file.c') - let g:ale_c_gcc_options = '' + let g:ale_c_cc_options = '' AssertLinter 'gcc', \ ale#Escape('gcc') \ . ' -S -x c -o ' . (has('win32') ? 'nul': '/dev/null') - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/makefile_project/subdir')) + \ . ' -iquote %s:h' \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/makefile_project/include')) \ . ' -' -Execute(The C GCC handler should include 'include' directories for projects with a configure file): - call ale#assert#SetUpLinterTest('c', 'gcc') +Execute(The C cc linter should include 'include' directories for projects with a configure file): + call ale#assert#SetUpLinterTest('c', 'cc') call ale#test#SetFilename('../test_c_projects/configure_project/subdir/file.c') - let g:ale_c_gcc_options = '' + let g:ale_c_cc_options = '' AssertLinter 'gcc', \ ale#Escape('gcc') \ . ' -S -x c -o ' . (has('win32') ? 'nul': '/dev/null') - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/configure_project/subdir')) + \ . ' -iquote %s:h' \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/configure_project/include')) \ . ' -' -Execute(The C GCC handler should include root directories for projects with .h files in them): - call ale#assert#SetUpLinterTest('c', 'gcc') +Execute(The C cc linter should include root directories for projects with .h files in them): + call ale#assert#SetUpLinterTest('c', 'cc') call ale#test#SetFilename('../test_c_projects/h_file_project/subdir/file.c') - let g:ale_c_gcc_options = '' + let g:ale_c_cc_options = '' AssertLinter 'gcc', \ ale#Escape('gcc') \ . ' -S -x c -o ' . (has('win32') ? 'nul': '/dev/null') - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/h_file_project/subdir')) + \ . ' -iquote %s:h' \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/h_file_project')) \ . ' -' -Execute(The C GCC handler should include root directories for projects with .hpp files in them): - call ale#assert#SetUpLinterTest('c', 'gcc') +Execute(The C cc linter should include root directories for projects with .hpp files in them): + call ale#assert#SetUpLinterTest('c', 'cc') call ale#test#SetFilename('../test_c_projects/hpp_file_project/subdir/file.c') - let g:ale_c_gcc_options = '' + let g:ale_c_cc_options = '' AssertLinter 'gcc', \ ale#Escape('gcc') \ . ' -S -x c -o ' . (has('win32') ? 'nul': '/dev/null') - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/hpp_file_project/subdir')) - \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/hpp_file_project')) - \ . ' -' - -Execute(The C Clang handler should include 'include' directories for projects with a Makefile): - call ale#assert#SetUpLinterTest('c', 'clang') - call ale#test#SetFilename('../test_c_projects/makefile_project/subdir/file.c') - let g:ale_c_clang_options = '' - - AssertLinter 'clang', - \ ale#Escape('clang') - \ . ' -S -x c -fsyntax-only' - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/makefile_project/subdir')) - \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/makefile_project/include')) - \ . ' -' - -Execute(The C Clang handler should include 'include' directories for projects with a configure file): - call ale#assert#SetUpLinterTest('c', 'clang') - call ale#test#SetFilename('../test_c_projects/h_file_project/subdir/file.c') - let g:ale_c_clang_options = '' - - AssertLinter 'clang', - \ ale#Escape('clang') - \ . ' -S -x c -fsyntax-only' - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/h_file_project/subdir')) - \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/h_file_project')) - \ . ' -' - -Execute(The C Clang handler should include root directories for projects with .h files in them): - call ale#assert#SetUpLinterTest('c', 'clang') - call ale#test#SetFilename('../test_c_projects/h_file_project/subdir/file.c') - let g:ale_c_clang_options = '' - - AssertLinter 'clang', - \ ale#Escape('clang') - \ . ' -S -x c -fsyntax-only' - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/h_file_project/subdir')) - \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/h_file_project')) - \ . ' -' - -Execute(The C Clang handler should include root directories for projects with .hpp files in them): - call ale#assert#SetUpLinterTest('c', 'clang') - call ale#test#SetFilename('../test_c_projects/hpp_file_project/subdir/file.c') - let g:ale_c_clang_options = '' - - AssertLinter 'clang', - \ ale#Escape('clang') - \ . ' -S -x c -fsyntax-only' - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/hpp_file_project/subdir')) + \ . ' -iquote %s:h' \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/hpp_file_project')) \ . ' -' @@ -131,99 +93,51 @@ Execute(The C ClangTidy handler should include 'include' directories for project \ . ' %s ' \ . '-- -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/makefile_project/include')) -Execute(The C++ GCC handler should include 'include' directories for projects with a Makefile): - call ale#assert#SetUpLinterTest('cpp', 'gcc') +Execute(The C++ cc linter should include 'include' directories for projects with a Makefile): + call ale#assert#SetUpLinterTest('cpp', 'cc') call ale#test#SetFilename('../test_c_projects/makefile_project/subdir/file.cpp') - let g:ale_cpp_gcc_options = '' + let g:ale_cpp_cc_options = '' AssertLinter 'gcc', \ ale#Escape('gcc') \ . ' -S -x c++ -o ' . (has('win32') ? 'nul': '/dev/null') - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/makefile_project/subdir')) + \ . ' -iquote %s:h' \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/makefile_project/include')) \ . ' -' -Execute(The C++ GCC handler should include 'include' directories for projects with a configure file): - call ale#assert#SetUpLinterTest('cpp', 'gcc') +Execute(The C++ cc linter should include 'include' directories for projects with a configure file): + call ale#assert#SetUpLinterTest('cpp', 'cc') call ale#test#SetFilename('../test_c_projects/configure_project/subdir/file.cpp') - let g:ale_cpp_gcc_options = '' + let g:ale_cpp_cc_options = '' AssertLinter 'gcc', \ ale#Escape('gcc') \ . ' -S -x c++ -o ' . (has('win32') ? 'nul': '/dev/null') - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/configure_project/subdir')) + \ . ' -iquote %s:h' \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/configure_project/include')) \ . ' -' -Execute(The C++ GCC handler should include root directories for projects with .h files in them): - call ale#assert#SetUpLinterTest('cpp', 'gcc') +Execute(The C++ cc linter should include root directories for projects with .h files in them): + call ale#assert#SetUpLinterTest('cpp', 'cc') call ale#test#SetFilename('../test_c_projects/h_file_project/subdir/file.cpp') - let g:ale_cpp_gcc_options = '' + let g:ale_cpp_cc_options = '' AssertLinter 'gcc', \ ale#Escape('gcc') \ . ' -S -x c++ -o ' . (has('win32') ? 'nul': '/dev/null') - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/h_file_project/subdir')) + \ . ' -iquote %s:h' \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/h_file_project')) \ . ' -' -Execute(The C++ GCC handler should include root directories for projects with .hpp files in them): - call ale#assert#SetUpLinterTest('cpp', 'gcc') +Execute(The C++ cc linter should include root directories for projects with .hpp files in them): + call ale#assert#SetUpLinterTest('cpp', 'cc') call ale#test#SetFilename('../test_c_projects/hpp_file_project/subdir/file.cpp') - let g:ale_cpp_gcc_options = '' + let g:ale_cpp_cc_options = '' AssertLinter 'gcc', \ ale#Escape('gcc') \ . ' -S -x c++ -o ' . (has('win32') ? 'nul': '/dev/null') - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/hpp_file_project/subdir')) - \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/hpp_file_project')) - \ . ' -' - -Execute(The C++ Clang handler should include 'include' directories for projects with a Makefile): - call ale#assert#SetUpLinterTest('cpp', 'clang') - call ale#test#SetFilename('../test_c_projects/makefile_project/subdir/file.cpp') - let g:ale_cpp_clang_options = '' - - AssertLinter 'clang++', - \ ale#Escape('clang++') - \ . ' -S -x c++ -fsyntax-only' - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/makefile_project/subdir')) - \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/makefile_project/include')) - \ . ' -' - -Execute(The C++ Clang handler should include 'include' directories for projects with a configure file): - call ale#assert#SetUpLinterTest('cpp', 'clang') - call ale#test#SetFilename('../test_c_projects/configure_project/subdir/file.cpp') - let g:ale_cpp_clang_options = '' - - AssertLinter 'clang++', - \ ale#Escape('clang++') - \ . ' -S -x c++ -fsyntax-only' - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/configure_project/subdir')) - \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/configure_project/include')) - \ . ' -' - -Execute(The C++ Clang handler should include root directories for projects with .h files in them): - call ale#assert#SetUpLinterTest('cpp', 'clang') - call ale#test#SetFilename('../test_c_projects/h_file_project/subdir/file.cpp') - let g:ale_cpp_clang_options = '' - - AssertLinter 'clang++', - \ ale#Escape('clang++') - \ . ' -S -x c++ -fsyntax-only' - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/h_file_project/subdir')) - \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/h_file_project')) - \ . ' -' - -Execute(The C++ Clang handler should include root directories for projects with .hpp files in them): - call ale#assert#SetUpLinterTest('cpp', 'clang') - call ale#test#SetFilename('../test_c_projects/hpp_file_project/subdir/file.cpp') - let g:ale_cpp_clang_options = '' - - AssertLinter 'clang++', - \ ale#Escape('clang++') - \ . ' -S -x c++ -fsyntax-only' - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/hpp_file_project/subdir')) + \ . ' -iquote %s:h' \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/hpp_file_project')) \ . ' -' diff --git a/test/command_callback/test_cpp_cc_command_callbacks.vader b/test/command_callback/test_cpp_cc_command_callbacks.vader new file mode 100644 index 00000000..dec3a07c --- /dev/null +++ b/test/command_callback/test_cpp_cc_command_callbacks.vader @@ -0,0 +1,55 @@ +Before: + Save g:ale_c_parse_makefile + Save g:ale_history_enabled + + let g:ale_c_parse_makefile = 0 + let g:ale_history_enabled = 0 + + let g:get_cflags_return_value = '' + let g:executable_map = {} + + runtime autoload/ale/c.vim + runtime autoload/ale/engine.vim + + function! ale#engine#IsExecutable(buffer, executable) abort + return has_key(g:executable_map, a:executable) + endfunction + + function! ale#c#GetCFlags(buffer, output) abort + return g:get_cflags_return_value + endfunction + + call ale#assert#SetUpLinterTest('cpp', 'cc') + + let b:command_tail = ' -S -x c++' + \ . ' -o ' . (has('win32') ? 'nul': '/dev/null') + \ . ' -iquote %s:h' + \ . ' -std=c++14 -Wall -' + +After: + unlet! g:get_cflags_return_value + unlet! g:executable_map + unlet! b:command_tail + + runtime autoload/ale/c.vim + runtime autoload/ale/engine.vim + + call ale#assert#TearDownLinterTest() + +Execute(clang++ should be used instead of gcc, if available): + let g:executable_map = {'clang++': 1} + + AssertLinter 'clang++', [ale#Escape('clang++') . b:command_tail] + +Execute(The executable should be configurable): + AssertLinter 'gcc', [ale#Escape('gcc') . b:command_tail] + + let b:ale_cpp_cc_executable = 'foobar' + + AssertLinter 'foobar', [ale#Escape('foobar') . b:command_tail] + +Execute(The -std flag should be replaced by parsed C flags): + let b:command_tail = substitute(b:command_tail, 'c++14', 'c++11 ', '') + let g:get_cflags_return_value = '-std=c++11' + + AssertLinter 'gcc', ale#Escape('gcc') . b:command_tail diff --git a/test/command_callback/test_cpp_clang_command_callbacks.vader b/test/command_callback/test_cpp_clang_command_callbacks.vader deleted file mode 100644 index e96fd8e7..00000000 --- a/test/command_callback/test_cpp_clang_command_callbacks.vader +++ /dev/null @@ -1,19 +0,0 @@ -Before: - Save g:ale_c_parse_makefile - let g:ale_c_parse_makefile = 0 - - call ale#assert#SetUpLinterTest('cpp', 'clang') - let b:command_tail = ' -S -x c++ -fsyntax-only -iquote' - \ . ' ' . ale#Escape(getcwd()) - \ . ' -std=c++14 -Wall -' - -After: - unlet! b:command_tail - call ale#assert#TearDownLinterTest() - -Execute(The executable should be configurable): - AssertLinter 'clang++', ale#Escape('clang++') . b:command_tail - - let b:ale_cpp_clang_executable = 'foobar' - - AssertLinter 'foobar', ale#Escape('foobar') . b:command_tail diff --git a/test/command_callback/test_cpp_gcc_command_callbacks.vader b/test/command_callback/test_cpp_gcc_command_callbacks.vader deleted file mode 100644 index cfa4ecc0..00000000 --- a/test/command_callback/test_cpp_gcc_command_callbacks.vader +++ /dev/null @@ -1,20 +0,0 @@ -Before: - Save g:ale_c_parse_makefile - let g:ale_c_parse_makefile = 0 - - call ale#assert#SetUpLinterTest('cpp', 'gcc') - let b:command_tail = ' -S -x c++' - \ . ' -o ' . (has('win32') ? 'nul': '/dev/null') - \ . ' -iquote ' . ale#Escape(getcwd()) - \ . ' -std=c++14 -Wall -' - -After: - unlet! b:command_tail - call ale#assert#TearDownLinterTest() - -Execute(The executable should be configurable): - AssertLinter 'gcc', ale#Escape('gcc') . b:command_tail - - let b:ale_cpp_gcc_executable = 'foobar' - - AssertLinter 'foobar', ale#Escape('foobar') . b:command_tail diff --git a/test/command_callback/test_elixir_credo.vader b/test/command_callback/test_elixir_credo.vader index 1a146db8..3eb88846 100644 --- a/test/command_callback/test_elixir_credo.vader +++ b/test/command_callback/test_elixir_credo.vader @@ -8,6 +8,18 @@ After: call ale#assert#TearDownLinterTest() +Execute(Builds credo command with normal project): + AssertLinter 'mix', + \ ale#path#CdString(ale#path#Simplify(g:dir . '/elixir_paths/mix_project')) + \ . 'mix help credo && mix credo suggest --format=flycheck --read-from-stdin %s' + +Execute(Builds credo command with umbrella project): + call ale#test#SetFilename('elixir_paths/umbrella_project/apps/mix_project/lib/app.ex') + + AssertLinter 'mix', + \ ale#path#CdString(ale#path#Simplify(g:dir . '/elixir_paths/umbrella_project')) + \ . 'mix help credo && mix credo suggest --format=flycheck --read-from-stdin %s' + Execute(Builds credo command with --strict mode when set to 1): let g:ale_elixir_credo_strict = 1 diff --git a/test/command_callback/test_embertemplatelint_command_callbacks.vader b/test/command_callback/test_embertemplatelint_command_callbacks.vader new file mode 100644 index 00000000..97687d29 --- /dev/null +++ b/test/command_callback/test_embertemplatelint_command_callbacks.vader @@ -0,0 +1,17 @@ +Before: + call ale#assert#SetUpLinterTest('handlebars', 'embertemplatelint') + + GivenCommandOutput ['1.6.0'] + +After: + call ale#assert#TearDownLinterTest() + +Execute(ember-template-lint executables runs the right command): + AssertLinter 'ember-template-lint', + \ ale#Escape('ember-template-lint') . ' --json --filename %s' + +Execute(old ember-template-lint executables runs the right command): + GivenCommandOutput [] + + AssertLinter 'ember-template-lint', + \ ale#Escape('ember-template-lint') . ' --json %t' diff --git a/test/command_callback/test_flake8_command_callback.vader b/test/command_callback/test_flake8_command_callback.vader index f082a63a..09f64ee3 100644 --- a/test/command_callback/test_flake8_command_callback.vader +++ b/test/command_callback/test_flake8_command_callback.vader @@ -34,13 +34,52 @@ Execute(The flake8 callbacks should return the correct default values): \] Execute(The option for disabling changing directories should work): - let g:ale_python_flake8_change_directory = 0 + let g:ale_python_flake8_change_directory = 'off' AssertLinter 'flake8', [ \ ale#Escape('flake8') . ' --version', \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -', \] + let g:ale_python_flake8_change_directory = 0 + + AssertLinter 'flake8', [ + \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -', + \] + + " Invalid options should be considered the same as turning the setting off. + let g:ale_python_flake8_change_directory = 'xxx' + + AssertLinter 'flake8', [ + \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -', + \] + +Execute(The option for changing directory to project root should work): + silent execute 'file ' . fnameescape(g:dir . '/python_paths/namespace_package_tox/namespace/foo/bar.py') + + AssertLinter 'flake8', [ + \ ale#Escape('flake8') . ' --version', + \ ale#path#CdString(ale#python#FindProjectRootIni(bufnr(''))) + \ . ale#Escape('flake8') . ' --format=default --stdin-display-name %s -', + \] + +Execute(The option for changing directory to file dir should work): + let g:ale_python_flake8_change_directory = 'file' + silent execute 'file ' . fnameescape(g:dir . '/python_paths/namespace_package_tox/namespace/foo/bar.py') + + AssertLinter 'flake8', [ + \ ale#Escape('flake8') . ' --version', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('flake8') . ' --format=default --stdin-display-name %s -', + \] + + let g:ale_python_flake8_change_directory = 1 + + AssertLinter 'flake8', [ + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('flake8') . ' --format=default --stdin-display-name %s -', + \] + Execute(The flake8 command callback should let you set options): let g:ale_python_flake8_options = '--some-option' @@ -163,5 +202,5 @@ Execute(Pipenv is detected when python_flake8_auto_pipenv is set): call ale#test#SetFilename('../python_fixtures/pipenv/whatever.py') AssertLinter 'pipenv', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(ale#python#FindProjectRootIni(bufnr(''))) \ . ale#Escape('pipenv') . ' run flake8 --format=default --stdin-display-name %s -' diff --git a/test/command_callback/test_gobuild_command_callback.vader b/test/command_callback/test_gobuild_command_callback.vader index fdf23866..063f3f2f 100644 --- a/test/command_callback/test_gobuild_command_callback.vader +++ b/test/command_callback/test_gobuild_command_callback.vader @@ -11,14 +11,14 @@ After: Execute(The default commands should be correct): AssertLinter 'go', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . 'go test -c -o /dev/null ./' Execute(Go environment variables should be supported): let b:ale_go_go111module = 'on' AssertLinter 'go', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Env('GO111MODULE', 'on') \ . 'go test -c -o /dev/null ./' @@ -28,7 +28,7 @@ Execute(Extra options should be supported): let g:ale_go_gobuild_options = '--foo-bar' AssertLinter 'go', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . 'go test --foo-bar -c -o /dev/null ./' let g:ale_go_gobuild_options = '' @@ -37,5 +37,5 @@ Execute(The executable should be configurable): let g:ale_go_go_executable = 'foobar' AssertLinter 'foobar', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . 'foobar test -c -o /dev/null ./' diff --git a/test/command_callback/test_gofmt_command_callback.vader b/test/command_callback/test_gofmt_command_callback.vader index 4da1f6c8..88b2e6b0 100644 --- a/test/command_callback/test_gofmt_command_callback.vader +++ b/test/command_callback/test_gofmt_command_callback.vader @@ -1,5 +1,8 @@ Before: Save g:ale_go_go111module + Save b:ale_go_go111module + + let b:ale_go_go111module = '' call ale#assert#SetUpLinterTest('go', 'gofmt') call ale#test#SetFilename('../go_files/testfile2.go') diff --git a/test/command_callback/test_golangci_lint_command_callback.vader b/test/command_callback/test_golangci_lint_command_callback.vader index 7f1e2ac4..37fb1f7d 100644 --- a/test/command_callback/test_golangci_lint_command_callback.vader +++ b/test/command_callback/test_golangci_lint_command_callback.vader @@ -13,7 +13,7 @@ After: Execute(The golangci-lint defaults should be correct): AssertLinter 'golangci-lint', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Escape('golangci-lint') \ . ' run ' . ale#Escape(expand('%' . ':t')) \ . ' --enable-all' @@ -22,7 +22,7 @@ Execute(The golangci-lint callback should use a configured executable): let b:ale_go_golangci_lint_executable = 'something else' AssertLinter 'something else', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Escape('something else') \ . ' run ' . ale#Escape(expand('%' . ':t')) \ . ' --enable-all' @@ -31,7 +31,7 @@ Execute(The golangci-lint callback should use configured options): let b:ale_go_golangci_lint_options = '--foobar' AssertLinter 'golangci-lint', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Escape('golangci-lint') \ . ' run ' . ale#Escape(expand('%' . ':t')) \ . ' --foobar' @@ -40,7 +40,7 @@ Execute(The golangci-lint callback should support environment variables): let b:ale_go_go111module = 'on' AssertLinter 'golangci-lint', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Env('GO111MODULE', 'on') \ . ale#Escape('golangci-lint') \ . ' run ' . ale#Escape(expand('%' . ':t')) @@ -50,5 +50,5 @@ Execute(The golangci-lint `lint_package` option should use the correct command): let b:ale_go_golangci_lint_package = 1 AssertLinter 'golangci-lint', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Escape('golangci-lint') . ' run --enable-all' diff --git a/test/command_callback/test_gometalinter_command_callback.vader b/test/command_callback/test_gometalinter_command_callback.vader index d922efc6..567997d8 100644 --- a/test/command_callback/test_gometalinter_command_callback.vader +++ b/test/command_callback/test_gometalinter_command_callback.vader @@ -13,7 +13,7 @@ After: Execute(The gometalinter defaults should be correct): AssertLinter 'gometalinter', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Escape('gometalinter') \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t'))) \ . ' .' @@ -22,7 +22,7 @@ Execute(The gometalinter callback should use a configured executable): let b:ale_go_gometalinter_executable = 'something else' AssertLinter 'something else', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Escape('something else') \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t'))) \ . ' .' @@ -31,7 +31,7 @@ Execute(The gometalinter callback should use configured options): let b:ale_go_gometalinter_options = '--foobar' AssertLinter 'gometalinter', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Escape('gometalinter') \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t'))) \ . ' --foobar' . ' .' @@ -40,7 +40,7 @@ Execute(The gometalinter should use configured environment variables): let b:ale_go_go111module = 'off' AssertLinter 'gometalinter', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Env('GO111MODULE', 'off') \ . ale#Escape('gometalinter') \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t'))) @@ -50,5 +50,5 @@ Execute(The gometalinter `lint_package` option should use the correct command): let b:ale_go_gometalinter_lint_package = 1 AssertLinter 'gometalinter', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Escape('gometalinter') . ' .' diff --git a/test/command_callback/test_gosimple_command_callback.vader b/test/command_callback/test_gosimple_command_callback.vader index ee89eed8..b006f783 100644 --- a/test/command_callback/test_gosimple_command_callback.vader +++ b/test/command_callback/test_gosimple_command_callback.vader @@ -11,11 +11,12 @@ After: Execute(The default gosimple command should be correct): AssertLinter 'gosimple', - \ ale#path#CdString(expand('%:p:h')) . ' gosimple .' + \ ale#path#BufferCdString(bufnr('')) + \ . ' gosimple .' Execute(The gosimple command should support Go environment variables): let b:ale_go_go111module = 'on' AssertLinter 'gosimple', - \ ale#path#CdString(expand('%:p:h')) . ' ' - \ . ale#Env('GO111MODULE', 'on') . 'gosimple .' + \ ale#path#BufferCdString(bufnr('')) + \ . ' ' . ale#Env('GO111MODULE', 'on') . 'gosimple .' diff --git a/test/command_callback/test_gotype_command_callback.vader b/test/command_callback/test_gotype_command_callback.vader index 1334fcff..204197d9 100644 --- a/test/command_callback/test_gotype_command_callback.vader +++ b/test/command_callback/test_gotype_command_callback.vader @@ -11,7 +11,8 @@ After: Execute(The default gotype command should be correct): AssertLinter 'gotype', - \ ale#path#CdString(expand('%:p:h')) . ' gotype -e .' + \ ale#path#BufferCdString(bufnr('')) + \ . ' gotype -e .' Execute(The gotype callback should ignore test files): call ale#test#SetFilename('bla_test.go') @@ -22,6 +23,6 @@ Execute(The gotype callback should support Go environment variables): let b:ale_go_go111module = 'on' AssertLinter 'gotype', - \ ale#path#CdString(expand('%:p:h')) . ' ' - \ . ale#Env('GO111MODULE', 'on') + \ ale#path#BufferCdString(bufnr('')) + \ . ' ' . ale#Env('GO111MODULE', 'on') \ . 'gotype -e .' diff --git a/test/command_callback/test_govet_command_callback.vader b/test/command_callback/test_govet_command_callback.vader index 59022180..0e1ea092 100644 --- a/test/command_callback/test_govet_command_callback.vader +++ b/test/command_callback/test_govet_command_callback.vader @@ -13,22 +13,22 @@ After: call ale#assert#TearDownLinterTest() Execute(The default command should be correct): - AssertLinter 'go', ale#path#CdString(expand('%:p:h')) . ' go vet .' + AssertLinter 'go', ale#path#BufferCdString(bufnr('')) . ' go vet .' Execute(Extra options should be supported): let g:ale_go_govet_options = '--foo-bar' - AssertLinter 'go', ale#path#CdString(expand('%:p:h')) . ' go vet --foo-bar .' + AssertLinter 'go', ale#path#BufferCdString(bufnr('')) . ' go vet --foo-bar .' Execute(The executable should be configurable): let g:ale_go_go_executable = 'foobar' - AssertLinter 'foobar', ale#path#CdString(expand('%:p:h')) . ' foobar vet .' + AssertLinter 'foobar', ale#path#BufferCdString(bufnr('')) . ' foobar vet .' Execute(Go environment variables should be supported): let b:ale_go_go111module = 'on' AssertLinter 'go', - \ ale#path#CdString(expand('%:p:h')) . ' ' + \ ale#path#BufferCdString(bufnr('')) . ' ' \ . ale#Env('GO111MODULE', 'on') \ . 'go vet .' diff --git a/test/command_callback/test_graphql_gqlint_command_callbacks.vader b/test/command_callback/test_graphql_gqlint_command_callbacks.vader index 0f4e9770..e8ed0e5d 100644 --- a/test/command_callback/test_graphql_gqlint_command_callbacks.vader +++ b/test/command_callback/test_graphql_gqlint_command_callbacks.vader @@ -6,6 +6,6 @@ After: Execute(The linter should run from the directory of the file in the buffer): AssertLinter 'gqlint', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . 'gqlint --reporter=simple' \ . ' %t' diff --git a/test/command_callback/test_javac_command_callback.vader b/test/command_callback/test_javac_command_callback.vader index d2eebf7a..ac898e5f 100644 --- a/test/command_callback/test_javac_command_callback.vader +++ b/test/command_callback/test_javac_command_callback.vader @@ -3,7 +3,7 @@ Before: call ale#test#SetFilename('dummy.java') let g:cp_sep = has('unix') ? ':' : ';' - let g:prefix = ale#path#CdString(expand('%:p:h')) + let g:prefix = ale#path#BufferCdString(bufnr('')) \ . ale#Escape('javac') . ' -Xlint' function! GetCommand(previous_output) abort @@ -51,7 +51,7 @@ Execute(The executable should be configurable): let g:ale_java_javac_executable = 'foobar' AssertLinter 'foobar', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Escape('foobar') . ' -Xlint' \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' @@ -197,7 +197,8 @@ Execute(The javac callback should combine discovered sourcepath and manual ones) let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {}) AssertEqual - \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('javac') . ' -Xlint' \ . ' -sourcepath ' . ale#Escape(join([ \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'), \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/'), @@ -210,7 +211,8 @@ Execute(The javac callback should combine discovered sourcepath and manual ones) let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {}) AssertEqual - \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('javac') . ' -Xlint' \ . ' -sourcepath ' . ale#Escape(join([ \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'), \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/'), @@ -223,7 +225,8 @@ Execute(The javac callback should combine discovered sourcepath and manual ones) let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {}) AssertEqual - \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('javac') . ' -Xlint' \ . ' -sourcepath ' . ale#Escape(join([ \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'), \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/') @@ -238,7 +241,8 @@ Execute(The javac callback should combine discovered sourcepath and manual ones) let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {}) AssertEqual - \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('javac') . ' -Xlint' \ . ' -sourcepath ' . ale#Escape(join([ \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'), \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/'), @@ -253,7 +257,8 @@ Execute(The javac callback should detect source directories): call ale#engine#InitBufferInfo(bufnr('')) AssertLinter 'javac', - \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('javac') . ' -Xlint' \ . ' -sourcepath ' . ale#Escape( \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/') \ ) @@ -272,7 +277,8 @@ Execute(The javac callback should combine detected source directories and classp \], {}) AssertEqual - \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('javac') . ' -Xlint' \ . ' -cp ' . ale#Escape(join(['/foo/bar.jar', '/xyz/abc.jar'], g:cp_sep)) \ . ' -sourcepath ' . ale#Escape( \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/') @@ -294,7 +300,8 @@ Execute(The javac callback should include src/test/java for test paths): call ale#engine#InitBufferInfo(bufnr('')) AssertLinter 'javac', - \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('javac') . ' -Xlint' \ . ' -sourcepath ' . ale#Escape(join([ \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'), \ ale#path#Simplify(g:dir . '/java_paths/src/test/java/'), @@ -307,7 +314,8 @@ Execute(The javac callback should include src/main/jaxb when available): call ale#engine#InitBufferInfo(bufnr('')) AssertLinter 'javac', - \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('javac') . ' -Xlint' \ . ' -sourcepath ' . ale#Escape(join([ \ ale#path#Simplify(g:dir . '/java_paths_with_jaxb/src/main/java/'), \ ale#path#Simplify(g:dir . '/java_paths_with_jaxb/src/main/jaxb/'), @@ -320,7 +328,8 @@ Execute(The javac callback should add -sourcepath even if src/java/main doesn't call ale#engine#InitBufferInfo(bufnr('')) AssertLinter 'javac', - \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('javac') . ' -Xlint' \ . ' -sourcepath ' . ale#Escape(join([ \ ale#path#Simplify(g:dir . '/java_paths_no_main/src/test/java/'), \ ], g:cp_sep)) diff --git a/test/command_callback/test_lintr_command_callback.vader b/test/command_callback/test_lintr_command_callback.vader index 187d3875..ac4b419b 100644 --- a/test/command_callback/test_lintr_command_callback.vader +++ b/test/command_callback/test_lintr_command_callback.vader @@ -6,7 +6,7 @@ After: Execute(The default lintr command should be correct): AssertLinter 'Rscript', - \ ale#path#CdString(getcwd()) + \ ale#path#BufferCdString(bufnr('')) \ . 'Rscript --vanilla -e ' \ . ale#Escape('suppressPackageStartupMessages(library(lintr));' \ . 'lint(cache = FALSE, commandArgs(TRUE), ' @@ -17,7 +17,7 @@ Execute(The lintr options should be configurable): let b:ale_r_lintr_options = 'with_defaults(object_usage_linter = NULL)' AssertLinter 'Rscript', - \ ale#path#CdString(getcwd()) + \ ale#path#BufferCdString(bufnr('')) \ . 'Rscript --vanilla -e ' \ . ale#Escape('suppressPackageStartupMessages(library(lintr));' \ . 'lint(cache = FALSE, commandArgs(TRUE), ' @@ -28,7 +28,7 @@ Execute(If the lint_package flag is set, lintr::lint_package should be called): let b:ale_r_lintr_lint_package = 1 AssertLinter 'Rscript', - \ ale#path#CdString(getcwd()) + \ ale#path#BufferCdString(bufnr('')) \ . 'Rscript --vanilla -e ' \ . ale#Escape('suppressPackageStartupMessages(library(lintr));' \ . 'lint_package(cache = FALSE, ' diff --git a/test/command_callback/test_markdown_markdownlint_command_callback.vader b/test/command_callback/test_markdown_markdownlint_command_callback.vader new file mode 100644 index 00000000..12766cfd --- /dev/null +++ b/test/command_callback/test_markdown_markdownlint_command_callback.vader @@ -0,0 +1,13 @@ +Before: + call ale#assert#SetUpLinterTest('markdown', 'markdownlint') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'markdownlint', ale#Escape('markdownlint') . ' %s' + +Execute(The options should be configurable): + let g:ale_markdown_markdownlint_options = '--config ~/custom/.markdownlintrc' + + AssertLinter 'markdownlint', ale#Escape('markdownlint') . ' --config ~/custom/.markdownlintrc %s' diff --git a/test/command_callback/test_mypy_command_callback.vader b/test/command_callback/test_mypy_command_callback.vader index afa9f9af..b9b6ae70 100644 --- a/test/command_callback/test_mypy_command_callback.vader +++ b/test/command_callback/test_mypy_command_callback.vader @@ -75,14 +75,14 @@ Execute(Setting executable to 'pipenv' appends 'run mypy'): let g:ale_python_mypy_executable = 'path/to/pipenv' AssertLinter 'path/to/pipenv', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('path/to/pipenv') . ' run mypy' \ . ' --show-column-numbers --shadow-file %s %t %s' Execute(Pipenv is detected when python_mypy_auto_pipenv is set): let g:ale_python_mypy_auto_pipenv = 1 - call ale#test#SetFilename('/testplugin/test/python_fixtures/pipenv/whatever.py') + call ale#test#SetFilename('../python_fixtures/pipenv/whatever.py') AssertLinter 'pipenv', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('pipenv') . ' run mypy --show-column-numbers --shadow-file %s %t %s' diff --git a/test/command_callback/test_nasm_nasm_command_callbacks.vader b/test/command_callback/test_nasm_nasm_command_callbacks.vader index 8e077306..2bfe2b0d 100644 --- a/test/command_callback/test_nasm_nasm_command_callbacks.vader +++ b/test/command_callback/test_nasm_nasm_command_callbacks.vader @@ -2,9 +2,9 @@ Before: call ale#assert#SetUpLinterTest('nasm', 'nasm') let b:command_tail = - \ ' -X gnu -I ' . ale#Escape(getcwd() . (has('win32') ? '\' : '/')) . ' %s -o ' . (has('win32') ? 'NUL' : '/dev/null') + \ ' -X gnu -I %s:h' . (has('win32') ? '\' : '/') . ' %s -o ' . (has('win32') ? 'NUL' : '/dev/null') let b:command_tail_opt = - \ ' -X gnu -I ' . ale#Escape(getcwd() . (has('win32') ? '\' : '/')) . ' -w+orphan-labels %s -o ' . (has('win32') ? 'NUL' : '/dev/null') + \ ' -X gnu -I %s:h' . (has('win32') ? '\' : '/') . ' -w+orphan-labels %s -o ' . (has('win32') ? 'NUL' : '/dev/null') After: unlet! b:command_tail @@ -23,7 +23,8 @@ Execute(The options should be configurable): let b:ale_nasm_nasm_options = '-w-macro-params' AssertLinter 'nasm', ale#Escape('nasm') - \ . ' -X gnu -I ' . ale#Escape(getcwd() . (has('win32') ? '\' : '/')) . ' -w-macro-params %s -o ' . (has('win32') ? 'NUL' : '/dev/null') + \ . ' -X gnu -I %s:h' . (has('win32') ? '\' : '/') + \ . ' -w-macro-params %s -o ' . (has('win32') ? 'NUL' : '/dev/null') Execute(The options should be used in command): let b:ale_nasm_nasm_options = '-w+orphan-labels' diff --git a/test/command_callback/test_psalm_command_callbacks.vader b/test/command_callback/test_psalm_command_callbacks.vader index 70b5af95..d32780e6 100644 --- a/test/command_callback/test_psalm_command_callbacks.vader +++ b/test/command_callback/test_psalm_command_callbacks.vader @@ -2,6 +2,9 @@ Before: call ale#assert#SetUpLinterTest('php', 'psalm') After: + unlet! g:i + unlet! g:matched + if isdirectory(g:dir . '/.git') call delete(g:dir . '/.git', 'd') endif @@ -22,19 +25,36 @@ Execute(Vendor executables should be detected): \ . '/psalm-project/vendor/bin/psalm' \ )) . ' --language-server' + let g:ale_php_psalm_use_global = 1 + + AssertLinter 'psalm', + \ ale#Escape('psalm') . ' --language-server' + Execute(User provided options should be used): - let g:ale_psalm_langserver_options = '--my-user-provided-option my-value' + let g:ale_php_psalm_options = '--my-user-provided-option my-value' AssertLinter 'psalm', \ ale#Escape('psalm') \ . ' --language-server --my-user-provided-option my-value' - Execute(The project path should be correct for .git directories): call ale#test#SetFilename('psalm-project/test.php') + let g:matched = 0 - if !isdirectory(g:dir . '/.git') - call mkdir(g:dir . '/.git') - endif + for g:i in range(4) + if !isdirectory(g:dir . '/.git') + call mkdir(g:dir . '/.git') + endif + + try + AssertLSPProject g:dir + catch /.+/ + endtry - AssertLSPProject g:dir + let g:matched = 1 + break + endfor + + if !g:matched + AssertLSPProject g:dir + endif diff --git a/test/command_callback/test_pydocstyle_command_callback.vader b/test/command_callback/test_pydocstyle_command_callback.vader index 7e0df9ca..511443a6 100644 --- a/test/command_callback/test_pydocstyle_command_callback.vader +++ b/test/command_callback/test_pydocstyle_command_callback.vader @@ -1,5 +1,6 @@ Before: call ale#assert#SetUpLinterTest('python', 'pydocstyle') + call ale#test#SetFilename('test.py') After: call ale#assert#TearDownLinterTest() @@ -7,33 +8,33 @@ After: Execute(The pydocstyle command callback should return default string): AssertLinter 'pydocstyle', \ ale#path#BufferCdString(bufnr('')) - \ . ale#Escape('pydocstyle') . ' ' . ale#Escape('dummy.txt') + \ . ale#Escape('pydocstyle') . ' %s:t' Execute(The pydocstyle command callback should allow options): let g:ale_python_pydocstyle_options = '--verbose' AssertLinter 'pydocstyle', \ ale#path#BufferCdString(bufnr('')) - \ . ale#Escape('pydocstyle') . ' --verbose ' . ale#Escape('dummy.txt') + \ . ale#Escape('pydocstyle') . ' --verbose %s:t' Execute(The pydocstyle executable should be configurable): let g:ale_python_pydocstyle_executable = '~/.local/bin/pydocstyle' AssertLinter '~/.local/bin/pydocstyle', \ ale#path#BufferCdString(bufnr('')) - \ . ale#Escape('~/.local/bin/pydocstyle') . ' ' . ale#Escape('dummy.txt') + \ . ale#Escape('~/.local/bin/pydocstyle') . ' %s:t' Execute(Setting executable to 'pipenv' appends 'run pydocstyle'): let g:ale_python_pydocstyle_executable = 'path/to/pipenv' AssertLinter 'path/to/pipenv', \ ale#path#BufferCdString(bufnr('')) - \ . ale#Escape('path/to/pipenv') . ' run pydocstyle ' . ale#Escape('dummy.txt') + \ . ale#Escape('path/to/pipenv') . ' run pydocstyle %s:t' Execute(Pipenv is detected when python_pydocstyle_auto_pipenv is set): let g:ale_python_pydocstyle_auto_pipenv = 1 - call ale#test#SetFilename('/testplugin/test/python_fixtures/pipenv/whatever.py') + call ale#test#SetFilename('../python_fixtures/pipenv/whatever.py') AssertLinter 'pipenv', \ ale#path#BufferCdString(bufnr('')) - \ . ale#Escape('pipenv') . ' run pydocstyle ' . ale#Escape('whatever.py') + \ . ale#Escape('pipenv') . ' run pydocstyle %s:t' diff --git a/test/command_callback/test_pylama_command_callback.vader b/test/command_callback/test_pylama_command_callback.vader index 417cb5c9..0aea9a93 100644 --- a/test/command_callback/test_pylama_command_callback.vader +++ b/test/command_callback/test_pylama_command_callback.vader @@ -14,7 +14,7 @@ After: Execute(The pylama command callback should return a default): AssertLinter 'pylama', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('pylama') . b:command_tail Execute(The option for disabling changing directories should work): @@ -26,14 +26,14 @@ Execute(The pylama executable should be configurable, and escaped properly): let g:ale_python_pylama_executable = 'executable with spaces' AssertLinter 'executable with spaces', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('executable with spaces') . b:command_tail Execute(The pylama command callback should let you set options): let g:ale_python_pylama_options = '--some-option' AssertLinter 'pylama', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('pylama') . ' --some-option' . b:command_tail Execute(The pylama command callback should switch directories to the detected project root): @@ -73,13 +73,13 @@ Execute(Setting executable to 'pipenv' appends 'run pylama'): let g:ale_python_pylama_executable = 'path/to/pipenv' AssertLinter 'path/to/pipenv', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('path/to/pipenv') . ' run pylama' . b:command_tail Execute(Pipenv is detected when python_pylama_auto_pipenv is set): let g:ale_python_pylama_auto_pipenv = 1 - call ale#test#SetFilename('/testplugin/test/python_fixtures/pipenv/whatever.py') + call ale#test#SetFilename('../python_fixtures/pipenv/whatever.py') AssertLinter 'pipenv', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('pipenv') . ' run pylama' . b:command_tail diff --git a/test/command_callback/test_pylint_command_callback.vader b/test/command_callback/test_pylint_command_callback.vader index c41c8398..755dd292 100644 --- a/test/command_callback/test_pylint_command_callback.vader +++ b/test/command_callback/test_pylint_command_callback.vader @@ -1,4 +1,8 @@ Before: + Save g:ale_python_auto_pipenv + + let g:ale_python_auto_pipenv = 0 + call ale#assert#SetUpLinterTest('python', 'pylint') let b:bin_dir = has('win32') ? 'Scripts' : 'bin' @@ -13,7 +17,7 @@ After: Execute(The pylint callbacks should return the correct default values): AssertLinter 'pylint', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('pylint') . ' ' . b:command_tail Execute(The option for disabling changing directories should work): @@ -25,14 +29,14 @@ Execute(The pylint executable should be configurable, and escaped properly): let g:ale_python_pylint_executable = 'executable with spaces' AssertLinter 'executable with spaces', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('executable with spaces') . ' ' . b:command_tail Execute(The pylint command callback should let you set options): let g:ale_python_pylint_options = '--some-option' AssertLinter 'pylint', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('pylint') . ' --some-option' . b:command_tail Execute(The pylint callbacks shouldn't detect virtualenv directories where they don't exist): @@ -65,15 +69,15 @@ Execute(Setting executable to 'pipenv' appends 'run pylint'): let g:ale_python_pylint_executable = 'path/to/pipenv' AssertLinter 'path/to/pipenv', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('path/to/pipenv') . ' run pylint' \ . ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n %s' Execute(Pipenv is detected when python_pylint_auto_pipenv is set): let g:ale_python_pylint_auto_pipenv = 1 - call ale#test#SetFilename('/testplugin/test/python_fixtures/pipenv/whatever.py') + call ale#test#SetFilename('../python_fixtures/pipenv/whatever.py') AssertLinter 'pipenv', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('pipenv') . ' run pylint' \ . ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n %s' diff --git a/test/command_callback/test_pyrex_cython_command_callback.vader b/test/command_callback/test_pyrex_cython_command_callback.vader index b9020f11..af86366a 100644 --- a/test/command_callback/test_pyrex_cython_command_callback.vader +++ b/test/command_callback/test_pyrex_cython_command_callback.vader @@ -6,8 +6,8 @@ After: Execute(The default cython command should be correct): AssertLinter 'cython', ale#Escape('cython') - \ . ' --working ' . ale#Escape(g:dir) - \ . ' --include-dir ' . ale#Escape(g:dir) + \ . ' --working %s:h' + \ . ' --include-dir %s:h' \ . ' --warning-extra' \ . ' --output-file ' . g:ale#util#nul_file . ' %t' @@ -15,8 +15,8 @@ Execute(The cython executable should be configurable): let b:ale_pyrex_cython_executable = 'cython_foobar' AssertLinter 'cython_foobar', ale#Escape('cython_foobar') - \ . ' --working ' . ale#Escape(g:dir) - \ . ' --include-dir ' . ale#Escape(g:dir) + \ . ' --working %s:h' + \ . ' --include-dir %s:h' \ . ' --warning-extra' \ . ' --output-file ' . g:ale#util#nul_file . ' %t' @@ -24,7 +24,7 @@ Execute(Additional cython options should be configurable): let b:ale_pyrex_cython_options = '--foobar' AssertLinter 'cython', ale#Escape('cython') - \ . ' --working ' . ale#Escape(g:dir) - \ . ' --include-dir ' . ale#Escape(g:dir) + \ . ' --working %s:h' + \ . ' --include-dir %s:h' \ . ' --foobar' \ . ' --output-file ' . g:ale#util#nul_file . ' %t' diff --git a/test/command_callback/test_rubocop_command_callback.vader b/test/command_callback/test_rubocop_command_callback.vader index 7f42a8c0..e7cc32e8 100644 --- a/test/command_callback/test_rubocop_command_callback.vader +++ b/test/command_callback/test_rubocop_command_callback.vader @@ -10,20 +10,17 @@ After: Execute(Executable should default to rubocop): AssertLinter 'rubocop', ale#Escape('rubocop') - \ . ' --format json --force-exclusion --stdin ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb')) + \ . ' --format json --force-exclusion --stdin %s' Execute(Should be able to set a custom executable): let g:ale_ruby_rubocop_executable = 'bin/rubocop' AssertLinter 'bin/rubocop' , ale#Escape('bin/rubocop') - \ . ' --format json --force-exclusion --stdin ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb')) + \ . ' --format json --force-exclusion --stdin %s' Execute(Setting bundle appends 'exec rubocop'): let g:ale_ruby_rubocop_executable = 'path to/bundle' AssertLinter 'path to/bundle', ale#Escape('path to/bundle') \ . ' exec rubocop' - \ . ' --format json --force-exclusion --stdin ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb')) + \ . ' --format json --force-exclusion --stdin %s' diff --git a/test/command_callback/test_ruumba_command_callback.vader b/test/command_callback/test_ruumba_command_callback.vader index 244b264a..9fa48903 100644 --- a/test/command_callback/test_ruumba_command_callback.vader +++ b/test/command_callback/test_ruumba_command_callback.vader @@ -10,20 +10,17 @@ After: Execute(Executable should default to ruumba): AssertLinter 'ruumba', ale#Escape('ruumba') - \ . ' --format json --force-exclusion --stdin ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.html.erb')) + \ . ' --format json --force-exclusion --stdin %s' Execute(Should be able to set a custom executable): let g:ale_eruby_ruumba_executable = 'bin/ruumba' AssertLinter 'bin/ruumba' , ale#Escape('bin/ruumba') - \ . ' --format json --force-exclusion --stdin ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.html.erb')) + \ . ' --format json --force-exclusion --stdin %s' Execute(Setting bundle appends 'exec ruumba'): let g:ale_eruby_ruumba_executable = 'path to/bundle' AssertLinter 'path to/bundle', ale#Escape('path to/bundle') \ . ' exec ruumba' - \ . ' --format json --force-exclusion --stdin ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.html.erb')) + \ . ' --format json --force-exclusion --stdin %s' diff --git a/test/command_callback/test_shellcheck_command_callback.vader b/test/command_callback/test_shellcheck_command_callback.vader index 1d5b056b..9fb5303a 100644 --- a/test/command_callback/test_shellcheck_command_callback.vader +++ b/test/command_callback/test_shellcheck_command_callback.vader @@ -2,7 +2,7 @@ Before: call ale#assert#SetUpLinterTest('sh', 'shellcheck') call ale#test#SetFilename('test.sh') - let b:prefix = ale#path#CdString(ale#path#Simplify(g:dir)) + let b:prefix = ale#path#BufferCdString(bufnr('')) let b:suffix = ' -f gcc -' After: diff --git a/test/command_callback/test_sqllint_command_callback.vader b/test/command_callback/test_sqllint_command_callback.vader new file mode 100644 index 00000000..eea9b4e0 --- /dev/null +++ b/test/command_callback/test_sqllint_command_callback.vader @@ -0,0 +1,12 @@ +Before: + " Load the linter and set up a series of commands, reset linter variables, + " clear caches, etc. + " + " Vader's 'Save' command will be called here for linter variables. + call ale#assert#SetUpLinterTest('sql', 'sqllint') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'sql-lint', ['sql-lint'] diff --git a/test/command_callback/test_standardrb_command_callback.vader b/test/command_callback/test_standardrb_command_callback.vader index 7bc1c976..108dd870 100644 --- a/test/command_callback/test_standardrb_command_callback.vader +++ b/test/command_callback/test_standardrb_command_callback.vader @@ -10,20 +10,17 @@ After: Execute(Executable should default to standardrb): AssertLinter 'standardrb', ale#Escape('standardrb') - \ . ' --format json --force-exclusion --stdin ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb')) + \ . ' --format json --force-exclusion --stdin %s' Execute(Should be able to set a custom executable): let g:ale_ruby_standardrb_executable = 'bin/standardrb' AssertLinter 'bin/standardrb' , ale#Escape('bin/standardrb') - \ . ' --format json --force-exclusion --stdin ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb')) + \ . ' --format json --force-exclusion --stdin %s' Execute(Setting bundle appends 'exec standardrb'): let g:ale_ruby_standardrb_executable = 'path to/bundle' AssertLinter 'path to/bundle', ale#Escape('path to/bundle') \ . ' exec standardrb' - \ . ' --format json --force-exclusion --stdin ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb')) + \ . ' --format json --force-exclusion --stdin %s' diff --git a/test/command_callback/test_staticcheck_command_callback.vader b/test/command_callback/test_staticcheck_command_callback.vader index ae0d3584..871a5510 100644 --- a/test/command_callback/test_staticcheck_command_callback.vader +++ b/test/command_callback/test_staticcheck_command_callback.vader @@ -11,7 +11,7 @@ After: Execute(The staticcheck callback should return the right defaults): AssertLinter 'staticcheck', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . 'staticcheck ' \ . ale#Escape(expand('%' . ':t')) @@ -19,7 +19,7 @@ Execute(The staticcheck callback should use configured options): let b:ale_go_staticcheck_options = '-test' AssertLinter 'staticcheck', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . 'staticcheck ' \ . '-test ' . ale#Escape(expand('%' . ':t')) @@ -27,13 +27,14 @@ Execute(The staticcheck `lint_package` option should use the correct command): let b:ale_go_staticcheck_lint_package = 1 AssertLinter 'staticcheck', - \ ale#path#CdString(expand('%:p:h')) . 'staticcheck .', + \ ale#path#BufferCdString(bufnr('')) + \ . 'staticcheck .', Execute(The staticcheck callback should use the `GO111MODULE` option if set): let b:ale_go_go111module = 'off' AssertLinter 'staticcheck', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Env('GO111MODULE', 'off') \ . 'staticcheck ' \ . ale#Escape(expand('%' . ':t')) @@ -42,6 +43,6 @@ Execute(The staticcheck callback should use the `GO111MODULE` option if set): let b:ale_go_staticcheck_lint_package = 1 AssertLinter 'staticcheck', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Env('GO111MODULE', 'off') \ . 'staticcheck .' diff --git a/test/command_callback/test_swift_swiftformat_command_callbacks.vader b/test/command_callback/test_swift_swiftformat_command_callbacks.vader new file mode 100644 index 00000000..7be20bf7 --- /dev/null +++ b/test/command_callback/test_swift_swiftformat_command_callbacks.vader @@ -0,0 +1,25 @@ +Before: + call ale#assert#SetUpLinterTest('swift', 'swiftformat') + +After: + call ale#assert#TearDownLinterTest() + +Execute(Should use default command when not in a swift package): + call ale#test#SetFilename('../swift-test-files/non-swift-package-project/src/folder/dummy.swift') + + AssertLinter 'swift-format', + \ ale#Escape('swift-format') . ' --mode lint %t' + +Execute(Should use swift run when in a swift package): + call ale#test#SetFilename('../swift-test-files/swift-package-project/src/folder/dummy.swift') + + AssertLinter 'swift', + \ ale#Escape('swift') . ' run swift-format --mode lint %t' + +Execute(Should let users configure a global executable and override local paths): + call ale#test#SetFilename('../swift-test-files/swift-package-project/src/folder/dummy.swift') + + let g:ale_swift_swiftformat_executable = '/path/to/custom/swift-format' + + AssertLinter '/path/to/custom/swift-format', + \ ale#Escape('/path/to/custom/swift-format') . ' --mode lint %t' diff --git a/test/command_callback/test_tslint_command_callback.vader b/test/command_callback/test_tslint_command_callback.vader index 229ccc96..cc5d2666 100644 --- a/test/command_callback/test_tslint_command_callback.vader +++ b/test/command_callback/test_tslint_command_callback.vader @@ -7,14 +7,14 @@ After: Execute(The default tslint command should be correct): AssertLinter 'tslint', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Escape('tslint') . ' --format json %t' Execute(The rules directory option should be included if set): let b:ale_typescript_tslint_rules_dir = '/foo/bar' AssertLinter 'tslint', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Escape('tslint') . ' --format json' \ . ' -r ' . ale#Escape('/foo/bar') \ . ' %t' @@ -23,5 +23,5 @@ Execute(The executable should be configurable and escaped): let b:ale_typescript_tslint_executable = 'foo bar' AssertLinter 'foo bar', - \ ale#path#CdString(expand('%:p:h')) + \ ale#path#BufferCdString(bufnr('')) \ . ale#Escape('foo bar') . ' --format json %t' diff --git a/test/command_callback/test_vint_command_callback.vader b/test/command_callback/test_vint_command_callback.vader index e0051f26..4ce277e8 100644 --- a/test/command_callback/test_vint_command_callback.vader +++ b/test/command_callback/test_vint_command_callback.vader @@ -1,7 +1,7 @@ Before: call ale#assert#SetUpLinterTest('vim', 'vint') let b:command_tail = (has('nvim') ? ' --enable-neovim' : '') - \ . ' -f "{file_path}:{line_number}:{column_number}: {severity}: {description} (see {reference})" %t' + \ . ' -f "{file_path}:{line_number}:{column_number}: {severity}: {policy_name} - {description} (see {reference})" %t' After: unlet! b:bin_dir diff --git a/test/command_callback/test_vulture_command_callback.vader b/test/command_callback/test_vulture_command_callback.vader index d6c866b9..bacf8f12 100644 --- a/test/command_callback/test_vulture_command_callback.vader +++ b/test/command_callback/test_vulture_command_callback.vader @@ -12,7 +12,7 @@ After: Execute(The vulture command callback should lint file directory by default): AssertLinter 'vulture', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('vulture') . ' .' Execute(The vulture command callback should lint project root, when present): @@ -31,14 +31,14 @@ Execute(The vulture executable should be configurable, and escaped properly): let g:ale_python_vulture_executable = 'executable with spaces' AssertLinter 'executable with spaces', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('executable with spaces') . ' .' Execute(The vulture command callback should let you set options): let g:ale_python_vulture_options = '--some-option' AssertLinter 'vulture', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('vulture') . ' --some-option .' Execute(The vulture command callback should detect virtualenv directories and switch to the project root): @@ -64,5 +64,5 @@ Execute(Setting executable to 'pipenv' appends 'run vulture'): let g:ale_python_vulture_executable = 'path/to/pipenv' AssertLinter 'path/to/pipenv', - \ ale#path#BufferCdString(bufnr('')) + \ ale#path#CdString(expand('#' . bufnr('') . ':p:h')) \ . ale#Escape('path/to/pipenv') . ' run vulture' . ' .' diff --git a/test/completion/test_ale_import_command.vader b/test/completion/test_ale_import_command.vader new file mode 100644 index 00000000..2ba9b8d7 --- /dev/null +++ b/test/completion/test_ale_import_command.vader @@ -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, should_save) abort + Assert !a: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': 11, + \ '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': 11, + \ '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': 11, + \ 'line': 2, + \ 'prefix': 'missingword', + \ }], + \ [0, 'ts@completionEntryDetails', { + \ 'file': expand('%:p'), + \ 'entryNames': [{'name': 'missingword'}], + \ 'offset': 11, + \ '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': 11, + \ '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': 11, + \ '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': 7, + \ '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': 7, + \ '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#ToURI(expand('%:p'))}, + \ 'position': {'character': 6, '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': 7, + \ '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': 7, + \ '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#ToURI(expand('%:p'))}, + \ 'position': {'character': 6, '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() diff --git a/test/completion/test_completion_events.vader b/test/completion/test_completion_events.vader index 3a7a31d0..87bd10ad 100644 --- a/test/completion/test_completion_events.vader +++ b/test/completion/test_completion_events.vader @@ -35,7 +35,7 @@ Before: let g:ale_completion_delay = 0 " Run this check a few times, as it can fail randomly. - for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1) + for l:i in range(has('nvim-0.3') || has('win32') ? 5 : 1) call ale#completion#Queue() sleep 1m diff --git a/test/completion/test_completion_filtering.vader b/test/completion/test_completion_filtering.vader index c5f14266..172203a4 100644 --- a/test/completion/test_completion_filtering.vader +++ b/test/completion/test_completion_filtering.vader @@ -12,13 +12,24 @@ After: Execute(Prefix filtering should work for Lists of strings): AssertEqual \ ['FooBar', 'foo'], - \ ale#completion#Filter(bufnr(''), '', ['FooBar', 'FongBar', 'baz', 'foo'], 'foo') + \ ale#completion#Filter(bufnr(''), '', ['FooBar', 'FongBar', 'baz', 'foo'], 'foo', 0) AssertEqual \ ['FooBar', 'FongBar', 'baz', 'foo'], - \ ale#completion#Filter(bufnr(''), '', ['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'], '') + \ 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 @@ -32,7 +43,8 @@ Execute(Prefix filtering should work for completion items): \ {'word': 'baz'}, \ {'word': 'foo'}, \ ], - \ 'foo' + \ 'foo', + \ 0, \ ) AssertEqual @@ -51,7 +63,8 @@ Execute(Prefix filtering should work for completion items): \ {'word': 'baz'}, \ {'word': 'foo'}, \ ], - \ '.' + \ '.', + \ 0, \ ) Execute(Excluding words from completion results should work): @@ -66,7 +79,8 @@ Execute(Excluding words from completion results should work): \ {'word': 'Italian'}, \ {'word': 'it'}, \ ], - \ 'it' + \ 'it', + \ 0, \ ) AssertEqual @@ -78,7 +92,8 @@ Execute(Excluding words from completion results should work): \ {'word': 'describe'}, \ {'word': 'Deutsch'}, \ ], - \ 'de' + \ 'de', + \ 0, \ ) AssertEqual @@ -90,7 +105,8 @@ Execute(Excluding words from completion results should work): \ {'word': 'describe'}, \ {'word': 'Deutsch'}, \ ], - \ '.' + \ '.', + \ 0, \ ) Execute(Excluding words from completion results should work with lists of Strings): @@ -98,29 +114,29 @@ Execute(Excluding words from completion results should work with lists of String AssertEqual \ ['Italian'], - \ ale#completion#Filter(bufnr(''), '', ['Italian', 'it'], 'it') + \ ale#completion#Filter(bufnr(''), '', ['Italian', 'it'], 'it', 0) AssertEqual \ ['Deutsch'], - \ ale#completion#Filter(bufnr(''), '', ['describe', 'Deutsch'], 'de') + \ ale#completion#Filter(bufnr(''), '', ['describe', 'Deutsch'], 'de', 0) AssertEqual \ ['Deutsch'], - \ ale#completion#Filter(bufnr(''), '', ['describe', 'Deutsch'], '.') + \ ale#completion#Filter(bufnr(''), '', ['describe', 'Deutsch'], '.', 0) AssertEqual \ ['Deutsch'], - \ ale#completion#Filter(bufnr(''), '', ['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, '.') + AssertEqual [], ale#completion#Filter(bufnr(''), '', b:suggestions, '.', 0) AssertEqual b:suggestions, [{'word': 'describe'}] - AssertEqual [], ale#completion#Filter(bufnr(''), '', b:suggestions, 'de') + 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, '.') - AssertEqual b:suggestions, ale#completion#Filter(bufnr(''), 'rust', b:suggestions, '.') - AssertEqual b:suggestions, ale#completion#Filter(bufnr(''), 'rust', b:suggestions, '::') + 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) diff --git a/test/completion/test_lsp_completion_parsing.vader b/test/completion/test_lsp_completion_parsing.vader index 8b8b41c7..b8e71320 100644 --- a/test/completion/test_lsp_completion_parsing.vader +++ b/test/completion/test_lsp_completion_parsing.vader @@ -609,6 +609,7 @@ Execute(Should handle completion messages with additionalTextEdits when ale_comp 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 \ [], @@ -645,3 +646,36 @@ Execute(Should not handle completion messages with additionalTextEdits when ale_ \ ], \ }, \ }) + +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', + \ 'menu': 'PlayTimeCallback', + \ 'info': '', + \ 'kind': 'v', + \ 'icase': 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': [], + \ }, + \ ], + \ }, + \ }) diff --git a/test/completion/test_tsserver_completion_parsing.vader b/test/completion/test_tsserver_completion_parsing.vader index 4515afd1..aaaaae95 100644 --- a/test/completion/test_tsserver_completion_parsing.vader +++ b/test/completion/test_tsserver_completion_parsing.vader @@ -1,4 +1,11 @@ +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): @@ -242,3 +249,54 @@ Execute(Entries without details should be included in the responses): \ }, \ ], \}) + +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({ + \ 'codeActions': [{ + \ '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': [], + \ }, + \ ], + \ }, + \ ], + \ }) diff --git a/test/ember-template-lint-test-files/app/template.hbs b/test/ember-template-lint-test-files/app/template.hbs new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/ember-template-lint-test-files/app/template.hbs diff --git a/test/ember-template-lint-test-files/package.json b/test/ember-template-lint-test-files/package.json new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/ember-template-lint-test-files/package.json diff --git a/test/fix/test_ale_fix.vader b/test/fix/test_ale_fix.vader index c3dd20e4..a51a5a53 100644 --- a/test/fix/test_ale_fix.vader +++ b/test/fix/test_ale_fix.vader @@ -5,18 +5,22 @@ Before: 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 @@ -70,6 +74,10 @@ Before: 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 @@ -82,56 +90,6 @@ Before: return [{'lnum': 1, 'col': 1, 'text': 'xxx'}] endfunction - function! FirstChainCallback(buffer) - return {'command': 'echo echoline', 'chain_with': 'SecondChainCallback'} - endfunction - - function! FirstChainCallbackSkipped(buffer) - 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 - " echo will output a single blank line, and we should ingore it. function! IgnoredEmptyOutput(buffer, output) return {'command': has('win32') ? 'echo(' : 'echo'} @@ -203,16 +161,10 @@ After: delfunction CatLineDeferred delfunction ReplaceWithTempFile delfunction CatWithTempFile + delfunction EchoFilename delfunction RemoveLastLine delfunction RemoveLastLineOneArg delfunction TestCallback - delfunction FirstChainCallback - delfunction FirstChainCallbackSkipped - delfunction FirstChainCallbackSecondSkipped - delfunction SecondChainCallback - delfunction ThirdChainCallback - delfunction ChainWhereLastIsSkipped - delfunction ChainEndSkipped delfunction SetUpLinters delfunction GetLastMessage delfunction IgnoredEmptyOutput @@ -264,6 +216,25 @@ Expect(The first function should be used): ^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 @@ -756,6 +727,19 @@ 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 @@ -814,57 +798,6 @@ Execute(ALE should tolerate valid fixers with minuses in the name): 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 - Execute(Empty output should be ignored): let g:ale_fixers.testft = ['IgnoredEmptyOutput'] ALEFix diff --git a/test/fixers/test_clangtidy_fixer_callback.vader b/test/fixers/test_clangtidy_fixer_callback.vader index 68416b36..ca08e6bc 100644 --- a/test/fixers/test_clangtidy_fixer_callback.vader +++ b/test/fixers/test_clangtidy_fixer_callback.vader @@ -1,8 +1,19 @@ 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') @@ -36,16 +47,3 @@ Execute(The clangtidy callback should include any additional options): \ . ' -fix -fix-errors --some-option %t', \ }, \ ale#fixers#clangtidy#Fix(bufnr('')) - -Execute(The clangtidy callback should support cpp files): - call ale#test#SetFilename('c_paths/dummy.cpp') - let g:ale_cpp_clangtidy_executable = 'invalidpp' - set filetype=cpp " The test fails without this - - AssertEqual - \ { - \ 'read_temporary_file': 1, - \ 'command': ale#Escape(g:ale_cpp_clangtidy_executable) - \ . ' -fix -fix-errors %t', - \ }, - \ ale#fixers#clangtidy#Fix(bufnr('')) diff --git a/test/fixers/test_dhall_fixer_callback.vader b/test/fixers/test_dhall_fixer_callback.vader new file mode 100644 index 00000000..f27880b7 --- /dev/null +++ b/test/fixers/test_dhall_fixer_callback.vader @@ -0,0 +1,11 @@ +Before: + call ale#assert#SetUpFixerTest('dhall', 'dhall') + +After: + call ale#assert#TearDownFixerTest() + +Execute(The default command should be correct): + AssertFixer + \ { 'read_temporary_file': 1, + \ 'command': ale#Escape('dhall') . ' format --inplace %t' + \ } diff --git a/test/fixers/test_eslint_fixer_callback.vader b/test/fixers/test_eslint_fixer_callback.vader index 400267ac..50fc6672 100644 --- a/test/fixers/test_eslint_fixer_callback.vader +++ b/test/fixers/test_eslint_fixer_callback.vader @@ -1,7 +1,11 @@ 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() diff --git a/test/fixers/test_isort_fixer_callback.vader b/test/fixers/test_isort_fixer_callback.vader index 50818621..7f389dcf 100644 --- a/test/fixers/test_isort_fixer_callback.vader +++ b/test/fixers/test_isort_fixer_callback.vader @@ -4,6 +4,7 @@ Before: " Use an invalid global executable, so we don't match it. let g:ale_python_isort_executable = 'xxxinvalid' + let g:ale_python_isort_options = '' call ale#test#SetDirectory('/testplugin/test/fixers') silent cd .. @@ -27,7 +28,7 @@ Execute(The isort callback should return the correct default values): silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') AssertEqual \ { - \ 'command': ale#path#CdString(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/subdir/foo')) + \ 'command': ale#path#BufferCdString(bufnr('')) \ . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/isort')) . ' -', \ }, \ ale#fixers#isort#Fix(bufnr('')) @@ -42,7 +43,7 @@ Execute(The isort callback should respect custom options): silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') AssertEqual \ { - \ 'command': ale#path#CdString(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/subdir/foo')) + \ 'command': ale#path#BufferCdString(bufnr('')) \ . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/isort')) \ . ' --multi-line=3 --trailing-comma -', \ }, diff --git a/test/fixers/test_latexindent_fixer_callback.vader b/test/fixers/test_latexindent_fixer_callback.vader index d0da94a1..a440ed65 100644 --- a/test/fixers/test_latexindent_fixer_callback.vader +++ b/test/fixers/test_latexindent_fixer_callback.vader @@ -18,10 +18,8 @@ Execute(The latexindent callback should return the correct default values): AssertEqual \ { - \ 'read_temporary_file': 1, \ 'command': ale#Escape('xxxinvalid') - \ . ' -l -w' - \ . ' %t', + \ . ' -l' \ }, \ ale#fixers#latexindent#Fix(bufnr('')) @@ -31,10 +29,8 @@ Execute(The latexindent callback should include custom gofmt options): AssertEqual \ { - \ 'read_temporary_file': 1, \ 'command': ale#Escape('xxxinvalid') - \ . ' -l -w' + \ . ' -l' \ . ' ' . g:ale_tex_latexindent_options - \ . ' %t', \ }, \ ale#fixers#latexindent#Fix(bufnr('')) diff --git a/test/fixers/test_ocamlformat_fixer_callback.vader b/test/fixers/test_ocamlformat_fixer_callback.vader index f0c36ed7..0ccdb070 100644 --- a/test/fixers/test_ocamlformat_fixer_callback.vader +++ b/test/fixers/test_ocamlformat_fixer_callback.vader @@ -19,8 +19,7 @@ Execute(The ocamlformat callback should return the correct default values): AssertEqual \ { \ 'command': ale#Escape('xxxinvalid') - \ . ' --name=' . ale#Escape(bufname(bufnr(''))) - \ . ' -', + \ . ' --name=%s -', \ }, \ ale#fixers#ocamlformat#Fix(bufnr('')) @@ -32,7 +31,6 @@ Execute(The ocamlformat callback should include custom ocamlformat options): \ { \ 'command': ale#Escape('xxxinvalid') \ . ' ' . g:ale_ocaml_ocamlformat_options - \ . ' --name=' . ale#Escape(bufname(bufnr(''))) - \ . ' -', + \ . ' --name=%s -', \ }, \ ale#fixers#ocamlformat#Fix(bufnr('')) diff --git a/test/fixers/test_prettier_eslint_fixer.callback.vader b/test/fixers/test_prettier_eslint_fixer.callback.vader index 90e11672..be8f04e3 100644 --- a/test/fixers/test_prettier_eslint_fixer.callback.vader +++ b/test/fixers/test_prettier_eslint_fixer.callback.vader @@ -1,5 +1,8 @@ Before: call ale#assert#SetUpFixerTest('javascript', 'prettier_eslint') + Save g:ale_command_wrapper + + let g:ale_command_wrapper = '' After: call ale#assert#TearDownFixerTest() @@ -70,7 +73,7 @@ Execute(The new --stdin-filepath option should be used when the version is new e GivenCommandOutput ['4.4.0'] AssertFixer \ { - \ 'command': ale#path#CdString(expand('%:p:h')) + \ 'command': ale#path#BufferCdString(bufnr('')) \ . ale#Escape('prettier-eslint') \ . ' --eslint-config-path ' . ale#Escape(ale#path#Simplify(g:dir . '/eslint-test-files/react-app/.eslintrc.js')) \ . ' --stdin-filepath %s --stdin', @@ -80,7 +83,7 @@ Execute(The version number should be cached): GivenCommandOutput ['4.4.0'] AssertFixer \ { - \ 'command': ale#path#CdString(expand('%:p:h')) + \ 'command': ale#path#BufferCdString(bufnr('')) \ . ale#Escape('prettier-eslint') \ . ' --stdin-filepath %s --stdin', \ } @@ -88,7 +91,7 @@ Execute(The version number should be cached): GivenCommandOutput [] AssertFixer \ { - \ 'command': ale#path#CdString(expand('%:p:h')) + \ 'command': ale#path#BufferCdString(bufnr('')) \ . ale#Escape('prettier-eslint') \ . ' --stdin-filepath %s --stdin', \ } diff --git a/test/fixers/test_prettier_fixer_callback.vader b/test/fixers/test_prettier_fixer_callback.vader index 062ae8cf..fdd97df3 100644 --- a/test/fixers/test_prettier_fixer_callback.vader +++ b/test/fixers/test_prettier_fixer_callback.vader @@ -1,5 +1,8 @@ Before: call ale#assert#SetUpFixerTest('javascript', 'prettier') + Save g:ale_command_wrapper + + let g:ale_command_wrapper = '' silent cd .. silent cd command_callback @@ -294,6 +297,17 @@ Execute(Should set --parser for experimental language, Handlebars): \ . ' --stdin-filepath %s --stdin', \ } +Execute(Changes to directory where .prettierignore is found): + call ale#test#SetFilename('../prettier-test-files/with_prettierignore/src/testfile.js') + + GivenCommandOutput ['1.6.0'] + AssertFixer + \ { + \ 'command': ale#path#CdString(expand('%:p:h:h')) + \ . ale#Escape(g:ale_javascript_prettier_executable) + \ . ' --stdin-filepath %s --stdin', + \ } + Execute(The prettier_d post-processor should permit regular JavaScript content): AssertEqual \ [ diff --git a/test/fixers/test_prettier_standard_callback.vader b/test/fixers/test_prettier_standard_callback.vader new file mode 100644 index 00000000..ab33fe20 --- /dev/null +++ b/test/fixers/test_prettier_standard_callback.vader @@ -0,0 +1,19 @@ +Before: + call ale#assert#SetUpFixerTest('javascript', 'prettier_standard') + + silent cd .. + silent cd command_callback + let g:dir = getcwd() + +After: + call ale#assert#TearDownFixerTest() + +Execute(The prettier callback should return the correct default values): + call ale#test#SetFilename('../prettier-test-files/testfile.js') + + AssertFixer + \ { + \ 'command': ale#Escape(g:ale_javascript_prettier_standard_executable) + \ . ' --stdin' + \ . ' --stdin-filepath=%s ', + \ } diff --git a/test/fixers/test_remark_lint_fixer_callback.vader b/test/fixers/test_remark_lint_fixer_callback.vader new file mode 100644 index 00000000..5e2e342d --- /dev/null +++ b/test/fixers/test_remark_lint_fixer_callback.vader @@ -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('')) diff --git a/test/fixers/test_rubocop_fixer_callback.vader b/test/fixers/test_rubocop_fixer_callback.vader index 305881e0..84579d31 100644 --- a/test/fixers/test_rubocop_fixer_callback.vader +++ b/test/fixers/test_rubocop_fixer_callback.vader @@ -23,8 +23,7 @@ Execute(The rubocop callback should return the correct default values): \ { \ 'process_with': 'ale#fixers#rubocop#PostProcess', \ 'command': ale#Escape(g:ale_ruby_rubocop_executable) - \ . ' --auto-correct --force-exclusion --stdin ' - \ . ale#Escape(expand('#' . bufnr('') . ':p')), + \ . ' --auto-correct --force-exclusion --stdin %s', \ }, \ ale#fixers#rubocop#Fix(bufnr('')) @@ -36,8 +35,7 @@ Execute(The rubocop callback should include configuration files): \ 'process_with': 'ale#fixers#rubocop#PostProcess', \ 'command': ale#Escape(g:ale_ruby_rubocop_executable) \ . ' --config ' . ale#Escape(ale#path#Simplify(g:dir . '/ruby_paths/with_config/.rubocop.yml')) - \ . ' --auto-correct --force-exclusion --stdin ' - \ . ale#Escape(expand('#' . bufnr('') . ':p')), + \ . ' --auto-correct --force-exclusion --stdin %s', \ }, \ ale#fixers#rubocop#Fix(bufnr('')) @@ -51,8 +49,7 @@ Execute(The rubocop callback should include custom rubocop options): \ 'command': ale#Escape(g:ale_ruby_rubocop_executable) \ . ' --config ' . ale#Escape(ale#path#Simplify(g:dir . '/ruby_paths/with_config/.rubocop.yml')) \ . ' --except Lint/Debugger' - \ . ' --auto-correct --force-exclusion --stdin ' - \ . ale#Escape(expand('#' . bufnr('') . ':p')), + \ . ' --auto-correct --force-exclusion --stdin %s', \ }, \ ale#fixers#rubocop#Fix(bufnr('')) @@ -65,8 +62,7 @@ Execute(The rubocop callback should use auto-correct-all option when set): \ 'process_with': 'ale#fixers#rubocop#PostProcess', \ 'command': ale#Escape(g:ale_ruby_rubocop_executable) \ . ' --config ' . ale#Escape(ale#path#Simplify(g:dir . '/ruby_paths/with_config/.rubocop.yml')) - \ . ' --auto-correct-all --force-exclusion --stdin ' - \ . ale#Escape(expand('#' . bufnr('') . ':p')), + \ . ' --auto-correct-all --force-exclusion --stdin %s' \ }, \ ale#fixers#rubocop#Fix(bufnr('')) diff --git a/test/fixers/test_standard_fixer_callback.vader b/test/fixers/test_standard_fixer_callback.vader index db9f20f6..f5e9c487 100644 --- a/test/fixers/test_standard_fixer_callback.vader +++ b/test/fixers/test_standard_fixer_callback.vader @@ -15,7 +15,7 @@ Execute(The executable path should be correct): \ 'read_temporary_file': 1, \ 'command': (has('win32') ? 'node.exe ' : '') \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/standard/bin/cmd.js')) - \ . ' --fix %t', + \ . ' --fix --stdin < %s > %t', \ }, \ ale#fixers#standard#Fix(bufnr('')) @@ -26,6 +26,6 @@ Execute(Custom options should be supported): AssertEqual \ { \ 'read_temporary_file': 1, - \ 'command': ale#Escape('standard') . ' --foo-bar --fix %t', + \ 'command': ale#Escape('standard') . ' --foo-bar --fix --stdin < %s > %t', \ }, \ ale#fixers#standard#Fix(bufnr('')) diff --git a/test/fixers/test_stylelint_fixer_callback.vader b/test/fixers/test_stylelint_fixer_callback.vader index f677cdf7..8fbd8a51 100644 --- a/test/fixers/test_stylelint_fixer_callback.vader +++ b/test/fixers/test_stylelint_fixer_callback.vader @@ -1,4 +1,8 @@ Before: + Save g:ale_stylelint_options + + let g:ale_stylelint_options = '' + call ale#assert#SetUpFixerTest('css', 'stylelint') After: @@ -10,7 +14,7 @@ Execute(The stylelint callback should return the correct default values): AssertFixer \ { \ 'read_temporary_file': 1, - \ 'command': ale#path#CdString(expand('%:p:h')) + \ 'command': ale#path#BufferCdString(bufnr('')) \ . (has('win32') ? 'node.exe ' : '') \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/stylelint/bin/stylelint.js')) \ . ' %t' @@ -24,7 +28,7 @@ Execute(The stylelint callback should include custom stylelint options): AssertFixer \ { \ 'read_temporary_file': 1, - \ 'command': ale#path#CdString(expand('%:p:h')) + \ 'command': ale#path#BufferCdString(bufnr('')) \ . (has('win32') ? 'node.exe ' : '') \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/stylelint/bin/stylelint.js')) \ . ' %t' diff --git a/test/handler/test_gcc_handler.vader b/test/handler/test_gcc_handler.vader index b67483a6..a4231cab 100644 --- a/test/handler/test_gcc_handler.vader +++ b/test/handler/test_gcc_handler.vader @@ -279,3 +279,38 @@ Execute(The GCC handler should handle errors for inlined header functions): \ ' __open_too_many_args ();', \ ' ^~~~~~~~~~~~~~~~~~~~~~~', \ ]) + +Execute(The GCC handler should handle macro expansion errors in current file): + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'col': 19, + \ 'type': 'E', + \ 'text': 'error message', + \ 'detail': "error message\n<stdin>:1:19: note: in expansion of macro 'TEST'", + \ }, + \ ], + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ + \ '<command-line>: error: error message', + \ '<stdin>:1:19: note: in expansion of macro ‘TEST’', + \ ' 1 | std::string str = TEST;', + \ ' | ^~~~', + \ ]) + +Execute(The GCC handler should handle macro expansion errors in other files): + AssertEqual + \ [ + \ { + \ 'lnum': 0, + \ 'type': 'E', + \ 'text': 'Error found in macro expansion. See :ALEDetail', + \ 'detail': "error message\ninc.h:1:19: note: in expansion of macro 'TEST'", + \ }, + \ ], + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ + \ '<command-line>: error: error message', + \ 'inc.h:1:19: note: in expansion of macro ‘TEST’', + \ ' 1 | std::string str = TEST;', + \ ' | ^~~~', + \ ]) diff --git a/test/handler/test_glslang_handler.vader b/test/handler/test_glslang_handler.vader index d51c9852..6d3a7999 100644 --- a/test/handler/test_glslang_handler.vader +++ b/test/handler/test_glslang_handler.vader @@ -1,3 +1,6 @@ +Before: + runtime ale_linters/glsl/glslang.vim + Execute(The glsl glslang handler should parse lines correctly): AssertEqual \ [ diff --git a/test/handler/test_sqllint_handler.vader b/test/handler/test_sqllint_handler.vader new file mode 100644 index 00000000..2f2283c8 --- /dev/null +++ b/test/handler/test_sqllint_handler.vader @@ -0,0 +1,23 @@ +Before: + " Load the file which defines the linter. + runtime ale_linters/sql/sqllint.vim + +After: + " Unload all linters again. + call ale#linter#Reset() + +Execute (The output should be correct): + + " Test that the right loclist items are parsed from the handler. + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'col': 0, + \ 'type': '', + \ 'text': 'stdin:1 [ER_NO_DB_ERROR] No database selected' + \ }, + \ ], + \ ale_linters#sql#sqllint#Handle(bufnr(''), [ + \ 'stdin:1 [ER_NO_DB_ERROR] No database selected' + \ ]) diff --git a/test/handler/test_standard_handler.vader b/test/handler/test_standard_handler.vader index 59ebe531..31e3a36b 100644 --- a/test/handler/test_standard_handler.vader +++ b/test/handler/test_standard_handler.vader @@ -1,3 +1,11 @@ +Before: + Save g:ale_javascript_eslint_suppress_eslintignore + + let g:ale_javascript_eslint_suppress_eslintignore = 0 + +After: + Restore + Execute(The standard handler should parse lines correctly): AssertEqual \ [ diff --git a/test/handler/test_swiftformat_handler.vader b/test/handler/test_swiftformat_handler.vader new file mode 100644 index 00000000..3dcc4f1a --- /dev/null +++ b/test/handler/test_swiftformat_handler.vader @@ -0,0 +1,28 @@ +Before: + runtime ale_linters/swift/swiftformat.vim + +After: + call ale#linter#Reset() + +Execute(The swiftformat handler should parse lines correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 4, + \ 'col': 21, + \ 'type': 'W', + \ 'code': 'DoNotUseSemicolons', + \ 'text': 'remove '';'' and move the next statement to the new line', + \ }, + \ { + \ 'lnum': 3, + \ 'col': 12, + \ 'type': 'W', + \ 'code': 'Spacing', + \ 'text': 'remove 1 space' + \ }, + \ ], + \ ale_linters#swift#swiftformat#Handle(bufnr(''), [ + \ 'Sources/main.swift:4:21: warning: [DoNotUseSemicolons]: remove '';'' and move the next statement to the new line', + \ 'Sources/main.swift:3:12: warning: [Spacing]: remove 1 space', + \ ]) diff --git a/test/handler/test_vlog_handler.vader b/test/handler/test_vlog_handler.vader index daf3cdcf..7262f63d 100644 --- a/test/handler/test_vlog_handler.vader +++ b/test/handler/test_vlog_handler.vader @@ -10,12 +10,14 @@ Execute(The vlog handler should parse old-style lines correctly): \ { \ 'lnum': 7, \ 'type': 'W', - \ 'text': '(vlog-2623) Undefined variable: C.' + \ 'text': '(vlog-2623) Undefined variable: C.', + \ 'filename': 'add.v' \ }, \ { \ 'lnum': 1, \ 'type': 'E', - \ 'text': '(vlog-13294) Identifier must be declared with a port mode: C.' + \ 'text': '(vlog-13294) Identifier must be declared with a port mode: C.', + \ 'filename': 'file.v' \ }, \ ], \ ale_linters#verilog#vlog#Handle(bufnr(''), [ @@ -29,12 +31,14 @@ Execute(The vlog handler should parse new-style lines correctly): \ { \ 'lnum': 7, \ 'type': 'W', - \ 'text': '(vlog-2623) Undefined variable: C.' + \ 'text': '(vlog-2623) Undefined variable: C.', + \ 'filename': 'add.v' \ }, \ { \ 'lnum': 1, \ 'type': 'E', - \ 'text': '(vlog-13294) Identifier must be declared with a port mode: C.' + \ 'text': '(vlog-13294) Identifier must be declared with a port mode: C.', + \ 'filename': 'file.v' \ }, \ ], \ ale_linters#verilog#vlog#Handle(bufnr(''), [ diff --git a/test/lsp/test_did_save_event.vader b/test/lsp/test_did_save_event.vader index bdea6d98..1d811363 100644 --- a/test/lsp/test_did_save_event.vader +++ b/test/lsp/test_did_save_event.vader @@ -33,8 +33,8 @@ Before: \ 'lsp': 'stdio', \ 'command': 'cat - > /dev/null', \ 'executable': has('win32') ? 'cmd' : 'echo', - \ 'language_callback': 'LanguageCallback', - \ 'project_root_callback': 'ProjectRootCallback', + \ 'language': function('LanguageCallback'), + \ 'project_root': function('ProjectRootCallback'), \ }) let g:ale_linters = {'foobar': ['dummy_linter']} diff --git a/test/lsp/test_engine_lsp_response_handling.vader b/test/lsp/test_engine_lsp_response_handling.vader index 9abfa087..8261f1da 100644 --- a/test/lsp/test_engine_lsp_response_handling.vader +++ b/test/lsp/test_engine_lsp_response_handling.vader @@ -44,9 +44,21 @@ After: Given foobar(An empty file): Execute(tsserver syntax error responses should be handled correctly): runtime ale_linters/typescript/tsserver.vim - call ale#test#SetFilename('filename.ts') + + if has('win32') + call ale#test#SetFilename('filename,[]^$.ts') + else + call ale#test#SetFilename('filename*?,{}[]^$.ts') + endif + call ale#engine#InitBufferInfo(bufnr('')) + if has('win32') + AssertEqual 'filename,[]^$.ts', expand('%:p:t') + else + AssertEqual 'filename*?,{}[]^$.ts', expand('%:p:t') + endif + " When we get syntax errors and no semantic errors, we should keep the " syntax errors. call ale#lsp_linter#HandleLSPResponse(1, { @@ -54,7 +66,7 @@ Execute(tsserver syntax error responses should be handled correctly): \ 'type': 'event', \ 'event': 'syntaxDiag', \ 'body': { - \ 'file': g:dir . '/filename.ts', + \ 'file': expand('%:p'), \ 'diagnostics':[ \ { \ 'start': { @@ -76,7 +88,7 @@ Execute(tsserver syntax error responses should be handled correctly): \ 'type': 'event', \ 'event': 'semanticDiag', \ 'body': { - \ 'file': g:dir . '/filename.ts', + \ 'file': expand('%:p'), \ 'diagnostics':[ \ ], \ }, @@ -104,7 +116,7 @@ Execute(tsserver syntax error responses should be handled correctly): \ 'type': 'event', \ 'event': 'syntaxDiag', \ 'body': { - \ 'file': g:dir . '/filename.ts', + \ 'file': expand('%:p'), \ 'diagnostics':[ \ ], \ }, @@ -146,9 +158,21 @@ Execute(tsserver syntax error responses should be handled correctly): Execute(tsserver semantic error responses should be handled correctly): runtime ale_linters/typescript/tsserver.vim - call ale#test#SetFilename('filename.ts') + + if has('win32') + call ale#test#SetFilename('filename,[]^$.ts') + else + call ale#test#SetFilename('filename*?,{}[]^$.ts') + endif + call ale#engine#InitBufferInfo(bufnr('')) + if has('win32') + AssertEqual 'filename,[]^$.ts', expand('%:p:t') + else + AssertEqual 'filename*?,{}[]^$.ts', expand('%:p:t') + endif + " When we get syntax errors and no semantic errors, we should keep the " syntax errors. call ale#lsp_linter#HandleLSPResponse(1, { @@ -156,7 +180,7 @@ Execute(tsserver semantic error responses should be handled correctly): \ 'type': 'event', \ 'event': 'syntaxDiag', \ 'body': { - \ 'file': g:dir . '/filename.ts', + \ 'file': expand('%:p'), \ 'diagnostics':[ \ ], \ }, @@ -166,7 +190,7 @@ Execute(tsserver semantic error responses should be handled correctly): \ 'type': 'event', \ 'event': 'semanticDiag', \ 'body': { - \ 'file': g:dir . '/filename.ts', + \ 'file': expand('%:p'), \ 'diagnostics':[ \ { \ 'start': { @@ -206,7 +230,7 @@ Execute(tsserver semantic error responses should be handled correctly): \ 'type': 'event', \ 'event': 'semanticDiag', \ 'body': { - \ 'file': g:dir . '/filename.ts', + \ 'file': expand('%:p'), \ 'diagnostics':[ \ ], \ }, @@ -270,15 +294,27 @@ Execute(tsserver errors should mark tsserver no longer active): Execute(LSP diagnostics responses should be handled correctly): let b:ale_linters = ['eclipselsp'] runtime ale_linters/java/eclipselsp.vim - call ale#test#SetFilename('filename.java') + + if has('win32') + call ale#test#SetFilename('filename,[]^$.ts') + else + call ale#test#SetFilename('filename*?,{}[]^$.java') + endif + call ale#engine#InitBufferInfo(bufnr('')) call ale#lsp_linter#SetLSPLinterMap({'1': 'eclipselsp'}) + if has('win32') + AssertEqual 'filename,[]^$.ts', expand('%:p:t') + else + AssertEqual 'filename*?,{}[]^$.java', expand('%:p:t') + endif + call ale#lsp_linter#HandleLSPResponse(1, { \ 'jsonrpc':'2.0', \ 'method':'textDocument/publishDiagnostics', \ 'params': { - \ 'uri':'file://' . g:dir . '/filename.java', + \ 'uri': ale#path#ToURI(expand('%:p')), \ 'diagnostics': [ \ { \ 'range': { diff --git a/test/lsp/test_lsp_command_formatting.vader b/test/lsp/test_lsp_command_formatting.vader index ec3b4120..e99e1dad 100644 --- a/test/lsp/test_lsp_command_formatting.vader +++ b/test/lsp/test_lsp_command_formatting.vader @@ -1,6 +1,10 @@ Before: + Save g:ale_command_wrapper + runtime autoload/ale/lsp.vim + let g:ale_command_wrapper = '' + let g:args = [] " Mock the StartProgram function so we can just capture the arguments. @@ -9,6 +13,8 @@ Before: endfunction After: + Restore + unlet! g:args runtime autoload/ale/lsp.vim @@ -18,8 +24,8 @@ Execute(Command formatting should be applied correctly for LSP linters): \ bufnr(''), \ { \ 'name': 'linter', - \ 'language_callback': {-> 'x'}, - \ 'project_root_callback': {-> '/foo/bar'}, + \ 'language': {-> 'x'}, + \ 'project_root': {-> '/foo/bar'}, \ 'lsp': 'stdio', \ 'executable': has('win32') ? 'cmd': 'true', \ 'command': '%e --foo', diff --git a/test/lsp/test_lsp_custom_request.vader b/test/lsp/test_lsp_custom_request.vader index 04f044af..c8767e59 100644 --- a/test/lsp/test_lsp_custom_request.vader +++ b/test/lsp/test_lsp_custom_request.vader @@ -25,7 +25,6 @@ Before: \ 'name': g:linter_name, \ 'project_root': {b -> g:project_root}, \ 'aliases': [], - \ 'language_callback': {b -> 'cpp'}, \ 'read_buffer': 1, \ 'command': '%e' \ }] diff --git a/test/lsp/test_lsp_startup.vader b/test/lsp/test_lsp_startup.vader index c29690bf..cd9b59dd 100644 --- a/test/lsp/test_lsp_startup.vader +++ b/test/lsp/test_lsp_startup.vader @@ -422,3 +422,13 @@ Execute(Deferred addresses should be handled correctly): Assert Start() call ale#test#FlushJobs() call AssertInitSuccess('foo', 'localhost:1234', 'foobar', '/foo/bar', '') + +Execute(Servers that have crashed should be restarted): + call ale#lsp#Register('foo', '/foo/bar', {}) + call extend(ale#lsp#GetConnections()['foo:/foo/bar'], {'initialized': 1}) + + " Starting the program again should reset initialized to `0`. + call ale#lsp#StartProgram('foo:/foo/bar', 'foobar', 'foobar --start') + + AssertEqual 0, ale#lsp#GetConnections()['foo:/foo/bar']['initialized'] + AssertEqual ['initialize'], map(PopMessages(), 'v:val[''method'']') diff --git a/test/prettier-test-files/with_prettierignore/.prettierignore b/test/prettier-test-files/with_prettierignore/.prettierignore new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/prettier-test-files/with_prettierignore/.prettierignore diff --git a/test/prettier-test-files/with_prettierignore/src/testfile.js b/test/prettier-test-files/with_prettierignore/src/testfile.js new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/prettier-test-files/with_prettierignore/src/testfile.js diff --git a/test/sign/test_linting_sets_signs.vader b/test/sign/test_linting_sets_signs.vader index 1d1f9802..1624449a 100644 --- a/test/sign/test_linting_sets_signs.vader +++ b/test/sign/test_linting_sets_signs.vader @@ -10,7 +10,9 @@ Before: Save g:ale_set_loclist Save g:ale_set_quickfix Save g:ale_set_signs + Save g:ale_command_wrapper + let g:ale_command_wrapper = '' let g:ale_buffer_info = {} let g:ale_run_synchronously = 1 unlet! g:ale_run_synchronously_callbacks diff --git a/test/sign/test_sign_placement.vader b/test/sign/test_sign_placement.vader index d8d05b28..7b80d83c 100644 --- a/test/sign/test_sign_placement.vader +++ b/test/sign/test_sign_placement.vader @@ -6,7 +6,9 @@ Before: Save g:ale_set_loclist Save g:ale_set_quickfix Save g:ale_set_signs + Save g:ale_command_wrapper + let g:ale_command_wrapper = '' let g:ale_buffer_info = {} let g:ale_run_synchronously = 1 let g:ale_set_signs = 1 diff --git a/test/smoke_test.vader b/test/smoke_test.vader index 53e08a8d..0b126cc6 100644 --- a/test/smoke_test.vader +++ b/test/smoke_test.vader @@ -1,8 +1,10 @@ Before: + Save g:ale_enabled Save g:ale_set_lists_synchronously Save g:ale_buffer_info Save &shell + let g:ale_enabled = 1 let g:ale_buffer_info = {} let g:ale_set_lists_synchronously = 1 diff --git a/test/test_autocmd_commands.vader b/test/test_autocmd_commands.vader index a69333d4..2f0a893f 100644 --- a/test/test_autocmd_commands.vader +++ b/test/test_autocmd_commands.vader @@ -92,8 +92,8 @@ Execute (All events should be set up when everything is on): \ 'FileType * call ale#events#FileTypeEvent( str2nr(expand(''<abuf>'')), expand(''<amatch>''))', \ 'InsertLeave * if ale#Var(str2nr(expand(''<abuf>'')), ''lint_on_insert_leave'') | call ale#Queue(0) | endif', \ 'InsertLeave if exists(''*ale#engine#Cleanup'') | call ale#cursor#EchoCursorWarning() | endif', - \ 'TextChanged * call ale#Queue(g:ale_lint_delay)', - \ 'TextChangedI * call ale#Queue(g:ale_lint_delay)', + \ 'TextChanged * call ale#Queue(ale#Var(str2nr(expand(''<abuf>'')), ''lint_delay''))', + \ 'TextChangedI * call ale#Queue(ale#Var(str2nr(expand(''<abuf>'')), ''lint_delay''))', \ ], \ CheckAutocmd('ALEEvents') @@ -145,8 +145,8 @@ Execute (g:ale_lint_on_text_changed = 1 bind both events): AssertEqual \ [ - \ 'TextChanged * call ale#Queue(g:ale_lint_delay)', - \ 'TextChangedI * call ale#Queue(g:ale_lint_delay)', + \ 'TextChanged * call ale#Queue(ale#Var(str2nr(expand(''<abuf>'')), ''lint_delay''))', + \ 'TextChangedI * call ale#Queue(ale#Var(str2nr(expand(''<abuf>'')), ''lint_delay''))', \ ], \ filter(CheckAutocmd('ALEEvents'), 'v:val =~ ''^TextChanged''') @@ -155,8 +155,8 @@ Execute (g:ale_lint_on_text_changed = 'always' should bind both events): AssertEqual \ [ - \ 'TextChanged * call ale#Queue(g:ale_lint_delay)', - \ 'TextChangedI * call ale#Queue(g:ale_lint_delay)', + \ 'TextChanged * call ale#Queue(ale#Var(str2nr(expand(''<abuf>'')), ''lint_delay''))', + \ 'TextChangedI * call ale#Queue(ale#Var(str2nr(expand(''<abuf>'')), ''lint_delay''))', \ ], \ filter(CheckAutocmd('ALEEvents'), 'v:val =~ ''^TextChanged''') @@ -165,7 +165,7 @@ Execute (g:ale_lint_on_text_changed = 'normal' should bind only TextChanged): AssertEqual \ [ - \ 'TextChanged * call ale#Queue(g:ale_lint_delay)', + \ 'TextChanged * call ale#Queue(ale#Var(str2nr(expand(''<abuf>'')), ''lint_delay''))', \ ], \ filter(CheckAutocmd('ALEEvents'), 'v:val =~ ''^TextChanged''') @@ -174,7 +174,7 @@ Execute (g:ale_lint_on_text_changed = 'insert' should bind only TextChangedI): AssertEqual \ [ - \ 'TextChangedI * call ale#Queue(g:ale_lint_delay)', + \ 'TextChangedI * call ale#Queue(ale#Var(str2nr(expand(''<abuf>'')), ''lint_delay''))', \ ], \ filter(CheckAutocmd('ALEEvents'), 'v:val =~ ''^TextChanged''') diff --git a/test/test_c_flag_parsing.vader b/test/test_c_flag_parsing.vader index 8ae6f9dc..99722b17 100644 --- a/test/test_c_flag_parsing.vader +++ b/test/test_c_flag_parsing.vader @@ -1,15 +1,43 @@ Before: Save g:ale_c_parse_makefile + Save g:ale_c_always_make + Save b:ale_c_always_make call ale#test#SetDirectory('/testplugin/test') let g:ale_c_parse_makefile = 1 + let g:ale_c_always_make = 1 + let b:ale_c_always_make = 1 + + function SplitAndParse(path_prefix, command) abort + let l:args = ale#c#ShellSplit(a:command) + + return ale#c#ParseCFlags(a:path_prefix, 0, l:args) + endfunction After: + delfunction SplitAndParse + Restore call ale#test#RestoreDirectory() +Execute(The make command should be correct): + call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') + + AssertEqual + \ ale#path#CdString(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project')) + \ . 'make -n --always-make', + \ ale#c#GetMakeCommand(bufnr('')) + + " You should be able to disable --always-make for a buffer. + let b:ale_c_always_make = 0 + + AssertEqual + \ ale#path#CdString(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project')) + \ . 'make -n', + \ ale#c#GetMakeCommand(bufnr('')) + Execute(The CFlags parser should be able to parse include directives): call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') @@ -18,7 +46,7 @@ Execute(The CFlags parser should be able to parse include directives): \ ale#c#ParseCFlagsFromMakeOutput(bufnr(''), ['gcc -Isubdir -c file.c']) AssertEqual - \ '-isystem ' . '/usr/include/dir', + \ '-isystem ' . ale#Escape('/usr/include/dir'), \ ale#c#ParseCFlagsFromMakeOutput(bufnr(''), ['gcc -isystem /usr/include/dir -c file.c']) Execute(ParseCFlags should ignore -c and -o): @@ -57,48 +85,21 @@ Execute(ParseCFlags should be able to parse flags with relative paths): \ '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')) \ . ' -DTEST=`date +%s`', - \ ale#c#ParseCFlags( + \ SplitAndParse( \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), \ 'gcc -Isubdir ' \ . '-I'. ale#path#Simplify('kernel/include') \ . ' -DTEST=`date +%s` -c file.c' \ ) -Execute(ParseCFlags should be able to parse -Dgoal): - AssertEqual - \ '-Dgoal=9' - \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) - \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')) - \ . ' -DTEST=`date +%s`', - \ ale#c#ParseCFlags( - \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), - \ 'gcc -Dgoal=9 -Isubdir ' - \ . '-I'. ale#path#Simplify('kernel/include') - \ . ' -DTEST=`date +%s` -c file.c' - \ ) - -Execute(ParseCFlags should ignore -T and other arguments): - AssertEqual - \ '-Dgoal=9' - \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) - \ . ' ' . '--sysroot=subdir' - \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')) - \ . ' -DTEST=`date +%s`', - \ ale#c#ParseCFlags( - \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), - \ 'gcc -Dgoal=9 -Tlinkerfile.ld blabla -Isubdir --sysroot=subdir ' - \ . '-I'. ale#path#Simplify('kernel/include') - \ . ' -DTEST=`date +%s` -c file.c' - \ ) - -Execute(ParseCFlags should handle paths with spaces in double quotes): +Execute(We should handle paths with spaces in double quotes): AssertEqual \ '-Dgoal=9' \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir with spaces')) \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')) \ . ' -DTEST=`date +%s`', - \ ale#c#ParseCFlags( + \ SplitAndParse( \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), \ 'gcc -Dgoal=9 -Tlinkerfile.ld blabla -Isubdir ' \ . '-I"dir with spaces"' . ' -I'. ale#path#Simplify('kernel/include') @@ -112,7 +113,7 @@ Execute(ParseCFlags should handle paths with spaces in single quotes): \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir with spaces')) \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')) \ . ' -DTEST=`date +%s`', - \ ale#c#ParseCFlags( + \ SplitAndParse( \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), \ 'gcc -Dgoal=9 -Tlinkerfile.ld blabla -Isubdir ' \ . '-I''dir with spaces''' . ' -I'. ale#path#Simplify('kernel/include') @@ -127,7 +128,7 @@ Execute(ParseCFlags should handle paths with minuses): \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir-with-dash')) \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')) \ . ' -DTEST=`date +%s`', - \ ale#c#ParseCFlags( + \ SplitAndParse( \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), \ 'gcc -Dgoal=9 -Tlinkerfile.ld blabla -Isubdir ' \ . '-I''dir with spaces''' . ' -Idir-with-dash' @@ -135,7 +136,7 @@ Execute(ParseCFlags should handle paths with minuses): \ . ' -DTEST=`date +%s` -c file.c' \ ) -Execute(ParseCFlags should handle -D with minuses): +Execute(We should handle -D with minuses): AssertEqual \ '-Dgoal=9' \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) @@ -144,7 +145,7 @@ Execute(ParseCFlags should handle -D with minuses): \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir-with-dash')) \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')) \ . ' -DTEST=`date +%s`', - \ ale#c#ParseCFlags( + \ SplitAndParse( \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), \ 'gcc -Dgoal=9 -Tlinkerfile.ld blabla -Isubdir ' \ . '-Dmacro-with-dash ' @@ -153,7 +154,7 @@ Execute(ParseCFlags should handle -D with minuses): \ . ' -DTEST=`date +%s` -c file.c' \ ) -Execute(ParseCFlags should handle flags at the end of the line): +Execute(We should handle flags at the end of the line): AssertEqual \ '-Dgoal=9' \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) @@ -161,7 +162,7 @@ Execute(ParseCFlags should handle flags at the end of the line): \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir with spaces')) \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir-with-dash')) \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')), - \ ale#c#ParseCFlags( + \ SplitAndParse( \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), \ 'gcc -Dgoal=9 -Tlinkerfile.ld blabla -Isubdir ' \ . '-Dmacro-with-dash ' @@ -178,50 +179,170 @@ Execute(ParseCompileCommandsFlags should tolerate empty values): Execute(ParseCompileCommandsFlags should parse some basic flags): silent noautocmd execute 'file! ' . fnameescape(ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c')) + " We should read the absolute path filename entry, not the other ones. AssertEqual - \ '-I ' . ale#path#Simplify('/usr/include/xmms2'), - \ ale#c#ParseCompileCommandsFlags(bufnr(''), { "xmms2-mpris.c": [ + \ '-I ' . ale#Escape(ale#path#Simplify('/usr/include/xmms2')), + \ ale#c#ParseCompileCommandsFlags( + \ bufnr(''), \ { - \ 'directory': ale#path#Simplify('/foo/bar/xmms2-mpris'), - \ 'command': '/usr/bin/cc -I' . ale#path#Simplify('/usr/include/xmms2') - \ . ' -o CMakeFiles/xmms2-mpris.dir/src/xmms2-mpris.c.o' - \ . ' -c ' . ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), - \ 'file': ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'): [ + \ { + \ 'directory': ale#path#Simplify('/foo/bar/xmms2-mpris'), + \ 'command': '/usr/bin/cc -I' . ale#path#Simplify('/usr/include/xmms2') + \ . ' -o CMakeFiles/xmms2-mpris.dir/src/xmms2-mpris.c.o' + \ . ' -c ' . ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ 'file': ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ }, + \ ], + \ "xmms2-mpris.c": [ + \ { + \ 'directory': ale#path#Simplify('/foo/bar/xmms2-mpris'), + \ 'command': '/usr/bin/cc -I' . ale#path#Simplify('/usr/include/ignoreme') + \ . ' -o CMakeFiles/xmms2-mpris.dir/src/xmms2-mpris.c.o' + \ . ' -c ' . ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ 'file': ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ }, + \ ], \ }, - \ ] }, {}) + \ { + \ ale#path#Simplify('/foo/bar/xmms2-mpris/src'): [ + \ { + \ 'directory': ale#path#Simplify('/foo/bar/xmms2-mpris/src'), + \ 'command': '/usr/bin/cc -I' . ale#path#Simplify('/usr/include/ignoreme') + \ . ' -o CMakeFiles/xmms2-mpris.dir/src/xmms2-mpris.c.o' + \ . ' -c ' . ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ 'file': 'other.c', + \ }, + \ ], + \ "src": [ + \ { + \ 'directory': ale#path#Simplify('/foo/bar/xmms2-mpris'), + \ 'command': '/usr/bin/cc -I' . ale#path#Simplify('/usr/include/ignoreme') + \ . ' -o CMakeFiles/xmms2-mpris.dir/src/xmms2-mpris.c.o' + \ . ' -c ' . ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ 'file': ale#path#Simplify((has('win32') ? 'C:' : '') . '/foo/bar/xmms2-mpris/src/xmms2-other.c'), + \ }, + \ ], + \ }, + \ ) -Execute(ParseCompileCommandsFlags should tolerate items without commands): +Execute(ParseCompileCommandsFlags should fall back to files with the same name): silent noautocmd execute 'file! ' . fnameescape(ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c')) + " We should prefer the basename file flags, not the base dirname flags. AssertEqual - \ '', - \ ale#c#ParseCompileCommandsFlags(bufnr(''), { "xmms2-mpris.c": [ + \ '-I ' . ale#Escape(ale#path#Simplify('/usr/include/xmms2')), + \ ale#c#ParseCompileCommandsFlags( + \ bufnr(''), + \ { + \ "xmms2-mpris.c": [ + \ { + \ 'directory': ale#path#Simplify('/foo/bar/xmms2-mpris'), + \ 'command': '/usr/bin/cc -I' . ale#path#Simplify('/usr/include/xmms2') + \ . ' -o CMakeFiles/xmms2-mpris.dir/src/xmms2-mpris.c.o' + \ . ' -c ' . ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ 'file': ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ }, + \ ], + \ }, + \ { + \ "src": [ + \ { + \ 'directory': ale#path#Simplify('/foo/bar/xmms2-mpris'), + \ 'command': '/usr/bin/cc -I' . ale#path#Simplify('/usr/include/ignoreme') + \ . ' -o CMakeFiles/xmms2-mpris.dir/src/xmms2-mpris.c.o' + \ . ' -c ' . ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ 'file': ale#path#Simplify((has('win32') ? 'C:' : '') . '/foo/bar/xmms2-mpris/src/xmms2-other.c'), + \ }, + \ ], + \ }, + \ ) + +Execute(ParseCompileCommandsFlags should parse flags for exact directory matches): + silent noautocmd execute 'file! ' . fnameescape(ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c')) + + " We should ues the exact directory flags, not the file basename flags. + AssertEqual + \ '-I ' . ale#Escape(ale#path#Simplify('/usr/include/xmms2')), + \ ale#c#ParseCompileCommandsFlags( + \ bufnr(''), \ { - \ 'directory': '/foo/bar/xmms2-mpris', - \ 'file': '/foo/bar/xmms2-mpris/src/xmms2-mpris.c', + \ "xmms2-mpris.c": [ + \ { + \ 'directory': ale#path#Simplify('/foo/bar/xmms2-mpris'), + \ 'command': '/usr/bin/cc -I' . ale#path#Simplify('/usr/include/ignoreme') + \ . ' -o CMakeFiles/xmms2-mpris.dir/src/xmms2-mpris.c.o' + \ . ' -c ' . ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ 'file': ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ }, + \ ], \ }, - \ ] }, {}) + \ { + \ ale#path#Simplify('/foo/bar/xmms2-mpris/src'): [ + \ { + \ 'directory': ale#path#Simplify('/foo/bar/xmms2-mpris/src'), + \ 'command': '/usr/bin/cc -I' . ale#path#Simplify('/usr/include/xmms2') + \ . ' -o CMakeFiles/xmms2-mpris.dir/src/xmms2-mpris.c.o' + \ . ' -c ' . ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ 'file': 'other.c', + \ }, + \ ], + \ "src": [ + \ { + \ 'directory': ale#path#Simplify('/foo/bar/xmms2-mpris'), + \ 'command': '/usr/bin/cc -I' . ale#path#Simplify('/usr/include/ignoreme') + \ . ' -o CMakeFiles/xmms2-mpris.dir/src/xmms2-mpris.c.o' + \ . ' -c ' . ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ 'file': ale#path#Simplify((has('win32') ? 'C:' : '') . '/foo/bar/xmms2-mpris/src/xmms2-other.c'), + \ }, + \ ], + \ }, + \ ) Execute(ParseCompileCommandsFlags should fall back to files in the same directory): silent noautocmd execute 'file! ' . fnameescape(ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c')) AssertEqual - \ '-I ' . ale#path#Simplify('/usr/include/xmms2'), - \ ale#c#ParseCompileCommandsFlags(bufnr(''), {}, { "src": [ + \ '-I ' . ale#Escape(ale#path#Simplify('/usr/include/xmms2')), + \ ale#c#ParseCompileCommandsFlags( + \ bufnr(''), + \ {}, + \ { + \ "src": [ + \ { + \ 'directory': ale#path#Simplify('/foo/bar/xmms2-mpris'), + \ 'command': '/usr/bin/cc -I' . ale#path#Simplify('/usr/include/xmms2') + \ . ' -o CMakeFiles/xmms2-mpris.dir/src/xmms2-mpris.c.o' + \ . ' -c ' . ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), + \ 'file': ale#path#Simplify((has('win32') ? 'C:' : '') . '/foo/bar/xmms2-mpris/src/xmms2-other.c'), + \ }, + \ ], + \ }, + \ ) + +Execute(ParseCompileCommandsFlags should tolerate items without commands): + silent noautocmd execute 'file! ' . fnameescape(ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c')) + + AssertEqual + \ '', + \ ale#c#ParseCompileCommandsFlags( + \ bufnr(''), \ { - \ 'directory': ale#path#Simplify('/foo/bar/xmms2-mpris'), - \ 'command': '/usr/bin/cc -I' . ale#path#Simplify('/usr/include/xmms2') - \ . ' -o CMakeFiles/xmms2-mpris.dir/src/xmms2-mpris.c.o' - \ . ' -c ' . ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.c'), - \ 'file': ale#path#Simplify((has('win32') ? 'C:' : '') . '/foo/bar/xmms2-mpris/src/xmms2-other.c'), + \ "xmms2-mpris.c": [ + \ { + \ 'directory': '/foo/bar/xmms2-mpris', + \ 'file': '/foo/bar/xmms2-mpris/src/xmms2-mpris.c', + \ }, + \ ], \ }, - \ ] }) + \ {}, + \ ) Execute(ParseCompileCommandsFlags should take commands from matching .c files for .h files): silent noautocmd execute 'file! ' . fnameescape(ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.h')) AssertEqual - \ '-I /usr/include/xmms2', + \ '-I ' . ale#Escape('/usr/include/xmms2'), \ ale#c#ParseCompileCommandsFlags( \ bufnr(''), \ { @@ -235,15 +356,14 @@ Execute(ParseCompileCommandsFlags should take commands from matching .c files fo \ }, \ ], \ }, - \ { - \ }, + \ {}, \ ) Execute(ParseCompileCommandsFlags should take commands from matching .cpp files for .hpp files): silent noautocmd execute 'file! ' . fnameescape(ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.hpp')) AssertEqual - \ '-I /usr/include/xmms2', + \ '-I ' . ale#Escape('/usr/include/xmms2'), \ ale#c#ParseCompileCommandsFlags( \ bufnr(''), \ { @@ -265,7 +385,7 @@ Execute(ParseCompileCommandsFlags should take commands from matching .cpp files silent noautocmd execute 'file! ' . fnameescape(ale#path#Simplify('/foo/bar/xmms2-mpris/src/xmms2-mpris.h')) AssertEqual - \ '-I /usr/include/xmms2', + \ '-I ' . ale#Escape('/usr/include/xmms2'), \ ale#c#ParseCompileCommandsFlags( \ bufnr(''), \ { @@ -305,42 +425,69 @@ Execute(ParseCompileCommandsFlags should not take commands from .c files for .h \ }, \ ) -Execute(ParseCFlags should not merge flags): +Execute(ShellSplit should not merge flags): AssertEqual - \ '-Dgoal=9' - \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) - \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir with spaces')) - \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir-with-dash')) - \ . ' ' . '-I' . ' ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')), - \ ale#c#ParseCFlags( - \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), + \ [ + \ 'gcc', + \ '-Dgoal=9', + \ '-Tlinkerfile.ld', + \ 'blabla', + \ '-Isubdir', + \ 'subdir/somedep1.o', + \ 'subdir/somedep2.o', + \ '-I''dir with spaces''', + \ '-Idir-with-dash', + \ 'subdir/somedep3.o', + \ 'subdir/somedep4.o', + \ '-I' . ale#path#Simplify('kernel/include'), + \ 'subdir/somedep5.o', + \ 'subdir/somedep6.o', + \ ], + \ ale#c#ShellSplit( \ 'gcc -Dgoal=9 -Tlinkerfile.ld blabla -Isubdir ' \ . 'subdir/somedep1.o ' . 'subdir/somedep2.o ' \ . '-I''dir with spaces''' . ' -Idir-with-dash ' \ . 'subdir/somedep3.o ' . 'subdir/somedep4.o ' \ . ' -I'. ale#path#Simplify('kernel/include') . ' ' - \ . 'subdir/somedep5.o ' . 'subdir/somedep6.o ' + \ . 'subdir/somedep5.o ' . 'subdir/somedep6.o' \ ) -Execute(ParseCFlags should handle parenthesis and quotes): +Execute(ShellSplit should handle parenthesis and quotes): AssertEqual - \ '-Dgoal=9 -Dtest1="('' '')" -Dtest2=''(` `)'' -Dtest3=`(" ")`', - \ ale#c#ParseCFlags( - \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), + \ [ + \ 'gcc', + \ '-Dgoal=9', + \ '-Tlinkerfile.ld', + \ 'blabla', + \ '-Dtest1="('' '')"', + \ 'file1.o', + \ '-Dtest2=''(` `)''', + \ 'file2.o', + \ '-Dtest3=`(" ")`', + \ 'file3.o', + \ ] , + \ ale#c#ShellSplit( \ 'gcc -Dgoal=9 -Tlinkerfile.ld blabla ' \ . '-Dtest1="('' '')" file1.o ' \ . '-Dtest2=''(` `)'' file2.o ' - \ . '-Dtest3=`(" ")` file3.o ' + \ . '-Dtest3=`(" ")` file3.o' \ ) -Execute(CFlags we want to pass): +Execute(We should include several important flags): AssertEqual - \ '-I ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/inc')) - \ . ' -I ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/include')) - \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/incquote')) - \ . ' -isystem ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/incsystem')) + \ '-I ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/inc')) + \ . ' -I ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/include')) + \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/incquote')) + \ . ' -isystem ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/incsystem')) \ . ' -idirafter ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/incafter')) - \ . ' -Dmacro=value -D macro2 -Bbdir -B bdir2' + \ . ' -iframework ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/incframework')) + \ . ' -include ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/foo bar')) + \ . ' -Dmacro="value"' + \ . ' -DGoal=9' + \ . ' -D macro2' + \ . ' -D macro3="value"' + \ . ' -Bbdir' + \ . ' -B bdir2' \ . ' -iprefix prefix -iwithprefix prefix2 -iwithprefixbefore prefix3' \ . ' -isysroot sysroot --sysroot=test --no-sysroot-suffix -imultilib multidir' \ . ' -Wsome-warning -std=c89 -pedantic -pedantic-errors -ansi' @@ -348,21 +495,175 @@ Execute(CFlags we want to pass): \ . ' -iplugindir=dir -march=native -w', \ ale#c#ParseCFlags( \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), - \ 'gcc' - \ . ' -Iinc -I include -iquote incquote -isystem incsystem -idirafter incafter' - \ . ' -Dmacro=value -D macro2 -Bbdir -B bdir2' + \ 0, + \ [ + \ 'gcc', + \ '-Iinc', + \ '-I', + \ 'include', + \ '-iquote', + \ 'incquote', + \ '-isystem', + \ 'incsystem', + \ '-idirafter', + \ 'incafter', + \ '-iframework', + \ 'incframework', + \ '-include', + \ '''foo bar''', + \ '-Dmacro="value"', + \ '-DGoal=9', + \ '-D', + \ 'macro2', + \ '-D', + \ 'macro3="value"', + \ '-Bbdir', + \ '-B', + \ 'bdir2', + \ '-iprefix', + \ 'prefix', + \ '-iwithprefix', + \ 'prefix2', + \ '-iwithprefixbefore', + \ 'prefix3', + \ '-isysroot', + \ 'sysroot', + \ '--sysroot=test', + \ '--no-sysroot-suffix', + \ '-imultilib', + \ 'multidir', + \ '-Wsome-warning', + \ '-std=c89', + \ '-pedantic', + \ '-pedantic-errors', + \ '-ansi', + \ '-foption', + \ '-O2', + \ '-C', + \ '-CC', + \ '-trigraphs', + \ '-nostdinc', + \ '-nostdinc++', + \ '-iplugindir=dir', + \ '-march=native', + \ '-w', + \ ], + \ ) + +Execute(We should quote the flags we need to quote): + AssertEqual + \ '-I ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/inc')) + \ . ' -I ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/include')) + \ . ' -iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/incquote')) + \ . ' -isystem ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/incsystem')) + \ . ' -idirafter ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/incafter')) + \ . ' -iframework ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/incframework')) + \ . ' -include ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/foo bar')) + \ . ' ' . ale#Escape('-Dmacro="value"') + \ . ' -DGoal=9' + \ . ' -D macro2' + \ . ' -D ' . ale#Escape('macro3="value"') + \ . ' -Bbdir' + \ . ' -B bdir2' \ . ' -iprefix prefix -iwithprefix prefix2 -iwithprefixbefore prefix3' - \ . ' -isysroot sysroot --sysroot=test --no-sysroot-suffix -imultilib multidir' + \ . ' -isysroot sysroot --sysroot=test' + \ . ' ' . ale#Escape('--sysroot="quoted"') + \ . ' ' . ale#Escape('--sysroot=foo bar') + \ . ' --no-sysroot-suffix -imultilib multidir' \ . ' -Wsome-warning -std=c89 -pedantic -pedantic-errors -ansi' \ . ' -foption -O2 -C -CC -trigraphs -nostdinc -nostdinc++' - \ . ' -iplugindir=dir -march=native -w' + \ . ' -iplugindir=dir -march=native -w', + \ ale#c#ParseCFlags( + \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), + \ 1, + \ [ + \ 'gcc', + \ '-Iinc', + \ '-I', + \ 'include', + \ '-iquote', + \ 'incquote', + \ '-isystem', + \ 'incsystem', + \ '-idirafter', + \ 'incafter', + \ '-iframework', + \ 'incframework', + \ '-include', + \ '''foo bar''', + \ '-Dmacro="value"', + \ '-DGoal=9', + \ '-D', + \ 'macro2', + \ '-D', + \ 'macro3="value"', + \ '-Bbdir', + \ '-B', + \ 'bdir2', + \ '-iprefix', + \ 'prefix', + \ '-iwithprefix', + \ 'prefix2', + \ '-iwithprefixbefore', + \ 'prefix3', + \ '-isysroot', + \ 'sysroot', + \ '--sysroot=test', + \ '--sysroot="quoted"', + \ '--sysroot=foo bar', + \ '--no-sysroot-suffix', + \ '-imultilib', + \ 'multidir', + \ '-Wsome-warning', + \ '-std=c89', + \ '-pedantic', + \ '-pedantic-errors', + \ '-ansi', + \ '-foption', + \ '-O2', + \ '-C', + \ '-CC', + \ '-trigraphs', + \ '-nostdinc', + \ '-nostdinc++', + \ '-iplugindir=dir', + \ '-march=native', + \ '-w', + \ ], \ ) -Execute(CFlags we dont want to pass): +Execute(We should exclude other flags that cause problems): AssertEqual \ '', \ ale#c#ParseCFlags( \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), - \ 'gcc -Wl,option -Wa,option -Wp,option filename.c somelib.a ' - \ . '-fdump-file=name -fdiagnostics-arg -fno-show-column' + \ 0, + \ [ + \ 'gcc', + \ '-Wl,option', + \ '-Wa,option', + \ '-Wp,option', + \ '-c', + \ 'filename.c', + \ 'somelib.a', + \ '-fdump-file=name', + \ '-fdiagnostics-arg', + \ '-fno-show-column', + \ '-fstack-usage', + \ '-Tlinkerfile.ld', + \ ], + \ ) + +Execute(We should expand @file in CFlags): + AssertEqual + \ '-DARGS1 -DARGS2 -O2', + \ ale#c#ParseCFlags( + \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), + \ 0, + \ [ + \ 'gcc', + \ '-g', + \ '@./args', + \ '-O2', + \ ], \ ) diff --git a/test/test_c_projects/makefile_project/args b/test/test_c_projects/makefile_project/args new file mode 100644 index 00000000..ccaf82ad --- /dev/null +++ b/test/test_c_projects/makefile_project/args @@ -0,0 +1,3 @@ +foolib.a +-DARGS1 +@subdir/args diff --git a/test/test_c_projects/makefile_project/subdir/args b/test/test_c_projects/makefile_project/subdir/args new file mode 100644 index 00000000..3fe9c3fe --- /dev/null +++ b/test/test_c_projects/makefile_project/subdir/args @@ -0,0 +1 @@ +-DARGS2 diff --git a/test/test_code_action.vader b/test/test_code_action.vader index b47f24ff..19de7268 100644 --- a/test/test_code_action.vader +++ b/test/test_code_action.vader @@ -1,4 +1,8 @@ Before: + Save g:ale_enabled + + let g:ale_enabled = 0 + runtime autoload/ale/code_action.vim runtime autoload/ale/util.vim @@ -35,6 +39,8 @@ Before: endfunction! After: + Restore + " Close the extra buffers if we opened it. if bufnr(g:file1) != -1 execute ':bp! | :bd! ' . bufnr(g:file1) @@ -50,9 +56,10 @@ After: call delete(g:file2) endif - unlet g:file1 - unlet g:file2 - unlet g:test + unlet! g:file1 + unlet! g:file2 + unlet! g:test + unlet! g:changes delfunction WriteFileAndEdit runtime autoload/ale/code_action.vim @@ -350,3 +357,36 @@ Execute(It should just modify file when should_save is set to v:false): \ ' value: string', \ '}', \], getline(1, '$') + +Given typescript(An example TypeScript file): + type Foo = {} + + export interface ISomething { + fooLongName: Foo | null + } + + export class SomethingElse implements ISomething { + // Bindings + fooLongName!: ISomething['fooLongName'] + } + +Execute(): + let g:changes = [ + \ {'end': {'offset': 14, 'line': 4}, 'newText': 'foo', 'start': {'offset': 3, 'line': 4}}, + \ {'end': {'offset': 40, 'line': 9}, 'newText': 'foo', 'start': {'offset': 29, 'line': 9}}, + \ {'end': {'offset': 14, 'line': 9}, 'newText': 'foo', 'start': {'offset': 3, 'line': 9}}, + \] + + call ale#code_action#ApplyChanges(expand('%:p'), g:changes, 0) + +Expect(The changes should be applied correctly): + type Foo = {} + + export interface ISomething { + foo: Foo | null + } + + export class SomethingElse implements ISomething { + // Bindings + foo!: ISomething['foo'] + } diff --git a/test/test_command_chain.vader b/test/test_command_chain.vader deleted file mode 100644 index 329ebc97..00000000 --- a/test/test_command_chain.vader +++ /dev/null @@ -1,73 +0,0 @@ -Before: - Save &shell, g:ale_run_synchronously - let g:ale_run_synchronously = 1 - unlet! g:ale_run_synchronously_callbacks - - if !has('win32') - set shell=/bin/sh - endif - - let g:linter_output = [] - let g:first_echo_called = 0 - let g:second_echo_called = 0 - let g:final_callback_called = 0 - - function! CollectResults(buffer, output) - let g:final_callback_called = 1 - let g:linter_output = map(copy(a:output), 'join(split(v:val))') - return [] - endfunction - function! RunFirstEcho(buffer) - let g:first_echo_called = 1 - - return 'echo foo' - endfunction - function! RunSecondEcho(buffer, output) - let g:second_echo_called = 1 - - return 'echo bar' - endfunction - - call ale#linter#Define('foobar', { - \ 'name': 'testlinter', - \ 'callback': 'CollectResults', - \ 'executable': has('win32') ? 'cmd' : 'echo', - \ 'command_chain': [ - \ { - \ 'callback': 'RunFirstEcho', - \ 'output_stream': 'stdout', - \ 'read_buffer': 0, - \ }, - \ { - \ 'callback': 'RunSecondEcho', - \ 'output_stream': 'stdout', - \ 'read_buffer': 0, - \ }, - \ ], - \}) - -After: - Restore - unlet! g:ale_run_synchronously_callbacks - unlet! g:first_echo_called - unlet! g:second_echo_called - unlet! g:final_callback_called - unlet! g:linter_output - let g:ale_buffer_info = {} - call ale#linter#Reset() - delfunction CollectResults - delfunction RunFirstEcho - delfunction RunSecondEcho - -Given foobar (Some imaginary filetype): - anything - -Execute(Check the results of running the chain): - AssertEqual 'foobar', &filetype - call ale#Queue(0) - call ale#test#FlushJobs() - - Assert g:first_echo_called, 'The first chain item was not called' - Assert g:second_echo_called, 'The second chain item was not called' - Assert g:final_callback_called, 'The final callback was not called' - AssertEqual ['bar'], g:linter_output diff --git a/test/test_computed_lint_file_values.vader b/test/test_computed_lint_file_values.vader new file mode 100644 index 00000000..399e96fe --- /dev/null +++ b/test/test_computed_lint_file_values.vader @@ -0,0 +1,134 @@ +Before: + Save g:ale_enabled + Save g:ale_run_synchronously + Save g:ale_set_lists_synchronously + Save g:ale_buffer_info + + let g:ale_enabled = 1 + let g:ale_buffer_info = {} + let g:ale_run_synchronously = 1 + let g:ale_set_lists_synchronously = 1 + + function! TestCallback(buffer, output) + " Windows adds extra spaces to the text from echo. + return [{ + \ 'lnum': 2, + \ 'col': 3, + \ 'text': 'testlinter1', + \}] + endfunction + function! TestCallback2(buffer, output) + " Windows adds extra spaces to the text from echo. + return [{ + \ 'lnum': 1, + \ 'col': 3, + \ 'text': 'testlinter2', + \}] + endfunction + function! TestCallback3(buffer, output) + " Windows adds extra spaces to the text from echo. + return [{ + \ 'lnum': 3, + \ 'col': 3, + \ 'text': 'testlinter3', + \}] + endfunction + + " These two linters computer their lint_file values after running commands. + call ale#linter#Define('foobar', { + \ 'name': 'testlinter1', + \ 'callback': 'TestCallback', + \ 'executable': has('win32') ? 'cmd' : 'echo', + \ 'command': has('win32') ? 'echo foo bar' : '/bin/sh -c ''echo foo bar''', + \ 'lint_file': {b -> ale#command#Run(b, 'echo', {-> 1})}, + \}) + call ale#linter#Define('foobar', { + \ 'name': 'testlinter2', + \ 'callback': 'TestCallback2', + \ 'executable': has('win32') ? 'cmd' : 'echo', + \ 'command': has('win32') ? 'echo foo bar' : '/bin/sh -c ''echo foo bar''', + \ 'lint_file': {b -> ale#command#Run(b, 'echo', {-> ale#command#Run(b, 'echo', {-> 1})})}, + \}) + " This one directly computes the result. + call ale#linter#Define('foobar', { + \ 'name': 'testlinter3', + \ 'callback': 'TestCallback3', + \ 'executable': has('win32') ? 'cmd' : 'echo', + \ 'command': has('win32') ? 'echo foo bar' : '/bin/sh -c ''echo foo bar''', + \ 'lint_file': {b -> 1}, + \}) + + let g:filename = tempname() + call writefile([], g:filename) + call ale#test#SetFilename(g:filename) + +After: + delfunction TestCallback + + call ale#engine#Cleanup(bufnr('')) + Restore + call ale#linter#Reset() + + " Items and markers, etc. + call setloclist(0, []) + call clearmatches() + call ale#sign#Clear() + + if filereadable(g:filename) + call delete(g:filename) + endif + + unlet g:filename + +Given foobar(A file with some lines): + foo + bar + baz + +Execute(lint_file results where the result is eventually computed should be run): + call ale#Queue(0, 'lint_file') + call ale#test#FlushJobs() + + AssertEqual + \ [ + \ { + \ 'bufnr': bufnr('%'), + \ 'lnum': 1, + \ 'vcol': 0, + \ 'col': 3, + \ 'text': 'testlinter2', + \ 'type': 'E', + \ 'nr': -1, + \ 'pattern': '', + \ 'valid': 1, + \ }, + \ { + \ 'bufnr': bufnr('%'), + \ 'lnum': 2, + \ 'vcol': 0, + \ 'col': 3, + \ 'text': 'testlinter1', + \ 'type': 'E', + \ 'nr': -1, + \ 'pattern': '', + \ 'valid': 1, + \ }, + \ { + \ 'bufnr': bufnr('%'), + \ 'lnum': 3, + \ 'vcol': 0, + \ 'col': 3, + \ 'text': 'testlinter3', + \ 'type': 'E', + \ 'nr': -1, + \ 'pattern': '', + \ 'valid': 1, + \ }, + \ ], + \ ale#test#GetLoclistWithoutModule() + +Execute(Linters where lint_file eventually evaluates to 1 shouldn't be run if we don't want to run them): + call ale#Queue(0, '') + call ale#test#FlushJobs() + + AssertEqual [], ale#test#GetLoclistWithoutModule() diff --git a/test/test_cursor_warnings.vader b/test/test_cursor_warnings.vader index 339cd71e..ef385061 100644 --- a/test/test_cursor_warnings.vader +++ b/test/test_cursor_warnings.vader @@ -30,7 +30,7 @@ Before: \ 'nr': -1, \ 'type': 'E', \ 'code': 'semi', - \ 'text': 'Missing semicolon.', + \ 'text': "Missing semicolon.\r", \ 'detail': "Every statement should end with a semicolon\nsecond line", \ }, \ { diff --git a/test/test_deferred_command_string.vader b/test/test_deferred_command_string.vader index 026be6fe..173b6bb2 100644 --- a/test/test_deferred_command_string.vader +++ b/test/test_deferred_command_string.vader @@ -12,7 +12,7 @@ Before: call ale#linter#Define('foobar', { \ 'name': 'lint_file_linter', \ 'callback': 'LintFileCallback', - \ 'executable': 'echo', + \ 'executable': has('win32') ? 'cmd' : 'echo', \ 'command': {b -> ale#command#Run(b, 'echo', {-> ale#command#Run(b, 'echo', {-> 'foo'})})}, \ 'read_buffer': 0, \}) @@ -28,7 +28,7 @@ After: Given foobar (Some imaginary filetype): Execute(It should be possible to compute an executable to check based on the result of commands): - AssertLinter 'echo', 'foo' + AssertLinter has('win32') ? 'cmd' : 'echo', 'foo' ALELint call ale#test#FlushJobs() @@ -40,7 +40,7 @@ Execute(It should be possible to compute an executable to check based on the res Execute(It handle the deferred command failing): let g:ale_emulate_job_failure = 1 - AssertLinter 'echo', 0 + AssertLinter has('win32') ? 'cmd' : 'echo', 0 ALELint call ale#test#FlushJobs() diff --git a/test/test_engine_invocation.vader b/test/test_engine_invocation.vader deleted file mode 100644 index af713953..00000000 --- a/test/test_engine_invocation.vader +++ /dev/null @@ -1,108 +0,0 @@ -Before: - function! CollectResults(buffer, output) - return [] - endfunction - - function! FirstChainFunction(buffer) - return 'first' - endfunction - - function! SecondChainFunction(buffer, output) - " We'll skip this command - return '' - endfunction - - function! ThirdChainFunction(buffer, output) - return 'third' - endfunction - - function! FourthChainFunction(buffer, output) - return 'fourth' - endfunction - - let g:linter = { - \ 'name': 'testlinter', - \ 'callback': 'CollectResults', - \ 'executable': 'echo', - \ 'command_chain': [ - \ {'callback': 'FirstChainFunction'}, - \ {'callback': 'SecondChainFunction'}, - \ {'callback': 'ThirdChainFunction'}, - \ {'callback': 'FourthChainFunction'}, - \ ], - \ 'read_buffer': 1, - \} - - function! ProcessIndex(chain_index) - let [l:command, l:options] = ale#engine#ProcessChain(347, '', g:linter, a:chain_index, []) - let l:options.command = l:command - - return l:options - endfunction - -After: - delfunction CollectResults - delfunction FirstChainFunction - delfunction SecondChainFunction - delfunction ThirdChainFunction - delfunction ProcessIndex - unlet! g:linter - unlet! g:result - -Execute(Engine invocation should return the command for the first item correctly): - let g:result = ProcessIndex(0) - - AssertEqual 'first', g:result.command - AssertEqual 1, g:result.next_chain_index - -Execute(Engine invocation should return the command for the second item correctly): - let g:result = ProcessIndex(1) - - AssertEqual 'third', g:result.command - AssertEqual 3, g:result.next_chain_index - -Execute(Engine invocation should return the command for the fourth item correctly): - let g:result = ProcessIndex(3) - - AssertEqual 'fourth', g:result.command - AssertEqual 4, g:result.next_chain_index - -Execute(Engine invocation should allow read_buffer to be enabled for a command in the middle of a chain): - let g:linter.command_chain[2].read_buffer = 1 - - let g:result = ProcessIndex(2) - - AssertEqual g:result.command, 'third' - AssertEqual g:result.read_buffer, 1 - -Execute(Engine invocation should allow read_buffer to be disabled for the end of a chain): - let g:linter.command_chain[3].read_buffer = 0 - - let g:result = ProcessIndex(3) - - AssertEqual g:result.command, 'fourth' - AssertEqual g:result.read_buffer, 0 - -Execute(Engine invocation should not use read_buffer from earlier items in a chain): - let g:linter.command_chain[1].read_buffer = 1 - - let g:result = ProcessIndex(1) - - AssertEqual g:result.command, 'third' - AssertEqual g:result.read_buffer, 0 - -Execute(Engine invocation should allow the output_stream setting to be changed in the middle of a chain): - let g:linter.command_chain[2].output_stream = 'both' - - let g:result = ProcessIndex(2) - - AssertEqual g:result.command, 'third' - AssertEqual g:result.output_stream, 'both' - -Execute(Engine invocation should not use output_stream from earlier items in a chain): - let g:linter.command_chain[1].output_stream = 'both' - - let g:result = ProcessIndex(1) - - AssertEqual g:result.command, 'third' - AssertEqual g:result.output_stream, 'stdout' diff --git a/test/test_filename_mapping.vader b/test/test_filename_mapping.vader new file mode 100644 index 00000000..e9af539a --- /dev/null +++ b/test/test_filename_mapping.vader @@ -0,0 +1,62 @@ +Before: + Save g:ale_filename_mappings + Save b:ale_filename_mappings + + let g:ale_filename_mappings = {} + unlet! b:ale_filename_mappings + +After: + Restore + +Execute(ale#GetFilenameMappings should return the correct mappings for given linters/fixers): + let g:ale_filename_mappings = {'a': [['foo', 'bar']], 'b': [['baz', 'foo']]} + + AssertEqual [['foo', 'bar']], ale#GetFilenameMappings(bufnr(''), 'a') + AssertEqual [['baz', 'foo']], ale#GetFilenameMappings(bufnr(''), 'b') + AssertEqual [], ale#GetFilenameMappings(bufnr(''), 'c') + + let b:ale_filename_mappings = {'b': [['abc', 'xyz']]} + + AssertEqual [], ale#GetFilenameMappings(bufnr(''), 'a') + AssertEqual [['abc', 'xyz']], ale#GetFilenameMappings(bufnr(''), 'b') + AssertEqual [], ale#GetFilenameMappings(bufnr(''), 'c') + +Execute(ale#GetFilenameMappings should return Lists set for use with all tools): + let g:ale_filename_mappings = [['foo', 'bar']] + + AssertEqual [['foo', 'bar']], ale#GetFilenameMappings(bufnr(''), 'a') + AssertEqual [['foo', 'bar']], ale#GetFilenameMappings(bufnr(''), '') + AssertEqual [['foo', 'bar']], ale#GetFilenameMappings(bufnr(''), v:null) + + let b:ale_filename_mappings = [['abc', 'xyz']] + + AssertEqual [['abc', 'xyz']], ale#GetFilenameMappings(bufnr(''), 'a') + AssertEqual [['abc', 'xyz']], ale#GetFilenameMappings(bufnr(''), '') + AssertEqual [['abc', 'xyz']], ale#GetFilenameMappings(bufnr(''), v:null) + +Execute(ale#GetFilenameMappings should let you use * as a fallback): + let g:ale_filename_mappings = {'a': [['foo', 'bar']], '*': [['abc', 'xyz']]} + + AssertEqual [['foo', 'bar']], ale#GetFilenameMappings(bufnr(''), 'a') + AssertEqual [['abc', 'xyz']], ale#GetFilenameMappings(bufnr(''), 'b') + AssertEqual [['abc', 'xyz']], ale#GetFilenameMappings(bufnr(''), '') + AssertEqual [['abc', 'xyz']], ale#GetFilenameMappings(bufnr(''), v:null) + +Execute(ale#filename_mapping#Invert should invert filename mappings): + AssertEqual + \ [['b', 'a'], ['y', 'x']], + \ ale#filename_mapping#Invert([['a', 'b'], ['x', 'y']]) + \ +Execute(ale#filename_mapping#Map return the filename as-is if there are no mappings): + AssertEqual + \ '/foo//bar', + \ ale#filename_mapping#Map('/foo//bar', [['/bar', '/data/']]) + +Execute(ale#filename_mapping#Map should map filenames): + AssertEqual + \ '/data/bar', + \ ale#filename_mapping#Map('/foo//bar', [ + \ ['/data/', '/baz/'], + \ ['/foo/', '/data/'], + \ ['/foo/', '/xyz/'], + \ ]) diff --git a/test/test_filetype_linter_defaults.vader b/test/test_filetype_linter_defaults.vader index 842cc394..e9980536 100644 --- a/test/test_filetype_linter_defaults.vader +++ b/test/test_filetype_linter_defaults.vader @@ -39,7 +39,7 @@ Execute(The defaults for the python filetype should be correct): AssertEqual [], GetLinterNames('python') Execute(The defaults for the rust filetype should be correct): - AssertEqual ['cargo'], GetLinterNames('rust') + AssertEqual ['cargo', 'rls'], GetLinterNames('rust') let g:ale_linters_explicit = 1 diff --git a/test/test_find_references.vader b/test/test_find_references.vader index 9949362a..ca05f631 100644 --- a/test/test_find_references.vader +++ b/test/test_find_references.vader @@ -63,6 +63,8 @@ Before: let g:preview_called = 1 let g:item_list = a:item_list let g:options = a:options + + call ale#preview#SetLastSelection(a:item_list, a:options) endfunction After: @@ -110,7 +112,16 @@ Given typescript(Some typescript file): bazxyzxyzxyz Execute(Results should be shown for tsserver responses): - call ale#references#SetMap({3: {}}) + " We should remember these options when we repeat the selection. + call ale#references#SetMap( + \ { + \ 3: { + \ 'ignorethis': 'x', + \ 'open_in': 'tab', + \ 'use_relative_paths': 1, + \ } + \ } + \) call ale#references#HandleTSServerResponse(1, { \ 'command': 'references', \ 'request_seq': 3, @@ -158,8 +169,7 @@ Execute(Results should be shown for tsserver responses): AssertEqual {}, ale#references#GetMap() " We should be able to repeat selections with ALERepeatSelection - let g:ale_item_list = [] - + let g:item_list = [] ALERepeatSelection AssertEqual @@ -170,6 +180,12 @@ Execute(Results should be shown for tsserver responses): \ ], \ g:item_list AssertEqual {}, ale#references#GetMap() + AssertEqual + \ { + \ 'open_in': 'tab', + \ 'use_relative_paths': 1, + \ }, + \ g:options Execute(The preview window should not be opened for empty tsserver responses): call ale#references#SetMap({3: {}}) diff --git a/test/test_format_command.vader b/test/test_format_command.vader index 15435326..9d730fce 100644 --- a/test/test_format_command.vader +++ b/test/test_format_command.vader @@ -25,12 +25,12 @@ After: Execute(FormatCommand should do nothing to basic command strings): AssertEqual \ ['', 'awesome-linter do something', 0], - \ ale#command#FormatCommand(bufnr('%'), '', 'awesome-linter do something', 0, v:null) + \ ale#command#FormatCommand(bufnr('%'), '', 'awesome-linter do something', 0, v:null, []) Execute(FormatCommand should handle %%, and ignore other percents): AssertEqual \ ['', '% %%d %%f %x %', 0], - \ ale#command#FormatCommand(bufnr('%'), '', '%% %%%d %%%f %x %', 0, v:null) + \ ale#command#FormatCommand(bufnr('%'), '', '%% %%%d %%%f %x %', 0, v:null, []) Execute(FormatCommand should convert %s to the current filename): AssertEqual @@ -39,10 +39,10 @@ Execute(FormatCommand should convert %s to the current filename): \ 'foo ' . ale#Escape(expand('%:p')) . ' bar ' . ale#Escape(expand('%:p')), \ 0, \ ], - \ ale#command#FormatCommand(bufnr('%'), '', 'foo %s bar %s', 0, v:null) + \ ale#command#FormatCommand(bufnr('%'), '', 'foo %s bar %s', 0, v:null, []) Execute(FormatCommand should convert %t to a new temporary filename): - let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo %t bar %t', 0, v:null) + let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo %t bar %t', 0, v:null, []) call CheckTempFile(g:result[0]) @@ -56,21 +56,21 @@ Execute(FormatCommand should convert %t to a new temporary filename): AssertEqual g:match[1], g:match[2] Execute(FormatCommand should not convert %t to a new temporary filename when the input is given as v:false): - let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo %t bar %t', 0, v:false) + let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo %t bar %t', 0, v:false, []) AssertEqual ['', 'foo %t bar %t', 0], g:result Execute(FormatCommand should signal that files are created when temporary files are needed): AssertEqual \ 1, - \ ale#command#FormatCommand(bufnr('%'), '', 'foo %t', 0, v:null)[2] + \ ale#command#FormatCommand(bufnr('%'), '', 'foo %t', 0, v:null, [])[2] AssertEqual \ 0, - \ ale#command#FormatCommand(bufnr('%'), '', 'foo %s', 0, v:null)[2] + \ ale#command#FormatCommand(bufnr('%'), '', 'foo %s', 0, v:null, [])[2] Execute(FormatCommand should let you combine %s and %t): - let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo %t bar %s', 0, v:null) + let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo %t bar %s', 0, v:null, []) call CheckTempFile(g:result[0]) @@ -87,30 +87,30 @@ Execute(FormatCommand should replace %e with the escaped executable): if has('win32') AssertEqual \ ['', 'foo foo', 0], - \ ale#command#FormatCommand(bufnr('%'), 'foo', '%e %e', 0, v:null) + \ ale#command#FormatCommand(bufnr('%'), 'foo', '%e %e', 0, v:null, []) AssertEqual \ ['', '"foo bar"', 0], - \ ale#command#FormatCommand(bufnr('%'), 'foo bar', '%e', 0, v:null) + \ ale#command#FormatCommand(bufnr('%'), 'foo bar', '%e', 0, v:null, []) AssertEqual \ ['', '%e %e', 0], - \ ale#command#FormatCommand(bufnr('%'), '', '%e %e', 0, v:null) + \ ale#command#FormatCommand(bufnr('%'), '', '%e %e', 0, v:null, []) else AssertEqual \ ['', '''foo'' ''foo''', 0], - \ ale#command#FormatCommand(bufnr('%'), 'foo', '%e %e', 0, v:null) + \ ale#command#FormatCommand(bufnr('%'), 'foo', '%e %e', 0, v:null, []) AssertEqual \ ['', '''foo bar''', 0], - \ ale#command#FormatCommand(bufnr('%'), 'foo bar', '%e', 0, v:null) + \ ale#command#FormatCommand(bufnr('%'), 'foo bar', '%e', 0, v:null, []) AssertEqual \ ['', '%e %e', 0], - \ ale#command#FormatCommand(bufnr('%'), '', '%e %e', 0, v:null) + \ ale#command#FormatCommand(bufnr('%'), '', '%e %e', 0, v:null, []) endif Execute(EscapeCommandPart should escape all percent signs): AssertEqual '%%s %%t %%%% %%s %%t %%%%', ale#engine#EscapeCommandPart('%s %t %% %s %t %%') Execute(EscapeCommandPart should pipe in temporary files appropriately): - let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo bar', 1, v:null) + let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo bar', 1, v:null, []) call CheckTempFile(g:result[0]) @@ -118,10 +118,57 @@ Execute(EscapeCommandPart should pipe in temporary files appropriately): Assert !empty(g:match), 'No match found! Result was: ' . g:result[1] AssertEqual ale#Escape(g:result[0]), g:match[1] - let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo bar %t', 1, v:null) + let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo bar %t', 1, v:null, []) call CheckTempFile(g:result[0]) let g:match = matchlist(g:result[1], '\v^foo bar (.*)$') Assert !empty(g:match), 'No match found! Result was: ' . g:result[1] AssertEqual ale#Escape(g:result[0]), g:match[1] + +Execute(FormatCommand should apply filename modifiers to the current file): + AssertEqual + \ ale#Escape(expand('%:p:h')) + \ . ' ' . ale#Escape('dummy.txt') + \ . ' ' . ale#Escape(expand('%:p:h:t')) + \ . ' ' . ale#Escape('txt') + \ . ' ' . ale#Escape(expand('%:p:r')), + \ ale#command#FormatCommand(bufnr(''), '', '%s:h %s:t %s:h:t %s:e %s:r', 0, v:null, [])[1] + +Execute(FormatCommand should apply filename modifiers to the temporary file): + let g:result = ale#command#FormatCommand(bufnr(''), '', '%t:h %t:t %t:h:t %t:e %t:r', 0, v:null, []) + + AssertEqual + \ ale#Escape(fnamemodify(g:result[0], ':h')) + \ . ' ' . ale#Escape('dummy.txt') + \ . ' ' . ale#Escape(fnamemodify(g:result[0], ':h:t')) + \ . ' ' . ale#Escape('txt') + \ . ' ' . ale#Escape(fnamemodify(g:result[0], ':r')), + \ g:result[1] + +Execute(FormatCommand should apply filename mappings the current file): + let g:result = ale#command#FormatCommand(bufnr('%'), '', '%s', 0, v:null, [ + \ [expand('%:p:h'), '/foo/bar'], + \]) + + Assert g:result[1] =~# '/foo/bar' + +Execute(FormatCommand should apply filename mappings to temporary files): + let g:result = ale#command#FormatCommand(bufnr('%'), '', '%t', 0, v:null, [ + \ [fnamemodify(tempname(), ':h:h'), '/foo/bar'] + \]) + + Assert g:result[1] =~# '/foo/bar' + +Execute(FormatCommand should apply filename modifiers to mapped filenames): + let g:result = ale#command#FormatCommand(bufnr('%'), '', '%s:h', 0, v:null, [ + \ [expand('%:p:h'), '/foo/bar'], + \]) + + AssertEqual ale#Escape('/foo/bar'), g:result[1] + + let g:result = ale#command#FormatCommand(bufnr('%'), '', '%t:h:h:h', 0, v:null, [ + \ [fnamemodify(tempname(), ':h:h'), '/foo/bar'] + \]) + + AssertEqual ale#Escape('/foo/bar'), g:result[1] diff --git a/test/test_go_to_definition.vader b/test/test_go_to_definition.vader index a517bd54..f2f34280 100644 --- a/test/test_go_to_definition.vader +++ b/test/test_go_to_definition.vader @@ -514,7 +514,7 @@ Execute(LSP tab type definition requests should be sent): let b:ale_linters = ['pyls'] call setpos('.', [bufnr(''), 1, 5, 0]) - ALEGoToTypeDefinitionInTab + ALEGoToTypeDefinition -tab " We shouldn't register the callback yet. AssertEqual '''''', string(g:Callback) diff --git a/test/test_linter_defintion_processing.vader b/test/test_linter_defintion_processing.vader index cd32ebc8..d000b158 100644 --- a/test/test_linter_defintion_processing.vader +++ b/test/test_linter_defintion_processing.vader @@ -39,13 +39,13 @@ Execute (PreProcess should throw when then callback is not a function): \}) AssertEqual '`callback` must be defined with a callback to accept output', g:vader_exception -Execute (PreProcess should throw when there is no executable or executable_callback): +Execute (PreProcess should throw when there is no executable): AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'callback': 'SomeFunction', \ 'command': 'echo', \}) - AssertEqual 'Either `executable` or `executable_callback` must be defined', g:vader_exception + AssertEqual '`executable` must be defined', g:vader_exception Execute (PreProcess should throw when executable is not a string): AssertThrows call ale#linter#PreProcess('testft', { @@ -56,15 +56,6 @@ Execute (PreProcess should throw when executable is not a string): \}) AssertEqual '`executable` must be a String or Function if defined', g:vader_exception -Execute (PreProcess should throw when executable_callback is not a callback): - AssertThrows call ale#linter#PreProcess('testft', { - \ 'name': 'foo', - \ 'callback': 'SomeFunction', - \ 'executable_callback': 123, - \ 'command': 'echo', - \}) - AssertEqual '`executable_callback` must be a callback if defined', g:vader_exception - Execute (PreProcess should allow executable to be a callback): call ale#linter#PreProcess('testft', { \ 'name': 'foo', @@ -79,7 +70,7 @@ Execute (PreProcess should throw when there is no command): \ 'callback': 'SomeFunction', \ 'executable': 'echo', \}) - AssertEqual 'Either `command`, `executable_callback`, `command_chain` must be defined', g:vader_exception + AssertEqual '`command` must be defined', g:vader_exception Execute (PreProcess should throw when command is not a string): AssertThrows call ale#linter#PreProcess('testft', { @@ -98,15 +89,6 @@ Execute (PreProcess should allow command to be a callback): \ 'command': function('type'), \}) -Execute (PreProcess should throw when command_callback is not a callback): - AssertThrows call ale#linter#PreProcess('testft', { - \ 'name': 'foo', - \ 'callback': 'SomeFunction', - \ 'executable': 'echo', - \ 'command_callback': 123, - \}) - AssertEqual '`command_callback` must be a callback if defined', g:vader_exception - Execute (PreProcess should when the output stream isn't a valid string): AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', @@ -152,117 +134,12 @@ Execute (PreProcess should accept a 'both' output_stream): \ 'output_stream': 'both', \}) -Execute(PreProcess should complain if the command_chain is not a List): - let g:linter = { - \ 'name': 'x', - \ 'callback': 'x', - \ 'executable': 'x', - \ 'command_chain': 'x', - \} - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual '`command_chain` must be a List', g:vader_exception - -Execute(PreProcess should complain if the command_chain is empty): - let g:linter = { - \ 'name': 'x', - \ 'callback': 'x', - \ 'executable': 'x', - \ 'command_chain': [], - \} - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual '`command_chain` must contain at least one item', g:vader_exception - -Execute(PreProcess should complain if the command_chain has no callback): - let g:linter = { - \ 'name': 'x', - \ 'callback': 'x', - \ 'executable': 'x', - \ 'command_chain': [{}], - \} - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual 'The `command_chain` item 0 must define a `callback` function', g:vader_exception - -Execute(PreProcess should complain if the command_chain callback is not a function): - let g:linter = { - \ 'name': 'x', - \ 'callback': 'x', - \ 'executable': 'x', - \ 'command_chain': [{'callback': 2}], - \} - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual 'The `command_chain` item 0 must define a `callback` function', g:vader_exception - -Execute(PreProcess should accept a chain with one callback): - let g:linter = { - \ 'name': 'x', - \ 'callback': 'x', - \ 'executable': 'x', - \ 'command_chain': [{'callback': 'foo'}], - \} - call ale#linter#PreProcess('testft', g:linter) - -Execute(PreProcess should complain about invalid output_stream values in the chain): - let g:linter = { - \ 'name': 'x', - \ 'callback': 'x', - \ 'executable': 'x', - \ 'command_chain': [{'callback': 'foo', 'output_stream': ''}], - \} - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual "The `command_chain` item 0 `output_stream` flag must be 'stdout', 'stderr', or 'both'", g:vader_exception - -Execute(PreProcess should complain about valid output_stream values in the chain): - let g:linter = { - \ 'name': 'x', - \ 'callback': 'x', - \ 'executable': 'x', - \ 'command_chain': [{'callback': 'foo', 'output_stream': 'stdout'}], - \} - call ale#linter#PreProcess('testft', g:linter) - let g:linter.command_chain[0].output_stream = 'stderr' - call ale#linter#PreProcess('testft', g:linter) - let g:linter.command_chain[0].output_stream = 'both' - call ale#linter#PreProcess('testft', g:linter) - -Execute(PreProcess should complain about invalid chain items at higher indices): - let g:linter = { - \ 'name': 'x', - \ 'callback': 'x', - \ 'executable': 'x', - \ 'command_chain': [{'callback': 'foo'}, {'callback': 123}], - \} - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual 'The `command_chain` item 1 must define a `callback` function', g:vader_exception - -Execute(PreProcess should complain when conflicting command options are used): - let g:linter = { - \ 'name': 'x', - \ 'callback': 'x', - \ 'executable': 'x', - \ 'command': 'foo', - \ 'command_chain': [{'callback': 'foo'}], - \} - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual 'Only one of `command`, `command_callback`, or `command_chain` should be set', g:vader_exception - - unlet g:linter.command - let g:linter.command_callback = 'foo' - - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual 'Only one of `command`, `command_callback`, or `command_chain` should be set', g:vader_exception - - let g:linter.command = 'foo' - unlet g:linter.command_chain - - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual 'Only one of `command`, `command_callback`, or `command_chain` should be set', g:vader_exception - Execute(PreProcess should process the read_buffer option correctly): let g:linter = { \ 'name': 'x', \ 'callback': 'x', \ 'executable': 'x', - \ 'command_chain': [{'callback': 'foo'}, {'callback': 'bar'}], + \ 'command': 'x', \ 'read_buffer': '0', \} @@ -277,25 +154,6 @@ Execute(PreProcess should process the read_buffer option correctly): call ale#linter#PreProcess('testft', g:linter) - unlet g:linter.read_buffer - let g:linter.command_chain[0].read_buffer = '0' - - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual 'The `command_chain` item 0 value for `read_buffer` must be `0` or `1`', g:vader_exception - - let g:linter.command_chain[0].read_buffer = 0 - - call ale#linter#PreProcess('testft', g:linter) - - let g:linter.command_chain[1].read_buffer = '0' - - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual 'The `command_chain` item 1 value for `read_buffer` must be `0` or `1`', g:vader_exception - - let g:linter.command_chain[1].read_buffer = 1 - - call ale#linter#PreProcess('testft', g:linter) - Execute(PreProcess should set a default value for read_buffer): let g:linter = { \ 'name': 'x', @@ -316,7 +174,7 @@ Execute(PreProcess should process the lint_file option correctly): \} AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual '`lint_file` must be `0` or `1`', g:vader_exception + AssertEqual '`lint_file` must be `0`, `1`, or a Function', g:vader_exception let g:linter.lint_file = 0 @@ -327,14 +185,17 @@ Execute(PreProcess should process the lint_file option correctly): let g:linter.lint_file = 1 AssertEqual 1, ale#linter#PreProcess('testft', g:linter).lint_file - " The default for read_buffer should change to 0 when lint_file is 1. - AssertEqual 0, ale#linter#PreProcess('testft', g:linter).read_buffer + " The default for read_buffer should still be 1 + AssertEqual 1, ale#linter#PreProcess('testft', g:linter).read_buffer let g:linter.read_buffer = 1 - " We shouldn't be able to set both options to 1 at the same time. - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual 'Only one of `lint_file` or `read_buffer` can be `1`', g:vader_exception + " We should be able to set `read_buffer` and `lint_file` at the same time. + AssertEqual 1, ale#linter#PreProcess('testft', g:linter).read_buffer + + let g:linter.lint_file = function('type') + + Assert type(ale#linter#PreProcess('testft', g:linter).lint_file) is v:t_func Execute(PreProcess should set a default value for lint_file): let g:linter = { @@ -394,151 +255,96 @@ Execute(PreProcess should accept tsserver LSP configuration): \ 'executable': 'x', \ 'command': 'x', \ 'lsp': 'tsserver', - \ 'language_callback': 'x', - \ 'project_root_callback': 'x', + \ 'language': 'x', + \ 'project_root': 'x', \} AssertEqual 'tsserver', ale#linter#PreProcess('testft', g:linter).lsp - call remove(g:linter, 'executable') - let g:linter.executable_callback = 'X' - - call ale#linter#PreProcess('testft', g:linter) - - call remove(g:linter, 'command') - let g:linter.command_callback = 'X' - - call ale#linter#PreProcess('testft', g:linter) - Execute(PreProcess should accept stdio LSP configuration): let g:linter = { \ 'name': 'x', \ 'executable': 'x', \ 'command': 'x', \ 'lsp': 'stdio', - \ 'language_callback': 'x', - \ 'project_root_callback': 'x', + \ 'language': 'x', + \ 'project_root': 'x', \} AssertEqual 'stdio', ale#linter#PreProcess('testft', g:linter).lsp - call remove(g:linter, 'executable') - let g:linter.executable_callback = 'X' - - call ale#linter#PreProcess('testft', g:linter) - - call remove(g:linter, 'command') - let g:linter.command_callback = 'X' - - call ale#linter#PreProcess('testft', g:linter) - Execute(PreProcess should accept LSP server configurations): let g:linter = { \ 'name': 'x', \ 'lsp': 'socket', - \ 'address_callback': 'X', - \ 'language_callback': 'x', - \ 'project_root_callback': 'x', - \} - - AssertEqual 'socket', ale#linter#PreProcess('testft', g:linter).lsp - -Execute(PreProcess should accept let you specify the language as just a string): - let g:linter = { - \ 'name': 'x', - \ 'lsp': 'socket', - \ 'address_callback': 'X', + \ 'address': 'X', \ 'language': 'foobar', - \ 'project_root_callback': 'x', + \ 'project_root': 'x', \} - AssertEqual 'foobar', ale#linter#PreProcess('testft', g:linter).language_callback(0) + AssertEqual 'socket', ale#linter#PreProcess('testft', g:linter).lsp -Execute(PreProcess should complain about using language and language_callback together): +Execute(PreProcess should accept let you specify the `language` as a Function): let g:linter = { \ 'name': 'x', \ 'lsp': 'socket', - \ 'address_callback': 'X', - \ 'language': 'x', - \ 'language_callback': 'x', - \ 'project_root_callback': 'x', + \ 'address': 'X', + \ 'language': {-> 'foobar'}, + \ 'project_root': 'x', \} - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual 'Only one of `language` or `language_callback` should be set', g:vader_exception + AssertEqual 'foobar', ale#linter#PreProcess('testft', g:linter).language(bufnr('')) Execute(PreProcess should complain about invalid language values): let g:linter = { \ 'name': 'x', \ 'lsp': 'socket', - \ 'address_callback': 'X', + \ 'address': 'X', \ 'language': 0, - \ 'project_root_callback': 'x', + \ 'project_root': 'x', \} AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual '`language` must be a String or Funcref', g:vader_exception + AssertEqual '`language` must be a String or Funcref if defined', g:vader_exception Execute(PreProcess should use the filetype as the language string by default): let g:linter = { \ 'name': 'x', \ 'lsp': 'socket', - \ 'address_callback': 'X', - \ 'project_root_callback': 'x', - \} - - AssertEqual 'testft', ale#linter#PreProcess('testft', g:linter).language_callback(0) - -Execute(PreProcess should allow language to be set to a callback): - let g:linter = { - \ 'name': 'x', - \ 'lsp': 'socket', - \ 'address_callback': 'X', - \ 'language': {-> 'foo'}, - \ 'project_root_callback': 'x', + \ 'address': 'X', + \ 'project_root': 'x', \} - AssertEqual 'foo', ale#linter#PreProcess('testft', g:linter).language_callback(0) + AssertEqual 'testft', ale#linter#PreProcess('testft', g:linter).language -Execute(PreProcess should require an address_callback for LSP socket configurations): +Execute(PreProcess should require an `address` for LSP socket configurations): let g:linter = { \ 'name': 'x', \ 'lsp': 'socket', \} AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual '`address` or `address_callback` must be defined for getting the LSP address', g:vader_exception + AssertEqual '`address` must be defined for getting the LSP address', g:vader_exception -Execute(PreProcess should complain about address_callback for non-LSP linters): +Execute(PreProcess should complain about `address` for non-LSP linters): let g:linter = { \ 'name': 'x', \ 'callback': 'SomeFunction', \ 'executable': 'echo', \ 'command': 'echo', - \ 'address_callback': 'X', + \ 'address': 'X', \} AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual '`address` or `address_callback` cannot be used when lsp != ''socket''', g:vader_exception - -Execute(PreProcess accept valid address_callback values): - let g:linter = ale#linter#PreProcess('testft', { - \ 'name': 'x', - \ 'lsp': 'socket', - \ 'address_callback': {-> 'foo:123'}, - \ 'language': 'x', - \ 'project_root_callback': 'x', - \}) - - AssertEqual 'foo:123', ale#linter#GetAddress(0, g:linter) + AssertEqual '`address` cannot be used when lsp != ''socket''', g:vader_exception -Execute(PreProcess accept address as a String): +Execute(PreProcess accept `address` as a String): let g:linter = ale#linter#PreProcess('testft', { \ 'name': 'x', \ 'lsp': 'socket', \ 'address': 'foo:123', \ 'language': 'x', - \ 'project_root_callback': 'x', + \ 'project_root': 'x', \}) AssertEqual 'foo:123', ale#linter#GetAddress(0, g:linter) @@ -549,7 +355,7 @@ Execute(PreProcess accept address as a Function): \ 'lsp': 'socket', \ 'address': {-> 'foo:123'}, \ 'language': 'x', - \ 'project_root_callback': 'x', + \ 'project_root': 'x', \}) AssertEqual 'foo:123', ale#linter#GetAddress(0, g:linter) @@ -560,11 +366,11 @@ Execute(PreProcess should complain about invalid address values): \ 'lsp': 'socket', \ 'address': 0, \ 'language': 'x', - \ 'project_root_callback': 'x', + \ 'project_root': 'x', \}) AssertEqual '`address` must be a String or Function if defined', g:vader_exception -Execute(PreProcess should accept allow the project root be set as a String): +Execute(PreProcess should allow the `project_root` to be set as a String): let g:linter = ale#linter#PreProcess('testft', { \ 'name': 'x', \ 'lsp': 'socket', @@ -575,7 +381,7 @@ Execute(PreProcess should accept allow the project root be set as a String): AssertEqual '/foo/bar', ale#lsp_linter#FindProjectRoot(0, g:linter) -Execute(PreProcess should accept allow the project root be set as a Function): +Execute(PreProcess should `project_root` be set as a Function): let g:linter = ale#linter#PreProcess('testft', { \ 'name': 'x', \ 'lsp': 'socket', @@ -586,7 +392,7 @@ Execute(PreProcess should accept allow the project root be set as a Function): AssertEqual '/foo/bar', ale#lsp_linter#FindProjectRoot(0, g:linter) -Execute(PreProcess should complain when the project_root valid is invalid): +Execute(PreProcess should complain when `project_root` is invalid): AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'x', \ 'lsp': 'socket', @@ -594,154 +400,74 @@ Execute(PreProcess should complain when the project_root valid is invalid): \ 'language': 'x', \ 'project_root': 0, \}) - AssertEqual '`project_root` must be a String or Function if defined', g:vader_exception + AssertEqual '`project_root` must be a String or Function', g:vader_exception -Execute(PreProcess should accept project_root_callback as a String): - call ale#linter#PreProcess('testft', { - \ 'name': 'x', - \ 'lsp': 'socket', - \ 'address': 'foo:123', - \ 'language': 'x', - \ 'project_root_callback': 'Foobar', - \}) - -Execute(PreProcess should accept project_root_callback as a Function): - let g:linter = ale#linter#PreProcess('testft', { - \ 'name': 'x', - \ 'lsp': 'socket', - \ 'address': 'foo:123', - \ 'language': 'x', - \ 'project_root_callback': {-> '/foo/bar'}, - \}) - - AssertEqual '/foo/bar', ale#lsp_linter#FindProjectRoot(0, g:linter) - -Execute(PreProcess should complain when the project_root_callback valid is invalid): - AssertThrows call ale#linter#PreProcess('testft', { - \ 'name': 'x', - \ 'lsp': 'socket', - \ 'address': 'foo:123', - \ 'language': 'x', - \ 'project_root_callback': 0, - \}) - AssertEqual '`project_root_callback` must be a callback if defined', g:vader_exception - -Execute(PreProcess should complain about using initialization_options and initialization_options_callback together): - let g:linter = { - \ 'name': 'x', - \ 'lsp': 'socket', - \ 'address_callback': 'X', - \ 'language': 'x', - \ 'project_root_callback': 'x', - \ 'initialization_options': 'x', - \ 'initialization_options_callback': 'x', - \} - - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual 'Only one of `initialization_options` or `initialization_options_callback` should be set', g:vader_exception - -Execute(PreProcess should throw when initialization_options_callback is not a callback): - AssertThrows call ale#linter#PreProcess('testft', { - \ 'name': 'foo', - \ 'lsp': 'socket', - \ 'address_callback': 'X', - \ 'language': 'x', - \ 'project_root_callback': 'x', - \ 'initialization_options_callback': {}, - \}) - AssertEqual '`initialization_options_callback` must be a callback if defined', g:vader_exception - -Execute(PreProcess should throw when initialization_options is not a Dictionary or callback): +Execute(PreProcess should throw when `initialization_options` is not a Dictionary or callback): AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'lsp': 'socket', - \ 'address_callback': 'X', + \ 'address': 'X', \ 'language': 'x', - \ 'project_root_callback': 'x', + \ 'project_root': 'x', \ 'initialization_options': 0, \}) - AssertEqual '`initialization_options` must be a String or Function if defined', g:vader_exception + AssertEqual '`initialization_options` must be a Dictionary or Function if defined', g:vader_exception -Execute(PreProcess should accept initialization_options as a Dictionary): +Execute(PreProcess should accept `initialization_options` as a Dictionary): let g:linter = ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'lsp': 'socket', - \ 'address_callback': 'X', + \ 'address': 'X', \ 'language': 'x', - \ 'project_root_callback': 'x', + \ 'project_root': 'x', \ 'initialization_options': {'foo': v:true}, \}) AssertEqual {'foo': v:true}, ale#lsp_linter#GetOptions(0, g:linter) -Execute(PreProcess should accept initialization_options as a Funcref): +Execute(PreProcess should accept `initialization_options` as a Function): let g:linter = ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'lsp': 'socket', - \ 'address_callback': 'X', + \ 'address': 'X', \ 'language': 'x', - \ 'project_root_callback': 'x', + \ 'project_root': 'x', \ 'initialization_options': {-> {'foo': v:true}}, \}) AssertEqual {'foo': v:true}, ale#lsp_linter#GetOptions(0, g:linter) -Execute(PreProcess should complain about using lsp_config and lsp_config_callback together): +Execute(PreProcess should accept `lsp_config` as a Dictionary): let g:linter = { \ 'name': 'x', \ 'lsp': 'socket', - \ 'address_callback': 'X', + \ 'address': 'X', \ 'language': 'x', - \ 'project_root_callback': 'x', - \ 'lsp_config': 'x', - \ 'lsp_config_callback': 'x', - \} - - AssertThrows call ale#linter#PreProcess('testft', g:linter) - AssertEqual 'Only one of `lsp_config` or `lsp_config_callback` should be set', g:vader_exception - -Execute(PreProcess should throw when lsp_config_callback is not a callback): - AssertThrows call ale#linter#PreProcess('testft', { - \ 'name': 'foo', - \ 'lsp': 'socket', - \ 'address_callback': 'X', - \ 'language': 'x', - \ 'project_root_callback': 'x', - \ 'lsp_config_callback': {}, - \}) - AssertEqual '`lsp_config_callback` must be a callback if defined', g:vader_exception - -Execute(PreProcess should accept LSP configuration options via lsp_config): - let g:linter = { - \ 'name': 'x', - \ 'lsp': 'socket', - \ 'address_callback': 'X', - \ 'language_callback': 'x', - \ 'project_root_callback': 'x', + \ 'project_root': 'x', \ 'lsp_config': {'foo': 'bar'}, \} AssertEqual {'foo': 'bar'}, ale#lsp_linter#GetConfig(0, g:linter) -Execute(PreProcess should accept LSP configuration options via lsp_config as a function): +Execute(PreProcess should accept `lsp_config` as a Function): let g:linter = { \ 'name': 'x', \ 'lsp': 'socket', - \ 'address_callback': 'X', - \ 'language_callback': 'x', - \ 'project_root_callback': 'x', + \ 'address': 'X', + \ 'language': 'x', + \ 'project_root': 'x', \ 'lsp_config': {-> {'foo': 'bar'}}, \} AssertEqual {'foo': 'bar'}, ale#lsp_linter#GetConfig(0, g:linter) -Execute(PreProcess should throw when lsp_config is not a Dictionary or Function): +Execute(PreProcess should throw when `lsp_config` is not a Dictionary or Function): AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'lsp': 'socket', - \ 'address_callback': 'X', + \ 'address': 'X', \ 'language': 'x', - \ 'project_root_callback': 'x', + \ 'project_root': 'x', \ 'lsp_config': 'x', \}) AssertEqual '`lsp_config` must be a Dictionary or Function if defined', g:vader_exception diff --git a/test/test_list_formatting.vader b/test/test_list_formatting.vader index dcefac53..d79a664b 100644 --- a/test/test_list_formatting.vader +++ b/test/test_list_formatting.vader @@ -36,7 +36,7 @@ After: call setqflist([]) Execute(Formatting with codes should work for the loclist): - call AddItem({'text': 'nocode'}) + call AddItem({'text': "nocode\r"}) call ale#list#SetLists(bufnr(''), g:loclist) AssertEqual @@ -79,7 +79,7 @@ Execute(Formatting with codes should work for the quickfix list): let g:ale_set_loclist = 0 let g:ale_set_quickfix = 1 - call AddItem({'text': 'nocode'}) + call AddItem({'text': "nocode\r"}) call ale#list#SetLists(bufnr(''), g:loclist) AssertEqual diff --git a/test/test_loclist_corrections.vader b/test/test_loclist_corrections.vader index 343620a5..d53b1411 100644 --- a/test/test_loclist_corrections.vader +++ b/test/test_loclist_corrections.vader @@ -1,7 +1,50 @@ +Before: + Save g:ale_filename_mappings + + let g:ale_filename_mappings = {} + After: unlet! b:temp_name unlet! b:other_bufnr + Restore + + +Execute(FixLocList should map filenames): + " Paths converted back into temporary filenames shouldn't be included. + let g:ale_filename_mappings = { + \ 'linter2': [['/xxx/', '/data/']], + \ 'linter1': [ + \ ['/bar/', '/data/special/'], + \ ['/foo/', '/data/'], + \ [ + \ ale#path#Simplify(fnamemodify(ale#util#Tempname(), ':h:h')) . '/', + \ '/x-tmp/', + \ ], + \ ], + \} + + AssertEqual + \ [ + \ '/foo/file.txt', + \ v:null, + \ '/bar/file.txt', + \ ], + \ map( + \ ale#engine#FixLocList( + \ bufnr('%'), + \ 'linter1', + \ 0, + \ [ + \ {'text': 'x', 'lnum': 1, 'filename': '/data/file.txt'}, + \ {'text': 'x', 'lnum': 1, 'filename': '/x-tmp/file.txt'}, + \ {'text': 'x', 'lnum': 1, 'filename': '/data/special/file.txt'}, + \ ], + \ ), + \ 'get(v:val, ''filename'', v:null)', + \ ) + + Given foo (Some file with lines to count): foo12345678 bar12345678 @@ -37,7 +80,7 @@ Execute(FixLocList should set all the default values correctly): \ 'nr': -1, \ 'linter_name': 'foobar', \ }, - \], + \ ], \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', @@ -58,7 +101,7 @@ Execute(FixLocList should use the values we supply): \ 'nr': 42, \ 'linter_name': 'foobar', \ }, - \], + \ ], \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', @@ -87,7 +130,7 @@ Execute(FixLocList should set items with lines beyond the end to the last line): \ 'nr': -1, \ 'linter_name': 'foobar', \ }, - \], + \ ], \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', @@ -108,7 +151,7 @@ Execute(FixLocList should move line 0 to line 1): \ 'nr': -1, \ 'linter_name': 'foobar', \ }, - \], + \ ], \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', @@ -130,7 +173,7 @@ Execute(FixLocList should convert line and column numbers correctly): \ 'nr': -1, \ 'linter_name': 'foobar', \ }, - \], + \ ], \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', @@ -164,7 +207,7 @@ Execute(FixLocList should pass on end_col values): \ 'nr': -1, \ 'linter_name': 'foobar', \ }, - \], + \ ], \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', @@ -202,7 +245,7 @@ Execute(FixLocList should pass on end_lnum values): \ 'nr': -1, \ 'linter_name': 'foobar', \ }, - \], + \ ], \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', @@ -227,7 +270,7 @@ Execute(FixLocList should allow subtypes to be set): \ 'nr': -1, \ 'linter_name': 'foobar', \ }, - \], + \ ], \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', @@ -289,7 +332,7 @@ Execute(FixLocList should accept filenames): \ 'nr': -1, \ 'linter_name': 'foobar', \ }, - \], + \ ], \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', @@ -327,7 +370,7 @@ Execute(FixLocList should interpret temporary filenames as being the current buf \ 'nr': -1, \ 'linter_name': 'foobar', \ }, - \], + \ ], \ ale#engine#FixLocList( \ bufnr(''), \ 'foobar', @@ -352,7 +395,7 @@ Execute(The error code should be passed on): \ 'linter_name': 'foobar', \ 'code': 'some-code' \ }, - \], + \ ], \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', @@ -385,7 +428,7 @@ Execute(FixLocList should mark problems as coming from other sources if requeste \ 'linter_name': 'foobar', \ 'from_other_source': 1, \ }, - \], + \ ], \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', @@ -407,7 +450,7 @@ Execute(character positions should be converted to byte positions): \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 7, 'end_col': 13, 'end_lnum': 1, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'}, \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 7, 'end_col': 17, 'end_lnum': 2, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'}, \ {'lnum': 2, 'bufnr': bufnr(''), 'col': 17, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'}, - \], + \ ], \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', diff --git a/test/test_shell_detection.vader b/test/test_shell_detection.vader index 6452287f..697054d0 100644 --- a/test/test_shell_detection.vader +++ b/test/test_shell_detection.vader @@ -98,6 +98,16 @@ Execute(The ksh dialect should be used for shellcheck if b:is_kornshell is 1): AssertEqual 'ksh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) +Execute(The filetype should be used as the default shell type when there is no hashbang line): + set filetype=zsh + AssertEqual 'zsh', ale#handlers#sh#GetShellType(bufnr('')) + + set filetype=tcsh + AssertEqual 'tcsh', ale#handlers#sh#GetShellType(bufnr('')) + + set filetype=python + AssertEqual '', ale#handlers#sh#GetShellType(bufnr('')) + Given(A file with /bin/ash): #!/bin/ash diff --git a/test/test_swiftlint_executable_detection.vader b/test/test_swiftlint_executable_detection.vader index dfd4930b..ac83ff8f 100644 --- a/test/test_swiftlint_executable_detection.vader +++ b/test/test_swiftlint_executable_detection.vader @@ -23,22 +23,22 @@ Execute(React Native apps using CocoaPods should take precedence over the defaul call ale#test#SetFilename('swiftlint-test-files/react-native/testfile.swift') AssertEqual - \ ale#path#Simplify(g:dir . '/swiftlint-test-files/react-native/ios/Pods/SwiftLint/swiftlint'), - \ ale_linters#swift#swiftlint#GetExecutable(bufnr('')) + \ tolower(ale#path#Simplify(g:dir . '/swiftlint-test-files/react-native/ios/Pods/SwiftLint/swiftlint')), + \ tolower(ale_linters#swift#swiftlint#GetExecutable(bufnr(''))) Execute(CocoaPods installation should take precedence over the default executable): call ale#test#SetFilename('swiftlint-test-files/cocoapods/testfile.swift') AssertEqual - \ ale#path#Simplify(g:dir . '/swiftlint-test-files/cocoapods/Pods/SwiftLint/swiftlint'), - \ ale_linters#swift#swiftlint#GetExecutable(bufnr('')) + \ tolower(ale#path#Simplify(g:dir . '/swiftlint-test-files/cocoapods/Pods/SwiftLint/swiftlint')), + \ tolower(ale_linters#swift#swiftlint#GetExecutable(bufnr(''))) Execute(Top level CocoaPods installation should take precedence over React Native installation): call ale#test#SetFilename('swiftlint-test-files/cocoapods-and-react-native/testfile.swift') AssertEqual - \ ale#path#Simplify(g:dir . '/swiftlint-test-files/cocoapods-and-react-native/Pods/SwiftLint/swiftlint'), - \ ale_linters#swift#swiftlint#GetExecutable(bufnr('')) + \ tolower(ale#path#Simplify(g:dir . '/swiftlint-test-files/cocoapods-and-react-native/Pods/SwiftLint/swiftlint')), + \ tolower(ale_linters#swift#swiftlint#GetExecutable(bufnr(''))) Execute(use-global should override other versions): let g:ale_swift_swiftlint_use_global = 1 diff --git a/test/test_temporary_file_management.vader b/test/test_temporary_file_management.vader index 9fff1ace..bb735886 100644 --- a/test/test_temporary_file_management.vader +++ b/test/test_temporary_file_management.vader @@ -40,7 +40,7 @@ Before: \ 'name': 'testlinter', \ 'executable': has('win32') ? 'cmd' : 'echo', \ 'callback': 'TestCallback', - \ 'command_callback': 'TestCommandCallback', + \ 'command': function('TestCommandCallback'), \}) call ale#command#ClearData() diff --git a/test/test_writefile_function.vader b/test/test_writefile_function.vader index 811d59e8..53a88331 100644 --- a/test/test_writefile_function.vader +++ b/test/test_writefile_function.vader @@ -69,3 +69,49 @@ Execute(Unix file lines should be written as normal): AssertEqual \ ['first', 'second', 'third', ''], \ readfile(g:new_line_test_file, 'b') + +Execute(Newline at end of file should be preserved even when nofixeol): + call ale#test#SetFilename(g:new_line_test_file) + + setlocal buftype= + noautocmd :w + noautocmd :e! ++ff=unix + set eol + set nofixeol + + call ale#util#Writefile(bufnr(''), getline(1, '$'), g:new_line_test_file) + + AssertEqual + \ ['first', 'second', 'third', ''], + \ readfile(g:new_line_test_file, 'b') + +Execute(Newline should not be appended on write when noeol and nofixeol): + call ale#test#SetFilename(g:new_line_test_file) + + setlocal buftype= + noautocmd :w + noautocmd :e! ++ff=unix + set noeol + set nofixeol + + call ale#util#Writefile(bufnr(''), getline(1, '$'), g:new_line_test_file) + + AssertEqual + \ ['first', 'second', 'third'], + \ readfile(g:new_line_test_file, 'b') + +Execute(Newline should be appended on write when noeol and fixeol): + call ale#test#SetFilename(g:new_line_test_file) + + setlocal buftype= + noautocmd :w + noautocmd :e! ++ff=unix + set noeol + set fixeol + + call ale#util#Writefile(bufnr(''), getline(1, '$'), g:new_line_test_file) + + AssertEqual + \ ['first', 'second', 'third', ''], + \ readfile(g:new_line_test_file, 'b') + diff --git a/test/util/test_cd_string_commands.vader b/test/util/test_cd_string_commands.vader index f2102e48..85c5065f 100644 --- a/test/util/test_cd_string_commands.vader +++ b/test/util/test_cd_string_commands.vader @@ -16,5 +16,5 @@ Execute(BufferCdString should output the correct command string): call ale#test#SetFilename('foo.txt') AssertEqual - \ has('unix') ? 'cd ' . ale#Escape(g:dir) . ' && ' : 'cd /d ' . ale#Escape(g:dir) . ' && ', + \ has('unix') ? 'cd %s:h && ' : 'cd /d %s:h && ', \ ale#path#BufferCdString(bufnr('')) |