diff options
Diffstat (limited to 'test')
209 files changed, 4431 insertions, 961 deletions
diff --git a/test/hack_files/testfile.php b/test/command_callback/ccls_paths/with_ccls-root/.ccls-root index e69de29b..e69de29b 100644 --- a/test/hack_files/testfile.php +++ b/test/command_callback/ccls_paths/with_ccls-root/.ccls-root diff --git a/test/command_callback/ccls_paths/with_ccls/.ccls b/test/command_callback/ccls_paths/with_ccls/.ccls new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/ccls_paths/with_ccls/.ccls diff --git a/test/command_callback/ccls_paths/with_compile_commands_json/compile_commands.json b/test/command_callback/ccls_paths/with_compile_commands_json/compile_commands.json new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/ccls_paths/with_compile_commands_json/compile_commands.json diff --git a/test/command_callback/cquery_paths/with_compile_commands_json/compile_commands.json b/test/command_callback/cquery_paths/with_compile_commands_json/compile_commands.json new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/cquery_paths/with_compile_commands_json/compile_commands.json diff --git a/test/command_callback/cquery_paths/with_cquery/.cquery b/test/command_callback/cquery_paths/with_cquery/.cquery new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/cquery_paths/with_cquery/.cquery diff --git a/test/command_callback/elixir_paths/mix_project/lib/app.ex b/test/command_callback/elixir_paths/mix_project/lib/app.ex new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/elixir_paths/mix_project/lib/app.ex diff --git a/test/command_callback/elixir_paths/mix_project/mix.exs b/test/command_callback/elixir_paths/mix_project/mix.exs new file mode 100644 index 00000000..419685ae --- /dev/null +++ b/test/command_callback/elixir_paths/mix_project/mix.exs @@ -0,0 +1,3 @@ +defmodule Test.MixProject do + # fake mix project file +end diff --git a/test/command_callback/elixir_paths/umbrella_project/apps/app1/lib/app.ex b/test/command_callback/elixir_paths/umbrella_project/apps/app1/lib/app.ex new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/elixir_paths/umbrella_project/apps/app1/lib/app.ex diff --git a/test/command_callback/elixir_paths/umbrella_project/apps/app1/mix.exs b/test/command_callback/elixir_paths/umbrella_project/apps/app1/mix.exs new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/elixir_paths/umbrella_project/apps/app1/mix.exs diff --git a/test/command_callback/elixir_paths/umbrella_project/apps/app2/lib/app.ex b/test/command_callback/elixir_paths/umbrella_project/apps/app2/lib/app.ex new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/elixir_paths/umbrella_project/apps/app2/lib/app.ex diff --git a/test/command_callback/elixir_paths/umbrella_project/apps/app2/mix.exs b/test/command_callback/elixir_paths/umbrella_project/apps/app2/mix.exs new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/elixir_paths/umbrella_project/apps/app2/mix.exs diff --git a/test/command_callback/elixir_paths/umbrella_project/mix.exs b/test/command_callback/elixir_paths/umbrella_project/mix.exs new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/elixir_paths/umbrella_project/mix.exs diff --git a/test/command_callback/go_paths/go1/prj1/file.go b/test/command_callback/go_paths/go1/prj1/file.go new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/go_paths/go1/prj1/file.go diff --git a/test/command_callback/go_paths/go2/prj2/file.go b/test/command_callback/go_paths/go2/prj2/file.go new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/go_paths/go2/prj2/file.go diff --git a/test/command_callback/julia-languageserver-project/REQUIRE b/test/command_callback/julia-languageserver-project/REQUIRE new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/julia-languageserver-project/REQUIRE diff --git a/test/command_callback/julia-languageserver-project/test.jl b/test/command_callback/julia-languageserver-project/test.jl new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/julia-languageserver-project/test.jl diff --git a/test/command_callback/mix_paths/wrapped_project/mix.exs b/test/command_callback/mix_paths/wrapped_project/mix.exs deleted file mode 100644 index d2d855e6..00000000 --- a/test/command_callback/mix_paths/wrapped_project/mix.exs +++ /dev/null @@ -1 +0,0 @@ -use Mix.Config diff --git a/test/command_callback/psalm-project/vendor/bin/psalm-language-server b/test/command_callback/psalm-project/vendor/bin/psalm-language-server new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/psalm-project/vendor/bin/psalm-language-server diff --git a/test/command_callback/stack_build_paths/stack.yaml b/test/command_callback/stack_build_paths/stack.yaml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/stack_build_paths/stack.yaml diff --git a/test/command_callback/stack_ghc_paths/stack.yaml b/test/command_callback/stack_ghc_paths/stack.yaml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/stack_ghc_paths/stack.yaml diff --git a/test/command_callback/test_ada_gcc_command_callbacks.vader b/test/command_callback/test_ada_gcc_command_callbacks.vader new file mode 100644 index 00000000..de6e355e --- /dev/null +++ b/test/command_callback/test_ada_gcc_command_callbacks.vader @@ -0,0 +1,44 @@ +Before: + call ale#assert#SetUpLinterTest('ada', 'gcc') + call ale#test#SetFilename('dummy.adb') + + function! GetOutputDir(command) abort + let l:split_command = split(a:command) + let l:index = index(l:split_command, '-o') + return l:split_command[l:index + 1] + endfunction + + let b:out_file = GetOutputDir(ale_linters#ada#gcc#GetCommand(bufnr(''))) + +After: + delfunction GetOutputDir + + unlet! b:out_file + + 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()) + \ . ' -gnatwa -gnatq %t' + + let b:ale_ada_gcc_executable = 'foo' + + AssertLinter 'foo', + \ ale#Escape('foo') . ' -x ada -c -gnatc' + \ . ' -o ' . b:out_file + \ . ' -I ' . ale#Escape(getcwd()) + \ . ' -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()) + \ . ' --foo --bar %t' diff --git a/test/command_callback/test_ansible_lint_command_callback.vader b/test/command_callback/test_ansible_lint_command_callback.vader new file mode 100644 index 00000000..ddc6c6c8 --- /dev/null +++ b/test/command_callback/test_ansible_lint_command_callback.vader @@ -0,0 +1,17 @@ +Before: + call ale#assert#SetUpLinterTest('ansible', 'ansible_lint') + let b:bin_dir = has('win32') ? 'Scripts' : 'bin' + +After: + unlet! b:bin_dir + unlet! b:executable + call ale#assert#TearDownLinterTest() + +Execute(The ansible_lint command callback should return default string): + AssertLinter 'ansible-lint', ale#Escape('ansible-lint') . ' -p %t' + +Execute(The ansible_lint executable should be configurable): + let g:ale_ansible_ansible_lint_executable = '~/.local/bin/ansible-lint' + + AssertLinter '~/.local/bin/ansible-lint', + \ ale#Escape('~/.local/bin/ansible-lint') . ' -p %t' diff --git a/test/command_callback/test_brakeman_command_callback.vader b/test/command_callback/test_brakeman_command_callback.vader index 61be4caf..15dbbe1c 100644 --- a/test/command_callback/test_brakeman_command_callback.vader +++ b/test/command_callback/test_brakeman_command_callback.vader @@ -12,7 +12,8 @@ Execute(The brakeman command callback should detect absence of a valid Rails app Execute(The brakeman command callback should find a valid Rails app root): call ale#test#SetFilename('../ruby_fixtures/valid_rails_app/db/test.rb') - AssertLinter 'brakeman', 'brakeman -f json -q -p ' + AssertLinter 'brakeman', ale#Escape('brakeman') + \ . ' -f json -q -p ' \ . ale#Escape(ale#path#Simplify(g:dir . '/../ruby_fixtures/valid_rails_app')) Execute(The brakeman command callback should include configured options): @@ -20,5 +21,17 @@ Execute(The brakeman command callback should include configured options): let g:ale_ruby_brakeman_options = '--combobulate' - AssertLinter 'brakeman', 'brakeman -f json -q --combobulate -p ' + AssertLinter 'brakeman', ale#Escape('brakeman') + \ . ' -f json -q --combobulate -p ' + \ . ale#Escape(ale#path#Simplify(g:dir . '/../ruby_fixtures/valid_rails_app')) + +Execute(Setting bundle appends 'exec brakeman'): + call ale#test#SetFilename('../ruby_fixtures/valid_rails_app/db/test.rb') + + let g:ale_ruby_brakeman_executable = 'bundle' + let g:ale_ruby_brakeman_options = '--combobulate' + + AssertLinter 'bundle', ale#Escape('bundle') + \ . ' exec brakeman' + \ . ' -f json -q --combobulate -p ' \ . ale#Escape(ale#path#Simplify(g:dir . '/../ruby_fixtures/valid_rails_app')) diff --git a/test/command_callback/test_c_ccls_command_callbacks.vader b/test/command_callback/test_c_ccls_command_callbacks.vader new file mode 100644 index 00000000..b8f3ab5b --- /dev/null +++ b/test/command_callback/test_c_ccls_command_callbacks.vader @@ -0,0 +1,43 @@ +" Author: Ye Jingchen <ye.jingchen@gmail.com>, Ben Falconer <ben@falconers.me.uk> +" Description: A language server for C + +Before: + call ale#assert#SetUpLinterTest('c', 'ccls') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The project root should be detected correctly using compile_commands.json file): + AssertLSPProject '' + + call ale#test#SetFilename('ccls_paths/with_compile_commands_json/dummy.c') + + AssertLSPProject ale#path#Simplify(g:dir . '/ccls_paths/with_compile_commands_json') + +Execute(The project root should be detected correctly using .ccls file): + AssertLSPProject '' + + call ale#test#SetFilename('ccls_paths/with_ccls/dummy.c') + + AssertLSPProject ale#path#Simplify(g:dir . '/ccls_paths/with_ccls') + +Execute(The project root should be detected correctly using .ccls-root file): + AssertLSPProject '' + + call ale#test#SetFilename('ccls_paths/with_ccls-root/dummy.c') + + AssertLSPProject ale#path#Simplify(g:dir . '/ccls_paths/with_ccls-root') + +Execute(The executable should be configurable): + AssertLinter 'ccls', ale#Escape('ccls') + + let b:ale_c_ccls_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') + +Execute(The initialization options should be configurable): + AssertLSPOptions {} + + let b:ale_c_ccls_init_options = { 'cacheDirectory': '/tmp/ccls' } + + AssertLSPOptions { 'cacheDirectory': '/tmp/ccls' } diff --git a/test/command_callback/test_c_clang_command_callbacks.vader b/test/command_callback/test_c_clang_command_callbacks.vader index 87f7fd06..7d2ff0bf 100644 --- a/test/command_callback/test_c_clang_command_callbacks.vader +++ b/test/command_callback/test_c_clang_command_callbacks.vader @@ -1,4 +1,7 @@ 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()) diff --git a/test/command_callback/test_c_clang_tidy_command_callback.vader b/test/command_callback/test_c_clang_tidy_command_callback.vader index 582d4798..f78d0ea7 100644 --- a/test/command_callback/test_c_clang_tidy_command_callback.vader +++ b/test/command_callback/test_c_clang_tidy_command_callback.vader @@ -7,7 +7,7 @@ After: Execute(The clangtidy command default should be correct): AssertLinter 'clang-tidy', - \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s' + \ ale#Escape('clang-tidy') . ' %s' Execute(You should be able to remove the -checks option for clang-tidy): let b:ale_c_clangtidy_checks = [] @@ -23,12 +23,14 @@ Execute(You should be able to set other checks for clang-tidy): \ . ' -checks=' . ale#Escape('-*,clang-analyzer-*') . ' %s' Execute(You should be able to manually set compiler flags for clang-tidy): + let b:ale_c_clangtidy_checks = ['*'] let b:ale_c_clangtidy_options = '-Wall' AssertLinter 'clang-tidy', \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' Execute(The build directory should be configurable): + let b:ale_c_clangtidy_checks = ['*'] let b:ale_c_build_dir = '/foo/bar' AssertLinter 'clang-tidy', @@ -37,6 +39,7 @@ Execute(The build directory should be configurable): \ . ' -p ' . ale#Escape('/foo/bar') Execute(The build directory setting should override the options): + let b:ale_c_clangtidy_checks = ['*'] let b:ale_c_build_dir = '/foo/bar' let b:ale_c_clangtidy_options = '-Wall' @@ -48,6 +51,7 @@ Execute(The build directory setting should override the options): Execute(The build directory should be ignored for header files): call ale#test#SetFilename('test.h') + let b:ale_c_clangtidy_checks = ['*'] let b:ale_c_build_dir = '/foo/bar' let b:ale_c_clangtidy_options = '-Wall' @@ -61,6 +65,7 @@ Execute(The build directory should be ignored for header files): \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' Execute(The executable should be configurable): + let b:ale_c_clangtidy_checks = ['*'] let b:ale_c_clangtidy_executable = 'foobar' AssertLinter 'foobar', diff --git a/test/command_callback/test_c_cppcheck_command_callbacks.vader b/test/command_callback/test_c_cppcheck_command_callbacks.vader index 3fc87a79..3ae4bdbe 100644 --- a/test/command_callback/test_c_cppcheck_command_callbacks.vader +++ b/test/command_callback/test_c_cppcheck_command_callbacks.vader @@ -19,6 +19,6 @@ Execute(cppcheck for C++ should detect compile_commands.json files): call ale#test#SetFilename('cppcheck_paths/one/foo.cpp') AssertLinter 'cppcheck', - \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) . ' && ' + \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ . ale#Escape('cppcheck') \ . ' -q --language=c --project=compile_commands.json --enable=style %t' diff --git a/test/command_callback/test_c_cquery_command_callbacks.vader b/test/command_callback/test_c_cquery_command_callbacks.vader new file mode 100644 index 00000000..13b7a567 --- /dev/null +++ b/test/command_callback/test_c_cquery_command_callbacks.vader @@ -0,0 +1,33 @@ +Before: + call ale#assert#SetUpLinterTest('c', 'cquery') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The project root should be detected correctly using compile_commands.json file): + AssertLSPProject '' + + call ale#test#SetFilename('cquery_paths/with_compile_commands_json/dummy.c') + + AssertLSPProject ale#path#Simplify(g:dir . '/cquery_paths/with_compile_commands_json') + +Execute(The project root should be detected correctly using .cquery file): + AssertLSPProject '' + + call ale#test#SetFilename('cquery_paths/with_cquery/dummy.c') + + AssertLSPProject ale#path#Simplify(g:dir . '/cquery_paths/with_cquery') + +Execute(The executable should be configurable): + AssertLinter 'cquery', ale#Escape('cquery') + + let b:ale_c_cquery_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') + +Execute(The cache directory should be configurable): + AssertLSPOptions {'cacheDirectory': expand('$HOME/.cache/cquery')} + + let b:ale_c_cquery_cache_directory = '/foo/bar' + + AssertLSPOptions {'cacheDirectory': '/foo/bar'} diff --git a/test/command_callback/test_c_flawfinder_command_callbacks.vader b/test/command_callback/test_c_flawfinder_command_callbacks.vader index 44573ff5..38385e2b 100644 --- a/test/command_callback/test_c_flawfinder_command_callbacks.vader +++ b/test/command_callback/test_c_flawfinder_command_callbacks.vader @@ -13,7 +13,7 @@ Execute(The minlevel of flawfinder should be configurable): AssertLinter 'flawfinder', ale#Escape('flawfinder') . ' -CDQS --minlevel=8 %t' Execute(Additional flawfinder options should be configurable): - let b:ale_c_flawfinder_options = ' --foobar' + let b:ale_c_flawfinder_options = '--foobar' AssertLinter 'flawfinder', \ ale#Escape('flawfinder') . ' -CDQS --foobar --minlevel=1 %t' diff --git a/test/command_callback/test_c_gcc_command_callbacks.vader b/test/command_callback/test_c_gcc_command_callbacks.vader index 45514051..1f51c3bc 100644 --- a/test/command_callback/test_c_gcc_command_callbacks.vader +++ b/test/command_callback/test_c_gcc_command_callbacks.vader @@ -1,4 +1,7 @@ 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 -fsyntax-only -iquote' diff --git a/test/command_callback/test_c_import_paths.vader b/test/command_callback/test_c_import_paths.vader new file mode 100644 index 00000000..0b5fac40 --- /dev/null +++ b/test/command_callback/test_c_import_paths.vader @@ -0,0 +1,223 @@ +Before: + " Make sure the c.vim file is loaded first. + call ale#c#FindProjectRoot(bufnr('')) + + Save g:ale_c_parse_makefile + Save g:__ale_c_project_filenames + + let g:original_project_filenames = g:__ale_c_project_filenames + + " Remove the .git/HEAD dir for C import paths for these tests. + " The tests run inside of a git repo. + let g:__ale_c_project_filenames = filter( + \ copy(g:__ale_c_project_filenames), + \ 'v:val isnot# ''.git/HEAD''' + \) + + let g:ale_c_parse_makefile = 0 + +After: + unlet! g:original_project_filenames + + call ale#assert#TearDownLinterTest() + +Execute(The C GCC handler should include 'include' directories for projects with a Makefile): + call ale#assert#SetUpLinterTest('c', 'gcc') + call ale#test#SetFilename('../test_c_projects/makefile_project/subdir/file.c') + let g:ale_c_gcc_options = '' + + AssertLinter 'gcc', + \ ale#Escape('gcc') + \ . ' -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 GCC handler should include 'include' directories for projects with a configure file): + call ale#assert#SetUpLinterTest('c', 'gcc') + call ale#test#SetFilename('../test_c_projects/configure_project/subdir/file.c') + let g:ale_c_gcc_options = '' + + AssertLinter 'gcc', + \ ale#Escape('gcc') + \ . ' -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 GCC handler should include root directories for projects with .h files in them): + call ale#assert#SetUpLinterTest('c', 'gcc') + call ale#test#SetFilename('../test_c_projects/h_file_project/subdir/file.c') + let g:ale_c_gcc_options = '' + + AssertLinter 'gcc', + \ ale#Escape('gcc') + \ . ' -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 GCC handler should include root directories for projects with .hpp files in them): + call ale#assert#SetUpLinterTest('c', 'gcc') + call ale#test#SetFilename('../test_c_projects/hpp_file_project/subdir/file.c') + let g:ale_c_gcc_options = '' + + AssertLinter 'gcc', + \ ale#Escape('gcc') + \ . ' -S -x c -fsyntax-only ' + \ . '-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')) + \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/hpp_file_project')) + \ . ' -' + +Execute(The C++ GCC handler should include 'include' directories for projects with a Makefile): + call ale#assert#SetUpLinterTest('cpp', 'gcc') + call ale#test#SetFilename('../test_c_projects/makefile_project/subdir/file.cpp') + let g:ale_cpp_gcc_options = '' + + AssertLinter 'gcc', + \ ale#Escape('gcc') + \ . ' -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++ GCC handler should include 'include' directories for projects with a configure file): + call ale#assert#SetUpLinterTest('cpp', 'gcc') + call ale#test#SetFilename('../test_c_projects/configure_project/subdir/file.cpp') + let g:ale_cpp_gcc_options = '' + + AssertLinter 'gcc', + \ ale#Escape('gcc') + \ . ' -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++ GCC handler should include root directories for projects with .h files in them): + call ale#assert#SetUpLinterTest('cpp', 'gcc') + call ale#test#SetFilename('../test_c_projects/h_file_project/subdir/file.cpp') + let g:ale_cpp_gcc_options = '' + + AssertLinter 'gcc', + \ ale#Escape('gcc') + \ . ' -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++ GCC handler should include root directories for projects with .hpp files in them): + call ale#assert#SetUpLinterTest('cpp', 'gcc') + call ale#test#SetFilename('../test_c_projects/hpp_file_project/subdir/file.cpp') + let g:ale_cpp_gcc_options = '' + + AssertLinter 'gcc', + \ ale#Escape('gcc') + \ . ' -S -x c++ -fsyntax-only ' + \ . '-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')) + \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/hpp_file_project')) + \ . ' -' + +Execute(The C++ ClangTidy handler should include json folders for projects with suitable build directory in them): + call ale#assert#SetUpLinterTest('cpp', 'clangtidy') + call ale#test#SetFilename('../test_c_projects/json_project/subdir/file.cpp') + + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') + \ . ' %s ' + \ . '-p ' . ale#Escape(ale#path#Simplify(g:dir . '/../test_c_projects/json_project/build')) diff --git a/test/command_callback/test_cargo_command_callbacks.vader b/test/command_callback/test_cargo_command_callbacks.vader index ac8846b0..f0afbc91 100644 --- a/test/command_callback/test_cargo_command_callbacks.vader +++ b/test/command_callback/test_cargo_command_callbacks.vader @@ -128,3 +128,27 @@ Execute(When a crate belongs to a workspace we chdir into the crate, unless we d \ 'cargo --version', \ 'cargo check --frozen --message-format=json -q', \] + +Execute(When ale_rust_cargo_use_clippy is set, cargo-clippy is used as linter): + let b:ale_rust_cargo_use_clippy = 1 + AssertLinter '', [ + \ 'cargo --version', + \ 'cargo clippy --frozen --message-format=json -q ', + \] + +Execute(When ale_rust_cargo_clippy_options is set, cargo-clippy appends it to commandline): + let b:ale_rust_cargo_use_clippy = 1 + let b:ale_rust_cargo_clippy_options = '-- -D warnings' + AssertLinter '', [ + \ 'cargo --version', + \ 'cargo clippy --frozen --message-format=json -q -- -D warnings', + \] + +Execute(cargo-check does not refer ale_rust_cargo_clippy_options): + let b:ale_rust_cargo_use_clippy = 0 + let b:ale_rust_cargo_use_check = 1 + let b:ale_rust_cargo_clippy_options = '-- -D warnings' + AssertLinter '', [ + \ 'cargo --version', + \ 'cargo check --frozen --message-format=json -q', + \] diff --git a/test/command_callback/test_clang_tidy_command_callback.vader b/test/command_callback/test_clang_tidy_command_callback.vader index f28609ee..3297a4cb 100644 --- a/test/command_callback/test_clang_tidy_command_callback.vader +++ b/test/command_callback/test_clang_tidy_command_callback.vader @@ -7,12 +7,13 @@ After: Execute(The clangtidy command default should be correct): AssertLinter 'clang-tidy', - \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s' + \ ale#Escape('clang-tidy') . ' %s' Execute(You should be able to remove the -checks option for clang-tidy): let b:ale_cpp_clangtidy_checks = [] - AssertLinter 'clang-tidy', ale#Escape('clang-tidy') . ' %s' + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' %s' Execute(You should be able to set other checks for clang-tidy): let b:ale_cpp_clangtidy_checks = ['-*', 'clang-analyzer-*'] @@ -22,34 +23,41 @@ Execute(You should be able to set other checks for clang-tidy): \ . ' -checks=' . ale#Escape('-*,clang-analyzer-*') . ' %s' Execute(You should be able to manually set compiler flags for clang-tidy): + let b:ale_cpp_clangtidy_checks = ['*'] let b:ale_cpp_clangtidy_options = '-Wall' AssertLinter 'clang-tidy', \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' - \ + Execute(The build directory should be configurable): + let b:ale_cpp_clangtidy_checks = ['*'] let b:ale_c_build_dir = '/foo/bar' AssertLinter 'clang-tidy', \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('*') . ' %s -p ' . ale#Escape('/foo/bar') + \ . ' -checks=' . ale#Escape('*') . ' %s' + \ . ' -p ' . ale#Escape('/foo/bar') Execute(The build directory setting should override the options): + let b:ale_cpp_clangtidy_checks = ['*'] let b:ale_c_build_dir = '/foo/bar' let b:ale_cpp_clangtidy_options = '-Wall' AssertLinter 'clang-tidy', \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('*') . ' %s -p ' . ale#Escape('/foo/bar') + \ . ' -checks=' . ale#Escape('*') . ' %s' + \ . ' -p ' . ale#Escape('/foo/bar') Execute(The build directory should be ignored for header files): call ale#test#SetFilename('test.h') + let b:ale_cpp_clangtidy_checks = ['*'] let b:ale_c_build_dir = '/foo/bar' let b:ale_cpp_clangtidy_options = '-Wall' AssertLinter 'clang-tidy', - \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' + \ ale#Escape('clang-tidy') + \ . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' call ale#test#SetFilename('test.hpp') @@ -57,6 +65,7 @@ Execute(The build directory should be ignored for header files): \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' Execute(The executable should be configurable): + let b:ale_cpp_clangtidy_checks = ['*'] let b:ale_cpp_clangtidy_executable = 'foobar' AssertLinter 'foobar', diff --git a/test/command_callback/test_cpp_ccls_command_callbacks.vader b/test/command_callback/test_cpp_ccls_command_callbacks.vader new file mode 100644 index 00000000..38947acf --- /dev/null +++ b/test/command_callback/test_cpp_ccls_command_callbacks.vader @@ -0,0 +1,43 @@ +" Author: Ye Jingchen <ye.jingchen@gmail.com>, Ben Falconer <ben@falconers.me.uk> +" Description: A language server for C++ + +Before: + call ale#assert#SetUpLinterTest('cpp', 'ccls') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The project root should be detected correctly using compile_commands.json file): + AssertLSPProject '' + + call ale#test#SetFilename('ccls_paths/with_compile_commands_json/dummy.cpp') + + AssertLSPProject ale#path#Simplify(g:dir . '/ccls_paths/with_compile_commands_json') + +Execute(The project root should be detected correctly using .ccls file): + AssertLSPProject '' + + call ale#test#SetFilename('ccls_paths/with_ccls/dummy.cpp') + + AssertLSPProject ale#path#Simplify(g:dir . '/ccls_paths/with_ccls') + +Execute(The project root should be detected correctly using .ccls-root file): + AssertLSPProject '' + + call ale#test#SetFilename('ccls_paths/with_ccls-root/dummy.cpp') + + AssertLSPProject ale#path#Simplify(g:dir . '/ccls_paths/with_ccls-root') + +Execute(The executable should be configurable): + AssertLinter 'ccls', ale#Escape('ccls') + + let b:ale_cpp_ccls_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') + +Execute(The initialization options should be configurable): + AssertLSPOptions {} + + let b:ale_cpp_ccls_init_options = { 'cacheDirectory': '/tmp/ccls' } + + AssertLSPOptions { 'cacheDirectory': '/tmp/ccls' } diff --git a/test/command_callback/test_cpp_clang_command_callbacks.vader b/test/command_callback/test_cpp_clang_command_callbacks.vader index 3a5ea945..e96fd8e7 100644 --- a/test/command_callback/test_cpp_clang_command_callbacks.vader +++ b/test/command_callback/test_cpp_clang_command_callbacks.vader @@ -1,4 +1,7 @@ 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()) diff --git a/test/command_callback/test_cpp_clazy_command_callback.vader b/test/command_callback/test_cpp_clazy_command_callback.vader new file mode 100644 index 00000000..1be43b96 --- /dev/null +++ b/test/command_callback/test_cpp_clazy_command_callback.vader @@ -0,0 +1,54 @@ +Before: + call ale#assert#SetUpLinterTest('cpp', 'clazy') + call ale#test#SetFilename('test.cpp') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The clazy command default should be correct): + AssertLinter 'clazy-standalone', + \ ale#Escape('clazy-standalone') . ' -checks=' . ale#Escape('level1') . ' %s' + +Execute(You should be able to remove the -checks option for clazy-standalone): + let b:ale_cpp_clazy_checks = [] + + AssertLinter 'clazy-standalone', ale#Escape('clazy-standalone') . ' %s' + +Execute(You should be able to set other checks for clazy-standalone): + let b:ale_cpp_clazy_checks = ['level2', 'level3'] + + AssertLinter 'clazy-standalone', + \ ale#Escape('clazy-standalone') + \ . ' -checks=' . ale#Escape('level2,level3') . ' %s' + +Execute(You should be able to manually set compiler flags for clazy-standalone): + let b:ale_cpp_clazy_options = '-qt4-compat' + + AssertLinter 'clazy-standalone', + \ ale#Escape('clazy-standalone') . ' -checks=' . ale#Escape('level1') . ' -qt4-compat' . ' %s' + \ +Execute(The build directory should be configurable): + let b:ale_c_build_dir = '/foo/bar' + + AssertLinter 'clazy-standalone', + \ ale#Escape('clazy-standalone') + \ . ' -checks=' . ale#Escape('level1') . ' -p ' . ale#Escape('/foo/bar') . ' %s' + +Execute(The build directory should be ignored for header files): + call ale#test#SetFilename('test.h') + + let b:ale_c_build_dir = '/foo/bar' + + AssertLinter 'clazy-standalone', + \ ale#Escape('clazy-standalone') . ' -checks=' . ale#Escape('level1') . ' %s' + + call ale#test#SetFilename('test.hpp') + + AssertLinter 'clazy-standalone', + \ ale#Escape('clazy-standalone') . ' -checks=' . ale#Escape('level1') . ' %s' + +Execute(The executable should be configurable): + let b:ale_cpp_clazy_executable = 'foobar' + + AssertLinter 'foobar', + \ ale#Escape('foobar') . ' -checks=' . ale#Escape('level1') . ' %s' diff --git a/test/command_callback/test_cpp_cppcheck_command_callbacks.vader b/test/command_callback/test_cpp_cppcheck_command_callbacks.vader index 3a7ada2c..352c88d5 100644 --- a/test/command_callback/test_cpp_cppcheck_command_callbacks.vader +++ b/test/command_callback/test_cpp_cppcheck_command_callbacks.vader @@ -17,6 +17,6 @@ Execute(cppcheck for C++ should detect compile_commands.json files): call ale#test#SetFilename('cppcheck_paths/one/foo.cpp') AssertLinter 'cppcheck', - \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) . ' && ' + \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ . ale#Escape('cppcheck') \ . ' -q --language=c++ --project=compile_commands.json --enable=style %t' diff --git a/test/command_callback/test_cpp_cquery_command_callbacks.vader b/test/command_callback/test_cpp_cquery_command_callbacks.vader index b355d052..682c90d5 100644 --- a/test/command_callback/test_cpp_cquery_command_callbacks.vader +++ b/test/command_callback/test_cpp_cquery_command_callbacks.vader @@ -7,6 +7,20 @@ Before: After: call ale#assert#TearDownLinterTest() +Execute(The project root should be detected correctly using compile_commands.json file): + AssertLSPProject '' + + call ale#test#SetFilename('cquery_paths/with_compile_commands_json/dummy.cpp') + + AssertLSPProject ale#path#Simplify(g:dir . '/cquery_paths/with_compile_commands_json') + +Execute(The project root should be detected correctly using .cquery file): + AssertLSPProject '' + + call ale#test#SetFilename('cquery_paths/with_cquery/dummy.cpp') + + AssertLSPProject ale#path#Simplify(g:dir . '/cquery_paths/with_cquery') + Execute(The executable should be configurable): AssertLinter 'cquery', ale#Escape('cquery') diff --git a/test/command_callback/test_cpp_gcc_command_callbacks.vader b/test/command_callback/test_cpp_gcc_command_callbacks.vader index f9fad8c8..0a86df4f 100644 --- a/test/command_callback/test_cpp_gcc_command_callbacks.vader +++ b/test/command_callback/test_cpp_gcc_command_callbacks.vader @@ -1,4 +1,7 @@ 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++ -fsyntax-only -iquote' \ . ' ' . ale#Escape(getcwd()) diff --git a/test/command_callback/test_cs_mcsc_command_callbacks.vader b/test/command_callback/test_cs_mcsc_command_callbacks.vader index 20ddb28b..d15898e0 100644 --- a/test/command_callback/test_cs_mcsc_command_callbacks.vader +++ b/test/command_callback/test_cs_mcsc_command_callbacks.vader @@ -5,43 +5,43 @@ After: call ale#assert#TearDownLinterTest() Execute(The mcsc linter should return the correct default command): - AssertLinter 'mcs', 'cd ' . ale#Escape(g:dir) . ' && ' + AssertLinter 'mcs', ale#path#CdString(g:dir) \ . 'mcs -unsafe -out:TEMP -t:module -recurse:' . ale#Escape('*.cs') Execute(The options should be be used in the command): let g:ale_cs_mcsc_options = '-pkg:dotnet' - AssertLinter 'mcs', 'cd ' . ale#Escape(g:dir) . ' && ' + AssertLinter 'mcs', ale#path#CdString(g:dir) \ . 'mcs -unsafe -pkg:dotnet -out:TEMP -t:module -recurse:' . ale#Escape('*.cs') Execute(The souce path should be be used in the command): let g:ale_cs_mcsc_source = '../foo/bar' - AssertLinter 'mcs', 'cd ' . ale#Escape('../foo/bar') . ' && ' + AssertLinter 'mcs', ale#path#CdString('../foo/bar') \ . 'mcs -unsafe -out:TEMP -t:module -recurse:' . ale#Escape('*.cs') Execute(The list of search pathes for assemblies should be be used in the command if not empty): let g:ale_cs_mcsc_assembly_path = ['/usr/lib/mono', '../foo/bar'] - AssertLinter 'mcs', 'cd ' . ale#Escape(g:dir) . ' && ' + AssertLinter 'mcs', ale#path#CdString(g:dir) \ . 'mcs -unsafe' \ . ' -lib:' . ale#Escape('/usr/lib/mono') . ',' . ale#Escape('../foo/bar') \ . ' -out:TEMP -t:module -recurse:' . ale#Escape('*.cs') let g:ale_cs_mcsc_assembly_path = [] - AssertLinter 'mcs', 'cd ' . ale#Escape(g:dir) . ' && ' + AssertLinter 'mcs', ale#path#CdString(g:dir) \ . 'mcs -unsafe -out:TEMP -t:module -recurse:' . ale#Escape('*.cs') Execute(The list of assemblies should be be used in the command if not empty): let g:ale_cs_mcsc_assemblies = ['foo.dll', 'bar.dll'] - AssertLinter 'mcs', 'cd ' . ale#Escape(g:dir) . ' && ' + AssertLinter 'mcs', ale#path#CdString(g:dir) \ . 'mcs -unsafe' \ . ' -r:' . ale#Escape('foo.dll') . ',' . ale#Escape('bar.dll') \ . ' -out:TEMP -t:module -recurse:' . ale#Escape('*.cs') let g:ale_cs_mcsc_assemblies = [] - AssertLinter 'mcs', 'cd ' . ale#Escape(g:dir) . ' && ' + AssertLinter 'mcs', ale#path#CdString(g:dir) \ . 'mcs -unsafe -out:TEMP -t:module -recurse:' . ale#Escape('*.cs') diff --git a/test/command_callback/test_cuda_nvcc_command_callbacks.vader b/test/command_callback/test_cuda_nvcc_command_callbacks.vader index 9e2b5ac6..4578d052 100644 --- a/test/command_callback/test_cuda_nvcc_command_callbacks.vader +++ b/test/command_callback/test_cuda_nvcc_command_callbacks.vader @@ -12,3 +12,9 @@ Execute(The executable should be configurable): AssertLinter 'foobar', \ ale#Escape('foobar') . ' -cuda -std=c++11 %s -o ' . g:ale#util#nul_file + +Execute(The options should be configurable): + let g:ale_cuda_nvcc_options = '--foobar' + + AssertLinter 'nvcc', + \ ale#Escape('nvcc') . ' -cuda --foobar %s -o ' . g:ale#util#nul_file diff --git a/test/command_callback/test_d_dls_callbacks.vader b/test/command_callback/test_d_dls_callbacks.vader new file mode 100644 index 00000000..156ebf66 --- /dev/null +++ b/test/command_callback/test_d_dls_callbacks.vader @@ -0,0 +1,19 @@ +Before: + call ale#assert#SetUpLinterTest('d', 'dls') + + Save &filetype + let &filetype = 'd' + +After: + call ale#assert#TearDownLinterTest() + +Execute(The language string should be correct): + AssertLSPLanguage 'd' + +Execute(The default executable should be correct): + AssertLinter 'dls', 'dls' + +Execute(The executable should be configurable): + let g:ale_d_dls_executable = 'foobar' + + AssertLinter 'foobar', 'foobar' diff --git a/test/command_callback/test_dart_language_server_command_callback.vader b/test/command_callback/test_dart_language_server_command_callback.vader new file mode 100644 index 00000000..5567f271 --- /dev/null +++ b/test/command_callback/test_dart_language_server_command_callback.vader @@ -0,0 +1,8 @@ +Before: + call ale#assert#SetUpLinterTest('dart', 'language_server') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'dart_language_server', ale#Escape('dart_language_server') diff --git a/test/command_callback/test_dockerfile_lint_command_callback.vader b/test/command_callback/test_dockerfile_lint_command_callback.vader new file mode 100644 index 00000000..abc32e0d --- /dev/null +++ b/test/command_callback/test_dockerfile_lint_command_callback.vader @@ -0,0 +1,19 @@ +Before: + call ale#assert#SetUpLinterTest('dockerfile', 'dockerfile_lint') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'dockerfile_lint', ale#Escape('dockerfile_lint') . ' -p -j -f %t' + +Execute(The executable should be configurable): + let b:ale_dockerfile_dockerfile_lint_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') . ' -p -j -f %t' + +Execute(The options should be configurable): + let b:ale_dockerfile_dockerfile_lint_options = '-r additional.yaml' + + AssertLinter 'dockerfile_lint', ale#Escape('dockerfile_lint') . ' -r additional.yaml -p -j -f %t' + diff --git a/test/command_callback/test_elixir_ls_command_callbacks.vader b/test/command_callback/test_elixir_ls_command_callbacks.vader new file mode 100644 index 00000000..ca785054 --- /dev/null +++ b/test/command_callback/test_elixir_ls_command_callbacks.vader @@ -0,0 +1,35 @@ +Before: + call ale#assert#SetUpLinterTest('elixir', 'elixir_ls') + + let g:ale_has_override['win32'] = 0 + +After: + let g:ale_has_override = {} + + call ale#assert#TearDownLinterTest() + +Execute(should set correct defaults (unix)): + AssertLinter 'elixir-ls/language_server.sh', 'elixir-ls/language_server.sh' + +Execute(should set correct defaults (win32)): + let g:ale_has_override['win32'] = 1 + + AssertLinter 'elixir-ls\language_server.bat', 'elixir-ls\language_server.bat' + +Execute(should configure elixir-ls release location): + let b:ale_elixir_elixir_ls_release = 'boo' + + AssertLinter 'boo/language_server.sh', 'boo/language_server.sh' + +Execute(should set correct LSP values): + call ale#test#SetFilename('elixir_paths/umbrella_project/apps/app1/lib/app.ex') + + AssertLSPLanguage 'elixir' + AssertLSPOptions {} + AssertLSPConfig {} + AssertLSPProject ale#path#Simplify(g:dir . '/elixir_paths/umbrella_project') + +Execute(should accept configuration settings): + AssertLSPConfig {} + let b:ale_elixir_elixir_ls_config = {'elixirLS': {'dialyzerEnabled': v:false}} + AssertLSPConfig {'elixirLS': {'dialyzerEnabled': v:false}} diff --git a/test/command_callback/test_elixir_mix_command_callbacks.vader b/test/command_callback/test_elixir_mix_command_callbacks.vader index 18fb13ed..b0d0af98 100644 --- a/test/command_callback/test_elixir_mix_command_callbacks.vader +++ b/test/command_callback/test_elixir_mix_command_callbacks.vader @@ -11,9 +11,23 @@ After: call ale#assert#TearDownLinterTest() Execute(The default mix command should be correct): - call ale#test#SetFilename('mix_paths/wrapped_project/lib/app.ex') + call ale#test#SetFilename('elixir_paths/mix_project/lib/app.ex') AssertLinter 'mix', - \ ale#path#CdString(ale#path#Simplify(g:dir . '/mix_paths/wrapped_project')) + \ ale#path#CdString(ale#path#Simplify(g:dir . '/elixir_paths/mix_project')) \ . g:env_prefix \ . 'mix compile %s' + +Execute(FindMixProjectRoot should detect the project root directory via mix.exs): + silent execute 'file ' . fnameescape(g:dir . '/elixir_paths/mix_project/lib/app.ex') + + AssertEqual + \ ale#path#Simplify(g:dir . '/elixir_paths/mix_project'), + \ ale#handlers#elixir#FindMixProjectRoot(bufnr('')) + +Execute(FindMixUmbrellaRoot should detect the umbrella root directory via mix.exs): + silent execute 'file ' . fnameescape(g:dir . '/elixir_paths/umbrella_project/apps/app1/lib/app.ex') + + AssertEqual + \ ale#path#Simplify(g:dir . '/elixir_paths/umbrella_project'), + \ ale#handlers#elixir#FindMixUmbrellaRoot(bufnr('')) diff --git a/test/command_callback/test_elm_make_command_callback.vader b/test/command_callback/test_elm_make_command_callback.vader new file mode 100644 index 00000000..6d95676f --- /dev/null +++ b/test/command_callback/test_elm_make_command_callback.vader @@ -0,0 +1,32 @@ +Before: + call ale#assert#SetUpLinterTest('elm', 'make') + +After: + unlet! g:executable + + call ale#assert#TearDownLinterTest() + +Execute(should get valid executable with default params): + call ale#test#SetFilename('../elm-test-files/app/testfile.elm') + + let g:executable = ale#path#Simplify(g:dir . '/../elm-test-files/app/node_modules/.bin/elm') + + AssertLinter g:executable, + \ ale#Escape(g:executable) . ' make --report=json --output=/dev/null %t' + +Execute(should get valid executable with 'use_global' params): + let g:ale_elm_make_use_global = 1 + + call ale#test#SetFilename('../elm-test-files/app/testfile.elm') + + AssertLinter 'elm', + \ ale#Escape('elm') . ' make --report=json --output=/dev/null %t' + +Execute(should get valid executable with 'use_global' and 'executable' params): + let g:ale_elm_make_executable = 'other-elm' + let g:ale_elm_make_use_global = 1 + + call ale#test#SetFilename('../elm-test-files/app/testfile.elm') + + AssertLinter 'other-elm', + \ ale#Escape('other-elm') . ' make --report=json --output=/dev/null %t' diff --git a/test/command_callback/test_flake8_command_callback.vader b/test/command_callback/test_flake8_command_callback.vader index f12b6747..ede511e0 100644 --- a/test/command_callback/test_flake8_command_callback.vader +++ b/test/command_callback/test_flake8_command_callback.vader @@ -1,5 +1,6 @@ Before: call ale#assert#SetUpLinterTest('python', 'flake8') + let b:bin_dir = has('win32') ? 'Scripts' : 'bin' WithChainResults ['3.0.0'] @@ -152,8 +153,16 @@ Execute(Using `python -m flake8` should be supported for running flake8): Execute(Setting executable to 'pipenv' should append 'run flake8'): let g:ale_python_flake8_executable = 'path/to/pipenv' - " FIXME: pipenv should check the vresion with flake8. + " FIXME: pipenv should check the version with flake8. WithChainResults [] AssertLinter 'path/to/pipenv', \ ale#path#BufferCdString(bufnr('')) \ . ale#Escape('path/to/pipenv') . ' run flake8 --format=default -' + +Execute(Pipenv is detected when python_flake8_auto_pipenv is set): + let g:ale_python_flake8_auto_pipenv = 1 + call ale#test#SetFilename('/testplugin/test/python_fixtures/pipenv/whatever.py') + + AssertLinter 'pipenv', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('pipenv') . ' run flake8 --format=default --stdin-display-name %s -' diff --git a/test/command_callback/test_fsc_command_callback.vader b/test/command_callback/test_fsc_command_callback.vader index 5fb5e7fa..278e7c16 100644 --- a/test/command_callback/test_fsc_command_callback.vader +++ b/test/command_callback/test_fsc_command_callback.vader @@ -10,4 +10,4 @@ Execute(The default executable and command should be correct): Given scala.sbt(An empty SBT file): Execute(fsc should not be run for sbt files): - AssertLinter '', '' + AssertLinterNotExecuted diff --git a/test/command_callback/test_gawk_command_callback.vader b/test/command_callback/test_gawk_command_callback.vader index 6bc0a438..ba9f59ab 100644 --- a/test/command_callback/test_gawk_command_callback.vader +++ b/test/command_callback/test_gawk_command_callback.vader @@ -6,14 +6,14 @@ After: Execute(The default command should be correct): AssertLinter 'gawk', - \ ale#Escape('gawk') . ' --source ''BEGIN { exit } END { exit 1 }''' + \ ale#Escape('gawk') . ' --source ' . ale#Escape('BEGIN { exit } END { exit 1 }') \ . ' -f %t --lint /dev/null' Execute(The executable should be configurable): let b:ale_awk_gawk_executable = '/other/gawk' AssertLinter '/other/gawk', - \ ale#Escape('/other/gawk') . ' --source ''BEGIN { exit } END { exit 1 }''' + \ ale#Escape('/other/gawk') . ' --source ' . ale#Escape('BEGIN { exit } END { exit 1 }') \ . ' -f %t --lint /dev/null' Execute(The options should be configurable): @@ -21,5 +21,5 @@ Execute(The options should be configurable): let b:ale_awk_gawk_options = '--something' AssertLinter 'gawk', - \ ale#Escape('gawk') . ' --source ''BEGIN { exit } END { exit 1 }''' + \ ale#Escape('gawk') . ' --source ' . ale#Escape('BEGIN { exit } END { exit 1 }') \ . ' --something -f %t --lint /dev/null' diff --git a/test/command_callback/test_gfortran_command_callback.vader b/test/command_callback/test_gfortran_command_callback.vader index a6ab50cd..3e6ef951 100644 --- a/test/command_callback/test_gfortran_command_callback.vader +++ b/test/command_callback/test_gfortran_command_callback.vader @@ -5,20 +5,20 @@ After: call ale#assert#TearDownLinterTest() Execute(The fortran gcc command callback should return the correct default string): - AssertLinter 'gcc', 'gcc -S -x f95 -fsyntax-only -ffree-form -Wall -' + AssertLinter 'gcc', ale#Escape('gcc') . ' -S -x f95 -fsyntax-only -ffree-form -Wall -' Execute(The fortran gcc command callback should let you set options): let g:ale_fortran_gcc_options = '-Wotherthings' - AssertLinter 'gcc', 'gcc -S -x f95 -fsyntax-only -ffree-form -Wotherthings -' + AssertLinter 'gcc', ale#Escape('gcc') . ' -S -x f95 -fsyntax-only -ffree-form -Wotherthings -' Execute(The fortran gcc command callback should let you use -ffixed-form): let g:ale_fortran_gcc_use_free_form = 0 - AssertLinter 'gcc', 'gcc -S -x f95 -fsyntax-only -ffixed-form -Wall -' + AssertLinter 'gcc', ale#Escape('gcc') . ' -S -x f95 -fsyntax-only -ffixed-form -Wall -' Execute(The fortran executable should be configurable): let g:ale_fortran_gcc_executable = 'gfortran' AssertLinter 'gfortran', - \ 'gfortran -S -x f95 -fsyntax-only -ffree-form -Wall -' + \ ale#Escape('gfortran') . ' -S -x f95 -fsyntax-only -ffree-form -Wall -' diff --git a/test/command_callback/test_gobuild_command_callback.vader b/test/command_callback/test_gobuild_command_callback.vader index 86113728..c6e324f2 100644 --- a/test/command_callback/test_gobuild_command_callback.vader +++ b/test/command_callback/test_gobuild_command_callback.vader @@ -1,36 +1,31 @@ Before: - call ale#assert#SetUpLinterTest('go', 'gobuild') + Save g:ale_go_go_executable - let g:env_prefix = has('win32') - \ ? 'set GOPATH=' . ale#Escape('/foo/bar') . ' && ' - \ : 'GOPATH=' . ale#Escape('/foo/bar') . ' ' - call ale_linters#go#gobuild#ResetEnv() + call ale#assert#SetUpLinterTest('go', 'gobuild') WithChainResults ['/foo/bar', '/foo/baz'] After: - unlet! g:env_prefix + Restore call ale#assert#TearDownLinterTest() Execute(The default commands should be correct): - AssertLinter 'go', [ - \ 'go env GOPATH GOROOT', - \ g:env_prefix . 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' - \ . 'go test -c -o /dev/null ./' - \] - - " We shouldn't run `go env` many times after we've got it. - AssertLinter 'go', [ - \ '', - \ g:env_prefix . 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + AssertLinter 'go', + \ ale#path#CdString(expand('%:p:h')) \ . 'go test -c -o /dev/null ./' - \] Execute(Extra options should be supported): let g:ale_go_gobuild_options = '--foo-bar' - AssertLinter 'go', [ - \ 'go env GOPATH GOROOT', - \ g:env_prefix . 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + AssertLinter 'go', + \ ale#path#CdString(expand('%:p:h')) \ . 'go test --foo-bar -c -o /dev/null ./' - \] + + let g:ale_go_gobuild_options = '' + +Execute(The executable should be configurable): + let g:ale_go_go_executable = 'foobar' + + AssertLinter 'foobar', + \ ale#path#CdString(expand('%:p:h')) + \ . 'foobar test -c -o /dev/null ./' diff --git a/test/command_callback/test_golangci_lint_command_callback.vader b/test/command_callback/test_golangci_lint_command_callback.vader new file mode 100644 index 00000000..345f58b1 --- /dev/null +++ b/test/command_callback/test_golangci_lint_command_callback.vader @@ -0,0 +1,38 @@ +Before: + call ale#assert#SetUpLinterTest('go', 'golangci_lint') + call ale#test#SetFilename('test.go') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The golangci-lint defaults should be correct): + AssertLinter 'golangci-lint', + \ ale#path#CdString(expand('%:p:h')) + \ . ale#Escape('golangci-lint') + \ . ' run ' . ale#Escape(expand('%' . ':t')) + \ . ' --enable-all' + +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#Escape('something else') + \ . ' run ' . ale#Escape(expand('%' . ':t')) + \ . ' --enable-all' + +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#Escape('golangci-lint') + \ . ' run ' . ale#Escape(expand('%' . ':t')) + \ . ' --foobar' + +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#Escape('golangci-lint') . ' run --enable-all' diff --git a/test/command_callback/test_golangserver_command_callback.vader b/test/command_callback/test_golangserver_command_callback.vader new file mode 100644 index 00000000..90fdc26f --- /dev/null +++ b/test/command_callback/test_golangserver_command_callback.vader @@ -0,0 +1,68 @@ +Before: + Save $GOPATH + Save g:ale_completion_enabled + + let g:ale_completion_enabled = 0 + let g:sep = has('win32') ? ';' : ':' + + call ale#assert#SetUpLinterTest('go', 'langserver') + let $GOPATH = ale#path#Simplify(g:dir . '/go_paths/go1') + \ . g:sep + \ . ale#path#Simplify(g:dir . '/go_paths/go2') + +After: + Restore + + unlet! b:ale_completion_enabled + unlet! g:sep + + call ale#assert#TearDownLinterTest() + +Execute(should set correct defaults): + AssertLinter 'go-langserver', ale#Escape('go-langserver') + +Execute(should configure go-langserver callback executable): + let b:ale_go_langserver_executable = 'boo' + + AssertLinter 'boo', ale#Escape('boo') + +Execute(should set go-langserver options): + call ale#test#SetFilename('go_paths/go1/prj1/file.go') + let b:ale_completion_enabled = 1 + let b:ale_go_langserver_options = '' + + AssertLinter 'go-langserver', + \ ale#Escape('go-langserver') . ' -gocodecompletion' + + let b:ale_go_langserver_options = '-trace' + + AssertLinter 'go-langserver', + \ ale#Escape('go-langserver') . ' -gocodecompletion -trace' + +Execute(should ignore go-langserver -gocodecompletion option): + call ale#test#SetFilename('go_paths/go1/prj1/file.go') + + let b:ale_go_langserver_options = '-trace -gocodecompletion' + let b:ale_completion_enabled = 1 + + AssertLinter 'go-langserver', + \ ale#Escape('go-langserver') . ' -gocodecompletion -trace' + + let b:ale_completion_enabled = 0 + + AssertLinter 'go-langserver', ale#Escape('go-langserver') . ' -trace' + +Execute(should set go-langserver for go app1): + call ale#test#SetFilename('go_paths/go1/prj1/file.go') + + AssertLSPLanguage 'go' + AssertLSPConfig {} + AssertLSPProject ale#path#Simplify(g:dir . '/go_paths/go1') + +Execute(should set go-langserver for go app2): + call ale#test#SetFilename('go_paths/go2/prj1/file.go') + + AssertLSPLanguage 'go' + AssertLSPOptions {} + AssertLSPConfig {} + AssertLSPProject ale#path#Simplify(g:dir . '/go_paths/go2') diff --git a/test/command_callback/test_golint_command_callbacks.vader b/test/command_callback/test_golint_command_callbacks.vader new file mode 100644 index 00000000..7c300309 --- /dev/null +++ b/test/command_callback/test_golint_command_callbacks.vader @@ -0,0 +1,18 @@ +Before: + call ale#assert#SetUpLinterTest('go', 'golint') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default golint command should be correct): + AssertLinter 'golint', ale#Escape('golint') . ' %t' + +Execute(The golint executable should be configurable): + let b:ale_go_golint_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') . ' %t' + +Execute(The golint options should be configurable): + let b:ale_go_golint_options = '--foo' + + AssertLinter 'golint', ale#Escape('golint') . ' --foo %t' diff --git a/test/command_callback/test_gometalinter_command_callback.vader b/test/command_callback/test_gometalinter_command_callback.vader index d788c5bd..88e86801 100644 --- a/test/command_callback/test_gometalinter_command_callback.vader +++ b/test/command_callback/test_gometalinter_command_callback.vader @@ -7,7 +7,7 @@ After: Execute(The gometalinter defaults should be correct): AssertLinter 'gometalinter', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ ale#path#CdString(expand('%:p:h')) \ . ale#Escape('gometalinter') \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t'))) \ . ' .' @@ -16,7 +16,7 @@ Execute(The gometalinter callback should use a configured executable): let b:ale_go_gometalinter_executable = 'something else' AssertLinter 'something else', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ ale#path#CdString(expand('%:p:h')) \ . ale#Escape('something else') \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t'))) \ . ' .' @@ -25,7 +25,7 @@ Execute(The gometalinter callback should use configured options): let b:ale_go_gometalinter_options = '--foobar' AssertLinter 'gometalinter', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ ale#path#CdString(expand('%:p:h')) \ . ale#Escape('gometalinter') \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t'))) \ . ' --foobar' . ' .' @@ -34,5 +34,5 @@ Execute(The gometalinter `lint_package` option should use the correct command): let b:ale_go_gometalinter_lint_package = 1 AssertLinter 'gometalinter', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ ale#path#CdString(expand('%:p:h')) \ . ale#Escape('gometalinter') . ' .' diff --git a/test/command_callback/test_gosimple_command_callback.vader b/test/command_callback/test_gosimple_command_callback.vader index 7b8c66ae..59013df0 100644 --- a/test/command_callback/test_gosimple_command_callback.vader +++ b/test/command_callback/test_gosimple_command_callback.vader @@ -7,4 +7,4 @@ After: Execute(The default gosimple command should be correct): AssertLinter 'gosimple', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && gosimple .' + \ ale#path#CdString(expand('%:p:h')) . ' gosimple .' diff --git a/test/command_callback/test_gotype_command_callback.vader b/test/command_callback/test_gotype_command_callback.vader index da9ceaf3..1898a0cb 100644 --- a/test/command_callback/test_gotype_command_callback.vader +++ b/test/command_callback/test_gotype_command_callback.vader @@ -7,7 +7,7 @@ After: Execute(The default gotype command should be correct): AssertLinter 'gotype', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && gotype .' + \ ale#path#CdString(expand('%:p:h')) . ' gotype .' Execute(The gotype callback should ignore test files): call ale#test#SetFilename('bla_test.go') diff --git a/test/command_callback/test_govet_command_callback.vader b/test/command_callback/test_govet_command_callback.vader index a73118ae..a55c0812 100644 --- a/test/command_callback/test_govet_command_callback.vader +++ b/test/command_callback/test_govet_command_callback.vader @@ -1,8 +1,19 @@ Before: + Save g:ale_go_go_executable + Save g:ale_go_govet_options call ale#assert#SetUpLinterTest('go', 'govet') After: + Restore call ale#assert#TearDownLinterTest() Execute(The default command should be correct): - AssertLinter 'go', 'cd ' . ale#Escape(expand('%:p:h')) . ' && go vet .' + AssertLinter 'go', ale#path#CdString(expand('%:p:h')) . ' 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 .' + +Execute(The executable should be configurable): + let g:ale_go_go_executable = 'foobar' + AssertLinter 'foobar', ale#path#CdString(expand('%:p:h')) . ' foobar vet .' diff --git a/test/command_callback/test_haml_hamllint_command_callback.vader b/test/command_callback/test_haml_hamllint_command_callback.vader index a59446ca..694b21d3 100644 --- a/test/command_callback/test_haml_hamllint_command_callback.vader +++ b/test/command_callback/test_haml_hamllint_command_callback.vader @@ -35,3 +35,7 @@ Execute(The command should include a .rubocop.yml and a .haml-lint if both are f AssertLinter 'haml-lint', \ ale#Env('HAML_LINT_RUBOCOP_CONF', b:conf_rubocop) \ . 'haml-lint --config ' . ale#Escape(b:conf_hamllint) . ' %t' + +Execute(The executable can be overridden): + let b:ale_haml_hamllint_executable = 'bin/haml-lint' + AssertLinter 'bin/haml-lint', 'bin/haml-lint %t' diff --git a/test/command_callback/test_haskell_ghc_mod_command_callbacks.vader b/test/command_callback/test_haskell_ghc_mod_command_callbacks.vader new file mode 100644 index 00000000..c1cc8597 --- /dev/null +++ b/test/command_callback/test_haskell_ghc_mod_command_callbacks.vader @@ -0,0 +1,10 @@ +Before: + call ale#assert#SetUpLinterTest('haskell', 'ghc_mod') + +After: + call ale#assert#TearDownLinterTest() + +Execute(Default should use ghc-mod): + AssertLinter + \ 'ghc-mod', + \ ale#Escape('ghc-mod') . ' --map-file %s=%t check %s' diff --git a/test/command_callback/test_haskell_hie_callbacks.vader b/test/command_callback/test_haskell_hie_callbacks.vader new file mode 100644 index 00000000..5bd2794c --- /dev/null +++ b/test/command_callback/test_haskell_hie_callbacks.vader @@ -0,0 +1,27 @@ +Before: + call ale#assert#SetUpLinterTest('haskell', 'hie') + + Save &filetype + let &filetype = 'haskell' + +After: + call ale#assert#TearDownLinterTest() + +Execute(The language string should be correct): + AssertLSPLanguage 'haskell' + +Execute(The default executable should be correct): + AssertLinter 'hie', + \ ale#Escape('hie') . ' --lsp' + +Execute(The project root should be detected correctly): + AssertLSPProject g:dir + + call ale#test#SetFilename('hie_paths/file.hs') + + AssertLSPProject ale#path#Simplify(g:dir . '/hie_paths') + +Execute(The executable should be configurable): + let g:ale_haskell_hie_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') . ' --lsp' diff --git a/test/command_callback/test_haskell_hlint_command_callbacks.vader b/test/command_callback/test_haskell_hlint_command_callbacks.vader new file mode 100644 index 00000000..6d227c9d --- /dev/null +++ b/test/command_callback/test_haskell_hlint_command_callbacks.vader @@ -0,0 +1,17 @@ +Before: + call ale#assert#SetUpLinterTest('haskell', 'hlint') + + let b:base_opts = '--color=never --json -' + +After: + unlet! b:base_opts + call ale#assert#TearDownLinterTest() + +Execute(executable should be configurable): + AssertLinter 'hlint', ale#Escape('hlint') . ' ' . b:base_opts + let b:ale_haskell_hlint_executable = 'myHlint' + AssertLinter 'myHlint', ale#Escape('myHlint') . ' ' . b:base_opts + +Execute(should accept options): + let b:ale_haskell_hlint_options= '-h myhlintfile.yaml' + AssertLinter 'hlint', ale#Escape('hlint') . ' -h myhlintfile.yaml ' . b:base_opts diff --git a/test/command_callback/test_haskell_stack_build_command_callback.vader b/test/command_callback/test_haskell_stack_build_command_callback.vader new file mode 100644 index 00000000..f1e6f755 --- /dev/null +++ b/test/command_callback/test_haskell_stack_build_command_callback.vader @@ -0,0 +1,13 @@ +Before: + call ale#assert#SetUpLinterTest('haskell', 'stack_build') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The linter should not be executed when there's no stack.yaml file): + AssertLinterNotExecuted + +Execute(The linter should be executed when there is a stack.yaml file): + call ale#test#SetFilename('stack_build_paths/test.hs') + + AssertLinter 'stack', 'stack build --fast' diff --git a/test/command_callback/test_haskell_stack_ghc_command_callback.vader b/test/command_callback/test_haskell_stack_ghc_command_callback.vader new file mode 100644 index 00000000..4adab583 --- /dev/null +++ b/test/command_callback/test_haskell_stack_ghc_command_callback.vader @@ -0,0 +1,14 @@ +Before: + call ale#assert#SetUpLinterTest('haskell', 'stack_ghc') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The linter should not be executed when there's no stack.yaml file): + AssertLinterNotExecuted + +Execute(The linter should be executed when there is a stack.yaml file): + call ale#test#SetFilename('stack_ghc_paths/test.hs') + + AssertLinter 'stack', 'stack ghc -- -fno-code -v0 %t' + diff --git a/test/command_callback/test_html_stylelint_command_callback.vader b/test/command_callback/test_html_stylelint_command_callback.vader new file mode 100644 index 00000000..49d7d143 --- /dev/null +++ b/test/command_callback/test_html_stylelint_command_callback.vader @@ -0,0 +1,60 @@ +Before: + Save g:ale_html_stylelint_executable + Save g:ale_html_stylelint_use_global + Save g:ale_html_stylelint_options + + unlet! b:executable + + unlet! g:ale_html_stylelint_executable + unlet! g:ale_html_stylelint_use_global + unlet! g:ale_html_stylelint_options + + call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#test#SetFilename('testfile.html') + + runtime ale_linters/html/stylelint.vim + +After: + Restore + + unlet! b:executable + unlet! b:ale_html_stylelint_executable + unlet! b:ale_html_stylelint_use_global + unlet! b:ale_html_stylelint_options + + call ale#test#SetFilename('test.txt') + + call ale#test#RestoreDirectory() + call ale#linter#Reset() + +Execute(node_modules directories should be discovered): + call ale#test#SetFilename('stylelint_paths/nested/testfile.html') + + let b:executable = ale#path#Simplify( + \ g:dir + \ . '/stylelint_paths/node_modules/.bin/stylelint' + \) + + AssertEqual b:executable, ale_linters#html#stylelint#GetExecutable(bufnr('')) + AssertEqual + \ ale#Escape(b:executable) . ' --stdin-filename %s', + \ ale_linters#html#stylelint#GetCommand(bufnr('')) + +Execute(The global override should work): + let b:ale_html_stylelint_executable = 'foobar' + let b:ale_html_stylelint_use_global = 1 + + call ale#test#SetFilename('stylelint_paths/nested/testfile.html') + + AssertEqual 'foobar', ale_linters#html#stylelint#GetExecutable(bufnr('')) + AssertEqual + \ ale#Escape('foobar') . ' --stdin-filename %s', + \ ale_linters#html#stylelint#GetCommand(bufnr('')) + +Execute(Extra options should be configurable): + let b:ale_html_stylelint_options = '--whatever' + + AssertEqual 'stylelint', ale_linters#html#stylelint#GetExecutable(bufnr('')) + AssertEqual + \ ale#Escape('stylelint') . ' --whatever --stdin-filename %s', + \ ale_linters#html#stylelint#GetCommand(bufnr('')) diff --git a/test/command_callback/test_ispc_ispc_command_callbacks.vader b/test/command_callback/test_ispc_ispc_command_callbacks.vader new file mode 100644 index 00000000..f1aeb2f8 --- /dev/null +++ b/test/command_callback/test_ispc_ispc_command_callbacks.vader @@ -0,0 +1,20 @@ +Before: + call ale#assert#SetUpLinterTest('ispc', 'ispc') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The executable should be configurable): + AssertLinter 'ispc', + \ ale#Escape('ispc') . ' --nowrap %s' + + let b:ale_ispc_ispc_executable = 'foo' + + AssertLinter 'foo', + \ ale#Escape('foo') . ' --nowrap %s' + +Execute(The options should be configurable): + let g:ale_ispc_ispc_options = '--foo' + + AssertLinter 'ispc', + \ ale#Escape('ispc') . ' --nowrap --foo' . ' %s' diff --git a/test/command_callback/test_javac_command_callback.vader b/test/command_callback/test_javac_command_callback.vader index 07a0794a..2dcb6a1b 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 = 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + let g:prefix = ale#path#CdString(expand('%:p:h')) \ . ale#Escape('javac') . ' -Xlint' function! GetCommand(previous_output) abort @@ -43,7 +43,7 @@ Execute(The executable should be configurable): let g:ale_java_javac_executable = 'foobar' AssertLinter 'foobar', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ ale#path#CdString(expand('%:p:h')) \ . ale#Escape('foobar') . ' -Xlint' \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' @@ -106,7 +106,7 @@ Execute(The javac callback should detect source directories): call ale#engine#InitBufferInfo(bufnr('')) AssertLinter 'javac', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' . ale#Escape('javac') . ' -Xlint' + \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' \ . ' -sourcepath ' . ale#Escape( \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/') \ ) @@ -124,7 +124,7 @@ Execute(The javac callback should combine detected source directories and classp \ '/xyz/abc.jar', \] AssertLinter 'javac', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' . ale#Escape('javac') . ' -Xlint' + \ ale#path#CdString(expand('%:p:h')) . 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/') @@ -147,7 +147,7 @@ Execute(The javac callback should include src/test/java for test paths): call ale#engine#InitBufferInfo(bufnr('')) AssertLinter 'javac', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' . ale#Escape('javac') . ' -Xlint' + \ ale#path#CdString(expand('%:p:h')) . 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/'), @@ -160,7 +160,7 @@ Execute(The javac callback should include src/main/jaxb when available): call ale#engine#InitBufferInfo(bufnr('')) AssertLinter 'javac', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' . ale#Escape('javac') . ' -Xlint' + \ ale#path#CdString(expand('%:p:h')) . 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/'), diff --git a/test/command_callback/test_javalsp_command_callback.vader b/test/command_callback/test_javalsp_command_callback.vader new file mode 100644 index 00000000..1fbfddfb --- /dev/null +++ b/test/command_callback/test_javalsp_command_callback.vader @@ -0,0 +1,10 @@ + +Before: + call ale#assert#SetUpLinterTest('java', 'javalsp') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The javalsp callback should return the correct default value): + AssertLinter 'java', ale#Escape('java -cp javacs.jar -Xverify:none org.javacs.Main') + diff --git a/test/command_callback/test_javascript_tsserver_command_callback.vader b/test/command_callback/test_javascript_tsserver_command_callback.vader new file mode 100644 index 00000000..638dd873 --- /dev/null +++ b/test/command_callback/test_javascript_tsserver_command_callback.vader @@ -0,0 +1,8 @@ +Before: + call ale#assert#SetUpLinterTest('javascript', 'tsserver') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'tsserver', ale#Escape('tsserver') diff --git a/test/command_callback/test_jshint_command_callback.vader b/test/command_callback/test_jshint_command_callback.vader new file mode 100644 index 00000000..517c957c --- /dev/null +++ b/test/command_callback/test_jshint_command_callback.vader @@ -0,0 +1,17 @@ +Before: + Save g:ale_jshint_config_loc + + unlet! g:ale_jshint_config_loc + + call ale#assert#SetUpLinterTest('javascript', 'jshint') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'jshint', ale#Escape('jshint') . ' --reporter unix --extract auto --filename %s -' + +Execute(Setting a config location should add the config parameter): + let g:ale_jshint_config_loc = '/some/file' + + AssertLinter 'jshint', ale#Escape('jshint') . ' --reporter unix --extract auto --config ' . ale#Escape('/some/file') . ' --filename %s -' diff --git a/test/command_callback/test_julia_languageserver_callbacks.vader b/test/command_callback/test_julia_languageserver_callbacks.vader new file mode 100644 index 00000000..3bc46e3d --- /dev/null +++ b/test/command_callback/test_julia_languageserver_callbacks.vader @@ -0,0 +1,30 @@ +Before: + Save g:ale_julia_executable + + call ale#assert#SetUpLinterTest('julia', 'languageserver') + +After: + Restore + + call ale#assert#TearDownLinterTest() + +Execute(The default executable path should be correct): + AssertLinter 'julia', + \ ale#Escape('julia') . + \' --startup-file=no --history-file=no -e ' . + \ ale#Escape('using LanguageServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, false); server.runlinter = true; run(server);') + +Execute(The executable should be configurable): + let g:ale_julia_executable = 'julia-new' + + AssertLinter 'julia-new', + \ ale#Escape('julia-new') . + \' --startup-file=no --history-file=no -e ' . + \ ale#Escape('using LanguageServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, false); server.runlinter = true; run(server);') + +Execute(The project root should be detected correctly): + AssertLSPProject '' + + call ale#test#SetFilename('julia-languageserver-project/test.jl') + + AssertLSPProject ale#path#Simplify(g:dir . '/julia-languageserver-project') diff --git a/test/command_callback/test_kotlin_languageserver_command_callback.vader b/test/command_callback/test_kotlin_languageserver_command_callback.vader new file mode 100644 index 00000000..e83a4f37 --- /dev/null +++ b/test/command_callback/test_kotlin_languageserver_command_callback.vader @@ -0,0 +1,8 @@ +Before: + call ale#assert#SetUpLinterTest('kotlin', 'languageserver') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'kotlin-language-server', ale#Escape('kotlin-language-server') diff --git a/test/command_callback/test_lintr_command_callback.vader b/test/command_callback/test_lintr_command_callback.vader index 8a0e6c1c..187d3875 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', - \ 'cd ' . ale#Escape(getcwd()) . ' && ' + \ ale#path#CdString(getcwd()) \ . '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', - \ 'cd ' . ale#Escape(getcwd()) . ' && ' + \ ale#path#CdString(getcwd()) \ . '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', - \ 'cd ' . ale#Escape(getcwd()) . ' && ' + \ ale#path#CdString(getcwd()) \ . 'Rscript --vanilla -e ' \ . ale#Escape('suppressPackageStartupMessages(library(lintr));' \ . 'lint_package(cache = FALSE, ' diff --git a/test/command_callback/test_luac_command_callback.vader b/test/command_callback/test_luac_command_callback.vader index 8a2345ec..55f39cba 100644 --- a/test/command_callback/test_luac_command_callback.vader +++ b/test/command_callback/test_luac_command_callback.vader @@ -5,9 +5,9 @@ After: call ale#assert#TearDownLinterTest() Execute(The default command should be correct): - AssertLinter 'luac', ale#Escape('luac') . ' -p - ' + AssertLinter 'luac', ale#Escape('luac') . ' -p -' Execute(The luac executable should be configurable): let g:ale_lua_luac_executable = 'luac.sh' - AssertLinter 'luac.sh', ale#Escape('luac.sh') . ' -p - ' + AssertLinter 'luac.sh', ale#Escape('luac.sh') . ' -p -' diff --git a/test/command_callback/test_luacheck_command_callback.vader b/test/command_callback/test_luacheck_command_callback.vader index 58d0cdc0..f0ef221c 100644 --- a/test/command_callback/test_luacheck_command_callback.vader +++ b/test/command_callback/test_luacheck_command_callback.vader @@ -6,7 +6,7 @@ After: Execute(The lua luacheck command callback should return the correct default string): AssertLinter 'luacheck', - \ ale#Escape('luacheck') . ' --formatter plain --codes --filename %s -' + \ ale#Escape('luacheck') . ' --formatter plain --codes --filename %s -' Execute(The lua luacheck command callback should let you set options): let g:ale_lua_luacheck_options = '--config filename' @@ -20,4 +20,4 @@ Execute(The luacheck executable should be configurable): let g:ale_lua_luacheck_executable = 'luacheck.sh' AssertLinter 'luacheck.sh', - \ ale#Escape('luacheck.sh') . ' --formatter plain --codes --filename %s -' + \ ale#Escape('luacheck.sh') . ' --formatter plain --codes --filename %s -' diff --git a/test/command_callback/test_mercury_mmc_command_callback.vader b/test/command_callback/test_mercury_mmc_command_callback.vader index 2948e799..ab61fddf 100644 --- a/test/command_callback/test_mercury_mmc_command_callback.vader +++ b/test/command_callback/test_mercury_mmc_command_callback.vader @@ -8,18 +8,18 @@ After: Execute(The default command should be correct): AssertLinter 'mmc', \ ale#path#BufferCdString(bufnr('')) - \ . 'mmc --errorcheck-only --make --output-compile-error-lines 100 dummy' + \ . ale#Escape('mmc') . ' --errorcheck-only --make --output-compile-error-lines 100 dummy' Execute(The executable should be configurable): let b:ale_mercury_mmc_executable = 'foo' AssertLinter 'foo', \ ale#path#BufferCdString(bufnr('')) - \ . 'foo --errorcheck-only --make --output-compile-error-lines 100 dummy' + \ . ale#Escape('foo') . ' --errorcheck-only --make --output-compile-error-lines 100 dummy' Execute(The options should be configurable): let b:ale_mercury_mmc_options = '--bar' AssertLinter 'mmc', \ ale#path#BufferCdString(bufnr('')) - \ . 'mmc --errorcheck-only --bar dummy' + \ . ale#Escape('mmc') . ' --errorcheck-only --bar dummy' diff --git a/test/command_callback/test_mypy_command_callback.vader b/test/command_callback/test_mypy_command_callback.vader index 988dfb1b..8ca35207 100644 --- a/test/command_callback/test_mypy_command_callback.vader +++ b/test/command_callback/test_mypy_command_callback.vader @@ -12,7 +12,7 @@ After: Execute(The mypy callbacks should return the correct default values): AssertLinter 'mypy', - \ 'cd ' . ale#Escape(g:dir) . ' && ' . ale#Escape('mypy') + \ ale#path#CdString(g:dir) . ale#Escape('mypy') \ . ' --show-column-numbers ' \ . '--shadow-file %s %t %s' @@ -20,7 +20,7 @@ Execute(The mypy executable should be configurable, and escaped properly): let g:ale_python_mypy_executable = 'executable with spaces' AssertLinter 'executable with spaces', - \ 'cd ' . ale#Escape(g:dir) . ' && ' . ale#Escape('executable with spaces') + \ ale#path#CdString(g:dir) . ale#Escape('executable with spaces') \ . ' --show-column-numbers ' \ . '--shadow-file %s %t %s' @@ -28,7 +28,7 @@ Execute(The mypy command callback should let you set options): let g:ale_python_mypy_options = '--some-option' AssertLinter 'mypy', - \ 'cd ' . ale#Escape(g:dir) . ' && ' . ale#Escape('mypy') + \ ale#path#CdString(g:dir) . ale#Escape('mypy') \ . ' --show-column-numbers --some-option ' \ . '--shadow-file %s %t %s' @@ -36,8 +36,8 @@ Execute(The mypy command should switch directories to the detected project root) silent execute 'file ' . fnameescape(g:dir . '/python_paths/no_virtualenv/subdir/foo/bar.py') AssertLinter 'mypy', - \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/no_virtualenv/subdir')) - \ . ' && ' . ale#Escape('mypy') + \ ale#path#CdString(ale#path#Simplify(g:dir . '/python_paths/no_virtualenv/subdir')) + \ . ale#Escape('mypy') \ . ' --show-column-numbers ' \ . '--shadow-file %s %t %s' @@ -47,8 +47,8 @@ Execute(The mypy callbacks should detect virtualenv directories and switch to th let b:executable = ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/mypy') AssertLinter b:executable, - \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/subdir')) - \ . ' && ' . ale#Escape(b:executable) + \ ale#path#CdString(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/subdir')) + \ . ale#Escape(b:executable) \ . ' --show-column-numbers ' \ . '--shadow-file %s %t %s' @@ -57,8 +57,8 @@ Execute(You should able able to use the global mypy instead): let g:ale_python_mypy_use_global = 1 AssertLinter 'mypy', - \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/subdir')) - \ . ' && ' . ale#Escape('mypy') + \ ale#path#CdString(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/subdir')) + \ . ale#Escape('mypy') \ . ' --show-column-numbers ' \ . '--shadow-file %s %t %s' @@ -69,3 +69,11 @@ Execute(Setting executable to 'pipenv' appends 'run mypy'): \ ale#path#BufferCdString(bufnr('')) \ . 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') + + AssertLinter 'pipenv', + \ ale#path#BufferCdString(bufnr('')) + \ . 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 4e0cf608..8e077306 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' + \ ' -X gnu -I ' . ale#Escape(getcwd() . (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' + \ ' -X gnu -I ' . ale#Escape(getcwd() . (has('win32') ? '\' : '/')) . ' -w+orphan-labels %s -o ' . (has('win32') ? 'NUL' : '/dev/null') After: unlet! b:command_tail @@ -23,7 +23,7 @@ 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' + \ . ' -X gnu -I ' . ale#Escape(getcwd() . (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_objc_ccls_command_callbacks.vader b/test/command_callback/test_objc_ccls_command_callbacks.vader new file mode 100644 index 00000000..9d0c7690 --- /dev/null +++ b/test/command_callback/test_objc_ccls_command_callbacks.vader @@ -0,0 +1,40 @@ +Before: + call ale#assert#SetUpLinterTest('objc', 'ccls') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The project root should be detected correctly using compile_commands.json file): + AssertLSPProject '' + + call ale#test#SetFilename('ccls_paths/with_compile_commands_json/dummy.m') + + AssertLSPProject ale#path#Simplify(g:dir . '/ccls_paths/with_compile_commands_json') + +Execute(The project root should be detected correctly using .ccls file): + AssertLSPProject '' + + call ale#test#SetFilename('ccls_paths/with_ccls/dummy.m') + + AssertLSPProject ale#path#Simplify(g:dir . '/ccls_paths/with_ccls') + +Execute(The project root should be detected correctly using .ccls-root file): + AssertLSPProject '' + + call ale#test#SetFilename('ccls_paths/with_ccls-root/dummy.m') + + AssertLSPProject ale#path#Simplify(g:dir . '/ccls_paths/with_ccls-root') + +Execute(The executable should be configurable): + AssertLinter 'ccls', ale#Escape('ccls') + + let b:ale_objc_ccls_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') + +Execute(The initialization options should be configurable): + AssertLSPOptions {} + + let b:ale_objc_ccls_init_options = { 'cacheDirectory': '/tmp/ccls' } + + AssertLSPOptions { 'cacheDirectory': '/tmp/ccls' } diff --git a/test/command_callback/test_perl6_command_callback.vader b/test/command_callback/test_perl6_command_callback.vader new file mode 100644 index 00000000..d3ec6e17 --- /dev/null +++ b/test/command_callback/test_perl6_command_callback.vader @@ -0,0 +1,14 @@ +Before: + call ale#assert#SetUpLinterTest('perl6', 'perl6') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default Perl6 command callback should be correct): + AssertLinter 'perl6', 'perl6' . ' -c -Ilib %t' + +Execute(Overriding the executable and command should work): + let b:ale_perl6_perl6_executable = 'foobar' + let b:ale_perl6_perl6_options = '-w' + + AssertLinter 'foobar', 'foobar' . ' -w %t' diff --git a/test/command_callback/test_php_command_callback.vader b/test/command_callback/test_php_command_callback.vader new file mode 100644 index 00000000..670d7196 --- /dev/null +++ b/test/command_callback/test_php_command_callback.vader @@ -0,0 +1,15 @@ +Before: + call ale#assert#SetUpLinterTest('php', 'php') + let b:command_tail = ' -l -d error_reporting=E_ALL -d display_errors=1' + \ . ' -d log_errors=0 --' + +After: + unlet! b:command_tail + call ale#assert#TearDownLinterTest() + +Execute(The executable should be configurable): + AssertLinter 'php', ale#Escape('php') . b:command_tail + + let b:ale_php_php_executable = '/path/to/php' + + AssertLinter '/path/to/php', ale#Escape('/path/to/php') . b:command_tail diff --git a/test/command_callback/test_phpcs_command_callback.vader b/test/command_callback/test_phpcs_command_callback.vader new file mode 100644 index 00000000..e5d2f449 --- /dev/null +++ b/test/command_callback/test_phpcs_command_callback.vader @@ -0,0 +1,35 @@ +Before: + call ale#assert#SetUpLinterTest('php', 'phpcs') + +After: + unlet! g:executable + + call ale#assert#TearDownLinterTest() + +Execute(The local phpcs executable should be used): + call ale#test#SetFilename('../phpcs-test-files/project-with-phpcs/foo/test.php') + + let g:executable = ale#path#Simplify(g:dir . '/../phpcs-test-files/project-with-phpcs/vendor/bin/phpcs') + + AssertLinter g:executable, + \ ale#Escape(g:executable) . ' -s --report=emacs --stdin-path=%s' + +Execute(use_global should override local executable detection): + let g:ale_php_phpcs_use_global = 1 + + call ale#test#SetFilename('../phpcs-test-files/project-with-phpcs/foo/test.php') + + AssertLinter 'phpcs', + \ ale#Escape('phpcs') . ' -s --report=emacs --stdin-path=%s' + +Execute(Projects without local executables should use the global one): + call ale#test#SetFilename('../phpcs-test-files/project-without-phpcs/foo/test.php') + + AssertLinter 'phpcs', + \ ale#Escape('phpcs') . ' -s --report=emacs --stdin-path=%s' + +Execute(User provided options are used): + let g:ale_php_phpcs_options = '--my-user-provided-option my-value' + + AssertLinter 'phpcs', + \ ale#Escape('phpcs') . ' -s --report=emacs --stdin-path=%s --my-user-provided-option my-value' diff --git a/test/command_callback/test_phpstan_command_callbacks.vader b/test/command_callback/test_phpstan_command_callbacks.vader index c7db587a..665661a3 100644 --- a/test/command_callback/test_phpstan_command_callbacks.vader +++ b/test/command_callback/test_phpstan_command_callbacks.vader @@ -1,6 +1,8 @@ Before: call ale#assert#SetUpLinterTest('php', 'phpstan') + WithChainResults ['0.10.2'] + After: call ale#assert#TearDownLinterTest() @@ -22,3 +24,11 @@ Execute(Custom phpstan configuration file): AssertLinter 'phpstan', \ ale#Escape('phpstan') . ' analyze -l4 --errorFormat raw -c phpstan_config %s' + +Execute(Choose the right format for error format param): + WithChainResults ['0.10.3'] + + AssertLinter 'phpstan', [ + \ ale#Escape('phpstan') . ' --version', + \ ale#Escape('phpstan') . ' analyze -l4 --error-format raw %s' + \ ] diff --git a/test/command_callback/test_prospector_command_callback.vader b/test/command_callback/test_prospector_command_callback.vader index 316b9883..0d692bde 100644 --- a/test/command_callback/test_prospector_command_callback.vader +++ b/test/command_callback/test_prospector_command_callback.vader @@ -10,3 +10,11 @@ Execute(Setting executable to 'pipenv' appends 'run prospector'): AssertLinter 'path/to/pipenv', \ ale#Escape('path/to/pipenv') . ' run prospector' \ . ' --messages-only --absolute-paths --zero-exit --output-format json %s' + +Execute(Pipenv is detected when python_prospector_auto_pipenv is set): + let g:ale_python_prospector_auto_pipenv = 1 + call ale#test#SetFilename('/testplugin/test/python_fixtures/pipenv/whatever.py') + + AssertLinter 'pipenv', + \ ale#Escape('pipenv') . ' run prospector' + \ . ' --messages-only --absolute-paths --zero-exit --output-format json %s' diff --git a/test/command_callback/test_psalm_command_callbacks.vader b/test/command_callback/test_psalm_command_callbacks.vader new file mode 100644 index 00000000..d731054f --- /dev/null +++ b/test/command_callback/test_psalm_command_callbacks.vader @@ -0,0 +1,29 @@ +Before: + call ale#assert#SetUpLinterTest('php', 'psalm') + +After: + if isdirectory(g:dir . '/.git') + call delete(g:dir . '/.git', 'd') + endif + + call ale#assert#TearDownLinterTest() + +Execute(The default executable path should be correct): + AssertLinter 'psalm-language-server', + \ ale#Escape('psalm-language-server') + +Execute(Vendor executables should be detected): + call ale#test#SetFilename('psalm-project/test.php') + + AssertLinter + \ ale#path#Simplify(g:dir . '/psalm-project/vendor/bin/psalm-language-server'), + \ ale#Escape(ale#path#Simplify( + \ g:dir + \ . '/psalm-project/vendor/bin/psalm-language-server' + \ )) + +Execute(The project path should be correct for .git directories): + call ale#test#SetFilename('psalm-project/test.php') + call mkdir(g:dir . '/.git') + + AssertLSPProject g:dir
\ No newline at end of file diff --git a/test/command_callback/test_pycodestyle_command_callback.vader b/test/command_callback/test_pycodestyle_command_callback.vader index 851eede9..a3a338a9 100644 --- a/test/command_callback/test_pycodestyle_command_callback.vader +++ b/test/command_callback/test_pycodestyle_command_callback.vader @@ -24,3 +24,10 @@ Execute(Setting executable to 'pipenv' appends 'run pycodestyle'): AssertLinter 'path/to/pipenv', \ ale#Escape('path/to/pipenv') . ' run pycodestyle -' + +Execute(Pipenv is detected when python_pycodestyle_auto_pipenv is set): + let g:ale_python_pycodestyle_auto_pipenv = 1 + call ale#test#SetFilename('/testplugin/test/python_fixtures/pipenv/whatever.py') + + AssertLinter 'pipenv', + \ ale#Escape('pipenv') . ' run pycodestyle -' diff --git a/test/command_callback/test_pyflakes_command_callback.vader b/test/command_callback/test_pyflakes_command_callback.vader index efc925fe..92f83820 100644 --- a/test/command_callback/test_pyflakes_command_callback.vader +++ b/test/command_callback/test_pyflakes_command_callback.vader @@ -37,3 +37,10 @@ Execute(Setting executable to 'pipenv' appends 'run pyflakes'): AssertLinter 'path/to/pipenv', \ ale#Escape('path/to/pipenv') . ' run pyflakes %t', + +Execute(Pipenv is detected when python_pyflakes_auto_pipenv is set): + let g:ale_python_pyflakes_auto_pipenv = 1 + call ale#test#SetFilename('/testplugin/test/python_fixtures/pipenv/whatever.py') + + AssertLinter 'pipenv', + \ ale#Escape('pipenv') . ' run pyflakes %t' diff --git a/test/command_callback/test_pylint_command_callback.vader b/test/command_callback/test_pylint_command_callback.vader index be2908f9..6b21b127 100644 --- a/test/command_callback/test_pylint_command_callback.vader +++ b/test/command_callback/test_pylint_command_callback.vader @@ -68,3 +68,12 @@ Execute(Setting executable to 'pipenv' appends 'run pylint'): \ ale#path#BufferCdString(bufnr('')) \ . 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') + + AssertLinter 'pipenv', + \ ale#path#BufferCdString(bufnr('')) + \ . 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_pyls_command_callback.vader b/test/command_callback/test_pyls_command_callback.vader index 53bf3000..531b5b3b 100644 --- a/test/command_callback/test_pyls_command_callback.vader +++ b/test/command_callback/test_pyls_command_callback.vader @@ -38,3 +38,10 @@ Execute(Setting executable to 'pipenv' appends 'run pyls'): let g:ale_python_pyls_executable = 'path/to/pipenv' AssertLinter 'path/to/pipenv', ale#Escape('path/to/pipenv') . ' run pyls' + +Execute(Pipenv is detected when python_pyls_auto_pipenv is set): + let g:ale_python_pyls_auto_pipenv = 1 + call ale#test#SetFilename('/testplugin/test/python_fixtures/pipenv/whatever.py') + + AssertLinter 'pipenv', + \ ale#Escape('pipenv') . ' run pyls' diff --git a/test/command_callback/test_pyre_command_callback.vader b/test/command_callback/test_pyre_command_callback.vader index 6ad19b56..ba57c117 100644 --- a/test/command_callback/test_pyre_command_callback.vader +++ b/test/command_callback/test_pyre_command_callback.vader @@ -37,3 +37,10 @@ Execute(Setting executable to 'pipenv' appends 'run pyre'): AssertLinter 'path/to/pipenv', \ ale#Escape('path/to/pipenv') . ' run pyre persistent' + +Execute(Pipenv is detected when python_pyre_auto_pipenv is set): + let g:ale_python_pyre_auto_pipenv = 1 + call ale#test#SetFilename('/testplugin/test/python_fixtures/pipenv/whatever.py') + + AssertLinter 'pipenv', + \ ale#Escape('pipenv') . ' run pyre persistent' diff --git a/test/command_callback/test_reek_command_callback.vader b/test/command_callback/test_reek_command_callback.vader index 059e5e36..a7cb7fb9 100644 --- a/test/command_callback/test_reek_command_callback.vader +++ b/test/command_callback/test_reek_command_callback.vader @@ -7,8 +7,8 @@ After: Execute(The reek callbacks should return the correct default values): WithChainResults ['reek 5.0.0'] AssertLinter 'reek', [ - \ 'reek --version', - \ 'reek -f json --no-progress --no-color --stdin-filename %s', + \ ale#Escape('reek') . ' --version', + \ ale#Escape('reek') . ' -f json --no-progress --no-color --force-exclusion --stdin-filename %s', \] " Try with older versions. @@ -16,19 +16,35 @@ Execute(The reek callbacks should return the correct default values): WithChainResults ['reek 4.8.2'] AssertLinter 'reek', [ - \ 'reek --version', - \ 'reek -f json --no-progress --no-color', + \ ale#Escape('reek') . ' --version', + \ ale#Escape('reek') . ' -f json --no-progress --no-color --force-exclusion', \] +Execute(Setting bundle appends 'exec reek'): + let g:ale_ruby_reek_executable = 'bundle' + + WithChainResults ['reek 5.0.0'] + AssertLinter 'bundle', ale#Escape('bundle') + \ . ' exec reek' + \ . ' -f json --no-progress --no-color --force-exclusion --stdin-filename %s', + + " Try with older versions. + call ale#semver#ResetVersionCache() + + WithChainResults ['reek 4.8.2'] + AssertLinter 'bundle', ale#Escape('bundle') + \ . ' exec reek' + \ . ' -f json --no-progress --no-color --force-exclusion' + Execute(The reek version check should be cached): WithChainResults ['reek 5.0.0'] AssertLinter 'reek', [ - \ 'reek --version', - \ 'reek -f json --no-progress --no-color --stdin-filename %s', + \ ale#Escape('reek') . ' --version', + \ ale#Escape('reek') . ' -f json --no-progress --no-color --force-exclusion --stdin-filename %s', \] WithChainResults [] AssertLinter 'reek', [ \ '', - \ 'reek -f json --no-progress --no-color --stdin-filename %s', + \ ale#Escape('reek') . ' -f json --no-progress --no-color --force-exclusion --stdin-filename %s', \] diff --git a/test/command_callback/test_ruby_solargraph.vader b/test/command_callback/test_ruby_solargraph.vader new file mode 100644 index 00000000..c6aee271 --- /dev/null +++ b/test/command_callback/test_ruby_solargraph.vader @@ -0,0 +1,44 @@ +" Author: Horacio Sanson <https://github.com/hsanson> +" Description: Tests for solargraph lsp linter. + +Before: + call ale#assert#SetUpLinterTest('ruby', 'solargraph') + +After: + call ale#assert#TearDownLinterTest() + +Execute(command callback should return default string): + AssertLinter 'solargraph', ale#Escape('solargraph') . ' stdio' + +Execute(command callback executable can be overridden): + let g:ale_ruby_solargraph_executable = 'foobar' + AssertLinter 'foobar', ale#Escape('foobar') . ' stdio' + +Execute(should set solargraph for rails app): + call ale#test#SetFilename('../ruby_fixtures/valid_rails_app/app/models/thing.rb') + AssertLSPLanguage 'ruby' + AssertLSPOptions {} + AssertLSPProject ale#path#Simplify(g:dir . 'command_callback/../ruby_fixtures/valid_rails_app') + +Execute(should set solargraph for ruby app1): + call ale#test#SetFilename('../ruby_fixtures/valid_ruby_app1/lib/file.rb') + AssertLSPLanguage 'ruby' + AssertLSPOptions {} + AssertLSPProject ale#path#Simplify(g:dir . 'command_callback/../ruby_fixtures/valid_ruby_app1') + +Execute(should set solargraph for ruby app2): + call ale#test#SetFilename('../ruby_fixtures/valid_ruby_app2/lib/file.rb') + AssertLSPLanguage 'ruby' + AssertLSPOptions {} + AssertLSPProject ale#path#Simplify(g:dir . 'command_callback/../ruby_fixtures/valid_ruby_app2') + +Execute(should set solargraph for ruby app3): + call ale#test#SetFilename('../ruby_fixtures/valid_ruby_app3/lib/file.rb') + AssertLSPLanguage 'ruby' + AssertLSPOptions {} + AssertLSPProject ale#path#Simplify(g:dir . 'command_callback/../ruby_fixtures/valid_ruby_app3') + +Execute(should accept initialization options): + AssertLSPOptions {} + let b:ale_ruby_solargraph_options = { 'diagnostics': 'true' } + AssertLSPOptions { 'diagnostics': 'true' } diff --git a/test/command_callback/test_rustc_command_callback.vader b/test/command_callback/test_rustc_command_callback.vader index 7ca02760..f765e725 100644 --- a/test/command_callback/test_rustc_command_callback.vader +++ b/test/command_callback/test_rustc_command_callback.vader @@ -5,7 +5,7 @@ After: call ale#assert#TearDownLinterTest() Execute(The default command should be correct): - AssertLinter 'rustc', 'rustc --error-format=json -Z no-trans -' + AssertLinter 'rustc', 'rustc --error-format=json -Z no-codegen -' Execute(The options should be configurable): let b:ale_rust_rustc_options = '--foo' @@ -15,7 +15,7 @@ Execute(The options should be configurable): Execute(Some default paths should be included when the project is a Cargo project): call ale#test#SetFilename('cargo_paths/test.rs') - AssertLinter 'rustc', 'rustc --error-format=json -Z no-trans' + AssertLinter 'rustc', 'rustc --error-format=json -Z no-codegen' \ . ' -L ' . ale#Escape(ale#path#GetAbsPath(g:dir, 'cargo_paths/target/debug/deps')) \ . ' -L ' . ale#Escape(ale#path#GetAbsPath(g:dir, 'cargo_paths/target/release/deps')) \ . ' -' diff --git a/test/command_callback/test_ruumba_command_callback.vader b/test/command_callback/test_ruumba_command_callback.vader new file mode 100644 index 00000000..244b264a --- /dev/null +++ b/test/command_callback/test_ruumba_command_callback.vader @@ -0,0 +1,29 @@ +Before: + call ale#assert#SetUpLinterTest('eruby', 'ruumba') + call ale#test#SetFilename('dummy.html.erb') + + let g:ale_eruby_ruumba_executable = 'ruumba' + let g:ale_eruby_ruumba_options = '' + +After: + call ale#assert#TearDownLinterTest() + +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')) + +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')) + +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')) diff --git a/test/command_callback/test_sasslint_command_callback.vader b/test/command_callback/test_sasslint_command_callback.vader index 4d7cc4c7..9142c441 100644 --- a/test/command_callback/test_sasslint_command_callback.vader +++ b/test/command_callback/test_sasslint_command_callback.vader @@ -7,5 +7,5 @@ After: Execute(The default sasslint command should be correct): AssertLinter 'sass-lint', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ ale#path#CdString(expand('%:p:h')) \ . ale#Escape('sass-lint') . ' -v -q -f compact %t' diff --git a/test/command_callback/test_scala_sbtserver.vader b/test/command_callback/test_scala_sbtserver.vader new file mode 100644 index 00000000..1c7d8472 --- /dev/null +++ b/test/command_callback/test_scala_sbtserver.vader @@ -0,0 +1,21 @@ +" Author: ophirr33 <coghlan.ty@gmail.com> +" Description: Tests for the sbt Server lsp linter + +Before: + call ale#assert#SetUpLinterTest('scala', 'sbtserver') +After: + call ale#assert#TearDownLinterTest() +Execute(should set sbtserver for sbt project with build.sbt): + call ale#test#SetFilename('../scala_fixtures/valid_sbt_project/Main.scala') + AssertLSPLanguage 'scala' + AssertLSPOptions {} + AssertLSPConfig {} + AssertLSPProject ale#path#Simplify(g:dir . 'command_callback/../scala_fixtures/valid_sbt_project') + AssertLSPAddress '127.0.0.1:4273' +Execute(should not set sbtserver for sbt project without build.sbt): + call ale#test#SetFilename('../scala_fixtures/invalid_sbt_project/Main.scala') + AssertLSPLanguage 'scala' + AssertLSPOptions {} + AssertLSPConfig {} + AssertLSPProject '' + AssertLSPAddress '127.0.0.1:4273' diff --git a/test/command_callback/test_scalac_command_callback.vader b/test/command_callback/test_scalac_command_callback.vader index 115731b3..5184aa0b 100644 --- a/test/command_callback/test_scalac_command_callback.vader +++ b/test/command_callback/test_scalac_command_callback.vader @@ -6,8 +6,8 @@ After: Given scala(An empty Scala file): Execute(The default executable and command should be correct): - AssertLinter 'scalac', ale#Escape('scalac') . ' -Ystop-after:parser %t' + AssertLinter 'scalac', ale#Escape('scalac') . ' -Ystop-before:jvm %t' Given scala.sbt(An empty SBT file): Execute(scalac should not be run for sbt files): - AssertLinter '', '' + AssertLinterNotExecuted diff --git a/test/command_callback/test_scss_stylelint_command_callback.vader b/test/command_callback/test_scss_stylelint_command_callback.vader new file mode 100644 index 00000000..9c3a02d8 --- /dev/null +++ b/test/command_callback/test_scss_stylelint_command_callback.vader @@ -0,0 +1,31 @@ +Before: + call ale#assert#SetUpLinterTest('scss', 'stylelint') + unlet! b:executable + +After: + unlet! b:executable + call ale#assert#TearDownLinterTest() + +Execute(node_modules directories should be discovered): + call ale#test#SetFilename('stylelint_paths/nested/testfile.scss') + + let b:executable = ale#path#Simplify( + \ g:dir + \ . '/stylelint_paths/node_modules/.bin/stylelint' + \) + + AssertLinter b:executable, ale#Escape(b:executable) . ' --stdin-filename %s' + +Execute(The global override should work): + let b:ale_scss_stylelint_executable = 'foobar' + let b:ale_scss_stylelint_use_global = 1 + + call ale#test#SetFilename('stylelint_paths/nested/testfile.scss') + + AssertLinter 'foobar', ale#Escape('foobar') . ' --stdin-filename %s' + +Execute(Extra options should be configurable): + let b:ale_scss_stylelint_options = '--configFile ''/absolute/path/to/file''' + + AssertLinter 'stylelint', + \ ale#Escape('stylelint') . ' --configFile ''/absolute/path/to/file'' --stdin-filename %s' diff --git a/test/command_callback/test_shellcheck_command_callback.vader b/test/command_callback/test_shellcheck_command_callback.vader index 23684026..22a9ccb5 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 = 'cd ' . ale#Escape(ale#path#Simplify(g:dir)) . ' && ' + let b:prefix = ale#path#CdString(ale#path#Simplify(g:dir)) let b:suffix = ' -f gcc -' After: diff --git a/test/command_callback/test_staticcheck_command_callback.vader b/test/command_callback/test_staticcheck_command_callback.vader index 918c12a0..7f17b146 100644 --- a/test/command_callback/test_staticcheck_command_callback.vader +++ b/test/command_callback/test_staticcheck_command_callback.vader @@ -7,7 +7,7 @@ After: Execute(The staticcheck callback should return the right defaults): AssertLinter 'staticcheck', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ ale#path#CdString(expand('%:p:h')) \ . 'staticcheck ' \ . ale#Escape(expand('%' . ':t')) @@ -15,7 +15,7 @@ Execute(The staticcheck callback should use configured options): let b:ale_go_staticcheck_options = '-test' AssertLinter 'staticcheck', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ ale#path#CdString(expand('%:p:h')) \ . 'staticcheck ' \ . '-test ' . ale#Escape(expand('%' . ':t')) @@ -23,4 +23,4 @@ Execute(The staticcheck `lint_package` option should use the correct command): let b:ale_go_staticcheck_lint_package = 1 AssertLinter 'staticcheck', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && staticcheck .', + \ ale#path#CdString(expand('%:p:h')) . 'staticcheck .', diff --git a/test/command_callback/test_swaglint_command_callback.vader b/test/command_callback/test_swaglint_command_callback.vader index fe8fb722..68fb1406 100644 --- a/test/command_callback/test_swaglint_command_callback.vader +++ b/test/command_callback/test_swaglint_command_callback.vader @@ -5,25 +5,25 @@ After: call ale#assert#TearDownLinterTest() Execute(The yaml swaglint command callback should return the correct default string): - AssertLinter 'swaglint', 'swaglint -r compact --stdin' + AssertLinter 'swaglint', ale#Escape('swaglint') . ' -r compact --stdin' Execute(The yaml swaglint command callback should be configurable): let g:ale_yaml_swaglint_executable = '~/.local/bin/swaglint' AssertLinter '~/.local/bin/swaglint', - \ '~/.local/bin/swaglint -r compact --stdin' + \ ale#Escape('~/.local/bin/swaglint') . ' -r compact --stdin' Execute(The yaml swaglint command callback should allow a global installation to be used): let g:ale_yaml_swaglint_executable = '/usr/local/bin/swaglint' let g:ale_yaml_swaglint_use_global = 1 AssertLinter '/usr/local/bin/swaglint', - \ '/usr/local/bin/swaglint -r compact --stdin' + \ ale#Escape('/usr/local/bin/swaglint') . ' -r compact --stdin' Execute(The yaml swaglint command callback should allow a local installation to be used): call ale#test#SetFilename('swaglint_paths/docs/swagger.yaml') AssertLinter \ ale#path#Simplify(g:dir . '/swaglint_paths/node_modules/.bin/swaglint'), - \ ale#path#Simplify(g:dir . '/swaglint_paths/node_modules/.bin/swaglint') + \ ale#Escape(ale#path#Simplify(g:dir . '/swaglint_paths/node_modules/.bin/swaglint')) \ . ' -r compact --stdin' diff --git a/test/command_callback/test_terraform_tflint_command_callback.vader b/test/command_callback/test_terraform_tflint_command_callback.vader index c32d9bcf..0cef0176 100644 --- a/test/command_callback/test_terraform_tflint_command_callback.vader +++ b/test/command_callback/test_terraform_tflint_command_callback.vader @@ -17,3 +17,12 @@ Execute(Overriding options should work): let g:ale_terraform_tflint_options = '--whatever' AssertLinter 'fnord', ale#Escape('fnord') . ' --whatever -f json %t' + +Execute(Configuration files should be found): + call ale#test#SetFilename('../tflint-test-files/foo/bar.tf') + + AssertLinter 'tflint', + \ ale#Escape('tflint') + \ . ' --config ' + \ . ale#Escape(ale#path#Simplify(g:dir . '/../tflint-test-files/foo/.tflint.hcl')) + \ . ' -f json %t' diff --git a/test/command_callback/test_thrift_command_callback.vader b/test/command_callback/test_thrift_command_callback.vader index ea217259..cbada818 100644 --- a/test/command_callback/test_thrift_command_callback.vader +++ b/test/command_callback/test_thrift_command_callback.vader @@ -23,22 +23,22 @@ After: call ale#assert#TearDownLinterTest() Execute(The default command should be correct): - AssertLinter 'thrift', ale#Escape('thrift') . ' --gen cpp -strict' . b:suffix + AssertLinter 'thrift', ale#Escape('thrift') . ' --gen cpp -I . -strict' . b:suffix Execute(The executable should be configurable): let b:ale_thrift_thrift_executable = 'foobar' - AssertLinter 'foobar', ale#Escape('foobar') . ' --gen cpp -strict' . b:suffix + AssertLinter 'foobar', ale#Escape('foobar') . ' --gen cpp -I . -strict' . b:suffix Execute(The list of generators should be configurable): let b:ale_thrift_thrift_generators = ['java', 'py:dynamic'] AssertLinter 'thrift', ale#Escape('thrift') - \ . ' --gen java --gen py:dynamic -strict' . b:suffix + \ . ' --gen java --gen py:dynamic -I . -strict' . b:suffix let b:ale_thrift_thrift_generators = [] - AssertLinter 'thrift', ale#Escape('thrift') . ' --gen cpp -strict' . b:suffix + AssertLinter 'thrift', ale#Escape('thrift') . ' --gen cpp -I . -strict' . b:suffix Execute(The list of include paths should be configurable): let b:ale_thrift_thrift_includes = ['included/path'] @@ -50,4 +50,4 @@ Execute(The string of compiler options should be configurable): let b:ale_thrift_thrift_options = '-strict --allow-64bit-consts' AssertLinter 'thrift', ale#Escape('thrift') - \ . ' --gen cpp -strict --allow-64bit-consts' . b:suffix + \ . ' --gen cpp -I . -strict --allow-64bit-consts' . b:suffix diff --git a/test/command_callback/test_tslint_command_callback.vader b/test/command_callback/test_tslint_command_callback.vader index bd8a12ec..229ccc96 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', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ ale#path#CdString(expand('%:p:h')) \ . 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', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ ale#path#CdString(expand('%:p:h')) \ . 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', - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ ale#path#CdString(expand('%:p:h')) \ . ale#Escape('foo bar') . ' --format json %t' diff --git a/test/command_callback/test_typescript_tsserver_command_callback.vader b/test/command_callback/test_typescript_tsserver_command_callback.vader new file mode 100644 index 00000000..719ac184 --- /dev/null +++ b/test/command_callback/test_typescript_tsserver_command_callback.vader @@ -0,0 +1,8 @@ +Before: + call ale#assert#SetUpLinterTest('typescript', 'tsserver') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'tsserver', ale#Escape('tsserver') diff --git a/test/command_callback/test_yang_lsp_command_callbacks.vader b/test/command_callback/test_yang_lsp_command_callbacks.vader new file mode 100644 index 00000000..5be7501f --- /dev/null +++ b/test/command_callback/test_yang_lsp_command_callbacks.vader @@ -0,0 +1,12 @@ +Before: + call ale#assert#SetUpLinterTest('yang', 'yang_lsp') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The executable should be configurable): + AssertLinter 'yang-language-server', ale#Escape('yang-language-server') + + let b:ale_yang_lsp_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') diff --git a/test/completion/test_completion_events.vader b/test/completion/test_completion_events.vader index f3e05950..3f0bfa70 100644 --- a/test/completion/test_completion_events.vader +++ b/test/completion/test_completion_events.vader @@ -129,6 +129,10 @@ Execute(ale#completion#Show() should remember the omnifunc setting and replace i AssertEqual 'FooBar', b:ale_old_omnifunc AssertEqual 'ale#completion#OmniFunc', &l:omnifunc + AssertEqual [], g:feedkeys_calls + sleep 1ms + AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls + Execute(ale#completion#Show() should remember the completeopt setting and replace it): let &l:completeopt = 'menu' @@ -137,6 +141,10 @@ Execute(ale#completion#Show() should remember the completeopt setting and replac AssertEqual 'menu', b:ale_old_completopt AssertEqual 'menu,menuone,noselect,noinsert', &l:completeopt + AssertEqual [], g:feedkeys_calls + sleep 1ms + AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls + Execute(ale#completion#Show() should set the preview option if it's set): let &l:completeopt = 'menu,preview' @@ -145,6 +153,10 @@ Execute(ale#completion#Show() should set the preview option if it's set): AssertEqual 'menu,preview', b:ale_old_completopt AssertEqual 'menu,menuone,preview,noselect,noinsert', &l:completeopt + AssertEqual [], g:feedkeys_calls + sleep 1ms + AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls + Execute(ale#completion#OmniFunc() should also remember the completeopt setting and replace it): let &l:completeopt = 'menu' @@ -164,6 +176,8 @@ Execute(ale#completion#OmniFunc() should set the preview option if it's set): Execute(ale#completion#Show() should make the correct feedkeys() call): call ale#completion#Show('Response', 'Parser') + AssertEqual [], g:feedkeys_calls + sleep 1ms AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls Execute(ale#completion#Show() shouldn't do anything if you switch back to normal mode): diff --git a/test/completion/test_completion_filtering.vader b/test/completion/test_completion_filtering.vader index ae91a952..ffb313ef 100644 --- a/test/completion/test_completion_filtering.vader +++ b/test/completion/test_completion_filtering.vader @@ -12,16 +12,17 @@ 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') AssertEqual \ ['FooBar', 'FongBar', 'baz', 'foo'], - \ ale#completion#Filter(bufnr(''), ['FooBar', 'FongBar', 'baz', 'foo'], '.') + \ ale#completion#Filter(bufnr(''), '', ['FooBar', 'FongBar', 'baz', 'foo'], '.') Execute(Prefix filtering should work for completion items): AssertEqual \ [{'word': 'FooBar'}, {'word': 'foo'}], \ ale#completion#Filter( \ bufnr(''), + \ '', \ [ \ {'word': 'FooBar'}, \ {'word': 'FongBar'}, @@ -40,6 +41,7 @@ Execute(Prefix filtering should work for completion items): \ ], \ ale#completion#Filter( \ bufnr(''), + \ '', \ [ \ {'word': 'FooBar'}, \ {'word': 'FongBar'}, @@ -56,6 +58,7 @@ Execute(Excluding words from completion results should work): \ [{'word': 'Italian'}], \ ale#completion#Filter( \ bufnr(''), + \ '', \ [ \ {'word': 'Italian'}, \ {'word': 'it'}, @@ -67,6 +70,7 @@ Execute(Excluding words from completion results should work): \ [{'word': 'Deutsch'}], \ ale#completion#Filter( \ bufnr(''), + \ '', \ [ \ {'word': 'describe'}, \ {'word': 'Deutsch'}, @@ -78,6 +82,7 @@ Execute(Excluding words from completion results should work): \ [{'word': 'Deutsch'}], \ ale#completion#Filter( \ bufnr(''), + \ '', \ [ \ {'word': 'describe'}, \ {'word': 'Deutsch'}, @@ -90,19 +95,26 @@ 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') AssertEqual \ ['Deutsch'], - \ ale#completion#Filter(bufnr(''), ['describe', 'Deutsch'], 'de') + \ ale#completion#Filter(bufnr(''), '', ['describe', 'Deutsch'], 'de') AssertEqual \ ['Deutsch'], - \ ale#completion#Filter(bufnr(''), ['describe', 'Deutsch'], '.') + \ ale#completion#Filter(bufnr(''), '', ['describe', 'Deutsch'], '.') 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, '.') AssertEqual b:suggestions, [{'word': 'describe'}] - AssertEqual [], ale#completion#Filter(bufnr(''), b:suggestions, 'de') + AssertEqual [], ale#completion#Filter(bufnr(''), '', b:suggestions, 'de') 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, '::') diff --git a/test/completion/test_completion_prefixes.vader b/test/completion/test_completion_prefixes.vader index 0b2cfeaf..3f2cab15 100644 --- a/test/completion/test_completion_prefixes.vader +++ b/test/completion/test_completion_prefixes.vader @@ -43,3 +43,23 @@ Execute(Completion should be done after words in parens in Rust): Execute(Completion should not be done after parens in Rust): AssertEqual '', ale#completion#GetPrefix(&filetype, 3, 15) + +Given lisp(): + (minus-name + (full-name) + +Execute(Completion should be done for function names with minuses in Lisp): + AssertEqual 'minus-name', ale#completion#GetPrefix(&filetype, 1, 12) + +Execute(Completion should not be done after parens in Lisp): + AssertEqual '', ale#completion#GetPrefix(&filetype, 2, 12) + +Given clojure(): + (minus-name + (full-name) + +Execute(Completion should be done for function names with minuses in Clojure): + AssertEqual 'minus-name', ale#completion#GetPrefix(&filetype, 1, 12) + +Execute(Completion should not be done after parens in Clojure): + AssertEqual '', ale#completion#GetPrefix(&filetype, 2, 12) diff --git a/test/completion/test_lsp_completion_messages.vader b/test/completion/test_lsp_completion_messages.vader index ed0f358b..130f31b9 100644 --- a/test/completion/test_lsp_completion_messages.vader +++ b/test/completion/test_lsp_completion_messages.vader @@ -14,17 +14,17 @@ Before: let g:message_list = [] let g:capability_checked = '' + let g:conn_id = v:null let g:Callback = '' let g:wait_callback_list = [] function! ale#lsp_linter#StartLSP(buffer, linter) abort - let l:conn = ale#lsp#NewConnection({}) - let l:conn.id = 347 - let l:conn.open_documents = {a:buffer : -1} + let g:conn_id = ale#lsp#Register('executable', '/foo/bar', {}) + call ale#lsp#MarkDocumentAsOpen(g:conn_id, a:buffer) return { \ 'buffer': a:buffer, - \ 'connection_id': 347, + \ 'connection_id': g:conn_id, \ 'project_root': '/foo/bar', \ 'language_id': 'python', \} @@ -35,7 +35,7 @@ Before: return 'i' endfunction - function! ale#lsp#WaitForCapability(conn_id, project_root, capability, callback) abort + function! ale#lsp#WaitForCapability(conn_id, capability, callback) abort let g:capability_checked = a:capability call add(g:wait_callback_list, a:callback) endfunction @@ -45,7 +45,7 @@ Before: endfunction " Replace the Send function for LSP, so we can monitor calls to it. - function! ale#lsp#Send(conn_id, message, ...) abort + function! ale#lsp#Send(conn_id, message) abort call add(g:message_list, a:message) return 1 @@ -54,9 +54,14 @@ Before: After: Restore + if g:conn_id isnot v:null + call ale#lsp#RemoveConnectionWithID(g:conn_id) + endif + unlet! g:message_list unlet! g:capability_checked unlet! g:wait_callback_list + unlet! g:conn_id unlet! g:Callback unlet! b:ale_old_omnifunc unlet! b:ale_old_completopt @@ -72,7 +77,6 @@ After: return call('mode', a:000) endfunction - call ale#lsp#RemoveConnectionWithID(347) call ale#test#RestoreDirectory() call ale#linter#Reset() @@ -102,7 +106,7 @@ Execute(The right message should be sent for the initial tsserver request): AssertEqual 1, len(g:wait_callback_list) AssertEqual 'completion', g:capability_checked - call map(g:wait_callback_list, 'v:val([347, ''/foo/bar''])') + call map(g:wait_callback_list, 'v:val([g:conn_id, ''/foo/bar''])') " We should send the right callback. AssertEqual @@ -116,7 +120,7 @@ Execute(The right message should be sent for the initial tsserver request): AssertEqual \ { \ 'line_length': 3, - \ 'conn_id': 347, + \ 'conn_id': g:conn_id, \ 'column': 3, \ 'request_id': 1, \ 'line': 1, @@ -189,7 +193,7 @@ Execute(The right message should be sent for the initial LSP request): AssertEqual 1, len(g:wait_callback_list) AssertEqual 'completion', g:capability_checked - call map(g:wait_callback_list, 'v:val([347, ''/foo/bar''])') + call map(g:wait_callback_list, 'v:val([g:conn_id, ''/foo/bar''])') " We should send the right callback. AssertEqual @@ -219,7 +223,7 @@ Execute(The right message should be sent for the initial LSP request): AssertEqual \ { \ 'line_length': 3, - \ 'conn_id': 347, + \ 'conn_id': g:conn_id, \ 'column': 3, \ 'request_id': 1, \ 'line': 1, diff --git a/test/completion/test_lsp_completion_parsing.vader b/test/completion/test_lsp_completion_parsing.vader index d5a45b54..71e53ab6 100644 --- a/test/completion/test_lsp_completion_parsing.vader +++ b/test/completion/test_lsp_completion_parsing.vader @@ -447,3 +447,27 @@ Execute(Should handle missing keys): \ ] \ } \ }) + +Execute(Should handle documentation in the markdown format): + AssertEqual + \ [ + \ {'word': 'migrations', 'menu': 'xxx', 'info': 'Markdown documentation', 'kind': 'f', 'icase': 1}, + \ ], + \ ale#completion#ParseLSPCompletions({ + \ 'jsonrpc': '2.0', + \ 'id': 6, + \ 'result': { + \ 'isIncomplete': v:false, + \ 'items': [ + \ { + \ 'label': 'migrations', + \ 'kind': 3, + \ 'detail': 'xxx', + \ 'documentation': { + \ 'kind': 'markdown', + \ 'value': 'Markdown documentation', + \ }, + \ }, + \ ], + \ }, + \ }) diff --git a/test/completion/test_tsserver_completion_parsing.vader b/test/completion/test_tsserver_completion_parsing.vader index c8e2c993..dbc4f9e2 100644 --- a/test/completion/test_tsserver_completion_parsing.vader +++ b/test/completion/test_tsserver_completion_parsing.vader @@ -32,6 +32,13 @@ Execute(TypeScript completion details responses should be parsed correctly): \ 'kind': 'f', \ 'icase': 1, \ }, + \ { + \ 'word': 'ghi', + \ 'menu': '(class) Foo', + \ 'info': '', + \ 'kind': 'f', + \ 'icase': 1, + \ }, \ ], \ ale#completion#ParseTSServerCompletionEntryDetails({ \ 'body': [ @@ -74,6 +81,17 @@ Execute(TypeScript completion details responses should be parsed correctly): \ {'text': 'baz'}, \ ], \ }, + \ { + \ 'name': 'ghi', + \ 'kind': 'className', + \ 'displayParts': [ + \ {'text': '('}, + \ {'text': 'class'}, + \ {'text': ')'}, + \ {'text': ' '}, + \ {'text': 'Foo'}, + \ ], + \ }, \ ], \}) diff --git a/test/fix/test_ale_fix.vader b/test/fix/test_ale_fix.vader index 67b8b212..90407681 100644 --- a/test/fix/test_ale_fix.vader +++ b/test/fix/test_ale_fix.vader @@ -23,7 +23,7 @@ Before: autocmd! autocmd User ALEFixPre let g:pre_success = 1 autocmd User ALEFixPost let g:post_success = 1 - augroup end + augroup END if !has('win32') let &shell = '/bin/bash' @@ -180,7 +180,7 @@ After: unlet! g:ale_emulate_job_failure unlet! b:ale_fixers unlet! b:ale_fix_on_save - augroup! VaderTest + unlet! b:ale_quitting delfunction AddCarets delfunction AddDollars delfunction DoNothing @@ -204,6 +204,12 @@ After: delfunction FixWithJSONPostProcessing delfunction JSONPostProcessor + augroup VaderTest + autocmd! + augroup END + + augroup! VaderTest + call ale#test#RestoreDirectory() call ale#fix#registry#ResetToDefaults() @@ -426,7 +432,7 @@ Given testft (A file with three lines): b c -Execute(ALEFix should save files on the save event): +Execute(ALEFix should fix files on the save event): let g:ale_fix_on_save = 1 let g:ale_lint_on_save = 1 let g:ale_enabled = 1 @@ -466,6 +472,36 @@ Expect(The buffer should be modified): $b $c +Execute(ALEFix should not fix files on :wq): + let g:ale_fix_on_save = 1 + let g:ale_lint_on_save = 1 + let g:ale_enabled = 1 + + noautocmd silent file fix_test_file + call writefile(getline(1, '$'), 'fix_test_file') + + let g:ale_fixers.testft = ['AddDollars'] + + " We have to set the buftype to empty so the file will be written. + setlocal buftype= + + call ale#events#QuitEvent(bufnr('')) + + call SetUpLinters() + call ale#events#SaveEvent(bufnr('')) + + " We should save the file. + AssertEqual ['a', 'b', 'c'], readfile('fix_test_file') + Assert &modified, 'The was not marked as ''modified''' + + " We should not run the linter. + AssertEqual [], ale#test#GetLoclistWithoutModule() + +Expect(The buffer should not be modified): + a + b + c + Given testft (A file with three lines): a b diff --git a/test/fixers/test_eslint_fixer_callback.vader b/test/fixers/test_eslint_fixer_callback.vader index be33825c..774595e3 100644 --- a/test/fixers/test_eslint_fixer_callback.vader +++ b/test/fixers/test_eslint_fixer_callback.vader @@ -170,3 +170,10 @@ Execute(The eslint_d post-processor should handle error messages correctly): \ ale#fixers#eslint#ProcessEslintDOutput(bufnr(''), [ \ 'Error: No ESLint configuration found.', \ ]) + +Execute(The eslint_d post-processor should handle failing to connect properly): + AssertEqual + \ [], + \ ale#fixers#eslint#ProcessEslintDOutput(bufnr(''), [ + \ 'Could not connect', + \ ]) diff --git a/test/fixers/test_gomod_fixer_callback.vader b/test/fixers/test_gomod_fixer_callback.vader new file mode 100644 index 00000000..a378e961 --- /dev/null +++ b/test/fixers/test_gomod_fixer_callback.vader @@ -0,0 +1,24 @@ +Before: + Save g:ale_go_go_executable + + " Use an invalid global executable, so we don't match it. + let g:ale_go_go_executable = 'xxxinvalid' + call ale#test#SetDirectory('/testplugin/test/fixers') + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The gomod callback should return the correct default values): + call ale#test#SetFilename('../go_files/go.mod') + setl ft=gomod + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('xxxinvalid') + \ . ' mod edit -fmt' + \ . ' %t', + \ }, + \ ale#fixers#gomod#Fix(bufnr('')) diff --git a/test/fixers/test_goofle_java_format_fixer_callback.vader b/test/fixers/test_goofle_java_format_fixer_callback.vader index d64e2788..4c28b330 100644 --- a/test/fixers/test_goofle_java_format_fixer_callback.vader +++ b/test/fixers/test_goofle_java_format_fixer_callback.vader @@ -1,8 +1,8 @@ Before: - Save g:ale_google_java_format_executable + Save g:ale_java_google_java_format_executable " Use an invalid global executable, so we don't match it. - let g:ale_google_java_format_executable = 'xxxinvalid' + let g:ale_java_google_java_format_executable = 'xxxinvalid' call ale#test#SetDirectory('/testplugin/test/fixers') @@ -17,11 +17,11 @@ Execute(The google-java-format callback should return 0 when the executable isn' \ ale#fixers#google_java_format#Fix(bufnr('')) Execute(The google-java-format callback should run the command when the executable test passes): - let g:ale_google_java_format_executable = has('win32') ? 'cmd' : 'echo' + let g:ale_java_google_java_format_executable = has('win32') ? 'cmd' : 'echo' AssertEqual \ { \ 'read_temporary_file': 1, - \ 'command': ale#Escape(ale_google_java_format_executable) . ' --replace %t' + \ 'command': ale#Escape(ale_java_google_java_format_executable) . ' --replace %t' \ }, \ ale#fixers#google_java_format#Fix(bufnr('')) diff --git a/test/fixers/test_hackfmt_fixer_callback.vader b/test/fixers/test_hackfmt_fixer_callback.vader index ed78fc85..d294c15e 100644 --- a/test/fixers/test_hackfmt_fixer_callback.vader +++ b/test/fixers/test_hackfmt_fixer_callback.vader @@ -1,10 +1,10 @@ Before: - Save g:ale_php_hackfmt_executable - Save g:ale_php_hackfmt_options + Save g:ale_hack_hackfmt_executable + Save g:ale_hack_hackfmt_options " Use an invalid global executable, so we don't match it. - let g:ale_php_hackfmt_executable = 'xxxinvalid' - let g:ale_php_hackfmt_options = '' + let g:ale_hack_hackfmt_executable = 'xxxinvalid' + let g:ale_hack_hackfmt_options = '' call ale#test#SetDirectory('/testplugin/test/fixers') @@ -14,7 +14,7 @@ After: call ale#test#RestoreDirectory() Execute(The hackfmt callback should return the correct default values): - call ale#test#SetFilename('../hack_files/testfile.php') + call ale#test#SetFilename('../hack_files/testfile.hack') AssertEqual \ { @@ -25,8 +25,8 @@ Execute(The hackfmt callback should return the correct default values): \ ale#fixers#hackfmt#Fix(bufnr('')) Execute(The hackfmt callback should include custom hackfmt options): - let g:ale_php_hackfmt_options = "--some-option" - call ale#test#SetFilename('../hack_files/testfile.php') + let g:ale_hack_hackfmt_options = "--some-option" + call ale#test#SetFilename('../hack_files/testfile.hack') AssertEqual \ { diff --git a/test/fixers/test_hlint_fixer_callback.vader b/test/fixers/test_hlint_fixer_callback.vader new file mode 100644 index 00000000..08f08fae --- /dev/null +++ b/test/fixers/test_hlint_fixer_callback.vader @@ -0,0 +1,20 @@ +Before: + call ale#test#SetDirectory('/testplugin/test/fixers') + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The hlint callback should return the correct default values): + call ale#test#SetFilename('../haskell_files/testfile.hs') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('hlint') + \ . ' --refactor' + \ . ' --refactor-options="--inplace"' + \ . ' %t', + \ }, + \ ale#fixers#hlint#Fix(bufnr('')) diff --git a/test/fixers/test_importjs_fixer_callback.vader b/test/fixers/test_importjs_fixer_callback.vader index c3e57f8b..53b87c2e 100644 --- a/test/fixers/test_importjs_fixer_callback.vader +++ b/test/fixers/test_importjs_fixer_callback.vader @@ -1,8 +1,8 @@ Before: - Save g:ale_js_importjs_executable + Save g:ale_javascript_importjs_executable " Use an invalid global executable, so we don't match it. - let g:ale_js_importjs_executable = 'xxxinvalid' + let g:ale_javascript_importjs_executable = 'xxxinvalid' call ale#test#SetDirectory('/testplugin/test/fixers') call ale#test#SetFilename('../javascript_files/test.js') @@ -18,12 +18,12 @@ Execute(The importjs callback should return 0 when the executable isn't executab \ ale#fixers#importjs#Fix(bufnr('')) Execute(The importjs callback should run the command when the executable test passes): - let g:ale_js_importjs_executable = has('win32') ? 'cmd' : 'echo' + let g:ale_javascript_importjs_executable = has('win32') ? 'cmd' : 'echo' AssertEqual \ { \ 'process_with': 'ale#fixers#importjs#ProcessOutput', - \ 'command': ale#Escape(g:ale_js_importjs_executable) . ' fix %s' + \ 'command': ale#Escape(g:ale_javascript_importjs_executable) . ' fix %s' \ }, \ ale#fixers#importjs#Fix(bufnr('')) diff --git a/test/fixers/test_isort_fixer_callback.vader b/test/fixers/test_isort_fixer_callback.vader index 56c08d26..50818621 100644 --- a/test/fixers/test_isort_fixer_callback.vader +++ b/test/fixers/test_isort_fixer_callback.vader @@ -27,7 +27,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': 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/subdir/foo')) . ' && ' + \ 'command': ale#path#CdString(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/subdir/foo')) \ . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/isort')) . ' -', \ }, \ ale#fixers#isort#Fix(bufnr('')) @@ -42,7 +42,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': 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/subdir/foo')) . ' && ' + \ 'command': ale#path#CdString(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/subdir/foo')) \ . 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_jq_fixer_callback.vader b/test/fixers/test_jq_fixer_callback.vader index 2e32bf8e..74580d3b 100644 --- a/test/fixers/test_jq_fixer_callback.vader +++ b/test/fixers/test_jq_fixer_callback.vader @@ -1,6 +1,7 @@ Before: Save g:ale_json_jq_executable Save g:ale_json_jq_options + Save g:ale_json_jq_filters After: Restore @@ -8,7 +9,18 @@ After: Execute(The jq fixer should use the options you set): let g:ale_json_jq_executable = 'foo' let g:ale_json_jq_options = '--bar' + let g:ale_json_jq_filters = '.baz' AssertEqual - \ {'command': ale#Escape('foo') . ' . --bar'}, + \ {'command': ale#Escape('foo') . ' .baz --bar'}, + \ ale#fixers#jq#Fix(bufnr('')) + +Execute(The jq fixer should return 0 when there are no filters): + let g:ale_json_jq_executable = 'jq' + let g:ale_json_jq_options = '' + + let g:ale_json_jq_filters = '' + + AssertEqual + \ 0, \ ale#fixers#jq#Fix(bufnr('')) diff --git a/test/fixers/test_ocamlformat_fixer_callback.vader b/test/fixers/test_ocamlformat_fixer_callback.vader new file mode 100644 index 00000000..f0c36ed7 --- /dev/null +++ b/test/fixers/test_ocamlformat_fixer_callback.vader @@ -0,0 +1,38 @@ +Before: + Save g:ale_ocaml_ocamlformat_executable + Save g:ale_ocaml_ocamlformat_options + + " Use an invalid global executable, so we don't match it. + let g:ale_ocaml_ocamlformat_executable = 'xxxinvalid' + let g:ale_ocaml_ocamlformat_options = '' + + call ale#test#SetDirectory('/testplugin/test/fixers') + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The ocamlformat callback should return the correct default values): + call ale#test#SetFilename('../ocaml-test-files/testfile.re') + + AssertEqual + \ { + \ 'command': ale#Escape('xxxinvalid') + \ . ' --name=' . ale#Escape(bufname(bufnr(''))) + \ . ' -', + \ }, + \ ale#fixers#ocamlformat#Fix(bufnr('')) + +Execute(The ocamlformat callback should include custom ocamlformat options): + let g:ale_ocaml_ocamlformat_options = "-m 78" + call ale#test#SetFilename('../ocaml-test-files/testfile.re') + + AssertEqual + \ { + \ 'command': ale#Escape('xxxinvalid') + \ . ' ' . g:ale_ocaml_ocamlformat_options + \ . ' --name=' . ale#Escape(bufname(bufnr(''))) + \ . ' -', + \ }, + \ 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 ef0b35df..5c899d86 100644 --- a/test/fixers/test_prettier_eslint_fixer.callback.vader +++ b/test/fixers/test_prettier_eslint_fixer.callback.vader @@ -85,7 +85,7 @@ Execute(The new --stdin-filepath option should be used when the version is new e AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . 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', @@ -106,7 +106,7 @@ Execute(The version number should be cached): " The newer command should be used. AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . 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 2018c3a6..7f25471b 100644 --- a/test/fixers/test_prettier_fixer_callback.vader +++ b/test/fixers/test_prettier_fixer_callback.vader @@ -74,7 +74,7 @@ Execute(--stdin-filepath should be used when prettier is new enough): AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . ale#Escape(g:ale_javascript_prettier_executable) \ . ' --no-semi' \ . ' --stdin-filepath %s --stdin', @@ -90,7 +90,7 @@ Execute(The version number should be cached): " Call it again without the version output. We should use the newer command. AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . ale#Escape(g:ale_javascript_prettier_executable) \ . ' --stdin-filepath %s --stdin', \ }, @@ -103,7 +103,7 @@ Execute(Should set --parser based on filetype, TypeScript): AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . ale#Escape(g:ale_javascript_prettier_executable) \ . ' --parser typescript' \ . ' --stdin-filepath %s --stdin', @@ -117,7 +117,7 @@ Execute(Should set --parser based on filetype, CSS): AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . ale#Escape(g:ale_javascript_prettier_executable) \ . ' --parser css' \ . ' --stdin-filepath %s --stdin', @@ -131,7 +131,7 @@ Execute(Should set --parser based on filetype, LESS): AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . ale#Escape(g:ale_javascript_prettier_executable) \ . ' --parser less' \ . ' --stdin-filepath %s --stdin', @@ -145,7 +145,7 @@ Execute(Should set --parser based on filetype, SCSS): AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . ale#Escape(g:ale_javascript_prettier_executable) \ . ' --parser scss' \ . ' --stdin-filepath %s --stdin', @@ -159,7 +159,7 @@ Execute(Should set --parser based on filetype, JSON): AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . ale#Escape(g:ale_javascript_prettier_executable) \ . ' --parser json' \ . ' --stdin-filepath %s --stdin', @@ -173,7 +173,7 @@ Execute(Should set --parser based on filetype, JSON5): AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . ale#Escape(g:ale_javascript_prettier_executable) \ . ' --parser json5' \ . ' --stdin-filepath %s --stdin', @@ -187,7 +187,7 @@ Execute(Should set --parser based on filetype, GraphQL): AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . ale#Escape(g:ale_javascript_prettier_executable) \ . ' --parser graphql' \ . ' --stdin-filepath %s --stdin', @@ -201,7 +201,7 @@ Execute(Should set --parser based on filetype, Markdown): AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . ale#Escape(g:ale_javascript_prettier_executable) \ . ' --parser markdown' \ . ' --stdin-filepath %s --stdin', @@ -215,13 +215,41 @@ Execute(Should set --parser based on filetype, Vue): AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . ale#Escape(g:ale_javascript_prettier_executable) \ . ' --parser vue' \ . ' --stdin-filepath %s --stdin', \ }, \ ale#fixers#prettier#ApplyFixForVersion(bufnr(''), ['1.6.0']) +Execute(Should set --parser based on filetype, YAML): + call ale#test#SetFilename('../prettier-test-files/testfile') + + set filetype=yaml + + AssertEqual + \ { + \ 'command': ale#path#CdString(expand('%:p:h')) + \ . ale#Escape(g:ale_javascript_prettier_executable) + \ . ' --parser yaml' + \ . ' --stdin-filepath %s --stdin', + \ }, + \ ale#fixers#prettier#ApplyFixForVersion(bufnr(''), ['1.6.0']) + +Execute(Should set --parser based on filetype, HTML): + call ale#test#SetFilename('../prettier-test-files/testfile') + + set filetype=html + + AssertEqual + \ { + \ 'command': ale#path#CdString(expand('%:p:h')) + \ . ale#Escape(g:ale_javascript_prettier_executable) + \ . ' --parser html' + \ . ' --stdin-filepath %s --stdin', + \ }, + \ ale#fixers#prettier#ApplyFixForVersion(bufnr(''), ['1.6.0']) + Execute(Should set --parser based on first filetype of multiple filetypes): call ale#test#SetFilename('../prettier-test-files/testfile') @@ -229,9 +257,27 @@ Execute(Should set --parser based on first filetype of multiple filetypes): AssertEqual \ { - \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ 'command': ale#path#CdString(expand('%:p:h')) \ . ale#Escape(g:ale_javascript_prettier_executable) \ . ' --parser css' \ . ' --stdin-filepath %s --stdin', \ }, \ ale#fixers#prettier#ApplyFixForVersion(bufnr(''), ['1.6.0']) + +Execute(The prettier_d post-processor should permit regular JavaScript content): + AssertEqual + \ [ + \ 'const x = ''Error: foo''', + \ 'const y = 3', + \ ], + \ ale#fixers#prettier#ProcessPrettierDOutput(bufnr(''), [ + \ 'const x = ''Error: foo''', + \ 'const y = 3', + \ ]) + +Execute(The prettier_d post-processor should handle error messages correctly): + AssertEqual + \ [], + \ ale#fixers#prettier#ProcessPrettierDOutput(bufnr(''), [ + \ 'SyntaxError: Unexpected token, expected "," (36:28)', + \ ]) diff --git a/test/fixers/test_python_add_blank_lines_fixer.vader b/test/fixers/test_python_add_blank_lines_fixer.vader index 4a91aa10..7d042c8a 100644 --- a/test/fixers/test_python_add_blank_lines_fixer.vader +++ b/test/fixers/test_python_add_blank_lines_fixer.vader @@ -6,15 +6,22 @@ After: Given python(Some Python without blank lines): def foo(): + """ This is a simple test docstring """ return 1 def bar(): + '''This is another simple test docstring''' return 1 return 4 def bar(): + """ + This is a multi-line + docstring + """ + if x: pass for l in x: @@ -44,16 +51,25 @@ Execute(Blank lines should be added appropriately): Expect python(Newlines should be added): def foo(): + """ This is a simple test docstring """ + return 1 def bar(): + '''This is another simple test docstring''' + return 1 return 4 def bar(): + """ + This is a multi-line + docstring + """ + if x: pass @@ -109,3 +125,43 @@ Expect python(extra newlines shouldn't be added to the main block): if __name__ == '__main__': main() + + +Given python(A file with variables/docstring that start with a control statement): + def some(): + """ + This is a docstring that contains an + break control statement and also contains a + return something funny. + """ + + continue_some_var = True + forward_something = False + + if ( + continue_some_var and + forwarded_something + ): + return True + + +Execute(Fix the file): + let g:ale_fixers = {'python': ['add_blank_lines_for_python_control_statements']} + ALEFix + +Expect python(Extra new lines are not added to the file): + def some(): + """ + This is a docstring that contains an + break control statement and also contains a + return something funny. + """ + + continue_some_var = True + forward_something = False + + if ( + continue_some_var and + forwarded_something + ): + return True diff --git a/test/fixers/test_rubocop_fixer_callback.vader b/test/fixers/test_rubocop_fixer_callback.vader index 045256f8..866326bf 100644 --- a/test/fixers/test_rubocop_fixer_callback.vader +++ b/test/fixers/test_rubocop_fixer_callback.vader @@ -23,7 +23,7 @@ Execute(The rubocop callback should return the correct default values): \ { \ 'read_temporary_file': 1, \ 'command': ale#Escape(g:ale_ruby_rubocop_executable) - \ . ' --auto-correct %t', + \ . ' --auto-correct --force-exclusion %t', \ }, \ ale#fixers#rubocop#Fix(bufnr('')) @@ -35,7 +35,7 @@ Execute(The rubocop callback should include configuration files): \ 'read_temporary_file': 1, \ 'command': ale#Escape(g:ale_ruby_rubocop_executable) \ . ' --config ' . ale#Escape(ale#path#Simplify(g:dir . '/ruby_paths/with_config/.rubocop.yml')) - \ . ' --auto-correct %t', + \ . ' --auto-correct --force-exclusion %t', \ }, \ ale#fixers#rubocop#Fix(bufnr('')) @@ -49,6 +49,6 @@ 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 %t', + \ . ' --auto-correct --force-exclusion %t', \ }, \ ale#fixers#rubocop#Fix(bufnr('')) diff --git a/test/fixers/test_shfmt_fixer_callback.vader b/test/fixers/test_shfmt_fixer_callback.vader index 5dc6e863..99cb0987 100644 --- a/test/fixers/test_shfmt_fixer_callback.vader +++ b/test/fixers/test_shfmt_fixer_callback.vader @@ -1,17 +1,52 @@ Before: Save g:ale_sh_shfmt_executable Save g:ale_sh_shfmt_options + Save &l:expandtab + Save &l:shiftwidth + Save &l:tabstop After: Restore -Execute(The shfmt callback should return the correct default values): +Execute(The shfmt callback should return 'shfmt' as default command): + setlocal noexpandtab + Assert + \ ale#fixers#shfmt#Fix(bufnr('')).command =~# '^' . ale#Escape('shfmt'), + \ "Default command name is expected to be 'shfmt'" + +Execute(The shfmt callback should return the command with no option as default when noexpandtab is set): + let g:ale_sh_shfmt_executable = 'shfmt' + let g:ale_sh_shfmt_options = '' + setlocal noexpandtab AssertEqual \ { \ 'command': ale#Escape('shfmt'), \ }, \ ale#fixers#shfmt#Fix(bufnr('')) +Execute(The shfmt callback should return the command specifying indent width by looking shiftwidth as default): + let g:ale_sh_shfmt_executable = 'shfmt' + let g:ale_sh_shfmt_options = '' + setlocal expandtab + setlocal shiftwidth=4 + AssertEqual + \ { + \ 'command': ale#Escape('shfmt') . ' -i 4', + \ }, + \ ale#fixers#shfmt#Fix(bufnr('')) + +Execute(The shfmt callback should return the command specifying indent width by looking tabstop when shiftwidth is 0 as default): + let g:ale_sh_shfmt_executable = 'shfmt' + let g:ale_sh_shfmt_options = '' + setlocal expandtab + setlocal shiftwidth=0 + setlocal tabstop=8 + AssertEqual + \ { + \ 'command': ale#Escape('shfmt') . ' -i 8', + \ }, + \ ale#fixers#shfmt#Fix(bufnr('')) + Execute(The shfmt executable and options should be configurable): let g:ale_sh_shfmt_executable = 'foobar' let g:ale_sh_shfmt_options = '--some-option' diff --git a/test/fixers/test_sqlfmt_fixer_callback.vader b/test/fixers/test_sqlfmt_fixer_callback.vader new file mode 100644 index 00000000..3046edb3 --- /dev/null +++ b/test/fixers/test_sqlfmt_fixer_callback.vader @@ -0,0 +1,26 @@ +Before: + Save g:ale_sql_sqlfmt_executable + Save g:ale_sql_sqlfmt_options + +After: + Restore + +Execute(The sqlfmt callback should return the correct default values): + AssertEqual + \ { + \ 'command': ale#Escape('sqlfmt') + \ . ' -w', + \ }, + \ ale#fixers#sqlfmt#Fix(bufnr('')) + +Execute(The sqlfmt executable and options should be configurable): + let g:ale_sql_sqlfmt_executable = '/path/to/sqlfmt' + let g:ale_sql_sqlfmt_options = '-u' + + AssertEqual + \ { + \ 'command': ale#Escape('/path/to/sqlfmt') + \ . ' -w' + \ . ' -u', + \ }, + \ ale#fixers#sqlfmt#Fix(bufnr('')) diff --git a/test/fixers/test_stylish_haskell_fixer_callback.vader b/test/fixers/test_stylish_haskell_fixer_callback.vader new file mode 100644 index 00000000..755d3430 --- /dev/null +++ b/test/fixers/test_stylish_haskell_fixer_callback.vader @@ -0,0 +1,24 @@ +Before: + Save g:ale_haskell_stylish_haskell_executable + + " Use an invalid global executable, so we don't match it. + let g:ale_haskell_stylish_haskell_executable = 'xxxinvalid' + + call ale#test#SetDirectory('/testplugin/test/fixers') + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The stylish-haskell callback should return the correct default values): + call ale#test#SetFilename('../haskell_files/testfile.hs') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('xxxinvalid') + \ . ' --inplace' + \ . ' %t', + \ }, + \ ale#fixers#stylish_haskell#Fix(bufnr('')) diff --git a/test/fixers/test_terraform_fmt_fixer_callback.vader b/test/fixers/test_terraform_fmt_fixer_callback.vader new file mode 100644 index 00000000..15377a7e --- /dev/null +++ b/test/fixers/test_terraform_fmt_fixer_callback.vader @@ -0,0 +1,34 @@ +Before: + Save g:ale_terraform_fmt_executable + Save g:ale_terraform_fmt_options + + " Use an invalid global executable, so we don't match it. + let g:ale_terraform_fmt_executable = 'xxxinvalid' + let g:ale_terraform_fmt_options = '' + + call ale#test#SetDirectory('/testplugin/test/fixers') + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The terraform fmt callback should return the correct default values): + + AssertEqual + \ { + \ 'command': ale#Escape('xxxinvalid') . ' fmt -', + \ }, + \ ale#fixers#terraform#Fix(bufnr('')) + +Execute(The terraform fmt callback should include custom options): + let g:ale_terraform_fmt_options = "-list=true" + + AssertEqual + \ { + \ 'command': ale#Escape('xxxinvalid') + \ . ' fmt' + \ . ' ' . g:ale_terraform_fmt_options + \ . ' -', + \ }, + \ ale#fixers#terraform#Fix(bufnr('')) diff --git a/test/fixers/test_uncrustify_fixer_callback.vader b/test/fixers/test_uncrustify_fixer_callback.vader new file mode 100644 index 00000000..8ef4e79b --- /dev/null +++ b/test/fixers/test_uncrustify_fixer_callback.vader @@ -0,0 +1,36 @@ +Before: + Save g:ale_c_uncrustify_executable + + " Use an invalid global executable, so we don't match it. + let g:ale_c_uncrustify_executable = 'xxxinvalid' + + call ale#test#SetDirectory('/testplugin/test/fixers') + silent cd .. + silent cd command_callback + let g:dir = getcwd() + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The clang-format callback should return the correct default values): + call ale#test#SetFilename('c_paths/dummy.c') + + AssertEqual + \ { + \ 'command': ale#Escape(g:ale_c_uncrustify_executable) + \ . ' --no-backup' + \ }, + \ ale#fixers#uncrustify#Fix(bufnr('')) + +Execute(The uncrustify callback should include any additional options): + call ale#test#SetFilename('c_paths/dummy.c') + let b:ale_c_uncrustify_options = '--some-option' + + AssertEqual + \ { + \ 'command': ale#Escape(g:ale_c_uncrustify_executable) + \ . ' --no-backup --some-option', + \ }, + \ ale#fixers#uncrustify#Fix(bufnr('')) diff --git a/test/fixers/test_xmllint_fixer_callback.vader b/test/fixers/test_xmllint_fixer_callback.vader new file mode 100644 index 00000000..54fe05bd --- /dev/null +++ b/test/fixers/test_xmllint_fixer_callback.vader @@ -0,0 +1,46 @@ +Before: + Save g:ale_xml_xmllint_executable + Save g:ale_xml_xmllint_indentsize + Save g:ale_xml_xmllint_options + + let g:ale_xml_xmllint_executable = '/path/to/xmllint' + let g:ale_xml_xmllint_indentsize = '' + let g:ale_xml_xmllint_options = '' + + call ale#test#SetDirectory('/testplugin/test/fixers') + +After: + Restore + +Execute(The xmllint callback should return the correct default command): + AssertEqual + \ { + \ 'command': ale#Escape('/path/to/xmllint') + \ . ' --format ' + \ . ale#Escape(bufname(bufnr(''))) + \ }, + \ ale#fixers#xmllint#Fix(bufnr('')) + +Execute(The xmllint callback should include the XMLLINT_INDENT variable): + let g:ale_xml_xmllint_indentsize = 2 + + AssertEqual + \ { + \ 'command': ale#Env('XMLLINT_INDENT', ' ') + \ . ale#Escape('/path/to/xmllint') + \ . ' --format ' + \ . ale#Escape(bufname(bufnr(''))) + \ }, + \ ale#fixers#xmllint#Fix(bufnr('')) + +Execute(The xmllint callback should include additional options): + let g:ale_xml_xmllint_options = '--nonet' + + AssertEqual + \ { + \ 'command': ale#Escape('/path/to/xmllint') + \ . ' --format ' + \ . ale#Escape(bufname(bufnr(''))) + \ . ' --nonet' + \ }, + \ ale#fixers#xmllint#Fix(bufnr('')) diff --git a/test/go_files/go.mod b/test/go_files/go.mod new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/test/go_files/go.mod @@ -0,0 +1 @@ + diff --git a/test/handler/test_ada_gcc_handler.vader b/test/handler/test_ada_gcc_handler.vader new file mode 100644 index 00000000..06ddfe1f --- /dev/null +++ b/test/handler/test_ada_gcc_handler.vader @@ -0,0 +1,36 @@ +Before: + runtime ale_linters/ada/gcc.vim + +After: + call ale#linter#Reset() + +Execute(The gcc handler for Ada should parse input correctly): + AssertEqual + \ [ + \ { + \ 'bufnr': 0, + \ 'lnum': 8, + \ 'col': 5, + \ 'type': 'W', + \ 'text': 'variable "X" is assigned but never read', + \ }, + \ { + \ 'bufnr': 0, + \ 'lnum': 6, + \ 'col': 22, + \ 'type': 'E', + \ 'text': 'type definition expected', + \ }, + \ { + \ 'bufnr': 0, + \ 'lnum': 8, + \ 'col': 9, + \ 'type': 'E', + \ 'text': 'aspect specifications not allowed here', + \ }, + \ ], + \ ale_linters#ada#gcc#Handle(0, [ + \ 'foobar.adb:8:05: warning: variable "X" is assigned but never read', + \ 'foobar.ads:6:22: type definition expected', + \ 'foobar.ads:8:09: aspect specifications not allowed here', + \ ]) diff --git a/test/handler/test_checkstyle_handler.vader b/test/handler/test_checkstyle_handler.vader index 2f1f0f8d..218fe344 100644 --- a/test/handler/test_checkstyle_handler.vader +++ b/test/handler/test_checkstyle_handler.vader @@ -26,3 +26,16 @@ Execute(The checkstyle handler should parse lines correctly): \ '[WARN] whatever:101: ''method def rcurly'' has incorrect indentation level 4, expected level should be 2. [Indentation]', \ '[WARN] whatever:63:3: Missing a Javadoc comment. [JavadocMethod]', \ ]) + +Execute(The checkstyle handler should parse lines from older checkstyle versions correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 289, + \ 'text': '''method def modifier'' have incorrect indentation level 4, expected level should be 2.', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#java#checkstyle#Handle(666, [ + \ '/home/languitar/src/rsb-java/rsb-java/src/main/java/rsb/Listener.java:289: warning: ''method def modifier'' have incorrect indentation level 4, expected level should be 2.', + \ ]) diff --git a/test/handler/test_clang_handler.vader b/test/handler/test_clang_handler.vader index 278737a8..cc8eabd0 100644 --- a/test/handler/test_clang_handler.vader +++ b/test/handler/test_clang_handler.vader @@ -8,9 +8,20 @@ Execute(clang errors from included files should be parsed correctly): \ 'type': 'E', \ 'text': 'expected identifier or ''(''', \ }, + \ { + \ 'lnum': 3, + \ 'text': 'Error found in header. See :ALEDetail', + \ 'detail': join([ + \ 'In file included from <stdin>:3:', + \ 'In file included from ./a.h:1:', + \ './b.h:1:1: error: expected identifier or ''(''', + \ '{{{', + \ '^', + \ ], "\n"), + \ }, \ ], - \ ale#handlers#gcc#HandleGCCFormat(347, [ - \ 'In file included from test.c:3:', + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ + \ 'In file included from <stdin>:3:', \ 'In file included from ./a.h:1:', \ './b.h:1:1: error: expected identifier or ''(''', \ '{{{', diff --git a/test/handler/test_credo_handler.vader b/test/handler/test_credo_handler.vader index 5eb0e967..1fd54bb5 100644 --- a/test/handler/test_credo_handler.vader +++ b/test/handler/test_credo_handler.vader @@ -10,20 +10,44 @@ Execute(The credo handler should parse lines correctly): \ { \ 'bufnr': 347, \ 'lnum': 1, + \ 'col': 24, + \ 'text': 'This code can be refactored', + \ 'type': 'W', + \ }, + \ { + \ 'bufnr': 347, + \ 'lnum': 1, \ 'col': 4, \ 'text': 'There is no whitespace around parentheses/brackets most of the time, but here there is.', - \ 'type': 'E', + \ 'type': 'W', + \ }, + \ { + \ 'bufnr': 347, + \ 'lnum': 5, + \ 'col': 21, + \ 'text': 'TODO comment', + \ 'type': 'I', \ }, \ { \ 'bufnr': 347, \ 'lnum': 26, \ 'col': 0, \ 'text': 'If/else blocks should not have a negated condition in `if`.', + \ 'type': 'I', + \ }, + \ { + \ 'bufnr': 347, + \ 'lnum': 15, + \ 'col': 1, + \ 'text': 'Warning in the code', \ 'type': 'W', \ }, \ ], \ ale_linters#elixir#credo#Handle(347, [ \ 'This line should be ignored completely', + \ 'lib/my_code/test.ex:1:24: F: This code can be refactored', \ 'lib/filename.ex:1:4: C: There is no whitespace around parentheses/brackets most of the time, but here there is.', + \ 'lib/my_code/test.ex:5:21: D: TODO comment', \ 'lib/phoenix/channel.ex:26: R: If/else blocks should not have a negated condition in `if`.', + \ 'lib/my_code/test.ex:15:1: W: Warning in the code', \ ]) diff --git a/test/handler/test_dockerfile_lint_handler.vader b/test/handler/test_dockerfile_lint_handler.vader new file mode 100644 index 00000000..619b7bde --- /dev/null +++ b/test/handler/test_dockerfile_lint_handler.vader @@ -0,0 +1,108 @@ +Before: + runtime ale_linters/dockerfile/dockerfile_lint.vim + +After: + call ale#linter#Reset() + +Execute(The dockerfile_lint handler should handle broken JSON): + AssertEqual + \ [], + \ ale_linters#dockerfile#dockerfile_lint#Handle(bufnr(''), ["{asdf"]) + +Execute(The dockerfile_lint handler should handle an empty string response): + AssertEqual + \ [], + \ ale_linters#dockerfile#dockerfile_lint#Handle(bufnr(''), []) + +Execute(The dockerfile_lint handler should handle an empty result, even if it shouldn't happen): + AssertEqual + \ [], + \ ale_linters#dockerfile#dockerfile_lint#Handle(bufnr(''), ["{}"]) + +Execute(The dockerfile_lint handler should handle a normal example): + AssertEqual + \ [ + \ { + \ 'lnum': -1, + \ 'type': 'E', + \ 'text': "Required LABEL name/key 'Name' is not defined", + \ }, + \ { + \ 'lnum': -1, + \ 'type': 'E', + \ 'text': "Required LABEL name/key 'Version' is not defined", + \ }, + \ { + \ 'lnum': 3, + \ 'type': 'I', + \ 'text': "the MAINTAINER command is deprecated. MAINTAINER is deprecated in favor of using LABEL since Docker v1.13.0", + \ }, + \ { + \ 'lnum': -1, + \ 'type': 'I', + \ 'text': "There is no 'CMD' instruction", + \ }, + \ ], + \ ale_linters#dockerfile#dockerfile_lint#Handle(bufnr(''), [ + \ '{', + \ ' "error": {', + \ ' "count": 2,', + \ ' "data": [', + \ ' {', + \ " \"message\": \"Required LABEL name/key 'Name' is not defined\",", + \ ' "line": -1,', + \ ' "level": "error",', + \ ' "lineContent": "",', + \ ' "reference_url": [', + \ ' "http://docs.projectatomic.io/container-best-practices/#",', + \ ' "_recommended_labels_for_your_project"', + \ ' ]', + \ ' },', + \ ' {', + \ " \"message\": \"Required LABEL name/key 'Version' is not defined\",", + \ ' "line": -1,', + \ ' "level": "error",', + \ ' "lineContent": "",', + \ ' "reference_url": [', + \ ' "http://docs.projectatomic.io/container-best-practices/#",', + \ ' "_recommended_labels_for_your_project"', + \ ' ]', + \ ' }', + \ ' ]', + \ ' },', + \ ' "warn": {', + \ ' "count": 0,', + \ ' "data": []', + \ ' },', + \ ' "info": {', + \ ' "count": 2,', + \ ' "data": [', + \ ' {', + \ ' "label": "maintainer_deprecated",', + \ ' "regex": {},', + \ ' "level": "info",', + \ ' "message": "the MAINTAINER command is deprecated",', + \ ' "description": "MAINTAINER is deprecated in favor of using LABEL since Docker v1.13.0",', + \ ' "reference_url": [', + \ ' "https://github.com/docker/cli/blob/master/docs/deprecated.md",', + \ ' "#maintainer-in-dockerfile"', + \ ' ],', + \ ' "lineContent": "MAINTAINER Alexander Olofsson <ace@haxalot.com>",', + \ ' "line": 3', + \ ' },', + \ ' {', + \ ' "instruction": "CMD",', + \ ' "count": 1,', + \ ' "level": "info",', + \ " \"message\": \"There is no 'CMD' instruction\",", + \ ' "description": "None",', + \ ' "reference_url": [', + \ ' "https://docs.docker.com/engine/reference/builder/",', + \ ' "#cmd"', + \ ' ]', + \ ' }', + \ ' ]', + \ ' },', + \ ' "summary": []', + \ '}', + \ ]) diff --git a/test/handler/test_eslint_handler.vader b/test/handler/test_eslint_handler.vader index 2e8bfd2a..4a57927b 100644 --- a/test/handler/test_eslint_handler.vader +++ b/test/handler/test_eslint_handler.vader @@ -365,3 +365,15 @@ Execute(eslint should handle react errors correctly): \ ale#handlers#eslint#Handle(bufnr(''), [ \ '/path/editor-help.jsx:59:9: Property should be placed on the same line as the component declaration [Error/react/jsx-first-prop-new-line]', \ ]) + +Execute(Failing to connect to eslint_d should be handled correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'text': 'Could not connect to eslint_d. Try updating eslint_d or killing it.', + \ }, + \ ], + \ ale#handlers#eslint#Handle(bufnr(''), [ + \ 'Could not connect', + \ ]) diff --git a/test/handler/test_flake8_handler.vader b/test/handler/test_flake8_handler.vader index efacdfb2..cdf20bc0 100644 --- a/test/handler/test_flake8_handler.vader +++ b/test/handler/test_flake8_handler.vader @@ -21,6 +21,7 @@ Execute(The flake8 handler should handle basic warnings and syntax errors): \ { \ 'lnum': 6, \ 'col': 6, + \ 'vcol': 1, \ 'type': 'E', \ 'text': 'indentation is not a multiple of four', \ 'code': 'E111', @@ -29,6 +30,7 @@ Execute(The flake8 handler should handle basic warnings and syntax errors): \ { \ 'lnum': 7, \ 'col': 6, + \ 'vcol': 1, \ 'type': 'W', \ 'text': 'some warning', \ 'code': 'W123', @@ -37,6 +39,7 @@ Execute(The flake8 handler should handle basic warnings and syntax errors): \ { \ 'lnum': 8, \ 'col': 3, + \ 'vcol': 1, \ 'type': 'E', \ 'text': 'SyntaxError: invalid syntax', \ 'code': 'E999', @@ -54,6 +57,7 @@ Execute(The flake8 handler should set end column indexes for certain errors): \ { \ 'lnum': 25, \ 'col': 1, + \ 'vcol': 1, \ 'type': 'E', \ 'end_col': 3, \ 'text': 'undefined name ''foo''', @@ -62,6 +66,7 @@ Execute(The flake8 handler should set end column indexes for certain errors): \ { \ 'lnum': 28, \ 'col': 5, + \ 'vcol': 1, \ 'type': 'E', \ 'end_col': 9, \ 'text': 'hello may be undefined, or defined from star imports: x', @@ -70,6 +75,7 @@ Execute(The flake8 handler should set end column indexes for certain errors): \ { \ 'lnum': 104, \ 'col': 5, + \ 'vcol': 1, \ 'type': 'E', \ 'end_col': 12, \ 'text': '''continue'' not properly in loop', @@ -78,6 +84,7 @@ Execute(The flake8 handler should set end column indexes for certain errors): \ { \ 'lnum': 106, \ 'col': 5, + \ 'vcol': 1, \ 'type': 'E', \ 'end_col': 9, \ 'text': '''break'' outside loop', @@ -86,6 +93,7 @@ Execute(The flake8 handler should set end column indexes for certain errors): \ { \ 'lnum': 109, \ 'col': 5, + \ 'vcol': 1, \ 'type': 'E', \ 'end_col': 8, \ 'text': 'local variable ''test'' is assigned to but never used', @@ -143,6 +151,7 @@ Execute(The flake8 handler should handle names with spaces): \ { \ 'lnum': 6, \ 'col': 6, + \ 'vcol': 1, \ 'type': 'E', \ 'text': 'indentation is not a multiple of four', \ 'code': 'E111', @@ -159,6 +168,7 @@ Execute(Warnings about trailing whitespace should be reported by default): \ { \ 'lnum': 6, \ 'col': 1, + \ 'vcol': 1, \ 'code': 'W291', \ 'type': 'W', \ 'sub_type': 'style', @@ -167,6 +177,7 @@ Execute(Warnings about trailing whitespace should be reported by default): \ { \ 'lnum': 6, \ 'col': 1, + \ 'vcol': 1, \ 'code': 'W293', \ 'type': 'W', \ 'sub_type': 'style', @@ -195,6 +206,7 @@ Execute(Warnings about trailing blank lines should be reported by default): \ { \ 'lnum': 6, \ 'col': 1, + \ 'vcol': 1, \ 'code': 'W391', \ 'type': 'W', \ 'sub_type': 'style', @@ -221,6 +233,7 @@ Execute(F401 should be a warning): \ { \ 'lnum': 6, \ 'col': 1, + \ 'vcol': 1, \ 'code': 'F401', \ 'type': 'W', \ 'text': 'module imported but unused', @@ -236,6 +249,7 @@ Execute(E112 should be a syntax error): \ { \ 'lnum': 6, \ 'col': 1, + \ 'vcol': 1, \ 'code': 'E112', \ 'type': 'E', \ 'text': 'expected an indented block', diff --git a/test/handler/test_gcc_handler.vader b/test/handler/test_gcc_handler.vader index 678d3f42..3daa9e60 100644 --- a/test/handler/test_gcc_handler.vader +++ b/test/handler/test_gcc_handler.vader @@ -1,7 +1,7 @@ Execute(The GCC handler should ignore other lines of output): AssertEqual \ [], - \ ale#handlers#gcc#HandleGCCFormat(347, [ + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ \ 'foo', \ 'bar', \ 'baz', @@ -17,12 +17,24 @@ Execute(GCC errors from included files should be parsed correctly): \ 'type': 'E', \ 'text': 'expected identifier or ''('' before ''{'' token', \ }, + \ { + \ 'lnum': 3, + \ 'col': 2, + \ 'text': 'Error found in header. See :ALEDetail', + \ 'detail': join([ + \ 'In file included from <stdin>:3:2:', + \ 'broken.h:1:1: error: expected identifier or ''('' before ''{'' token', + \ ' {{{', + \ ' ^', + \ ], "\n"), + \ }, \ ], - \ ale#handlers#gcc#HandleGCCFormat(347, [ - \ 'In file included from <stdin>:3:0:', + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ + \ 'In file included from <stdin>:3:2:', \ 'broken.h:1:1: error: expected identifier or ''('' before ''{'' token', \ ' {{{', \ ' ^', + \ 'compilation terminated.', \ ]) AssertEqual @@ -34,13 +46,25 @@ Execute(GCC errors from included files should be parsed correctly): \ 'type': 'E', \ 'text': 'expected identifier or ''('' before ''{'' token', \ }, + \ { + \ 'lnum': 5, + \ 'text': 'Error found in header. See :ALEDetail', + \ 'detail': join([ + \ 'In file included from a.h:1:0,', + \ ' from <stdin>:5:', + \ 'b.h:1:1: error: expected identifier or ''('' before ''{'' token', + \ ' {{{', + \ ' ^', + \ ], "\n"), + \ }, \ ], - \ ale#handlers#gcc#HandleGCCFormat(347, [ + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ \ 'In file included from a.h:1:0,', - \ ' from test.c:3:', + \ ' from <stdin>:5:', \ 'b.h:1:1: error: expected identifier or ''('' before ''{'' token', \ ' {{{', \ ' ^', + \ 'compilation terminated.', \ ]) AssertEqual @@ -59,16 +83,31 @@ Execute(GCC errors from included files should be parsed correctly): \ 'type': 'E', \ 'text': 'unknown type name ''other_bad_type''', \ }, + \ { + \ 'lnum': 3, + \ 'text': 'Error found in header. See :ALEDetail', + \ 'detail': join([ + \ 'In file included from a.h:1:0,', + \ ' from <stdin>:3:', + \ 'b.h:1:1: error: unknown type name ‘bad_type’', + \ ' bad_type x;', + \ ' ^', + \ 'b.h:2:1: error: unknown type name ‘other_bad_type’', + \ ' other_bad_type y;', + \ ' ^', + \ ], "\n"), + \ }, \ ], - \ ale#handlers#gcc#HandleGCCFormat(347, [ + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ \ 'In file included from a.h:1:0,', - \ ' from test.c:3:', + \ ' from <stdin>:3:', \ 'b.h:1:1: error: unknown type name ‘bad_type’', \ ' bad_type x;', \ ' ^', \ 'b.h:2:1: error: unknown type name ‘other_bad_type’', \ ' other_bad_type y;', \ ' ^', + \ 'compilation terminated.', \ ]) Execute(The GCC handler shouldn't complain about #pragma once for headers): @@ -76,7 +115,7 @@ Execute(The GCC handler shouldn't complain about #pragma once for headers): AssertEqual \ [], - \ ale#handlers#gcc#HandleGCCFormat(347, [ + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ \ '<stdin>:1:1: warning: #pragma once in main file [enabled by default]', \ ]) @@ -84,7 +123,7 @@ Execute(The GCC handler shouldn't complain about #pragma once for headers): AssertEqual \ [], - \ ale#handlers#gcc#HandleGCCFormat(347, [ + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ \ '<stdin>:1:1: warning: #pragma once in main file [enabled by default]', \ ]) @@ -119,7 +158,7 @@ Execute(The GCC handler should handle syntax errors): \ 'text': 'expected '';'' before ''o''' \ }, \ ], - \ ale#handlers#gcc#HandleGCCFormat(347, [ + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ \ '<stdin>:6:12: error: invalid suffix "p" on integer constant', \ '<stdin>:17:5: error: invalid suffix "n" on integer constant', \ '<stdin>:4: error: variable or field ''foo'' declared void', @@ -130,11 +169,27 @@ Execute(The GCC handler should handle syntax errors): Execute(The GCC handler should handle notes with no previous message): AssertEqual \ [], - \ ale#handlers#gcc#HandleGCCFormat(347, [ + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ \ '<stdin>:1:1: note: x', \ '<stdin>:1:1: note: x', \ ]) +Execute(The GCC handler should attach notes to previous messages): + AssertEqual + \ [ + \ { + \ 'lnum': 6, + \ 'col': 12, + \ 'type': 'E', + \ 'text': 'Some error', + \ 'detail': "Some error\n<stdin>:1:1: note: x", + \ }, + \ ], + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ + \ '-:6:12: error: Some error', + \ '<stdin>:1:1: note: x', + \ ]) + Execute(The GCC handler should interpret - as being the current file): AssertEqual \ [ @@ -145,7 +200,7 @@ Execute(The GCC handler should interpret - as being the current file): \ 'text': 'Some error', \ }, \ ], - \ ale#handlers#gcc#HandleGCCFormat(347, [ + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ \ '-:6:12: error: Some error', \ ]) @@ -159,6 +214,6 @@ Execute(The GCC handler should handle fatal error messages due to missing files) \ 'text': 'foo.h: No such file or directory' \ }, \ ], - \ ale#handlers#gcc#HandleGCCFormat(347, [ + \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [ \ '<stdin>:3:12: fatal error: foo.h: No such file or directory', \ ]) diff --git a/test/handler/test_gitlint_handler.vader b/test/handler/test_gitlint_handler.vader index 60d632a0..5c531664 100644 --- a/test/handler/test_gitlint_handler.vader +++ b/test/handler/test_gitlint_handler.vader @@ -61,6 +61,19 @@ Execute(Disabling trailing whitespace warnings should work): \ '8: T2 Trailing whitespace', \]) + AssertEqual + \ [ + \ { + \ 'lnum': 8, + \ 'type': 'E', + \ 'text': 'Trailing whitespace', + \ 'code': 'B2', + \ }, + \ ], + \ ale_linters#gitcommit#gitlint#Handle(bufnr(''), [ + \ '8: B2 Trailing whitespace', + \]) + let b:ale_warn_about_trailing_whitespace = 0 AssertEqual @@ -68,3 +81,9 @@ Execute(Disabling trailing whitespace warnings should work): \ ale_linters#gitcommit#gitlint#Handle(bufnr(''), [ \ '8: T2 Trailing whitespace', \ ]) + + AssertEqual + \ [], + \ ale_linters#gitcommit#gitlint#Handle(bufnr(''), [ + \ '8: B2 Trailing whitespace', + \ ]) diff --git a/test/handler/test_golangci_lint_handler.vader b/test/handler/test_golangci_lint_handler.vader new file mode 100644 index 00000000..fb6841f4 --- /dev/null +++ b/test/handler/test_golangci_lint_handler.vader @@ -0,0 +1,55 @@ +Before: + runtime ale_linters/go/golangci_lint.vim + +After: + call ale#linter#Reset() + +Execute (The golangci-lint handler should handle names with spaces): + " We can't test Windows paths with the path resovling on Linux, but we can + " test the regex. + AssertEqual + \ [ + \ [ + \ 'C:\something\file with spaces.go', + \ '12', + \ '3', + \ 'expected ''package'', found ''IDENT'' gibberish (staticcheck)', + \ ], + \ [ + \ 'C:\something\file with spaces.go', + \ '37', + \ '5', + \ 'expected ''package'', found ''IDENT'' gibberish (golint)', + \ ], + \ ], + \ map(ale_linters#go#golangci_lint#GetMatches([ + \ 'C:\something\file with spaces.go:12:3: expected ''package'', found ''IDENT'' gibberish (staticcheck)', + \ 'C:\something\file with spaces.go:37:5: expected ''package'', found ''IDENT'' gibberish (golint)', + \ ]), 'v:val[1:4]') + +Execute (The golangci-lint handler should handle paths correctly): + call ale#test#SetFilename('app/test.go') + + let file = ale#path#GetAbsPath(expand('%:p:h'), 'test.go') + + AssertEqual + \ [ + \ { + \ 'lnum': 12, + \ 'col': 3, + \ 'text': 'expected ''package'', found ''IDENT'' gibberish (staticcheck)', + \ 'type': 'E', + \ 'filename': ale#path#Simplify(expand('%:p:h') . '/test.go'), + \ }, + \ { + \ 'lnum': 37, + \ 'col': 5, + \ 'text': 'expected ''package'', found ''IDENT'' gibberish (golint)', + \ 'type': 'E', + \ 'filename': ale#path#Simplify(expand('%:p:h') . '/test.go'), + \ }, + \ ], + \ ale_linters#go#golangci_lint#Handler(bufnr(''), [ + \ file . ':12:3: expected ''package'', found ''IDENT'' gibberish (staticcheck)', + \ file . ':37:5: expected ''package'', found ''IDENT'' gibberish (golint)', + \ ]) diff --git a/test/handler/test_haskell_stack_handler.vader b/test/handler/test_haskell_stack_handler.vader new file mode 100644 index 00000000..07e7e69c --- /dev/null +++ b/test/handler/test_haskell_stack_handler.vader @@ -0,0 +1,7 @@ +Before: + runtime ale/handlers/haskell_stack.vim + +Execute(Escape stack should correctly identify a stack exec command): + AssertEqual + \ ale#Escape('stack') . ' exec ' . ale#Escape('hlint') . ' --', + \ ale#handlers#haskell_stack#EscapeExecutable('stack', 'hlint') diff --git a/test/handler/test_ispc_ispc_handler.vader b/test/handler/test_ispc_ispc_handler.vader new file mode 100644 index 00000000..619773fe --- /dev/null +++ b/test/handler/test_ispc_ispc_handler.vader @@ -0,0 +1,90 @@ +Before: + runtime ale_linters/ispc/ispc.vim + +After: + call ale#linter#Reset() + +Execute(The ispc handler should parse input correctly): + AssertEqual + \ [ + \ { + \ 'bufnr': 0, + \ 'lnum': 33, + \ 'col': 14, + \ 'type': 'E', + \ 'text': 'syntax error, unexpected ''int'', expecting '','' or '';''.', + \ }, + \ { + \ 'bufnr': 0, + \ 'lnum': 36, + \ 'col': 5, + \ 'type': 'E', + \ 'text': 'syntax error, unexpected ''for''.', + \ }, + \ { + \ 'bufnr': 0, + \ 'lnum': 51, + \ 'col': 9, + \ 'type': 'E', + \ 'text': '''foobar.h'' file not found', + \ }, + \ { + \ 'bufnr': 0, + \ 'lnum': 79, + \ 'col': 52, + \ 'type': 'W', + \ 'text': 'Modulus operator with varying types is very inefficient.', + \ }, + \ { + \ 'bufnr': 0, + \ 'lnum': 85, + \ 'col': 13, + \ 'type': 'W', + \ 'text': 'Undefined behavior: all program instances are writing to the same location!', + \ }, + \ { + \ 'bufnr': 0, + \ 'lnum': 93, + \ 'col': 19, + \ 'type': 'W', + \ 'text': 'Gather required to load value.', + \ }, + \ { + \ 'bufnr': 0, + \ 'lnum': 93, + \ 'col': 9, + \ 'type': 'W', + \ 'text': 'Scatter required to store value.', + \ }, + \ ], + \ ale_linters#ispc#ispc#Handle(0, [ + \ 'Warning: No output file or header file name specified. Program will be compiled and warnings/errors will be issued, but no output will be generated. ', + \ 'Warning: No --target specified on command-line. Using default system target "avx2-i32x8".', + \ 'mandelbrot.ispc:33:14: Error: syntax error, unexpected ''int'', expecting '','' or '';''.', + \ 'static iline int mandel(float c_re, float c_im, int count) {', + \ ' ^^^', + \ '', + \ 'mandelbrot.ispc:36:5: Error: syntax error, unexpected ''for''.', + \ ' for (i = 0; i < count; ++i) {', + \ ' ^^^', + \ '', + \ 'mandelbrot.ispc:51:9: fatal error: ''foobar.h'' file not found', + \ '#include<foobar.h>', + \ ' ^~~~~~~~~~', + \ 'mandelbrot.ispc:79:52: Performance Warning: Modulus operator with varying types is very inefficient.', + \ ' double x = x0 + i * (dx + epsilon*(k%2)*delta);', + \ ' ^^^', + \ '', + \ 'mandelbrot.ispc:85:13: Warning: Undefined behavior: all program instances are writing to the same location!', + \ ' output[index] = (NNN) / sample_size;', + \ ' ^^^^^^^^^^^^^', + \ '', + \ 'mandelbrot.ispc:93:19: Performance Warning: Gather required to load value.', + \ ' A[i*8] *= A[i*8];', + \ ' ^^^^^^', + \ '', + \ 'mandelbrot.ispc:93:9: Performance Warning: Scatter required to store value.', + \ ' A[i*8] *= A[i*8];', + \ ' ^^^^^^', + \ '', + \ ]) diff --git a/test/handler/test_perl6_handler.vader b/test/handler/test_perl6_handler.vader new file mode 100644 index 00000000..452a9174 --- /dev/null +++ b/test/handler/test_perl6_handler.vader @@ -0,0 +1,277 @@ +Before: + call ale#test#SetDirectory('/testplugin/test/handler') + + runtime ale_linters/perl6/perl6.vim + +After: + call ale#test#RestoreDirectory() + call ale#linter#Reset() + +Execute(The Perl6 linter should handle empty output): + call ale#test#SetFilename('bar.pl6') + + AssertEqual [], ale_linters#perl6#perl6#Handle(bufnr(''), []) + +Execute(The Perl6 linter should complain about undeclared variables): + call ale#test#SetFilename('bar.pl6') + + AssertEqual + \ [ + \ { + \ 'lnum': '6', + \ 'text': 'Variable ''$tes'' is not declared. Did you mean any of these? $res $test ', + \ 'type': 'E', + \ 'col': '', + \ 'end_lnum': '', + \ 'code': 'X::Undeclared', + \ } + \ ], + \ ale_linters#perl6#perl6#Handle(bufnr(''), [ + \ '{ + \ "X::Undeclared" : { + \ "highexpect" : [ ], + \ "is-compile-time" : 1, + \ "modules" : [ ], + \ "column" : null, + \ "pos" : 18, + \ "symbol" : "$tes", + \ "filename" : "bar.pl6", + \ "what" : "Variable", + \ "pre" : "my $test = 0; say ", + \ "post" : "$tes", + \ "suggestions" : [ + \ "$res", + \ "$test" + \ ], + \ "line" : 6, + \ "message" : "Variable ''$tes'' is not declared. Did you mean any of these?\n $res\n $test\n" + \ } + \ }' + \ ]) + +Execute(The Perl6 linter should complain about Comp::AdHoc errors): + call ale#test#SetFilename('bar.pl6') + + AssertEqual + \ [ + \ { + \ 'lnum': '3', + \ 'type': 'E', + \ 'text': 'is repr(...) trait needs a parameter', + \ 'col': '', + \ 'end_lnum': '', + \ 'code': 'X::Comp::AdHoc', + \ } + \ ], + \ ale_linters#perl6#perl6#Handle(bufnr(''), [ + \ '{ + \ "X::Comp::AdHoc" : { + \ "pre" : "class test is repr", + \ "message" : "is repr(...) trait needs a parameter", + \ "line" : 3, + \ "post" : " {}", + \ "is-compile-time" : true, + \ "pos" : 19, + \ "highexpect" : [ ], + \ "payload" : "is repr(...) trait needs a parameter", + \ "filename" : "bar.pl6", + \ "column" : null, + \ "modules" : [ ] + \ } + \ }' + \]) + +Execute(The Perl6 linter should be able to extract a line number from an error message): + call ale#test#SetFilename('bar.pl6') + + AssertEqual + \ [ + \ { + \ 'lnum': '3', + \ 'text': 'Could not find Module::Does::not::exist at line 3 in: /usr/share/perl6/site /usr/share/perl6/vendor /usr/share/perl6 CompUnit::Repository::AbsolutePath<94023691448416> CompUnit::Repository::NQP<94023670532736> CompUnit::Repository::Perl5<94023670532776>', + \ 'col': '', + \ 'type': 'E', + \ 'end_lnum': '', + \ 'code': 'X::CompUnit::UnsatisfiedDependency', + \ } + \ ], + \ ale_linters#perl6#perl6#Handle(bufnr(''), [ + \ '{ + \ "X::CompUnit::UnsatisfiedDependency" : { + \ "message" : "Could not find Module::Does::not::exist at line 3 in:\n /usr/share/perl6/site\n /usr/share/perl6/vendor\n /usr/share/perl6\n CompUnit::Repository::AbsolutePath<94023691448416>\n CompUnit::Repository::NQP<94023670532736>\n CompUnit::Repository::Perl5<94023670532776>", + \ "specification" : "Module::Does::not::exist" + \ } + \ }' + \ ]) + +Execute(The Perl6 linter should be able to differentiate between warnings and errors): + call ale#test#SetFilename('bar.pl6') + + AssertEqual + \ [ + \ { + \ 'lnum': '1', + \ 'col': '', + \ 'code': 'X::Syntax::Regex::Unterminated', + \ 'end_lnum': '', + \ 'type': 'E', + \ 'text': 'Regex not terminated.', + \ }, + \ { + \ 'lnum': '1', + \ 'col': '', + \ 'code': 'X::Comp::AdHoc', + \ 'end_lnum': '', + \ 'type': 'W', + \ 'text': 'Space is not significant here; please use quotes or :s (:sigspace) modifier (or, to suppress this warning, omit the space, or otherwise change the spacing)', + \ } + \ ], + \ ale_linters#perl6#perl6#Handle(bufnr(''), [ + \ '{ + \ "X::Comp::Group" : { + \ "message" : "Regex not terminated.\nUnable to parse regex; couldn''t find final ''/''\nSpace is not significant here; please use quotes or :s (:sigspace) modifier (or, to suppress this warning, omit the space, or otherwise change the spacing)", + \ "panic" : "Unable to parse regex; couldn''t find final ''/''", + \ "sorrows" : [ + \ { + \ "X::Syntax::Regex::Unterminated" : { + \ "highexpect" : [ + \ "infix stopper" + \ ], + \ "pos" : 6, + \ "is-compile-time" : 1, + \ "modules" : [ ], + \ "post" : "<EOL>", + \ "message" : "Regex not terminated.", + \ "line" : 1, + \ "filename" : "bar.pl6", + \ "column" : null, + \ "pre" : "/win 3" + \ } + \ } + \ ], + \ "worries" : [ + \ { + \ "X::Comp::AdHoc" : { + \ "filename" : "bar.pl6", + \ "line" : 1, + \ "column" : null, + \ "pre" : "/win", + \ "highexpect" : [ ], + \ "payload" : "Space is not significant here; please use quotes or :s (:sigspace) modifier (or, to suppress this warning, omit the space, or otherwise change the spacing)", + \ "post" : " 3", + \ "message" : "Space is not significant here; please use quotes or :s (:sigspace) modifier (or, to suppress this warning, omit the space, or otherwise change the spacing)", + \ "modules" : [ ], + \ "is-compile-time" : true, + \ "pos" : 4 + \ } + \ } + \ ] + \ } + \ }' + \]) + +Execute(The Perl6 linter should gracefully handle non-JSON messages): + call ale#test#SetFilename('bar.pl6') + + AssertEqual + \ [ + \ { + \ 'lnum': '1', + \ 'text': 'Received output in the default Perl6 error format. See :ALEDetail for details', + \ 'type': 'W', + \ 'detail': join([ + \ 'Potential difficulties:', + \ ' Redeclaration of symbol ''$_''', + \ ' at /home/travis/perl6-error-fail/insanity-test.pl6:1', + \ ' ------> sub foo($_) {.say}; my $_<HERE> = 1; .&foo;', + \ ' Space is not significant here; please use quotes or :s (:sigspace) modifier (or, to suppress this warning, omit the space, or otherwise change the spacing)', + \ ' at /home/travis/perl6-error-fail/insanity-test.pl6:4', + \ ' ------> /win<HERE> 3/', + \ 'Syntax OK',], "\n") + \ } + \ ], + \ ale_linters#perl6#perl6#Handle(bufnr(''), [ + \ 'Potential difficulties:', + \ ' Redeclaration of symbol ''$_''', + \ ' at /home/travis/perl6-error-fail/insanity-test.pl6:1', + \ ' ------> sub foo($_) {.say}; my $_<HERE> = 1; .&foo;', + \ ' Space is not significant here; please use quotes or :s (:sigspace) modifier (or, to suppress this warning, omit the space, or otherwise change the spacing)', + \ ' at /home/travis/perl6-error-fail/insanity-test.pl6:4', + \ ' ------> /win<HERE> 3/', + \ 'Syntax OK' + \ ]) + +Execute(The Perl6 linter should gracefully handle messages without a line number): + call ale#test#SetFilename('bar.pl6') + + AssertEqual + \ [ + \ { + \ 'lnum': '1', + \ 'end_lnum': '', + \ 'text': 'Cannot find method ''has_compile_time_value'' on object of type NQPMu', + \ 'type': 'E', + \ 'col' : '', + \ 'code': 'X::AdHoc', + \ } + \ ], + \ ale_linters#perl6#perl6#Handle(bufnr(''), [ + \ '{', + \ '"X::AdHoc" : {', + \ '"message" : "Cannot find method ''has_compile_time_value'' on object of type NQPMu",', + \ '"payload" : "Cannot find method ''has_compile_time_value'' on object of type NQPMu"', + \ '}', + \ '}', + \ ]) + +Execute(The Perl6 linter should not include errors from a known separate file): + call ale#test#SetFilename('bar.pl6') + + AssertEqual + \ [], + \ ale_linters#perl6#perl6#Handle(bufnr(''), [ + \ '{ + \ "X::Undeclared" : { + \ "highexpect" : [ ], + \ "is-compile-time" : 1, + \ "modules" : [ ], + \ "column" : null, + \ "pos" : 18, + \ "symbol" : "$tes", + \ "filename" : "foo.pl6", + \ "what" : "Variable", + \ "pre" : "my $test = 0; say ", + \ "post" : "$tes", + \ "suggestions" : [ + \ "$res", + \ "$test" + \ ], + \ "line" : 6, + \ "message" : "Variable ''$tes'' is not declared. Did you mean any of these?\n $res\n $test\n" + \ } + \ }' + \ ]) + +Execute(The Perl6 linter should not ignore errors without a filename): + call ale#test#SetFilename('bar.pl6') + + AssertEqual + \ [ + \ { + \ 'lnum': '3', + \ 'end_lnum': '', + \ 'text': 'Cannot find method ''has_compile_time_value'' on object of type NQPMu', + \ 'type': 'E', + \ 'col' : '', + \ 'code': 'X::AdHoc', + \ } + \ ], + \ ale_linters#perl6#perl6#Handle(bufnr(''), [ + \ '{', + \ '"X::AdHoc" : {', + \ '"line" : 3,', + \ '"message" : "Cannot find method ''has_compile_time_value'' on object of type NQPMu",', + \ '"payload" : "Cannot find method ''has_compile_time_value'' on object of type NQPMu"', + \ '}', + \ '}', + \ ]) diff --git a/test/handler/test_perl_handler.vader b/test/handler/test_perl_handler.vader index c5791d76..e769550c 100644 --- a/test/handler/test_perl_handler.vader +++ b/test/handler/test_perl_handler.vader @@ -7,6 +7,11 @@ After: call ale#test#RestoreDirectory() call ale#linter#Reset() +Execute(The Perl linter should handle empty output): + call ale#test#SetFilename('bar.pl') + + AssertEqual [], ale_linters#perl#perl#Handle(bufnr(''), []) + Execute(The Perl linter should ignore errors from other files): call ale#test#SetFilename('bar.pl') diff --git a/test/handler/test_pmd_handler.vader b/test/handler/test_pmd_handler.vader index 0c95fb2a..4f64c9ca 100644 --- a/test/handler/test_pmd_handler.vader +++ b/test/handler/test_pmd_handler.vader @@ -25,3 +25,18 @@ Execute(The pmd handler should parse lines correctly): \ '"1","rsb.performance.test.ros","/home/languitar/src/rsb-performance-test-api-ros/src/main/java/rsb/performance/test/ros/NodeHolder.java","3","18","Each class should declare at least one constructor","Code Style","AtLeastOneConstructor"', \ '"2","rsb.performance.test.ros","/home/languitar/src/rsb-performance-test-api-ros/src/main/java/rsb/performance/test/ros/NodeHolder.java","1","36","Local variable ''node'' could be declared final","Code Style","LocalVariableCouldBeFinal"' \ ]) + +Execute(The pmd handler should parse lines correctly for java files that use unnamed packages): + AssertEqual + \ [ + \ { + \ 'lnum': 8, + \ 'text': 'Avoid unused local variables such as ''stest''.', + \ 'code': 'Best Practices - UnusedLocalVariable', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#java#pmd#Handle(666, [ + \ '"Problem","Package","File","Priority","Line","Description","Rule set","Rule"', + \ '"1","","/Users/diego/Projects/github.com/dlresende/kata-fizz-buzz/src/main/java/App.java","3","8","Avoid unused local variables such as ''stest''.","Best Practices","UnusedLocalVariable"' + \ ]) diff --git a/test/handler/test_rust_handler.vader b/test/handler/test_rust_handler.vader index e3ab3e86..4764e713 100644 --- a/test/handler/test_rust_handler.vader +++ b/test/handler/test_rust_handler.vader @@ -285,3 +285,148 @@ Execute(The Rust handler should find correct files): \ }, \ }), \ ]) + +Execute(The Rust handler should remove secondary spans if set): + call ale#test#SetFilename('src/noerrors/mod.rs') + + let g:ale_rust_ignore_secondary_spans = 0 + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'end_lnum': 1, + \ 'type': 'E', + \ 'end_col': 21, + \ 'col': 1, + \ 'text': 'this function takes 1 parameter but 0 were supplied: defined here', + \ }, + \ { + \ 'lnum': 1, + \ 'end_lnum': 1, + \ 'type': 'E', + \ 'end_col': 46, + \ 'col': 40, + \ 'text': 'this function takes 1 parameter but 0 were supplied: expected 1 parameter', + \ }, + \ ], + \ ale#handlers#rust#HandleRustErrors(bufnr(''), [ + \ '', + \ 'fn test(x: u8) -> u8 { x } fn main() { x(); }', + \ json_encode({ + \ 'message': { + \ 'code': { + \ 'code': 'E0061', + \ 'explanation': 'Dummy explanation; not used' + \ }, + \ 'level': 'error', + \ 'message': 'this function takes 1 parameter but 0 were supplied', + \ 'spans': [ + \ { + \ 'byte_end': 20, + \ 'byte_start': 0, + \ 'column_end': 21, + \ 'column_start': 1, + \ 'file_name': 'src/noerrors/mod.rs', + \ 'is_primary': v:false, + \ 'label': 'defined here', + \ 'line_end': 1, + \ 'line_start': 1, + \ }, + \ { + \ 'byte_end': 45, + \ 'byte_start': 39, + \ 'column_end': 46, + \ 'column_start': 40, + \ 'file_name': '<anon>', + \ 'is_primary': v:true, + \ 'label': 'expected 1 parameter', + \ 'line_end': 1, + \ 'line_start': 1, + \ }, + \ ] + \ }, + \ }), + \ json_encode({ + \ 'message': { + \ 'code': v:null, + \ 'level': 'error', + \ 'message': 'aborting due to previous error', + \ 'spans': [] + \ }, + \ }), + \ json_encode({ + \ 'message': { + \ 'code': v:null, + \ 'level': 'error', + \ 'message': 'For more information about this error, try `rustc --explain E0061`.', + \ 'spans': [] + \ }, + \ }), + \ ]) + + let g:ale_rust_ignore_secondary_spans = 1 + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'end_lnum': 1, + \ 'type': 'E', + \ 'end_col': 46, + \ 'col': 40, + \ 'text': 'this function takes 1 parameter but 0 were supplied: expected 1 parameter', + \ }, + \ ], + \ ale#handlers#rust#HandleRustErrors(bufnr(''), [ + \ '', + \ 'fn test(x: u8) -> u8 { x } fn main() { x(); }', + \ json_encode({ + \ 'message': { + \ 'code': { + \ 'code': 'E0061', + \ 'explanation': 'Dummy explanation; not used' + \ }, + \ 'level': 'error', + \ 'message': 'this function takes 1 parameter but 0 were supplied', + \ 'spans': [ + \ { + \ 'byte_end': 20, + \ 'byte_start': 0, + \ 'column_end': 21, + \ 'column_start': 1, + \ 'file_name': 'src/noerrors/mod.rs', + \ 'is_primary': v:false, + \ 'label': 'defined here', + \ 'line_end': 1, + \ 'line_start': 1, + \ }, + \ { + \ 'byte_end': 45, + \ 'byte_start': 39, + \ 'column_end': 46, + \ 'column_start': 40, + \ 'file_name': '<anon>', + \ 'is_primary': v:true, + \ 'label': 'expected 1 parameter', + \ 'line_end': 1, + \ 'line_start': 1, + \ }, + \ ] + \ }, + \ }), + \ json_encode({ + \ 'message': { + \ 'code': v:null, + \ 'level': 'error', + \ 'message': 'aborting due to previous error', + \ 'spans': [] + \ }, + \ }), + \ json_encode({ + \ 'message': { + \ 'code': v:null, + \ 'level': 'error', + \ 'message': 'For more information about this error, try `rustc --explain E0061`.', + \ 'spans': [] + \ }, + \ }), + \ ]) diff --git a/test/handler/test_swipl_handler.vader b/test/handler/test_swipl_handler.vader new file mode 100644 index 00000000..9e425cf6 --- /dev/null +++ b/test/handler/test_swipl_handler.vader @@ -0,0 +1,95 @@ +Before: + runtime ale_linters/prolog/swipl.vim + +After: + call ale#linter#Reset() + +Execute (The swipl handler should handle oneline warning / error): + call ale#test#SetFilename('test.pl') + AssertEqual + \ [ + \ { + \ 'lnum': 5, + \ 'col': 1, + \ 'text': 'Syntax error: Operator expected', + \ 'type': 'E', + \ }, + \ ], + \ ale_linters#prolog#swipl#Handle(bufnr(''), [ + \ 'ERROR: /path/to/test.pl:5:1: Syntax error: Operator expected', + \ ]) + +Execute (The swipl handler should handle a warning / error of two lines): + call ale#test#SetFilename('test.pl') + AssertEqual + \ [ + \ { + \ 'lnum': 9, + \ 'col': 0, + \ 'text': 'Singleton variables: [M]', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#prolog#swipl#Handle(bufnr(''), [ + \ 'Warning: /path/to/test.pl:9:', + \ ' Singleton variables: [M]', + \ ]) + +Execute (The swipl handler should join three or more lines with '. '): + call ale#test#SetFilename('test.pl') + AssertEqual + \ [ + \ { + \ 'lnum': 10, + \ 'col': 0, + \ 'text': 'Clauses of fib/2 are not together in the source-file. Earlier definition at /path/to/test.pl:7. Current predicate: f/0. Use :- discontiguous fib/2. to suppress this message', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#prolog#swipl#Handle(bufnr(''), [ + \ 'Warning: /path/to/test.pl:10:', + \ ' Clauses of fib/2 are not together in the source-file', + \ ' Earlier definition at /path/to/test.pl:7', + \ ' Current predicate: f/0', + \ ' Use :- discontiguous fib/2. to suppress this message', + \ ]) + +Execute (The swipl handler should ignore warnings / errors 'No permission to call sandboxed ...'): + call ale#test#SetFilename('test.pl') + AssertEqual + \ [], + \ ale_linters#prolog#swipl#Handle(bufnr(''), [ + \ 'ERROR: /path/to/test.pl:11:', + \ ' No permission to call sandboxed `''$set_predicate_attribute''(_G3416:_G3417,_G3413,_G3414)''', + \ ' Reachable from:', + \ ' system:''$set_pattr''(A,B,C,D)', + \ ' system:''$set_pattr''(vimscript:A,B,C)', + \ ' vimscript: (multifile A)', + \ 'ERROR: /path/to/test.pl:12:', + \ ' No permission to call sandboxed `''$set_predicate_attribute''(_G205:_G206,_G202,_G203)''', + \ ' Reachable from:', + \ ' system:''$set_pattr''(A,B,C,D)', + \ ' system:''$set_pattr''(vimscript:A,B,C)', + \ ' vimscript: (multifile A)', + \ 'ERROR: /path/to/test.pl:13:', + \ ' No permission to call sandboxed `''$set_predicate_attribute''(_G1808:_G1809,_G1805,_G1806)''', + \ ' Reachable from:', + \ ' system:''$set_pattr''(A,B,C,D)', + \ ' system:''$set_pattr''(vimscript:A,B,C)', + \ ' vimscript: (multifile A)', + \ ]) + +Execute (The swipl handler should handle a warning / error with no line number): + call ale#test#SetFilename('test.pl') + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'col': 0, + \ 'text': 'Exported procedure module_name:pred/0 is not defined', + \ 'type': 'E', + \ }, + \ ], + \ ale_linters#prolog#swipl#Handle(bufnr(''), [ + \ 'ERROR: Exported procedure module_name:pred/0 is not defined', + \ ]) diff --git a/test/handler/test_vulture_handler.vader b/test/handler/test_vulture_handler.vader new file mode 100644 index 00000000..c6bd7643 --- /dev/null +++ b/test/handler/test_vulture_handler.vader @@ -0,0 +1,92 @@ +Before: + runtime ale_linters/python/vulture.vim + + call ale#test#SetDirectory('/testplugin/test/handler') + +After: + Restore + + call ale#test#RestoreDirectory() + call ale#linter#Reset() + + silent file something_else.py + +Execute(Basic vulture check with relative path in result should be handled): + call ale#test#SetFilename('something_else.py') + AssertEqual + \ [ + \ { + \ 'lnum': 34, + \ 'text': 'unused variable ''foo'' (60% confidence)', + \ 'type': 'W', + \ 'filename': ale#path#Simplify(g:dir . '/something_else.py'), + \ }, + \ ], + \ ale_linters#python#vulture#Handle(bufnr(''), [ + \ './something_else.py:34: unused variable ''foo'' (60% confidence)', + \ ]) + +Execute(Basic vulture check with absolute path in result should be handled): + call ale#test#SetFilename('something_else.py') + AssertEqual + \ [ + \ { + \ 'lnum': 34, + \ 'text': 'unused variable ''foo'' (60% confidence)', + \ 'type': 'W', + \ 'filename': ale#path#Simplify(g:dir . '/something_else.py'), + \ }, + \ ], + \ ale_linters#python#vulture#Handle(bufnr(''), [ + \ ale#path#Simplify(g:dir . '/something_else.py') . ':34: unused variable ''foo'' (60% confidence)', + \ ]) + +Execute(Vulture check for two files should be handled): + call ale#test#SetFilename('something_else.py') + AssertEqual + \ [ + \ { + \ 'lnum': 34, + \ 'text': 'unused variable ''foo'' (60% confidence)', + \ 'type': 'W', + \ 'filename': ale#path#Simplify(g:dir . '/something_else.py'), + \ }, + \ { + \ 'lnum': 12, + \ 'text': 'unused variable ''bar'' (60% confidence)', + \ 'type': 'W', + \ 'filename': ale#path#Simplify(g:dir . '/second_one.py'), + \ }, + \ ], + \ ale_linters#python#vulture#Handle(bufnr(''), [ + \ './something_else.py:34: unused variable ''foo'' (60% confidence)', + \ './second_one.py:12: unused variable ''bar'' (60% confidence)', + \ ]) + + +Execute(Vulture exception should be handled): + call ale#test#SetFilename('something_else.py') + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'text': 'An exception was thrown. See :ALEDetail', + \ 'detail': join([ + \ 'Traceback (most recent call last):', + \ ' File "/usr/lib/python3.6/site-packages/vulture/__init__.py", line 13, in <module>', + \ ' from .core import stuff', + \ 'BaddestException: Everything gone wrong', + \ ], "\n"), + \ } + \ ], + \ ale_linters#python#vulture#Handle(bufnr(''), [ + \ 'Traceback (most recent call last):', + \ ' File "/usr/lib/python3.6/site-packages/vulture/__init__.py", line 13, in <module>', + \ ' from .core import stuff', + \ 'BaddestException: Everything gone wrong', + \ ]) + +Execute(The vulture handler should handle empty output): + AssertEqual + \ [], + \ ale_linters#python#vulture#Handle(bufnr(''), []) diff --git a/test/lsp/test_did_save_event.vader b/test/lsp/test_did_save_event.vader index 428135fb..f8ff8f70 100644 --- a/test/lsp/test_did_save_event.vader +++ b/test/lsp/test_did_save_event.vader @@ -13,6 +13,7 @@ Before: let b:ale_enabled = 1 let g:ale_lsp_next_message_id = 1 let g:ale_run_synchronously = 1 + let g:conn_id = v:null let g:message_list = [] function! LanguageCallback() abort @@ -34,26 +35,29 @@ Before: let g:ale_linters = {'foobar': ['dummy_linter']} function! ale#lsp_linter#StartLSP(buffer, linter) abort - let l:conn = ale#lsp#NewConnection({}) - let l:conn.id = 347 - let l:conn.open_documents = {a:buffer : -1} + let g:conn_id = ale#lsp#Register('executable', '/foo/bar', {}) + call ale#lsp#MarkDocumentAsOpen(g:conn_id, a:buffer) return { \ 'buffer': a:buffer, - \ 'connection_id': 347, + \ 'connection_id': g:conn_id, \ 'project_root': '/foo/bar', \ 'language_id': 'foobar', \} endfunction " Replace the Send function for LSP, so we can monitor calls to it. - function! ale#lsp#Send(conn_id, message, ...) abort + function! ale#lsp#Send(conn_id, message) abort call add(g:message_list, a:message) endfunction After: Restore + if g:conn_id isnot v:null + call ale#lsp#RemoveConnectionWithID(g:conn_id) + endif + unlet! b:ale_enabled unlet! b:ale_linters unlet! g:message_list @@ -61,7 +65,6 @@ After: delfunction LanguageCallback delfunction ProjectRootCallback - call ale#lsp#RemoveConnectionWithID(347) call ale#test#RestoreDirectory() call ale#linter#Reset() diff --git a/test/lsp/test_lsp_client_messages.vader b/test/lsp/test_lsp_client_messages.vader index dc28c2e9..71768ce5 100644 --- a/test/lsp/test_lsp_client_messages.vader +++ b/test/lsp/test_lsp_client_messages.vader @@ -161,6 +161,17 @@ Execute(ale#lsp#message#References() should return correct messages): \ ], \ ale#lsp#message#References(bufnr(''), 12, 34) +Execute(ale#lsp#message#Symbol() should return correct messages): + AssertEqual + \ [ + \ 0, + \ 'workspace/symbol', + \ { + \ 'query': 'foobar', + \ } + \ ], + \ ale#lsp#message#Symbol('foobar') + Execute(ale#lsp#message#Hover() should return correct messages): AssertEqual \ [ @@ -175,6 +186,22 @@ Execute(ale#lsp#message#Hover() should return correct messages): \ ], \ ale#lsp#message#Hover(bufnr(''), 12, 34) +Execute(ale#lsp#message#DidChangeConfiguration() should return correct messages): + let g:ale_lsp_configuration = { + \ 'foo': 'bar' + \ } + AssertEqual + \ [ + \ 0, + \ 'workspace/didChangeConfiguration', + \ { + \ 'settings': { + \ 'foo': 'bar', + \ } + \ } + \ ], + \ ale#lsp#message#DidChangeConfiguration(bufnr(''), g:ale_lsp_configuration) + Execute(ale#lsp#tsserver_message#Open() should return correct messages): AssertEqual \ [ diff --git a/test/lsp/test_lsp_command_formatting.vader b/test/lsp/test_lsp_command_formatting.vader index 9d2c84ee..9721f37f 100644 --- a/test/lsp/test_lsp_command_formatting.vader +++ b/test/lsp/test_lsp_command_formatting.vader @@ -5,7 +5,7 @@ Before: " Mock the StartProgram function so we can just capture the arguments. function! ale#lsp#StartProgram(...) abort - let g:args = a:000 + let g:args = a:000[1:] endfunction After: @@ -27,10 +27,10 @@ Execute(Command formatting should be applied correctly for LSP linters): if has('win32') AssertEqual - \ ['cmd', 'cmd /s/c "cmd --foo"', {}], + \ ['cmd', 'cmd /s/c "cmd --foo"'], \ g:args else AssertEqual - \ ['true', [&shell, '-c', '''true'' --foo'], {}], + \ ['true', [&shell, '-c', '''true'' --foo']], \ g:args endif diff --git a/test/lsp/test_lsp_connections.vader b/test/lsp/test_lsp_connections.vader index ae64eadb..1c2fceab 100644 --- a/test/lsp/test_lsp_connections.vader +++ b/test/lsp/test_lsp_connections.vader @@ -225,57 +225,3 @@ Execute(ale#lsp#ReadMessageData() should handle a message with part of a second \ . '{"id":2,"jsonrpc":"2.0","result":{"foo":"barÜ"}}' \ . b:data \ ) - -Execute(Projects with regular project roots should be registered correctly): - let b:conn = ale#lsp#NewConnection({}) - call ale#lsp#RegisterProject(b:conn.id, '/foo/bar') - - AssertEqual - \ { - \ '/foo/bar': { - \ 'root': '/foo/bar', - \ 'initialized': 0, - \ 'message_queue': [], - \ 'capabilities_queue': [], - \ 'init_request_id': 0, - \ }, - \ }, - \ b:conn.projects - -Execute(Projects with regular project roots should be fetched correctly): - let b:conn = { - \ 'projects': { - \ '/foo/bar': {'initialized': 0, 'message_queue': [], 'init_request_id': 0}, - \ }, - \} - - AssertEqual - \ {'initialized': 0, 'message_queue': [], 'init_request_id': 0}, - \ ale#lsp#GetProject(b:conn, '/foo/bar') - -Execute(Projects with empty project roots should be registered correctly): - let b:conn = ale#lsp#NewConnection({}) - call ale#lsp#RegisterProject(b:conn.id, '') - - AssertEqual - \ { - \ '<<EMPTY>>': { - \ 'root': '', - \ 'initialized': 1, - \ 'message_queue': [], - \ 'capabilities_queue': [], - \ 'init_request_id': 0, - \ }, - \ }, - \ b:conn.projects - -Execute(Projects with empty project roots should be fetched correctly): - let b:conn = { - \ 'projects': { - \ '<<EMPTY>>': {'initialized': 1, 'message_queue': [], 'init_request_id': 0}, - \ }, - \} - - AssertEqual - \ {'initialized': 1, 'message_queue': [], 'init_request_id': 0}, - \ ale#lsp#GetProject(b:conn, '') diff --git a/test/lsp/test_other_initialize_message_handling.vader b/test/lsp/test_other_initialize_message_handling.vader index 45457979..2f59535d 100644 --- a/test/lsp/test_other_initialize_message_handling.vader +++ b/test/lsp/test_other_initialize_message_handling.vader @@ -1,83 +1,47 @@ Before: - let b:project = { + let b:conn = { + \ 'is_tsserver': 0, + \ 'data': '', + \ 'root': '/foo/bar', + \ 'open_documents': {}, \ 'initialized': 0, - \ 'init_request_id': 3, + \ 'init_request_id': 0, + \ 'init_options': {}, + \ 'config': {}, + \ 'callback_list': [], \ 'message_queue': [], \ 'capabilities_queue': [], - \} - - let b:conn = { - \ 'projects': { - \ '/foo/bar': b:project, - \ }, \ 'capabilities': { \ 'hover': 0, \ 'references': 0, \ 'completion': 0, \ 'completion_trigger_characters': [], \ 'definition': 0, + \ 'symbol_search': 0, \ }, \} After: - unlet! b:project unlet! b:conn -Execute(publishDiagnostics messages with files inside project directories should initialize projects): - " This is for some other file, ignore this one. - call ale#lsp#HandleOtherInitializeResponses(b:conn, { - \ 'method': 'textDocument/publishDiagnostics', - \ 'params': {'uri': 'file:///xyz/bar/baz.txt'}, - \}) - - AssertEqual - \ { - \ 'initialized': 0, - \ 'init_request_id': 3, - \ 'message_queue': [], - \ 'capabilities_queue': [], - \ }, - \ b:project - - call ale#lsp#HandleOtherInitializeResponses(b:conn, { - \ 'method': 'textDocument/publishDiagnostics', - \ 'params': {'uri': 'file:///foo/bar/baz.txt'}, - \}) - - AssertEqual - \ { - \ 'initialized': 1, - \ 'init_request_id': 3, - \ 'message_queue': [], - \ 'capabilities_queue': [], - \ }, - \ b:project - Execute(Messages with no method and capabilities should initialize projects): - call ale#lsp#HandleOtherInitializeResponses(b:conn, { + call ale#lsp#HandleInitResponse(b:conn, { \ 'result': {'capabilities': {}}, \}) - AssertEqual - \ { - \ 'initialized': 1, - \ 'init_request_id': 3, - \ 'message_queue': [], - \ 'capabilities_queue': [], - \ }, - \ b:project + AssertEqual 1, b:conn.initialized Execute(Other messages should not initialize projects): - call ale#lsp#HandleOtherInitializeResponses(b:conn, {'method': 'lolwat'}) + call ale#lsp#HandleInitResponse(b:conn, {'method': 'lolwat'}) - AssertEqual 0, b:project.initialized + AssertEqual 0, b:conn.initialized - call ale#lsp#HandleOtherInitializeResponses(b:conn, {'result': {'x': {}}}) + call ale#lsp#HandleInitResponse(b:conn, {'result': {'x': {}}}) - AssertEqual 0, b:project.initialized + AssertEqual 0, b:conn.initialized Execute(Capabilities should bet set up correctly): - call ale#lsp#HandleOtherInitializeResponses(b:conn, { + call ale#lsp#HandleInitResponse(b:conn, { \ 'jsonrpc': '2.0', \ 'id': 1, \ 'result': { @@ -105,34 +69,26 @@ Execute(Capabilities should bet set up correctly): \ }, \ 'definitionProvider': v:true, \ 'experimental': {}, - \ 'documentHighlightProvider': v:true + \ 'documentHighlightProvider': v:true, + \ 'workspaceSymbolProvider': v:true \ }, \ }, \}) + AssertEqual 1, b:conn.initialized AssertEqual \ { - \ 'capabilities': { - \ 'completion_trigger_characters': ['.'], - \ 'completion': 1, - \ 'references': 1, - \ 'hover': 1, - \ 'definition': 1, - \ }, - \ 'message_queue': [], - \ 'projects': { - \ '/foo/bar': { - \ 'initialized': 1, - \ 'message_queue': [], - \ 'capabilities_queue': [], - \ 'init_request_id': 3, - \ }, - \ }, + \ 'completion_trigger_characters': ['.'], + \ 'completion': 1, + \ 'references': 1, + \ 'hover': 1, + \ 'definition': 1, + \ 'symbol_search': 1, \ }, - \ b:conn + \ b:conn.capabilities Execute(Disabled capabilities should be recognised correctly): - call ale#lsp#HandleOtherInitializeResponses(b:conn, { + call ale#lsp#HandleInitResponse(b:conn, { \ 'jsonrpc': '2.0', \ 'id': 1, \ 'result': { @@ -161,23 +117,21 @@ Execute(Disabled capabilities should be recognised correctly): \ }, \}) + AssertEqual 1, b:conn.initialized AssertEqual \ { - \ 'capabilities': { - \ 'completion_trigger_characters': [], - \ 'completion': 0, - \ 'references': 0, - \ 'hover': 0, - \ 'definition': 0, - \ }, - \ 'message_queue': [], - \ 'projects': { - \ '/foo/bar': { - \ 'initialized': 1, - \ 'message_queue': [], - \ 'capabilities_queue': [], - \ 'init_request_id': 3, - \ }, - \ }, + \ 'completion_trigger_characters': [], + \ 'completion': 0, + \ 'references': 0, + \ 'hover': 0, + \ 'definition': 0, + \ 'symbol_search': 0, \ }, - \ b:conn + \ b:conn.capabilities + +Execute(Results that are not dictionaries should be handled correctly): + call ale#lsp#HandleInitResponse(b:conn, { + \ 'jsonrpc': '2.0', + \ 'id': 1, + \ 'result': v:null, + \}) diff --git a/test/lsp/test_read_lsp_diagnostics.vader b/test/lsp/test_read_lsp_diagnostics.vader index 6ca4f962..a5c5ded3 100644 --- a/test/lsp/test_read_lsp_diagnostics.vader +++ b/test/lsp/test_read_lsp_diagnostics.vader @@ -18,7 +18,7 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle errors): \ 'col': 11, \ 'end_lnum': 5, \ 'end_col': 16, - \ 'nr': 'some-error', + \ 'code': 'some-error', \ } \ ], \ ale#lsp#response#ReadDiagnostics({'params': {'uri': 'filename.ts', 'diagnostics': [ @@ -39,7 +39,7 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle warnings): \ 'col': 4, \ 'end_lnum': 2, \ 'end_col': 4, - \ 'nr': 'some-warning', + \ 'code': 'some-warning', \ } \ ], \ ale#lsp#response#ReadDiagnostics({'params': {'uri': 'filename.ts', 'diagnostics': [ @@ -60,7 +60,7 @@ Execute(ale#lsp#response#ReadDiagnostics() should treat messages with missing se \ 'col': 11, \ 'end_lnum': 5, \ 'end_col': 16, - \ 'nr': 'some-error', + \ 'code': 'some-error', \ } \ ], \ ale#lsp#response#ReadDiagnostics({'params': {'uri': 'filename.ts', 'diagnostics': [ @@ -109,6 +109,25 @@ Execute(ale#lsp#response#ReadDiagnostics() should include sources in detail): \ } \ ]}}) +Execute(ale#lsp#response#ReadDiagnostics() should consider -1 to be a meaningless code): + AssertEqual [ + \ { + \ 'type': 'E', + \ 'text': 'Something went wrong!', + \ 'lnum': 3, + \ 'col': 11, + \ 'end_lnum': 5, + \ 'end_col': 16, + \ } + \ ], + \ ale#lsp#response#ReadDiagnostics({'params': {'uri': 'filename.ts', 'diagnostics': [ + \ { + \ 'range': Range(2, 10, 4, 15), + \ 'message': 'Something went wrong!', + \ 'code': -1, + \ }, + \ ]}}) + Execute(ale#lsp#response#ReadDiagnostics() should handle multiple messages): AssertEqual [ \ { @@ -140,12 +159,42 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle multiple messages): \ }, \ ]}}) +Execute(ale#lsp#response#ReadDiagnostics() should use relatedInformation for detail): + AssertEqual [ + \ { + \ 'type': 'E', + \ 'text': 'Something went wrong!', + \ 'lnum': 1, + \ 'col': 3, + \ 'end_lnum': 1, + \ 'end_col': 3, + \ 'detail': "Something went wrong!\n/tmp/someotherfile.txt:43:80:\n\tmight be this" + \ } + \ ], + \ ale#lsp#response#ReadDiagnostics({'params': {'uri': 'filename.ts', 'diagnostics': [ + \ { + \ 'range': Range(0, 2, 0, 2), + \ 'message': 'Something went wrong!', + \ 'relatedInformation': [{ + \ 'message': 'might be this', + \ 'location': { + \ 'uri': 'file:///tmp/someotherfile.txt', + \ 'range': { + \ 'start': { 'line': 42, 'character': 79 }, + \ 'end': { 'line': 142, 'character': 179}, + \ } + \ } + \ }] + \ } + \ ]}}) + Execute(ale#lsp#response#ReadTSServerDiagnostics() should handle tsserver responses): AssertEqual \ [ \ { \ 'type': 'E', \ 'nr': 2365, + \ 'code': '2365', \ 'text': 'Operator ''''+'''' cannot be applied to types ''''3'''' and ''''{}''''.', \ 'lnum': 1, \ 'col': 11, @@ -162,6 +211,7 @@ Execute(ale#lsp#response#ReadTSServerDiagnostics() should handle warnings from t \ 'lnum': 27, \ 'col': 3, \ 'nr': 2515, + \ 'code': '2515', \ 'end_lnum': 27, \ 'type': 'W', \ 'end_col': 14, @@ -177,6 +227,7 @@ Execute(ale#lsp#response#ReadTSServerDiagnostics() should handle suggestions fro \ 'lnum': 27, \ 'col': 3, \ 'nr': 2515, + \ 'code': '2515', \ 'end_lnum': 27, \ 'type': 'I', \ 'end_col': 14, diff --git a/test/lsp/test_update_config.vader b/test/lsp/test_update_config.vader new file mode 100644 index 00000000..07068bc8 --- /dev/null +++ b/test/lsp/test_update_config.vader @@ -0,0 +1,17 @@ +Before: + runtime autoload/ale/lsp.vim + + let g:conn_id = ale#lsp#Register('executable', '/foo/bar', {}) + +After: + Restore + + unlet! g:conn_id + + runtime autoload/ale/lsp.vim + +Execute(Only send updates when the configuration dictionary changes): + AssertEqual 0, ale#lsp#UpdateConfig(g:conn_id, bufnr(''), {}) + AssertEqual 1, ale#lsp#UpdateConfig(g:conn_id, bufnr(''), {'a': 1}) + AssertEqual 0, ale#lsp#UpdateConfig(g:conn_id, bufnr(''), {'a': 1}) + AssertEqual 1, ale#lsp#UpdateConfig(g:conn_id, bufnr(''), {}) diff --git a/test/ocaml-test-files/testfile.ml b/test/ocaml-test-files/testfile.ml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/ocaml-test-files/testfile.ml diff --git a/test/python_fixtures/pipenv/Pipfile.lock b/test/python_fixtures/pipenv/Pipfile.lock new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/python_fixtures/pipenv/Pipfile.lock diff --git a/test/ruby_fixtures/valid_ruby_app1/Rakefile b/test/ruby_fixtures/valid_ruby_app1/Rakefile new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/ruby_fixtures/valid_ruby_app1/Rakefile diff --git a/test/ruby_fixtures/valid_ruby_app1/lib/file.rb b/test/ruby_fixtures/valid_ruby_app1/lib/file.rb new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/ruby_fixtures/valid_ruby_app1/lib/file.rb diff --git a/test/ruby_fixtures/valid_ruby_app2/Gemfile b/test/ruby_fixtures/valid_ruby_app2/Gemfile new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/ruby_fixtures/valid_ruby_app2/Gemfile diff --git a/test/ruby_fixtures/valid_ruby_app2/lib/file.rb b/test/ruby_fixtures/valid_ruby_app2/lib/file.rb new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/ruby_fixtures/valid_ruby_app2/lib/file.rb diff --git a/test/ruby_fixtures/valid_ruby_app3/.solargraph.yml b/test/ruby_fixtures/valid_ruby_app3/.solargraph.yml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/ruby_fixtures/valid_ruby_app3/.solargraph.yml diff --git a/test/ruby_fixtures/valid_ruby_app3/lib/file.rb b/test/ruby_fixtures/valid_ruby_app3/lib/file.rb new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/ruby_fixtures/valid_ruby_app3/lib/file.rb diff --git a/test/scala_fixtures/invalid_sbt_project/Main.scala b/test/scala_fixtures/invalid_sbt_project/Main.scala new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/scala_fixtures/invalid_sbt_project/Main.scala diff --git a/test/scala_fixtures/valid_sbt_project/Main.scala b/test/scala_fixtures/valid_sbt_project/Main.scala new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/scala_fixtures/valid_sbt_project/Main.scala diff --git a/test/scala_fixtures/valid_sbt_project/build.sbt b/test/scala_fixtures/valid_sbt_project/build.sbt new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/scala_fixtures/valid_sbt_project/build.sbt diff --git a/test/script/block-padding-checker b/test/script/block-padding-checker new file mode 100755 index 00000000..b13c9b92 --- /dev/null +++ b/test/script/block-padding-checker @@ -0,0 +1,117 @@ +#!/usr/bin/env python +""" +This script checks for missing or forbidden blank lines before or after +particular Vim commands. This script ensures that VimL scripts are padded +correctly, so they are easier to read. +""" + +import sys +import re + +INDENTATION_RE = re.compile(r'^ *') +COMMENT_LINE_RE = re.compile(r'^ *"') +COMMAND_RE = re.compile(r'^ *([a-zA-Z]+)') + +START_BLOCKS = set(['if', 'for', 'while', 'try', 'function']) +END_BLOCKS = set(['endif', 'endfor', 'endwhile', 'endtry', 'endfunction']) +MIDDLE_BLOCKS = set(['else', 'elseif', 'catch', 'finally']) +TERMINATORS = set(['return', 'throw']) + +WHITESPACE_BEFORE_SET = START_BLOCKS | TERMINATORS +WHITESPACE_FORBIDDEN_BEFORE_SET = END_BLOCKS | MIDDLE_BLOCKS +WHITESPACE_AFTER_SET = END_BLOCKS +WHITESPACE_FORBIDDEN_AFTER_SET = START_BLOCKS | MIDDLE_BLOCKS + + +def remove_comment_lines(line_iter): + for line_number, line in enumerate(line_iter, 1): + if not COMMENT_LINE_RE.match(line): + yield (line_number, line) + + +def check_lines(line_iter): + previous_indentation_level = None + previous_command = None + previous_line_blank = False + + for line_number, line in remove_comment_lines(line_iter): + if len(line) == 0: + # Check for commands where we shouldn't have blank lines after + # them, like `else` or the start of blocks like `function`. + if ( + previous_command is not None + and previous_command in WHITESPACE_FORBIDDEN_AFTER_SET + ): + yield ( + line_number, + 'Blank line forbidden after `%s`' % (command,) + ) + + previous_line_blank = True + previous_command = None + else: + indentation_level = INDENTATION_RE.match(line).end() + command_match = COMMAND_RE.match(line) + + if command_match: + command = command_match.group(1) + + # Check for commands requiring blank lines before them, if they + # aren't at the start of a block. + if ( + command in WHITESPACE_BEFORE_SET + and previous_indentation_level is not None + and indentation_level == previous_indentation_level + and previous_line_blank is False + ): + yield ( + line_number, + 'Blank line required before `%s`' % (command,) + ) + + # Check for commands where we shouldn't have blank lines before + # them, like `else` or the end of blocks like `endfunction`. + if ( + command in WHITESPACE_FORBIDDEN_BEFORE_SET + and previous_line_blank is True + ): + yield ( + line_number - 1, + 'Blank line forbidden before `%s`' % (command,) + ) + + # Check for commands requiring blank lines after them, if they + # aren't at the end of a block. + if ( + previous_command is not None + and previous_command in WHITESPACE_AFTER_SET + and previous_indentation_level is not None + and indentation_level == previous_indentation_level + and previous_line_blank is False + ): + yield ( + line_number - 1, + 'Blank line required after `%s`' % (command,) + ) + + previous_command = command + previous_line_blank = False + previous_indentation_level = indentation_level + + +def main(): + status = 0 + + for filename in sys.argv[1:]: + with open(filename) as vim_file: + line_iter = (line.rstrip() for line in vim_file) + + for line_number, message in check_lines(line_iter): + print('%s:%d %s' % (filename, line_number, message)) + status = 1 + + sys.exit(status) + + +if __name__ == "__main__": + main() diff --git a/test/script/custom-linting-rules b/test/script/custom-linting-rules index 69c4a7a1..77e87db4 100755 --- a/test/script/custom-linting-rules +++ b/test/script/custom-linting-rules @@ -59,10 +59,11 @@ check_errors() { fi for directory in "${directories[@]}"; do - while IFS= read -r match; do + # shellcheck disable=SC2086 + while read -r; do RETURN_CODE=1 - echo "$match $message" - done < <(grep -n "$regex" $include_arg "$directory"/**/*.vim \ + echo "$REPLY $message" + done < <(grep -H -n "$regex" $include_arg "$directory"/**/*.vim \ | grep -v 'no-custom-checks' \ | grep -o '^[^:]\+:[0-9]\+' \ | sed 's:^\./::') @@ -77,6 +78,17 @@ if (( FIX_ERRORS )); then sed -i 's/==?/is?/g' "$directory"/**/*.vim sed -i 's/!=#/isnot#/g' "$directory"/**/*.vim sed -i 's/!=?/isnot?/g' "$directory"/**/*.vim + # Improving type checks. + sed -i $'s/\\(==.\\?\\|is\\) type([\'"]\+)/is v:t_string/g' "$directory"/**/*.vim + sed -i 's/\(==.\?\|is\) type([0-9]\+)/is v:t_number/g' "$directory"/**/*.vim + sed -i 's/\(==.\?\|is\) type(\[\])/is v:t_list/g' "$directory"/**/*.vim + sed -i 's/\(==.\?\|is\) type({})/is v:t_dict/g' "$directory"/**/*.vim + sed -i 's/\(==.\?\|is\) type(function([^)]\+))/is v:t_func/g' "$directory"/**/*.vim + sed -i $'s/\\(!=.\\?\\|isnot\\) type([\'"]\+)/isnot v:t_string/g' "$directory"/**/*.vim + sed -i 's/\(!=.\?\|isnot\) type([0-9]\+)/isnot v:t_number/g' "$directory"/**/*.vim + sed -i 's/\(!=.\?\|isnot\) type(\[\])/isnot v:t_list/g' "$directory"/**/*.vim + sed -i 's/\(!=.\?\|isnot\) type({})/isnot v:t_dict/g' "$directory"/**/*.vim + sed -i 's/\(!=.\?\|isnot\) type(function([^)]\+))/isnot v:t_func/g' "$directory"/**/*.vim done fi @@ -102,5 +114,25 @@ check_errors '!=#' "Use 'isnot#' instead of '!=#'. 0 !=# 'foobar' is false" check_errors '!=?' "Use 'isnot?' instead of '!=?'. 0 !=? 'foobar' is false" check_errors '^ *:\?echo' "Stray echo line. Use \`execute echo\` if you want to echo something" check_errors $'name.:.*\'[a-z_]*[^a-z_0-9][a-z_0-9]*\',$' 'Use snake_case names for linters' '*/ale_linters/*' +# Checks for improving type checks. +check_errors $'\\(==.\\?\\|is\\) type([\'"]\+)' "Use 'is v:t_string' instead" +check_errors '\(==.\?\|is\) type([0-9]\+)' "Use 'is v:t_number' instead" +check_errors '\(==.\?\|is\) type(\[\])' "Use 'is v:t_list' instead" +check_errors '\(==.\?\|is\) type({})' "Use 'is v:t_dict' instead" +check_errors '\(==.\?\|is\) type(function([^)]\+))' "Use 'is v:t_func' instead" +check_errors $'\\(!=.\\?\\|isnot\\) type([\'"]\+)' "Use 'isnot v:t_string' instead" +check_errors '\(!=.\?\|isnot\) type([0-9]\+)' "Use 'isnot v:t_number' instead" +check_errors '\(!=.\?\|isnot\) type(\[\])' "Use 'isnot v:t_list' instead" +check_errors '\(!=.\?\|isnot\) type({})' "Use 'isnot v:t_dict' instead" +check_errors '\(!=.\?\|isnot\) type(function([^)]\+))' "Use 'isnot v:t_func' instead" + +# Run a Python script to find lines that require padding around them. For +# users without Python installed, we'll skip these checks. Travis CI will run +# the script. +if command -v python > /dev/null; then + if ! test/script/block-padding-checker "$directory"/**/*.vim; then + RETURN_CODE=1 + fi +fi exit $RETURN_CODE diff --git a/test/smoke_test.vader b/test/smoke_test.vader index 2708c86f..c87f95b2 100644 --- a/test/smoke_test.vader +++ b/test/smoke_test.vader @@ -65,7 +65,7 @@ Execute(Linters should run with the default options): " Try the test a few times over in NeoVim 0.3 or Windows, " where tests fail randomly. for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1) - call ale#Lint() + call ale#Queue(0, '') call ale#engine#WaitForJobs(2000) let g:results = ale#test#GetLoclistWithoutModule() @@ -109,7 +109,7 @@ Execute(Linters should run in PowerShell too): \ 'command': 'echo foo && echo bar', \}) - call ale#Lint() + call ale#Queue(0, '') call ale#engine#WaitForJobs(4000) AssertEqual [ @@ -139,7 +139,7 @@ Execute(Linters should run in PowerShell too): endif Execute(Previous errors should be removed when linters change): - call ale#Lint() + call ale#Queue(0, '') call ale#engine#WaitForJobs(2000) call ale#linter#Reset() @@ -166,7 +166,7 @@ Execute(Previous errors should be removed when linters change): " Try the test a few times over in NeoVim 0.3 or Windows, " where tests fail randomly. for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1) - call ale#Lint() + call ale#Queue(0, '') call ale#engine#WaitForJobs(2000) let g:results = ale#test#GetLoclistWithoutModule() diff --git a/test/test_ale_info.vader b/test/test_ale_info.vader index 39a2a85a..325c2aa8 100644 --- a/test/test_ale_info.vader +++ b/test/test_ale_info.vader @@ -88,14 +88,14 @@ Before: \ 'let g:ale_lint_delay = 200', \ 'let g:ale_lint_on_enter = 1', \ 'let g:ale_lint_on_filetype_changed = 1', + \ 'let g:ale_lint_on_insert_leave = 0', \ 'let g:ale_lint_on_save = 1', \ 'let g:ale_lint_on_text_changed = ''always''', - \ 'let g:ale_lint_on_insert_leave = 0', \ 'let g:ale_linter_aliases = {}', \ 'let g:ale_linters = {}', \ 'let g:ale_linters_explicit = 0', - \ 'let g:ale_list_window_size = 10', \ 'let g:ale_list_vertical = 0', + \ 'let g:ale_list_window_size = 10', \ 'let g:ale_loclist_msg_format = ''%code: %%s''', \ 'let g:ale_max_buffer_history_size = 20', \ 'let g:ale_max_signs = -1', @@ -118,6 +118,7 @@ Before: \ 'let g:ale_statusline_format = [''%d error(s)'', ''%d warning(s)'', ''OK'']', \ 'let g:ale_type_map = {}', \ 'let g:ale_use_global_executables = v:null', + \ 'let g:ale_virtualtext_cursor = 0', \ 'let g:ale_warn_about_trailing_blank_lines = 1', \ 'let g:ale_warn_about_trailing_whitespace = 1', \] diff --git a/test/test_alejobstarted_autocmd.vader b/test/test_alejobstarted_autocmd.vader index 388e5439..6fa1ff8e 100644 --- a/test/test_alejobstarted_autocmd.vader +++ b/test/test_alejobstarted_autocmd.vader @@ -23,10 +23,11 @@ After: let g:ale_run_synchronously = 0 - try - augroup! VaderTest - catch - endtry + augroup VaderTest + autocmd! + augroup END + + augroup! VaderTest unlet! g:job_started_success @@ -38,7 +39,7 @@ Execute(Run a lint cycle with an actual job to check for ALEJobStarted): augroup VaderTest autocmd! autocmd User ALEJobStarted let g:job_started_success = 1 - augroup end + augroup END ALELint diff --git a/test/test_alelint_autocmd.vader b/test/test_alelint_autocmd.vader index 5af1cd47..332cb36f 100644 --- a/test/test_alelint_autocmd.vader +++ b/test/test_alelint_autocmd.vader @@ -9,20 +9,21 @@ After: let g:ale_run_synchronously = 0 let g:ale_buffer_info = {} - try - augroup! VaderTest - catch - endtry + augroup VaderTest + autocmd! + augroup END + + augroup! VaderTest -Given foobar(An empty file): +Given testft(An empty file): Execute(Run a lint cycle, and check that a variable is set in the autocmd): augroup VaderTest autocmd! autocmd User ALELintPre let g:pre_success = 1 autocmd User ALELintPost let g:post_success = 1 - augroup end + augroup END - call ale#Lint() + call ale#Queue(0) AssertEqual g:pre_success, 1 AssertEqual g:post_success, 1 @@ -30,10 +31,10 @@ Execute(Run a lint cycle, and check that a variable is set in the autocmd): Execute(b:ale_linted should be increased after each lint cycle): AssertEqual get(b:, 'ale_linted'), 0 - call ale#Lint() + call ale#Queue(0) AssertEqual get(b:, 'ale_linted'), 1 - call ale#Lint() + call ale#Queue(0) AssertEqual get(b:, 'ale_linted'), 2 diff --git a/test/test_autocmd_commands.vader b/test/test_autocmd_commands.vader index 8d5048f0..4bb894ba 100644 --- a/test/test_autocmd_commands.vader +++ b/test/test_autocmd_commands.vader @@ -175,10 +175,19 @@ Execute (g:ale_lint_on_filetype_changed = 1 should bind the FileType event): \ filter(CheckAutocmd('ALEEvents'), 'v:val =~ ''\v^FileType''') Execute (ALECleanupGroup should include the right commands): - AssertEqual [ - \ 'BufDelete * if exists(''*ale#engine#Cleanup'') | call ale#engine#Cleanup(str2nr(expand(''<abuf>''))) | endif', - \ 'QuitPre * call ale#events#QuitEvent(str2nr(expand(''<abuf>'')))', - \], CheckAutocmd('ALECleanupGroup') + if exists('##VimSuspend') + AssertEqual [ + \ 'BufDelete * if exists(''*ale#engine#Cleanup'') | call ale#engine#Cleanup(str2nr(expand(''<abuf>''))) | endif', + \ 'QuitPre * call ale#events#QuitEvent(str2nr(expand(''<abuf>'')))', + \ 'VimSuspend * if exists(''*ale#engine#CleanupEveryBuffer'') | call ale#engine#CleanupEveryBuffer() | endif', + \], CheckAutocmd('ALECleanupGroup') + else + AssertEqual [ + \ 'BufDelete * if exists(''*ale#engine#Cleanup'') | call ale#engine#Cleanup(str2nr(expand(''<abuf>''))) | endif', + \ 'QuitPre * call ale#events#QuitEvent(str2nr(expand(''<abuf>'')))', + \], CheckAutocmd('ALECleanupGroup') + endif + Execute(Enabling completion should set up autocmd events correctly): let g:ale_completion_enabled = 0 diff --git a/test/test_c_flag_parsing.vader b/test/test_c_flag_parsing.vader new file mode 100644 index 00000000..8a9b7189 --- /dev/null +++ b/test/test_c_flag_parsing.vader @@ -0,0 +1,179 @@ +Before: + Save g:ale_c_parse_makefile + + call ale#test#SetDirectory('/testplugin/test') + + let g:ale_c_parse_makefile = 1 + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The CFlags parser should be able to parse include directives): + call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') + + AssertEqual + \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')), + \ ale#c#ParseCFlagsFromMakeOutput(bufnr(''), ['gcc -Isubdir -c file.c']) + +Execute(The CFlags parser should be able to parse macro directives): + call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') + + AssertEqual + \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) + \ . ' -DTEST=1', + \ ale#c#ParseCFlagsFromMakeOutput(bufnr(''), ['gcc -Isubdir -DTEST=1 -c file.c']) + +Execute(The CFlags parser should be able to parse macro directives with spaces): + call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') + + AssertEqual + \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) + \ . ' -DTEST=$(( 2 * 4 ))', + \ ale#c#ParseCFlagsFromMakeOutput(bufnr(''), ['gcc -Isubdir -DTEST=$(( 2 * 4 )) -c file.c']) + +Execute(The CFlags parser should be able to parse shell directives with spaces): + call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') + + AssertEqual + \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) + \ . ' -DTEST=`date +%s`', + \ ale#c#ParseCFlagsFromMakeOutput(bufnr(''), ['gcc -Isubdir -DTEST=`date +%s` -c file.c']) + +Execute(ParseCFlags should be able to parse flags with relative paths): + AssertEqual + \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) + \ . ' ' . ale#Escape('-I' . 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 -Isubdir ' + \ . '-I'. ale#path#Simplify('kernel/include') + \ . ' -DTEST=`date +%s` -c file.c' + \ ) + +Execute(ParseCFlags should be able to parse -Dgoal): + AssertEqual + \ '-Dgoal=9' + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) + \ . ' ' . ale#Escape('-I' . 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' + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) + \ . ' ' . ale#Escape('-I' . 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): + AssertEqual + \ '-Dgoal=9' + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir with spaces')) + \ . ' ' . ale#Escape('-I' . 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 ' + \ . '-I"dir with spaces"' . ' -I'. ale#path#Simplify('kernel/include') + \ . ' -DTEST=`date +%s` -c file.c' + \ ) + +Execute(ParseCFlags should handle paths with spaces in single quotes): + AssertEqual + \ '-Dgoal=9' + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir with spaces')) + \ . ' ' . ale#Escape('-I' . 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 ' + \ . '-I''dir with spaces''' . ' -I'. ale#path#Simplify('kernel/include') + \ . ' -DTEST=`date +%s` -c file.c' + \ ) + +Execute(ParseCFlags should handle paths with minuses): + AssertEqual + \ '-Dgoal=9' + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir with spaces')) + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir-with-dash')) + \ . ' ' . ale#Escape('-I' . 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 ' + \ . '-I''dir with spaces''' . ' -Idir-with-dash' + \ . ' -I'. ale#path#Simplify('kernel/include') + \ . ' -DTEST=`date +%s` -c file.c' + \ ) + +Execute(ParseCFlags should handle -D with minuses): + AssertEqual + \ '-Dgoal=9' + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) + \ . ' -Dmacro-with-dash' + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir with spaces')) + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir-with-dash')) + \ . ' ' . ale#Escape('-I' . 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 ' + \ . '-Dmacro-with-dash ' + \ . '-I''dir with spaces''' . ' -Idir-with-dash' + \ . ' -I'. ale#path#Simplify('kernel/include') + \ . ' -DTEST=`date +%s` -c file.c' + \ ) + +Execute(ParseCFlags should handle flags at the end of the line): + AssertEqual + \ '-Dgoal=9' + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')) + \ . ' -Dmacro-with-dash' + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir with spaces')) + \ . ' ' . ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir-with-dash')) + \ . ' ' . ale#Escape('-I' . 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 ' + \ . '-Dmacro-with-dash ' + \ . '-I''dir with spaces''' . ' -Idir-with-dash' + \ . ' -I'. ale#path#Simplify('kernel/include') + \ ) + +Execute(FlagsFromCompileCommands should tolerate empty values): + AssertEqual '', ale#c#FlagsFromCompileCommands(bufnr(''), '') + +Execute(ParseCompileCommandsFlags should tolerate empty values): + AssertEqual '', ale#c#ParseCompileCommandsFlags(bufnr(''), '', []) + +Execute(ParseCompileCommandsFlags should parse some basic flags): + 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(''), ale#path#Simplify('/foo/bar/xmms2-mpris'), [ + \ { + \ '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'), + \ }, + \ ]) diff --git a/test/test_c_import_paths.vader b/test/test_c_import_paths.vader deleted file mode 100644 index 0490dec6..00000000 --- a/test/test_c_import_paths.vader +++ /dev/null @@ -1,252 +0,0 @@ -Before: - " Make sure the c.vim file is loaded first. - call ale#c#FindProjectRoot(bufnr('')) - - Save g:ale_c_gcc_options - Save g:ale_c_clang_options - Save g:ale_cpp_gcc_options - Save g:ale_cpp_clang_options - Save g:__ale_c_project_filenames - - let g:original_project_filenames = g:__ale_c_project_filenames - - " Remove the .git/HEAD dir for C import paths for these tests. - " The tests run inside of a git repo. - let g:__ale_c_project_filenames = filter( - \ copy(g:__ale_c_project_filenames), - \ 'v:val isnot# ''.git/HEAD''' - \) - - call ale#test#SetDirectory('/testplugin/test') - - let g:ale_c_gcc_options = '' - let g:ale_c_clang_options = '' - let g:ale_cpp_gcc_options = '' - let g:ale_cpp_clang_options = '' - -After: - Restore - - unlet! g:original_project_filenames - - call ale#test#RestoreDirectory() - call ale#linter#Reset() - -Execute(The C GCC handler should include 'include' directories for projects with a Makefile): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ ale#Escape('gcc') - \ . ' -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')) . ' ' - \ . ' -' - \ , ale_linters#c#gcc#GetCommand(bufnr(''), []) - -Execute(The C GCC handler should include 'include' directories for projects with a configure file): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/configure_project/subdir/file.c') - - AssertEqual - \ ale#Escape('gcc') - \ . ' -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')) . ' ' - \ . ' -' - \ , ale_linters#c#gcc#GetCommand(bufnr(''), []) - -Execute(The C GCC handler should include root directories for projects with .h files in them): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/h_file_project/subdir/file.c') - - AssertEqual - \ ale#Escape('gcc') - \ . ' -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')) . ' ' - \ . ' -' - \ , ale_linters#c#gcc#GetCommand(bufnr(''), []) - -Execute(The C GCC handler should include root directories for projects with .hpp files in them): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/hpp_file_project/subdir/file.c') - - AssertEqual - \ ale#Escape('gcc') - \ . ' -S -x c -fsyntax-only ' - \ . '-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')) . ' ' - \ . ' -' - \ , ale_linters#c#gcc#GetCommand(bufnr(''), []) - -Execute(The C Clang handler should include 'include' directories for projects with a Makefile): - runtime! ale_linters/c/clang.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ 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')) . ' ' - \ . ' -' - \ , ale_linters#c#clang#GetCommand(bufnr(''), []) - -Execute(The C Clang handler should include 'include' directories for projects with a configure file): - runtime! ale_linters/c/clang.vim - - call ale#test#SetFilename('test_c_projects/h_file_project/subdir/file.c') - - AssertEqual - \ 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')) . ' ' - \ . ' -' - \ , ale_linters#c#clang#GetCommand(bufnr(''), []) - -Execute(The C Clang handler should include root directories for projects with .h files in them): - runtime! ale_linters/c/clang.vim - - call ale#test#SetFilename('test_c_projects/h_file_project/subdir/file.c') - - AssertEqual - \ 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')) . ' ' - \ . ' -' - \ , ale_linters#c#clang#GetCommand(bufnr(''), []) - -Execute(The C Clang handler should include root directories for projects with .hpp files in them): - runtime! ale_linters/c/clang.vim - - call ale#test#SetFilename('test_c_projects/hpp_file_project/subdir/file.c') - - AssertEqual - \ ale#Escape('clang') - \ . ' -S -x c -fsyntax-only ' - \ . '-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')) . ' ' - \ . ' -' - \ , ale_linters#c#clang#GetCommand(bufnr(''), []) - -Execute(The C++ GCC handler should include 'include' directories for projects with a Makefile): - runtime! ale_linters/cpp/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.cpp') - - AssertEqual - \ ale#Escape('gcc') - \ . ' -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')) . ' ' - \ . ' -' - \ , ale_linters#cpp#gcc#GetCommand(bufnr(''), []) - -Execute(The C++ GCC handler should include 'include' directories for projects with a configure file): - runtime! ale_linters/cpp/gcc.vim - - call ale#test#SetFilename('test_c_projects/configure_project/subdir/file.cpp') - - AssertEqual - \ ale#Escape('gcc') - \ . ' -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')) . ' ' - \ . ' -' - \ , ale_linters#cpp#gcc#GetCommand(bufnr(''), []) - -Execute(The C++ GCC handler should include root directories for projects with .h files in them): - runtime! ale_linters/cpp/gcc.vim - - call ale#test#SetFilename('test_c_projects/h_file_project/subdir/file.cpp') - - AssertEqual - \ ale#Escape('gcc') - \ . ' -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')) . ' ' - \ . ' -' - \ , ale_linters#cpp#gcc#GetCommand(bufnr(''), []) - -Execute(The C++ GCC handler should include root directories for projects with .hpp files in them): - runtime! ale_linters/cpp/gcc.vim - - call ale#test#SetFilename('test_c_projects/hpp_file_project/subdir/file.cpp') - - AssertEqual - \ ale#Escape('gcc') - \ . ' -S -x c++ -fsyntax-only ' - \ . '-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')) . ' ' - \ . ' -' - \ , ale_linters#cpp#gcc#GetCommand(bufnr(''), []) - -Execute(The C++ Clang handler should include 'include' directories for projects with a Makefile): - runtime! ale_linters/cpp/clang.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.cpp') - - AssertEqual - \ 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')) . ' ' - \ . ' -' - \ , ale_linters#cpp#clang#GetCommand(bufnr(''), []) - -Execute(The C++ Clang handler should include 'include' directories for projects with a configure file): - runtime! ale_linters/cpp/clang.vim - - call ale#test#SetFilename('test_c_projects/configure_project/subdir/file.cpp') - - AssertEqual - \ 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')) . ' ' - \ . ' -' - \ , ale_linters#cpp#clang#GetCommand(bufnr(''), []) - -Execute(The C++ Clang handler should include root directories for projects with .h files in them): - runtime! ale_linters/cpp/clang.vim - - call ale#test#SetFilename('test_c_projects/h_file_project/subdir/file.cpp') - - AssertEqual - \ 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')) . ' ' - \ . ' -' - \ , ale_linters#cpp#clang#GetCommand(bufnr(''), []) - -Execute(The C++ Clang handler should include root directories for projects with .hpp files in them): - runtime! ale_linters/cpp/clang.vim - - call ale#test#SetFilename('test_c_projects/hpp_file_project/subdir/file.cpp') - - AssertEqual - \ ale#Escape('clang++') - \ . ' -S -x c++ -fsyntax-only ' - \ . '-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')) . ' ' - \ . ' -' - \ , ale_linters#cpp#clang#GetCommand(bufnr(''), []) - -Execute(The C++ ClangTidy handler should include json folders for projects with suitable build directory in them): - runtime! ale_linters/cpp/clangtidy.vim - - call ale#test#SetFilename('test_c_projects/json_project/subdir/file.cpp') - - AssertEqual - \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('*') . ' %s ' - \ . '-p ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/json_project/build')) - \ , ale_linters#cpp#clangtidy#GetCommand(bufnr('')) diff --git a/test/test_c_parse_makefile.vader b/test/test_c_parse_makefile.vader deleted file mode 100644 index 7c2fc21e..00000000 --- a/test/test_c_parse_makefile.vader +++ /dev/null @@ -1,184 +0,0 @@ -Before: - Save g:ale_c_parse_makefile - Save g:ale_c_gcc_options - Save g:ale_c_clang_options - Save g:ale_cpp_gcc_options - Save g:ale_cpp_clang_options - - call ale#test#SetDirectory('/testplugin/test') - - let g:ale_c_parse_makefile=1 - let g:ale_c_gcc_options = '' - let g:ale_c_clang_options = '' - let g:ale_cpp_gcc_options = '' - let g:ale_cpp_clang_options = '' - -After: - Restore - - call ale#test#RestoreDirectory() - call ale#linter#Reset() - -Execute(The CFlags parser should be able to parse include directives): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ [ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir'))] - \ , ale#c#ParseCFlags(bufnr(''), 'gcc -Isubdir -c file.c') - -Execute(The CFlags parser should be able to parse macro directives): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ [ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')), - \ '-DTEST=1'] - \ , ale#c#ParseCFlags(bufnr(''), 'gcc -Isubdir -DTEST=1 -c file.c') - -Execute(The CFlags parser should be able to parse macro directives with spaces): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ [ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')), - \ '-DTEST=$(( 2 * 4 ))'] - \ , ale#c#ParseCFlags(bufnr(''), 'gcc -Isubdir -DTEST=$(( 2 * 4 )) -c file.c') - -Execute(The CFlags parser should be able to parse shell directives with spaces): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ [ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')), - \ '-DTEST=`date +%s`'] - \ , ale#c#ParseCFlags(bufnr(''), 'gcc -Isubdir -DTEST=`date +%s` -c file.c') - -Execute(The CFlagsToList parser should be able to parse multiple cflags): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ [ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')), - \ '-DTEST=`date +%s`'] - \ , ale#c#ParseCFlagsToList(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), - \ split('gcc -Isubdir -DTEST=`date +%s` -c file.c', '-')) - -Execute(The CFlagsToList parser should be able to parse multiple cflags #2): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ [ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')), - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')), - \ '-DTEST=`date +%s`'] - \ , ale#c#ParseCFlagsToList(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), - \ split('gcc -Isubdir ' . - \ '-I'. ale#path#Simplify('kernel/include') . - \ ' -DTEST=`date +%s` -c file.c', '-')) - -Execute(The CFlagsToList parser should be able to parse multiple cflags #3): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ ['-Dgoal=9', - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')), - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')), - \ '-DTEST=`date +%s`'] - \ , ale#c#ParseCFlagsToList(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), - \ split('gcc -Dgoal=9 -Isubdir ' . - \ '-I'. ale#path#Simplify('kernel/include') . - \ ' -DTEST=`date +%s` -c file.c', '-')) - -Execute(The CFlagsToList parser should be able to parse multiple cflags #4): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ ['-Dgoal=9', - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')), - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')), - \ '-DTEST=`date +%s`'] - \ , ale#c#ParseCFlagsToList(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), - \ split('gcc -Dgoal=9 -Tlinkerfile.ld blabla -Isubdir ' . - \ '-I'. ale#path#Simplify('kernel/include') . - \ ' -DTEST=`date +%s` -c file.c', '-')) - -Execute(The CFlagsToList parser should be able to parse multiple cflags #5): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ ['-Dgoal=9', - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')), - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir with spaces')), - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')), - \ '-DTEST=`date +%s`'] - \ , ale#c#ParseCFlagsToList(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), - \ split('gcc -Dgoal=9 -Tlinkerfile.ld blabla -Isubdir ' . - \ '-I"dir with spaces"' . ' -I'. ale#path#Simplify('kernel/include') . - \ ' -DTEST=`date +%s` -c file.c', '-')) - -Execute(The CFlagsToList parser should be able to parse multiple cflags #6): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ ['-Dgoal=9', - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')), - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir with spaces')), - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')), - \ '-DTEST=`date +%s`'] - \ , ale#c#ParseCFlagsToList(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), - \ split('gcc -Dgoal=9 -Tlinkerfile.ld blabla -Isubdir ' . - \ '-I''dir with spaces''' . ' -I'. ale#path#Simplify('kernel/include') . - \ ' -DTEST=`date +%s` -c file.c', '-')) - -Execute(The CFlagsToList parser should be able to parse multiple cflags #7): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ ['-Dgoal=9', - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')), - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir with spaces')), - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir-with-dash')), - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')), - \ '-DTEST=`date +%s`'] - \ , ale#c#ParseCFlagsToList(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), - \ split('gcc -Dgoal=9 -Tlinkerfile.ld blabla -Isubdir ' . - \ '-I''dir with spaces''' . ' -Idir-with-dash' . - \ ' -I'. ale#path#Simplify('kernel/include') . - \ ' -DTEST=`date +%s` -c file.c', '-')) - -Execute(The CFlagsToList parser should be able to parse multiple cflags #8): - runtime! ale_linters/c/gcc.vim - - call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') - - AssertEqual - \ ['-Dgoal=9', - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/subdir')), - \ '-Dmacro-with-dash', - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir with spaces')), - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/dir-with-dash')), - \ ale#Escape('-I' . ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/kernel/include')), - \ '-DTEST=`date +%s`'] - \ , ale#c#ParseCFlagsToList(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), - \ split('gcc -Dgoal=9 -Tlinkerfile.ld blabla -Isubdir ' . - \ '-Dmacro-with-dash ' . - \ '-I''dir with spaces''' . ' -Idir-with-dash' . - \ ' -I'. ale#path#Simplify('kernel/include') . - \ ' -DTEST=`date +%s` -c file.c', '-')) diff --git a/test/test_checkingbuffer_autocmd.vader b/test/test_checkingbuffer_autocmd.vader index 9e3a8188..9e642b15 100644 --- a/test/test_checkingbuffer_autocmd.vader +++ b/test/test_checkingbuffer_autocmd.vader @@ -31,7 +31,7 @@ After: augroup VaderTest autocmd! - augroup end + augroup END augroup! VaderTest @@ -40,7 +40,7 @@ Execute(ALELintPre should not return success on ale#engine#IsCheckingBuffer): augroup VaderTest autocmd! autocmd User ALELintPre let g:checking_buffer = ale#engine#IsCheckingBuffer(bufnr('')) ? 1 : 0 - augroup end + augroup END ALELint @@ -50,7 +50,7 @@ Execute(ALEJobStarted should return success on ale#engine#IsCheckingBuffer): augroup VaderTest autocmd! autocmd User ALEJobStarted let g:checking_buffer = ale#engine#IsCheckingBuffer(bufnr('')) ? 1 : 0 - augroup end + augroup END ALELint diff --git a/test/test_command_chain.vader b/test/test_command_chain.vader index 9059d630..591f6f40 100644 --- a/test/test_command_chain.vader +++ b/test/test_command_chain.vader @@ -62,7 +62,7 @@ Given foobar (Some imaginary filetype): Execute(Check the results of running the chain): AssertEqual 'foobar', &filetype - call ale#Lint() + call ale#Queue(0) Assert g:first_echo_called, 'The first chain item was not called' Assert g:second_echo_called, 'The second chain item was not called' diff --git a/test/test_elm_executable_detection.vader b/test/test_elm_executable_detection.vader deleted file mode 100644 index 9146eea6..00000000 --- a/test/test_elm_executable_detection.vader +++ /dev/null @@ -1,36 +0,0 @@ -Before: - call ale#test#SetDirectory('/testplugin/test') - runtime ale_linters/elm/make.vim - -After: - unlet! g:ale_elm_make_use_global - unlet! g:ale_elm_make_executable - - call ale#test#RestoreDirectory() - -Execute(should get valid executable with default params): - call ale#test#SetFilename('elm-test-files/app/testfile.elm') - - AssertEqual - \ ale#path#Simplify(g:dir . '/elm-test-files/app/node_modules/.bin/elm'), - \ ale_linters#elm#make#GetExecutable(bufnr('')) - -Execute(should get valid executable with 'use_global' params): - let g:ale_elm_make_use_global = 1 - - call ale#test#SetFilename('elm-test-files/app/testfile.elm') - - AssertEqual - \ 'elm', - \ ale_linters#elm#make#GetExecutable(bufnr('')) - -Execute(should get valid executable with 'use_global' and 'executable' params): - let g:ale_elm_make_executable = 'other-elm' - let g:ale_elm_make_use_global = 1 - - call ale#test#SetFilename('elm-test-files/app/testfile.elm') - - AssertEqual - \ 'other-elm', - \ ale_linters#elm#make#GetExecutable(bufnr('')) - diff --git a/test/test_engine_lsp_response_handling.vader b/test/test_engine_lsp_response_handling.vader index 517d82c0..04f12ad6 100644 --- a/test/test_engine_lsp_response_handling.vader +++ b/test/test_engine_lsp_response_handling.vader @@ -2,6 +2,8 @@ Before: Save g:ale_buffer_info Save g:ale_lsp_error_messages + let g:ale_buffer_info = {} + unlet! g:ale_lsp_error_messages call ale#test#SetDirectory('/testplugin/test') @@ -63,7 +65,7 @@ Execute(tsserver syntax error responses should be handled correctly): \ 'vcol': 0, \ 'nr': 1005, \ 'type': 'E', - \ 'text': ''','' expected.', + \ 'text': '1005: '','' expected.', \ 'valid': 1, \ 'pattern': '', \ }, @@ -136,7 +138,7 @@ Execute(tsserver semantic error responses should be handled correctly): \ 'vcol': 0, \ 'nr': 1005, \ 'type': 'E', - \ 'text': 'Some semantic error', + \ 'text': '1005: Some semantic error', \ 'valid': 1, \ 'pattern': '', \ }, diff --git a/test/test_find_references.vader b/test/test_find_references.vader index ecced068..88b2d762 100644 --- a/test/test_find_references.vader +++ b/test/test_find_references.vader @@ -9,6 +9,7 @@ Before: let g:preview_called = 0 let g:item_list = [] let g:capability_checked = '' + let g:conn_id = v:null let g:WaitCallback = v:null runtime autoload/ale/linter.vim @@ -17,19 +18,18 @@ Before: runtime autoload/ale/preview.vim function! ale#lsp_linter#StartLSP(buffer, linter) abort - let l:conn = ale#lsp#NewConnection({}) - let l:conn.id = 347 - let l:conn.open_documents = {a:buffer : -1} + let g:conn_id = ale#lsp#Register('executable', '/foo/bar', {}) + call ale#lsp#MarkDocumentAsOpen(g:conn_id, a:buffer) return { \ 'buffer': a:buffer, - \ 'connection_id': 347, + \ 'connection_id': g:conn_id, \ 'project_root': '/foo/bar', \ 'language_id': 'python', \} endfunction - function! ale#lsp#WaitForCapability(conn_id, project_root, capability, callback) abort + function! ale#lsp#WaitForCapability(conn_id, capability, callback) abort let g:capability_checked = a:capability let g:WaitCallback = a:callback endfunction @@ -38,7 +38,7 @@ Before: let g:Callback = a:callback endfunction - function! ale#lsp#Send(conn_id, message, root) abort + function! ale#lsp#Send(conn_id, message) abort call add(g:message_list, a:message) return 42 @@ -54,7 +54,10 @@ Before: endfunction After: - call ale#lsp#RemoveConnectionWithID(347) + if g:conn_id isnot v:null + call ale#lsp#RemoveConnectionWithID(g:conn_id) + endif + call ale#references#SetMap({}) call ale#test#RestoreDirectory() call ale#linter#Reset() @@ -62,6 +65,7 @@ After: unlet! g:capability_checked unlet! g:WaitCallback unlet! g:old_filename + unlet! g:conn_id unlet! g:Callback unlet! g:message_list unlet! g:expr_list @@ -168,7 +172,7 @@ Execute(tsserver reference requests should be sent): AssertEqual type(function('type')), type(g:WaitCallback) AssertEqual 'references', g:capability_checked - call call(g:WaitCallback, [347, '/foo/bar']) + call call(g:WaitCallback, [g:conn_id, '/foo/bar']) AssertEqual \ 'function(''ale#references#HandleTSServerResponse'')', @@ -249,7 +253,7 @@ Execute(LSP reference requests should be sent): AssertEqual type(function('type')), type(g:WaitCallback) AssertEqual 'references', g:capability_checked - call call(g:WaitCallback, [347, '/foo/bar']) + call call(g:WaitCallback, [g:conn_id, '/foo/bar']) AssertEqual \ 'function(''ale#references#HandleLSPResponse'')', diff --git a/test/test_go_to_definition.vader b/test/test_go_to_definition.vader index 7f0e3fcb..66c24fb6 100644 --- a/test/test_go_to_definition.vader +++ b/test/test_go_to_definition.vader @@ -7,6 +7,7 @@ Before: let g:message_list = [] let g:expr_list = [] let g:capability_checked = '' + let g:conn_id = v:null let g:WaitCallback = v:null runtime autoload/ale/linter.vim @@ -14,19 +15,18 @@ Before: runtime autoload/ale/util.vim function! ale#lsp_linter#StartLSP(buffer, linter) abort - let l:conn = ale#lsp#NewConnection({}) - let l:conn.id = 347 - let l:conn.open_documents = {a:buffer : -1} + let g:conn_id = ale#lsp#Register('executable', '/foo/bar', {}) + call ale#lsp#MarkDocumentAsOpen(g:conn_id, a:buffer) return { \ 'buffer': a:buffer, - \ 'connection_id': 347, + \ 'connection_id': g:conn_id, \ 'project_root': '/foo/bar', \ 'language_id': 'python', \} endfunction - function! ale#lsp#WaitForCapability(conn_id, project_root, capability, callback) abort + function! ale#lsp#WaitForCapability(conn_id, capability, callback) abort let g:capability_checked = a:capability let g:WaitCallback = a:callback endfunction @@ -35,7 +35,7 @@ Before: let g:Callback = a:callback endfunction - function! ale#lsp#Send(conn_id, message, root) abort + function! ale#lsp#Send(conn_id, message) abort call add(g:message_list, a:message) return 42 @@ -46,7 +46,10 @@ Before: endfunction After: - call ale#lsp#RemoveConnectionWithID(347) + if g:conn_id isnot v:null + call ale#lsp#RemoveConnectionWithID(g:conn_id) + endif + call ale#definition#SetMap({}) call ale#test#RestoreDirectory() call ale#linter#Reset() @@ -54,6 +57,7 @@ After: unlet! g:capability_checked unlet! g:WaitCallback unlet! g:old_filename + unlet! g:conn_id unlet! g:Callback unlet! g:message_list unlet! g:expr_list @@ -111,7 +115,7 @@ Execute(Other files should be jumped to for definition responses): AssertEqual \ [ - \ 'edit ' . fnameescape(ale#path#Simplify(g:dir . '/completion_dummy_file')), + \ 'edit +3 ' . fnameescape(ale#path#Simplify(g:dir . '/completion_dummy_file')), \ ], \ g:expr_list AssertEqual [3, 7], getpos('.')[1:2] @@ -136,7 +140,7 @@ Execute(Other files should be jumped to for definition responses in tabs too): AssertEqual \ [ - \ 'tabedit ' . fnameescape(ale#path#Simplify(g:dir . '/completion_dummy_file')), + \ 'tabedit +3 ' . fnameescape(ale#path#Simplify(g:dir . '/completion_dummy_file')), \ ], \ g:expr_list AssertEqual [3, 7], getpos('.')[1:2] @@ -153,7 +157,7 @@ Execute(tsserver completion requests should be sent): AssertEqual type(function('type')), type(g:WaitCallback) AssertEqual 'definition', g:capability_checked - call call(g:WaitCallback, [347, '/foo/bar']) + call call(g:WaitCallback, [g:conn_id, '/foo/bar']) AssertEqual \ 'function(''ale#definition#HandleTSServerResponse'')', @@ -174,7 +178,7 @@ Execute(tsserver tab completion requests should be sent): AssertEqual type(function('type')), type(g:WaitCallback) AssertEqual 'definition', g:capability_checked - call call(g:WaitCallback, [347, '/foo/bar']) + call call(g:WaitCallback, [g:conn_id, '/foo/bar']) AssertEqual \ 'function(''ale#definition#HandleTSServerResponse'')', @@ -206,10 +210,10 @@ Execute(Other files should be jumped to for LSP definition responses): AssertEqual \ [ - \ 'edit ' . fnameescape(ale#path#Simplify(g:dir . '/completion_dummy_file')), + \ 'edit +3 ' . fnameescape(ale#path#Simplify(g:dir . '/completion_dummy_file')), \ ], \ g:expr_list - AssertEqual [3, 7], getpos('.')[1:2] + AssertEqual [3, 8], getpos('.')[1:2] AssertEqual {}, ale#definition#GetMap() Execute(Locations inside the same file should be jumped to without using :edit): @@ -231,7 +235,7 @@ Execute(Locations inside the same file should be jumped to without using :edit): \ [ \ ], \ g:expr_list - AssertEqual [3, 7], getpos('.')[1:2] + AssertEqual [3, 8], getpos('.')[1:2] AssertEqual {}, ale#definition#GetMap() Execute(Other files should be jumped to in tabs for LSP definition responses): @@ -251,10 +255,10 @@ Execute(Other files should be jumped to in tabs for LSP definition responses): AssertEqual \ [ - \ 'tabedit ' . fnameescape(ale#path#Simplify(g:dir . '/completion_dummy_file')), + \ 'tabedit +3 ' . fnameescape(ale#path#Simplify(g:dir . '/completion_dummy_file')), \ ], \ g:expr_list - AssertEqual [3, 7], getpos('.')[1:2] + AssertEqual [3, 8], getpos('.')[1:2] AssertEqual {}, ale#definition#GetMap() Execute(Definition responses with lists should be handled): @@ -282,10 +286,10 @@ Execute(Definition responses with lists should be handled): AssertEqual \ [ - \ 'edit ' . fnameescape(ale#path#Simplify(g:dir . '/completion_dummy_file')), + \ 'edit +3 ' . fnameescape(ale#path#Simplify(g:dir . '/completion_dummy_file')), \ ], \ g:expr_list - AssertEqual [3, 7], getpos('.')[1:2] + AssertEqual [3, 8], getpos('.')[1:2] AssertEqual {}, ale#definition#GetMap() Execute(Definition responses with null response should be handled): @@ -306,7 +310,7 @@ Execute(LSP completion requests should be sent): AssertEqual type(function('type')), type(g:WaitCallback) AssertEqual 'definition', g:capability_checked - call call(g:WaitCallback, [347, '/foo/bar']) + call call(g:WaitCallback, [g:conn_id, '/foo/bar']) AssertEqual \ 'function(''ale#definition#HandleLSPResponse'')', @@ -342,7 +346,7 @@ Execute(LSP tab completion requests should be sent): AssertEqual type(function('type')), type(g:WaitCallback) AssertEqual 'definition', g:capability_checked - call call(g:WaitCallback, [347, '/foo/bar']) + call call(g:WaitCallback, [g:conn_id, '/foo/bar']) AssertEqual \ 'function(''ale#definition#HandleLSPResponse'')', diff --git a/test/test_gradle_build_classpath_command.vader b/test/test_gradle_build_classpath_command.vader index 3c1ecebe..491c2bf0 100644 --- a/test/test_gradle_build_classpath_command.vader +++ b/test/test_gradle_build_classpath_command.vader @@ -25,8 +25,8 @@ Execute(Should return 'gradlew' command if project includes gradle wapper): call ale#test#SetFilename('gradle-test-files/wrapped-project/src/main/kotlin/dummy.kt') AssertEqual - \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/gradle-test-files/wrapped-project')) - \ . ' && ' . ale#Escape(ale#path#Simplify(g:dir . '/gradle-test-files/wrapped-project/gradlew')) + \ ale#path#CdString(ale#path#Simplify(g:dir . '/gradle-test-files/wrapped-project')) + \ . ale#Escape(ale#path#Simplify(g:dir . '/gradle-test-files/wrapped-project/gradlew')) \ . g:command_tail, \ ale#gradle#BuildClasspathCommand(bufnr('')) @@ -36,8 +36,8 @@ Execute(Should return 'gradle' command if project does not include gradle wapper \ . ale#path#Simplify(g:dir . '/gradle-test-files') AssertEqual - \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/gradle-test-files/unwrapped-project')) - \ . ' && ' . ale#Escape('gradle') + \ ale#path#CdString(ale#path#Simplify(g:dir . '/gradle-test-files/unwrapped-project')) + \ . ale#Escape('gradle') \ . g:command_tail, \ ale#gradle#BuildClasspathCommand(bufnr('')) diff --git a/test/test_history_saving.vader b/test/test_history_saving.vader index 375e96a1..d7a307b5 100644 --- a/test/test_history_saving.vader +++ b/test/test_history_saving.vader @@ -73,7 +73,7 @@ Execute(History should be set when commands are run): " Retry this test until it works. This one can randomly fail. for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1) let b:ale_history = [] - call ale#Lint() + call ale#Queue(0) call ale#engine#WaitForJobs(2000) let g:history = filter( @@ -106,7 +106,7 @@ Execute(History should be not set when disabled): let g:ale_history_enabled = 0 - call ale#Lint() + call ale#Queue(0) call ale#engine#WaitForJobs(2000) AssertEqual [], ale#history#Get(bufnr('')) @@ -120,7 +120,7 @@ Execute(History should include command output if logging is enabled): " Retry this test until it works. This one can randomly fail. for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1) let b:ale_history = [] - call ale#Lint() + call ale#Queue(0) call ale#engine#WaitForJobs(2000) let g:history = ale#history#Get(bufnr('')) diff --git a/test/test_ignoring_linters.vader b/test/test_ignoring_linters.vader index af31fce3..866f9e0d 100644 --- a/test/test_ignoring_linters.vader +++ b/test/test_ignoring_linters.vader @@ -108,7 +108,7 @@ Before: let g:run_linters_called = 1 endfunction - function! ale#engine#HandleLoclist(linter_name, buffer, loclist) abort + function! ale#engine#HandleLoclist(linter_name, buffer, loclist, from_other_source) abort let g:loclist = a:loclist endfunction @@ -138,6 +138,9 @@ After: Given foobar(An empty file): Execute(Global ignore lists should be applied for linters): + " We have to set up buffer info so RunLinters is called. + let g:ale_buffer_info = {bufnr(''): {}} + ALELint Assert g:run_linters_called, "The mock callback wasn't called" AssertEqual ['testlinter'], map(g:linters, 'v:val.name') @@ -147,6 +150,9 @@ Execute(Global ignore lists should be applied for linters): AssertEqual [], g:linters Execute(buffer ignore lists should be applied for linters): + " We have to set up buffer info so RunLinters is called. + let g:ale_buffer_info = {bufnr(''): {}} + ALELint Assert g:run_linters_called, "The mock callback wasn't called" AssertEqual ['testlinter'], map(g:linters, 'v:val.name') @@ -190,6 +196,7 @@ Execute(Buffer ignore lists should be applied for tsserver): \ 'lnum': 2, \ 'col': 14, \ 'nr': 1005, + \ 'code': '1005', \ 'type': 'E', \ 'end_col': 15, \ 'end_lnum': 2, diff --git a/test/test_lint_file_linters.vader b/test/test_lint_file_linters.vader index ca093aa8..f67fad44 100644 --- a/test/test_lint_file_linters.vader +++ b/test/test_lint_file_linters.vader @@ -10,7 +10,6 @@ Before: let g:ale_run_synchronously = 1 let g:ale_set_lists_synchronously = 1 let b:ale_save_event_fired = 0 - call ale#ResetLintFileMarkers() let g:buffer_result = [ \ { diff --git a/test/test_linter_defintion_processing.vader b/test/test_linter_defintion_processing.vader index f0ec023a..d967761d 100644 --- a/test/test_linter_defintion_processing.vader +++ b/test/test_linter_defintion_processing.vader @@ -490,7 +490,7 @@ Execute(PreProcess should complain about using initialization_options and initia 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): +Execute(PreProcess should throw when initialization_options_callback is not a callback): AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'lsp': 'socket', @@ -500,3 +500,55 @@ Execute (PreProcess should throw when initialization_options_callback is not a c \ 'initialization_options_callback': {}, \}) AssertEqual '`initialization_options_callback` must be a callback if defined', g:vader_exception + +Execute(PreProcess should complain about using lsp_config and lsp_config_callback together): + let g:linter = { + \ 'name': 'x', + \ 'lsp': 'socket', + \ 'address_callback': '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:ale_lsp_configuration = { + \ 'foo': 'bar' + \} + + let g:linter = { + \ 'name': 'x', + \ 'lsp': 'socket', + \ 'address_callback': 'X', + \ 'language_callback': 'x', + \ 'project_root_callback': 'x', + \ 'lsp_config': g:ale_lsp_configuration, + \} + + AssertEqual {'foo': 'bar'}, ale#linter#PreProcess('testft', g:linter).lsp_config + +Execute(PreProcess should throw when lsp_config is not a Dictionary): + AssertThrows call ale#linter#PreProcess('testft', { + \ 'name': 'foo', + \ 'lsp': 'socket', + \ 'address_callback': 'X', + \ 'language': 'x', + \ 'project_root_callback': 'x', + \ 'lsp_config': 'x', + \}) + AssertEqual '`lsp_config` must be a Dictionary', g:vader_exception diff --git a/test/test_linter_retrieval.vader b/test/test_linter_retrieval.vader index 6c402d54..a1c34622 100644 --- a/test/test_linter_retrieval.vader +++ b/test/test_linter_retrieval.vader @@ -130,6 +130,8 @@ Execute (The local alias option shouldn't completely replace the global one): " global Dictionary. let b:ale_linter_aliases = {'testft3': ['testft1']} + AssertEqual [g:testlinter1, g:testlinter2], ale#linter#Get('testft1') + Execute (Lists should be accepted for local aliases): call ale#linter#Define('testft1', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) @@ -139,6 +141,15 @@ Execute (Lists should be accepted for local aliases): AssertEqual [g:testlinter2], ale#linter#Get('anything.else') +Execute (Strings should be accepted for local aliases): + call ale#linter#Define('testft1', g:testlinter1) + call ale#linter#Define('testft2', g:testlinter2) + let g:ale_linter_aliases = {'testft1': ['testft1', 'testft2']} + " We should load the testft2 linters for this buffer, with no duplicates. + let b:ale_linter_aliases = 'testft2' + + AssertEqual [g:testlinter2], ale#linter#Get('anything.else') + Execute (Buffer-local overrides for aliases should be used): call ale#linter#Define('testft1', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) diff --git a/test/test_linter_type_mapping.vader b/test/test_linter_type_mapping.vader index 0131b5f0..0ec22a56 100644 --- a/test/test_linter_type_mapping.vader +++ b/test/test_linter_type_mapping.vader @@ -16,7 +16,7 @@ Execute(It should be possible to remap errors to style errors): \ {'type': 'W', 'sub_type': 'style', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1, 'linter_name': 'foo'}, \ {'type': 'I', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1, 'linter_name': 'foo'}, \ ], - \ ale#engine#FixLocList(bufnr(''), 'foo', [ + \ ale#engine#FixLocList(bufnr(''), 'foo', 0, [ \ {'type': 'E', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, \ {'type': 'E', 'sub_type': 'style', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, \ {'type': 'W', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, @@ -35,7 +35,7 @@ Execute(It should be possible to remap errors to style errors with buffer-local \ {'type': 'W', 'sub_type': 'style', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1, 'linter_name': 'foo'}, \ {'type': 'I', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1, 'linter_name': 'foo'}, \ ], - \ ale#engine#FixLocList(bufnr(''), 'foo', [ + \ ale#engine#FixLocList(bufnr(''), 'foo', 0, [ \ {'type': 'E', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, \ {'type': 'E', 'sub_type': 'style', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, \ {'type': 'W', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, @@ -54,7 +54,7 @@ Execute(It should be possible to remap warnings to style warnings): \ {'type': 'W', 'sub_type': 'style', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1, 'linter_name': 'foo'}, \ {'type': 'I', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1, 'linter_name': 'foo'}, \ ], - \ ale#engine#FixLocList(bufnr(''), 'foo', [ + \ ale#engine#FixLocList(bufnr(''), 'foo', 0, [ \ {'type': 'E', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, \ {'type': 'E', 'sub_type': 'style', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, \ {'type': 'W', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, @@ -73,7 +73,7 @@ Execute(It should be possible to remap style errors to errors): \ {'type': 'W', 'sub_type': 'style', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1, 'linter_name': 'foo'}, \ {'type': 'I', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1, 'linter_name': 'foo'}, \ ], - \ ale#engine#FixLocList(bufnr(''), 'foo', [ + \ ale#engine#FixLocList(bufnr(''), 'foo', 0, [ \ {'type': 'E', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, \ {'type': 'E', 'sub_type': 'style', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, \ {'type': 'W', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, @@ -92,7 +92,7 @@ Execute(It should be possible to remap style warnings to warnings): \ {'type': 'W', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1, 'linter_name': 'foo'}, \ {'type': 'I', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1, 'linter_name': 'foo'}, \ ], - \ ale#engine#FixLocList(bufnr(''), 'foo', [ + \ ale#engine#FixLocList(bufnr(''), 'foo', 0, [ \ {'type': 'E', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, \ {'type': 'E', 'sub_type': 'style', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, \ {'type': 'W', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, @@ -111,7 +111,7 @@ Execute(It should be possible to info problems to warnings): \ {'type': 'W', 'sub_type': 'style', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1, 'linter_name': 'foo'}, \ {'type': 'W', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1, 'linter_name': 'foo'}, \ ], - \ ale#engine#FixLocList(bufnr(''), 'foo', [ + \ ale#engine#FixLocList(bufnr(''), 'foo', 0, [ \ {'type': 'E', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, \ {'type': 'E', 'sub_type': 'style', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, \ {'type': 'W', 'lnum': 1, 'text': 'x', 'bufnr': bufnr(''), 'col': 0, 'vcol': 0, 'nr': -1}, diff --git a/test/test_linting_blacklist.vader b/test/test_linting_blacklist.vader index 2d9ed585..73190b7f 100644 --- a/test/test_linting_blacklist.vader +++ b/test/test_linting_blacklist.vader @@ -10,7 +10,7 @@ Given unite (A Unite.vim file): anything Execute(Running ALE on a blacklisted file shouldn't change anything): - call ale#Lint() + call ale#Queue(0) call ale#engine#WaitForJobs(2000) AssertEqual {}, g:ale_buffer_info diff --git a/test/test_loclist_corrections.vader b/test/test_loclist_corrections.vader index 48aa1f78..343620a5 100644 --- a/test/test_loclist_corrections.vader +++ b/test/test_loclist_corrections.vader @@ -41,6 +41,7 @@ Execute(FixLocList should set all the default values correctly): \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', + \ 0, \ [{'text': 'a', 'lnum': 2}, {'text': 'b', 'lnum': 2}], \ ) @@ -61,6 +62,7 @@ Execute(FixLocList should use the values we supply): \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', + \ 0, \ [{ \ 'text': 'a', \ 'lnum': 3, @@ -89,6 +91,7 @@ Execute(FixLocList should set items with lines beyond the end to the last line): \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', + \ 0, \ [{'text': 'a', 'lnum': 11}], \ ) @@ -109,6 +112,7 @@ Execute(FixLocList should move line 0 to line 1): \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', + \ 0, \ [{'text': 'a', 'lnum': 0}], \ ) @@ -130,6 +134,7 @@ Execute(FixLocList should convert line and column numbers correctly): \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', + \ 0, \ [{'text': 'a', 'lnum': '010', 'col': '010'}], \ ) @@ -163,6 +168,7 @@ Execute(FixLocList should pass on end_col values): \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', + \ 0, \ [ \ {'text': 'a', 'lnum': '010', 'col': '010', 'end_col': '012'}, \ {'text': 'a', 'lnum': '010', 'col': '011', 'end_col': 12}, @@ -200,6 +206,7 @@ Execute(FixLocList should pass on end_lnum values): \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', + \ 0, \ [ \ {'text': 'a', 'lnum': '010', 'col': '010', 'end_col': '012', 'end_lnum': '013'}, \ {'text': 'a', 'lnum': '010', 'col': '011', 'end_col': 12, 'end_lnum': 13}, @@ -224,6 +231,7 @@ Execute(FixLocList should allow subtypes to be set): \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', + \ 0, \ [{'text': 'a', 'lnum': 11, 'sub_type': 'style'}], \ ) @@ -285,6 +293,7 @@ Execute(FixLocList should accept filenames): \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', + \ 0, \ [ \ {'text': 'a', 'lnum': 2, 'filename': expand('%:p')}, \ {'text': 'a', 'lnum': 3, 'filename': expand('%:p')}, @@ -322,6 +331,7 @@ Execute(FixLocList should interpret temporary filenames as being the current buf \ ale#engine#FixLocList( \ bufnr(''), \ 'foobar', + \ 0, \ [ \ {'text': 'a', 'lnum': 2, 'filename': b:temp_name}, \ {'text': 'a', 'lnum': 3, 'filename': substitute(b:temp_name, '\\', '/', 'g')}, @@ -346,9 +356,43 @@ Execute(The error code should be passed on): \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', + \ 0, \ [{'text': 'a', 'lnum': 11, 'code': 'some-code'}], \ ) +Execute(FixLocList should mark problems as coming from other sources if requested): + AssertEqual + \ [ + \ { + \ 'text': 'a', + \ 'lnum': 2, + \ 'col': 0, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'foobar', + \ 'from_other_source': 1, + \ }, + \ { + \ 'text': 'b', + \ 'lnum': 2, + \ 'col': 0, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'foobar', + \ 'from_other_source': 1, + \ }, + \], + \ ale#engine#FixLocList( + \ bufnr('%'), + \ 'foobar', + \ 1, + \ [{'text': 'a', 'lnum': 2}, {'text': 'b', 'lnum': 2}], + \ ) + Given(A file with Japanese multi-byte text): はじめまして! -私はワープです。 @@ -367,6 +411,7 @@ Execute(character positions should be converted to byte positions): \ ale#engine#FixLocList( \ bufnr('%'), \ 'foobar', + \ 0, \ [ \ {'text': 'a', 'lnum': 1, 'col': 0, 'vcol': 1}, \ {'text': 'a', 'lnum': 1, 'col': 1, 'vcol': 1}, diff --git a/test/test_other_sources.vader b/test/test_other_sources.vader new file mode 100644 index 00000000..e6f9911c --- /dev/null +++ b/test/test_other_sources.vader @@ -0,0 +1,153 @@ +Before: + Save g:ale_buffer_info + Save g:ale_set_signs + Save g:ale_set_quickfix + Save g:ale_set_loclist + Save g:ale_set_highlights + Save g:ale_echo_cursor + + let g:ale_buffer_info = {} + let g:ale_run_synchronously = 1 + let g:ale_set_lists_synchronously = 1 + let g:ale_set_signs = 0 + let g:ale_set_quickfix = 0 + let g:ale_set_loclist = 1 + let g:ale_set_highlights = 0 + let g:ale_echo_cursor = 0 + + function! TestCallback(buffer, output) + return [] + endfunction + + call ale#linter#Define('foobar', { + \ 'name': 'testlinter', + \ 'callback': 'TestCallback', + \ 'executable': has('win32') ? 'cmd' : 'echo', + \ 'command': has('win32') ? 'echo foo bar' : '/bin/sh -c ''echo foo bar''', + \}) + +After: + Restore + + unlet! b:ale_linters + unlet! g:want_results_signaled + unlet! g:want_results_buffer_value + unlet! g:lint_pre_signaled + unlet! g:ale_run_synchronously + unlet! g:ale_set_lists_synchronously + + delfunction TestCallback + + augroup VaderTest + autocmd! + augroup END + + augroup! VaderTest + + call ale#linter#Reset() + call setloclist(0, []) + +Given foobar (Some imaginary filetype): +Execute(StartChecking should mark a buffer as being actively checked): + Assert !ale#engine#IsCheckingBuffer(bufnr('')) + + call ale#other_source#StartChecking(bufnr(''), 'other-source-linter') + + Assert ale#engine#IsCheckingBuffer(bufnr('')) + +Execute(ShowResults sould make a buffer inactive): + call ale#other_source#StartChecking(bufnr(''), 'other-source-linter') + call ale#other_source#StartChecking(bufnr(''), 'second-other-source-linter') + + call ale#other_source#ShowResults(bufnr(''), 'other-source-linter', []) + + Assert ale#engine#IsCheckingBuffer(bufnr('')) + + call ale#other_source#ShowResults(bufnr(''), 'second-other-source-linter', []) + + Assert !ale#engine#IsCheckingBuffer(bufnr('')) + +Execute(ShowResults should show results at any time): + call ale#other_source#ShowResults(bufnr(''), 'other-source-linter', [ + \ {'text': 'xyz', 'lnum': 1}, + \]) + + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'bufnr': bufnr(''), + \ 'col': 0, + \ 'valid': 1, + \ 'vcol': 0, + \ 'nr': -1, + \ 'type': 'E', + \ 'pattern': '', + \ 'text': 'xyz', + \ }, + \ ], + \ ale#test#GetLoclistWithoutModule() + + call ale#other_source#ShowResults(bufnr(''), 'other-source-linter', []) + + AssertEqual [], ale#test#GetLoclistWithoutModule() + +Execute(A regular lint cycle shouldn't clear results from other sources): + call ale#other_source#ShowResults(bufnr(''), 'other-source-linter', [ + \ {'text': 'xyz', 'lnum': 1}, + \]) + ALELint + + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'bufnr': bufnr(''), + \ 'col': 0, + \ 'valid': 1, + \ 'vcol': 0, + \ 'nr': -1, + \ 'type': 'E', + \ 'pattern': '', + \ 'text': 'xyz', + \ }, + \ ], + \ ale#test#GetLoclistWithoutModule() + +Execute(ALEWantResults should be signaled when a buffer is checked): + augroup VaderTest + autocmd! + autocmd User ALEWantResults let g:want_results_signaled = 1 + autocmd User ALELintPre let g:lint_pre_signaled = 1 + augroup END + + " Even when all linters are disabled, we should send the signal. + let b:ale_linters = [] + ALELint + + Assert get(g:, 'want_results_signaled') + Assert !get(g:, 'lint_pre_signaled') + +Execute(ALEWantResults should set a variable indicating which buffer is being checked): + augroup VaderTest + autocmd! + autocmd User ALEWantResults let g:want_results_buffer_value = g:ale_want_results_buffer + augroup END + + let b:ale_linters = [] + ALELint + + AssertEqual bufnr(''), g:want_results_buffer_value + +Execute(ALEWantResults should lead to an ALELintPre signal if another source responds): + augroup VaderTest + autocmd! + autocmd User ALEWantResults call ale#other_source#StartChecking(bufnr(''), 'other-source-linter') + autocmd User ALELintPre let g:lint_pre_signaled = 1 + augroup END + + " Even when all linters are disabled, we should send the signal. + let b:ale_linters = [] + ALELint + + Assert get(g:, 'lint_pre_signaled') diff --git a/test/test_path_dirname.vader b/test/test_path_dirname.vader new file mode 100644 index 00000000..79b78d29 --- /dev/null +++ b/test/test_path_dirname.vader @@ -0,0 +1,8 @@ +Execute(ale#path#Dirname should return empty strings should be returned for empty values): + AssertEqual '', ale#path#Dirname('') + AssertEqual '', ale#path#Dirname(0) + AssertEqual '', ale#path#Dirname(v:null) + +Execute(ale#path#Dirname should return the dirname of paths): + AssertEqual '/foo', ale#path#Dirname('/foo/bar') + AssertEqual '/foo', ale#path#Dirname('/foo/bar/') diff --git a/test/test_phpcs_executable_detection.vader b/test/test_phpcs_executable_detection.vader deleted file mode 100644 index 020bfac3..00000000 --- a/test/test_phpcs_executable_detection.vader +++ /dev/null @@ -1,39 +0,0 @@ -Before: - Save g:ale_php_phpcs_executable - Save g:ale_php_phpcs_use_global - - let g:ale_php_phpcs_executable = 'phpcs_test' - let g:ale_php_phpcs_use_global = 0 - - call ale#test#SetDirectory('/testplugin/test') - - runtime ale_linters/php/phpcs.vim - -After: - Restore - - call ale#test#RestoreDirectory() - call ale#linter#Reset() - -Execute(project with phpcs should use local by default): - call ale#test#SetFilename('phpcs-test-files/project-with-phpcs/foo/test.php') - - AssertEqual - \ ale#path#Simplify(g:dir . '/phpcs-test-files/project-with-phpcs/vendor/bin/phpcs'), - \ ale_linters#php#phpcs#GetExecutable(bufnr('')) - -Execute(use-global should override local detection): - let g:ale_php_phpcs_use_global = 1 - - call ale#test#SetFilename('phpcs-test-files/project-with-phpcs/foo/test.php') - - AssertEqual - \ 'phpcs_test', - \ ale_linters#php#phpcs#GetExecutable(bufnr('')) - -Execute(project without phpcs should use global): - call ale#test#SetFilename('phpcs-test-files/project-without-phpcs/foo/test.php') - - AssertEqual - \ 'phpcs_test', - \ ale_linters#php#phpcs#GetExecutable(bufnr('')) diff --git a/test/test_python_pipenv.vader b/test/test_python_pipenv.vader new file mode 100644 index 00000000..91d957f8 --- /dev/null +++ b/test/test_python_pipenv.vader @@ -0,0 +1,13 @@ +Execute(ale#python#PipenvPresent is true when a pipenv environment is present): + call ale#test#SetFilename('/testplugin/test/python_fixtures/pipenv/whatever.py') + + AssertEqual + \ ale#python#PipenvPresent(bufnr('%')), + \ 1 + +Execute(ale#python#PipenvPresent is false true when no pipenv environment is present): + call ale#test#SetFilename('/testplugin/test/python_fixtures/no_pipenv/whatever.py') + + AssertEqual + \ ale#python#PipenvPresent(bufnr('%')), + \ 0 diff --git a/test/test_redundant_tsserver_rendering_avoided.vader b/test/test_redundant_tsserver_rendering_avoided.vader new file mode 100644 index 00000000..a292b014 --- /dev/null +++ b/test/test_redundant_tsserver_rendering_avoided.vader @@ -0,0 +1,136 @@ +Before: + Save g:ale_buffer_info + + function! CreateError(type, message) abort + let l:diagnostics = [] + + if !empty(a:message) + let l:diagnostics = [{ + \ 'start': {'line': 1, 'offset': 1}, + \ 'end': {'line': 1, 'offset':1}, + \ 'text': a:message, + \ 'code': 1005, + \}] + endif + + return { + \ 'seq': 0, + \ 'type': 'event', + \ 'event': a:type, + \ 'body': {'file': expand('%:p'), 'diagnostics': l:diagnostics}, + \} + endfunction + + function! CreateLoclist(message) abort + let l:list = [] + + if !empty(a:message) + let l:list = [{ + \ 'lnum': 1, + \ 'col': 1, + \ 'end_lnum': 1, + \ 'end_col': 1, + \ 'text': a:message, + \}] + endif + + return l:list + endfunction + + call ale#test#SetDirectory('/testplugin/test') + call ale#test#SetFilename('filename.ts') + + runtime autoload/ale/engine.vim + + let g:ale_buffer_info = {bufnr(''): {'loclist': []}} + let g:ale_handle_loclist_called = 0 + + function! ale#engine#HandleLoclist(linter_name, buffer, loclist, from_other_source) abort + let g:ale_handle_loclist_called = 1 + endfunction + +After: + Restore + + delfunction CreateError + delfunction CreateLoclist + + call ale#test#RestoreDirectory() + + runtime autoload/ale/engine.vim + +Execute(An initial empty list of syntax errors should be ignored): + call ale#lsp_linter#HandleLSPResponse(1, CreateError('syntaxDiag', '')) + + Assert !g:ale_handle_loclist_called + +Execute(An initial list of syntax errors should be handled): + call ale#lsp_linter#HandleLSPResponse(1, CreateError('syntaxDiag', 'x')) + + Assert g:ale_handle_loclist_called + +Execute(Subsequent empty lists should be ignored): + let g:ale_buffer_info[bufnr('')].syntax_loclist = [] + + call ale#lsp_linter#HandleLSPResponse(1, CreateError('syntaxDiag', '')) + + Assert !g:ale_handle_loclist_called + +Execute(Empty then non-empty syntax errors should be handled): + let g:ale_buffer_info[bufnr('')].syntax_loclist = [] + + call ale#lsp_linter#HandleLSPResponse(1, CreateError('syntaxDiag', 'x')) + + Assert g:ale_handle_loclist_called + +Execute(Non-empty then empty syntax errors should be handled): + let g:ale_buffer_info[bufnr('')].syntax_loclist = CreateLoclist('x') + + call ale#lsp_linter#HandleLSPResponse(1, CreateError('syntaxDiag', '')) + + Assert g:ale_handle_loclist_called + +Execute(Non-empty then non-empty syntax errors should be handled): + let g:ale_buffer_info[bufnr('')].syntax_loclist = CreateLoclist('x') + + call ale#lsp_linter#HandleLSPResponse(1, CreateError('syntaxDiag', 'x')) + + Assert g:ale_handle_loclist_called + +Execute(An initial empty list of semantic errors should be ignored): + call ale#lsp_linter#HandleLSPResponse(1, CreateError('semanticDiag', '')) + + Assert !g:ale_handle_loclist_called + +Execute(An initial list of semantic errors should be handled): + call ale#lsp_linter#HandleLSPResponse(1, CreateError('semanticDiag', 'x')) + + Assert g:ale_handle_loclist_called + +Execute(Subsequent empty lists should be ignored): + let g:ale_buffer_info[bufnr('')].semantic_loclist = [] + + call ale#lsp_linter#HandleLSPResponse(1, CreateError('semanticDiag', '')) + + Assert !g:ale_handle_loclist_called + +Execute(Empty then non-empty semantic errors should be handled): + let g:ale_buffer_info[bufnr('')].semantic_loclist = [] + + call ale#lsp_linter#HandleLSPResponse(1, CreateError('semanticDiag', 'x')) + + Assert g:ale_handle_loclist_called + +Execute(Non-empty then empty semantic errors should be handled): + let g:ale_buffer_info[bufnr('')].semantic_loclist = CreateLoclist('x') + + call ale#lsp_linter#HandleLSPResponse(1, CreateError('semanticDiag', '')) + + Assert g:ale_handle_loclist_called + +Execute(Non-empty then non-empty semantic errors should be handled): + let g:ale_buffer_info[bufnr('')].semantic_loclist = CreateLoclist('x') + + call ale#lsp_linter#HandleLSPResponse(1, CreateError('semanticDiag', 'x')) + + Assert g:ale_handle_loclist_called diff --git a/test/test_sandbox_execution.vader b/test/test_sandbox_execution.vader index 4dbcb0db..5a4974ba 100644 --- a/test/test_sandbox_execution.vader +++ b/test/test_sandbox_execution.vader @@ -47,7 +47,6 @@ Execute(ALE shouldn't blow up when run from a sandbox): sandbox call ale#Queue(0) sandbox call ale#Queue(1) - sandbox call ale#Lint() Execute(ALE shouldn't blow up if file cleanup happens in a sandbox): " Make a call to an engine function first, so the function will be defined diff --git a/test/test_setting_problems_found_in_previous_buffers.vader b/test/test_setting_problems_found_in_previous_buffers.vader index 4604005a..36eeb4ca 100644 --- a/test/test_setting_problems_found_in_previous_buffers.vader +++ b/test/test_setting_problems_found_in_previous_buffers.vader @@ -9,14 +9,14 @@ Before: let g:ale_buffer_info = {} call ale#engine#InitBufferInfo(bufnr('') + 1) let g:ale_buffer_info[bufnr('') + 1].loclist = - \ ale#engine#FixLocList(bufnr('') + 1, 'linter_one', [ + \ ale#engine#FixLocList(bufnr('') + 1, 'linter_one', 0, [ \ {'lnum': 1, 'filename': expand('%:p'), 'text': 'foo'}, \ {'lnum': 2, 'filename': expand('%:p'), 'text': 'bar'}, \ {'lnum': 2, 'text': 'ignore this one'}, \ ]) call ale#engine#InitBufferInfo(bufnr('') + 2) let g:ale_buffer_info[bufnr('') + 2].loclist = - \ ale#engine#FixLocList(bufnr('') + 2, 'linter_one', [ + \ ale#engine#FixLocList(bufnr('') + 2, 'linter_one', 0, [ \ {'lnum': 1, 'filename': expand('%:p'), 'text': 'foo'}, \ {'lnum': 3, 'filename': expand('%:p'), 'text': 'baz'}, \ {'lnum': 5, 'text': 'ignore this one'}, diff --git a/test/test_should_do_nothing_conditions.vader b/test/test_should_do_nothing_conditions.vader index 062ab875..de2e2782 100644 --- a/test/test_should_do_nothing_conditions.vader +++ b/test/test_should_do_nothing_conditions.vader @@ -4,10 +4,18 @@ Before: Save g:ale_enabled Save &l:statusline + let b:fake_mode = 'n' + call ale#test#SetDirectory('/testplugin/test') let b:funky_command_created = 0 + runtime autoload/ale/util.vim + + function! ale#util#Mode(...) abort + return b:fake_mode + endfunction + " We will test for the existence of this command, so create one if needed. if !exists(':CtrlPFunky') command CtrlPFunky echo @@ -25,6 +33,9 @@ After: endif unlet! b:funky_command_created + unlet! b:fake_mode + + runtime autoload/ale/util.vim Given foobar(An empty file): Execute(ALE shouldn't do much of anything for ctrlp-funky buffers): @@ -44,7 +55,7 @@ Execute(ALE shouldn't try to check buffers with '.' as the filename): Assert ale#ShouldDoNothing(bufnr('')) -Execute(DoNothing should return 0 when the filetype is empty): +Execute(DoNothing should return 1 when the filetype is empty): AssertEqual \ 0, \ ale#ShouldDoNothing(bufnr('')), @@ -54,6 +65,11 @@ Execute(DoNothing should return 0 when the filetype is empty): AssertEqual 1, ale#ShouldDoNothing(bufnr('')) +Execute(DoNothing should return 1 when an operator is pending): + let b:fake_mode = 'no' + + AssertEqual 1, ale#ShouldDoNothing(bufnr('')) + Execute(The DoNothing check should work if the ALE globals aren't defined): unlet! g:ale_filetype_blacklist unlet! g:ale_maximum_file_size diff --git a/test/test_symbol_search.vader b/test/test_symbol_search.vader new file mode 100644 index 00000000..d8b7a4a6 --- /dev/null +++ b/test/test_symbol_search.vader @@ -0,0 +1,173 @@ +Before: + call ale#test#SetDirectory('/testplugin/test') + call ale#test#SetFilename('dummy.txt') + + let g:Callback = '' + let g:expr_list = [] + let g:message_list = [] + let g:preview_called = 0 + let g:item_list = [] + let g:capability_checked = '' + let g:conn_id = v:null + let g:WaitCallback = v:null + + runtime autoload/ale/lsp_linter.vim + runtime autoload/ale/lsp.vim + runtime autoload/ale/util.vim + runtime autoload/ale/preview.vim + + function! ale#lsp_linter#StartLSP(buffer, linter) abort + let g:conn_id = ale#lsp#Register('executable', '/foo/bar', {}) + call ale#lsp#MarkDocumentAsOpen(g:conn_id, a:buffer) + + return { + \ 'buffer': a:buffer, + \ 'connection_id': g:conn_id, + \ 'project_root': '/foo/bar', + \ 'language_id': 'python', + \} + endfunction + + function! ale#lsp#WaitForCapability(conn_id, capability, callback) abort + let g:capability_checked = a:capability + let g:WaitCallback = a:callback + endfunction + + function! ale#lsp#RegisterCallback(conn_id, callback) abort + let g:Callback = a:callback + endfunction + + function! ale#lsp#Send(conn_id, message) abort + call add(g:message_list, a:message) + + return 42 + endfunction + + function! ale#util#Execute(expr) abort + call add(g:expr_list, a:expr) + endfunction + + function! ale#preview#ShowSelection(item_list) abort + let g:preview_called = 1 + let g:item_list = a:item_list + endfunction + +After: + call ale#test#RestoreDirectory() + call ale#linter#Reset() + + unlet! g:capability_checked + unlet! g:WaitCallback + unlet! g:conn_id + unlet! g:Callback + unlet! g:message_list + unlet! g:expr_list + unlet! b:ale_linters + unlet! g:item_list + unlet! g:preview_called + + runtime autoload/ale/lsp_linter.vim + runtime autoload/ale/lsp.vim + runtime autoload/ale/util.vim + runtime autoload/ale/preview.vim + +Execute(Other messages for the LSP handler should be ignored): + call ale#symbol#HandleLSPResponse(1, {'command': 'foo'}) + +Execute(Failed symbol responses should be handled correctly): + call ale#symbol#SetMap({3: {}}) + call ale#symbol#HandleLSPResponse(1, {'id': 3}) + AssertEqual {}, ale#symbol#GetMap() + +Execute(LSP symbol responses should be handled): + call ale#symbol#SetMap({3: {}}) + call ale#symbol#HandleLSPResponse( + \ 1, + \ { + \ 'id': 3, + \ 'result': [ + \ { + \ 'name': 'foo', + \ 'location': { + \ 'uri': ale#path#ToURI(ale#path#Simplify(g:dir . '/completion_dummy_file')), + \ 'range': { + \ 'start': {'line': 2, 'character': 7}, + \ }, + \ }, + \ }, + \ { + \ 'name': 'foobar', + \ 'location': { + \ 'uri': ale#path#ToURI(ale#path#Simplify(g:dir . '/other_file')), + \ 'range': { + \ 'start': {'line': 7, 'character': 15}, + \ }, + \ }, + \ }, + \ ], + \ } + \) + + AssertEqual + \ [ + \ { + \ 'filename': ale#path#Simplify(g:dir . '/completion_dummy_file'), + \ 'line': 3, + \ 'column': 8, + \ 'match': 'foo', + \ }, + \ { + \ 'filename': ale#path#Simplify(g:dir . '/other_file'), + \ 'line': 8, + \ 'column': 16, + \ 'match': 'foobar', + \ }, + \ ], + \ g:item_list + AssertEqual {}, ale#symbol#GetMap() + +Execute(Preview windows should not be opened for empty LSP symbol responses): + call ale#symbol#SetMap({3: {}}) + call ale#symbol#HandleLSPResponse( + \ 1, + \ { + \ 'id': 3, + \ 'result': [ + \ ], + \ } + \) + + Assert !g:preview_called + AssertEqual {}, ale#symbol#GetMap() + AssertEqual ['echom ''No symbols found.'''], g:expr_list + +Given python(Some Python file): + foo + somelongerline + bazxyzxyzxyz + +Execute(LSP symbol requests should be sent): + runtime ale_linters/python/pyls.vim + let b:ale_linters = ['pyls'] + call setpos('.', [bufnr(''), 1, 5, 0]) + + ALESymbolSearch foo bar + + " We shouldn't register the callback yet. + AssertEqual '''''', string(g:Callback) + + AssertEqual 'symbol_search', g:capability_checked + AssertEqual type(function('type')), type(g:WaitCallback) + call call(g:WaitCallback, [g:conn_id, '/foo/bar']) + + AssertEqual + \ 'function(''ale#symbol#HandleLSPResponse'')', + \ string(g:Callback) + + AssertEqual + \ [ + \ [0, 'workspace/symbol', {'query': 'foo bar'}], + \ ], + \ g:message_list + + AssertEqual {'42': {'buffer': bufnr('')}}, ale#symbol#GetMap() diff --git a/test/test_temporary_file_management.vader b/test/test_temporary_file_management.vader index e248331c..4847706a 100644 --- a/test/test_temporary_file_management.vader +++ b/test/test_temporary_file_management.vader @@ -67,7 +67,7 @@ Given foobar (Some imaginary filetype): Execute(ALE should delete managed files/directories appropriately after linting): AssertEqual 'foobar', &filetype - call ale#Lint() + call ale#Queue(0) call ale#engine#WaitForJobs(2000) Assert !filereadable(g:filename), 'The temporary file was not deleted' @@ -79,7 +79,7 @@ Execute(ALE should delete managed files even if no command is run): let g:command = '' - call ale#Lint() + call ale#Queue(0) call ale#engine#WaitForJobs(2000) Assert !filereadable(g:filename), 'The temporary file was not deleted' diff --git a/test/test_tflint_config_detection.vader b/test/test_tflint_config_detection.vader deleted file mode 100644 index 3500869b..00000000 --- a/test/test_tflint_config_detection.vader +++ /dev/null @@ -1,18 +0,0 @@ -Before: - call ale#test#SetDirectory('/testplugin/test') - runtime ale_linters/terraform/tflint.vim - -After: - call ale#test#RestoreDirectory() - call ale#linter#Reset() - -Execute(adjacent config file should be found): - call ale#test#SetFilename('tflint-test-files/foo/bar.tf') - AssertEqual - \ ( - \ ale#Escape('tflint') - \ . ' --config ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/tflint-test-files/foo/.tflint.hcl')) - \ . ' -f json %t' - \ ), - \ ale_linters#terraform#tflint#GetCommand(bufnr('')) diff --git a/test/test_verilog_verilator_options.vader b/test/test_verilog_verilator_options.vader index e53037b1..3ebabfcc 100644 --- a/test/test_verilog_verilator_options.vader +++ b/test/test_verilog_verilator_options.vader @@ -12,7 +12,7 @@ Execute(Set Verilog Verilator linter additional options to `-sv --default-langua " Additional args for the linter let g:ale_verilog_verilator_options = '-sv --default-language "1800-2012"' - call ale#Lint() + call ale#Queue(0) let g:run_cmd = ale_linters#verilog#verilator#GetCommand(bufnr('')) let g:matched = match(g:run_cmd, '\s' . g:ale_verilog_verilator_options . '\s') diff --git a/test/test_writefile_function.vader b/test/test_writefile_function.vader index 4e4aab53..8c8a6f17 100644 --- a/test/test_writefile_function.vader +++ b/test/test_writefile_function.vader @@ -28,7 +28,26 @@ Execute(Carriage returns should be included for ale#util#Writefile): AssertEqual \ ["first\r", "second\r", "third\r", ''], \ readfile('.newline-test', 'b') - \ + +Given(A file with extra carriage returns): + first
+ second
+ third
+ fourth + +Execute(Carriage returns should be de-depulicated): + call ale#test#SetFilename('.newline-test') + + setlocal buftype= + noautocmd :w + noautocmd :e! ++ff=dos + + call ale#util#Writefile(bufnr(''), getline(1, '$'), '.newline-test') + + AssertEqual + \ ["first\r", "second\r", "third\r", "fourth\r", ''], + \ readfile('.newline-test', 'b') + Given(A file with Unix line ending characters): first second diff --git a/test/util/test_cd_string_commands.vader b/test/util/test_cd_string_commands.vader index 5f0e92fd..f2102e48 100644 --- a/test/util/test_cd_string_commands.vader +++ b/test/util/test_cd_string_commands.vader @@ -9,10 +9,12 @@ After: Execute(CdString should output the correct command string): " We will check that escaping is done correctly for each platform. AssertEqual - \ has('unix') ? 'cd ''/foo bar/baz'' && ' : 'cd "/foo bar/baz" && ', + \ has('unix') ? 'cd ''/foo bar/baz'' && ' : 'cd /d "/foo bar/baz" && ', \ ale#path#CdString('/foo bar/baz') Execute(BufferCdString should output the correct command string): call ale#test#SetFilename('foo.txt') - AssertEqual 'cd ' . ale#Escape(g:dir) . ' && ', ale#path#BufferCdString(bufnr('')) + AssertEqual + \ has('unix') ? 'cd ' . ale#Escape(g:dir) . ' && ' : 'cd /d ' . ale#Escape(g:dir) . ' && ', + \ ale#path#BufferCdString(bufnr('')) |