diff options
Diffstat (limited to 'test')
299 files changed, 8274 insertions, 3730 deletions
diff --git a/test/elm-test-files/app/node_modules/.bin/elm-make b/test/command_callback/cargo_workspace_paths/Cargo.toml index e69de29b..e69de29b 100644 --- a/test/elm-test-files/app/node_modules/.bin/elm-make +++ b/test/command_callback/cargo_workspace_paths/Cargo.toml diff --git a/test/hack_files/testfile.php b/test/command_callback/cargo_workspace_paths/subpath/Cargo.toml index e69de29b..e69de29b 100644 --- a/test/hack_files/testfile.php +++ b/test/command_callback/cargo_workspace_paths/subpath/Cargo.toml diff --git a/test/command_callback/clangd_paths/compile_commands.json b/test/command_callback/clangd_paths/compile_commands.json new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/clangd_paths/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/fortran-fortls-project/.fortls b/test/command_callback/fortran-fortls-project/.fortls new file mode 100644 index 00000000..2c63c085 --- /dev/null +++ b/test/command_callback/fortran-fortls-project/.fortls @@ -0,0 +1,2 @@ +{ +} diff --git a/test/command_callback/htmlhint_paths/node_modules/.bin/htmlhint b/test/command_callback/htmlhint_paths/node_modules/.bin/htmlhint new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/htmlhint_paths/node_modules/.bin/htmlhint diff --git a/test/command_callback/htmlhint_paths/with_config/.htmlhintrc b/test/command_callback/htmlhint_paths/with_config/.htmlhintrc new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/htmlhint_paths/with_config/.htmlhintrc diff --git a/test/command_callback/mix_paths/wrapped_project/mix.exs b/test/command_callback/mix_paths/wrapped_project/mix.exs new file mode 100644 index 00000000..d2d855e6 --- /dev/null +++ b/test/command_callback/mix_paths/wrapped_project/mix.exs @@ -0,0 +1 @@ +use Mix.Config diff --git a/test/command_callback/php_paths/project-with-php-cs-fixer/test.php b/test/command_callback/php_paths/project-with-php-cs-fixer/test.php new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/php_paths/project-with-php-cs-fixer/test.php diff --git a/test/command_callback/php_paths/project-with-php-cs-fixer/vendor/bin/php-cs-fixer b/test/command_callback/php_paths/project-with-php-cs-fixer/vendor/bin/php-cs-fixer new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/php_paths/project-with-php-cs-fixer/vendor/bin/php-cs-fixer diff --git a/test/command_callback/php_paths/project-without-php-cs-fixer/test.php b/test/command_callback/php_paths/project-without-php-cs-fixer/test.php new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/php_paths/project-without-php-cs-fixer/test.php diff --git a/test/command_callback/python_paths/with_virtualenv/env/Scripts/black.exe b/test/command_callback/python_paths/with_virtualenv/env/Scripts/black.exe new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/python_paths/with_virtualenv/env/Scripts/black.exe diff --git a/test/command_callback/python_paths/with_virtualenv/env/Scripts/pyre.exe b/test/command_callback/python_paths/with_virtualenv/env/Scripts/pyre.exe new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/python_paths/with_virtualenv/env/Scripts/pyre.exe diff --git a/test/command_callback/python_paths/with_virtualenv/env/bin/black b/test/command_callback/python_paths/with_virtualenv/env/bin/black new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/python_paths/with_virtualenv/env/bin/black diff --git a/test/command_callback/python_paths/with_virtualenv/env/bin/pyre b/test/command_callback/python_paths/with_virtualenv/env/bin/pyre new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/python_paths/with_virtualenv/env/bin/pyre diff --git a/test/command_callback/remark_lint_paths/with_bin_path/node_modules/.bin/remark b/test/command_callback/remark_lint_paths/with_bin_path/node_modules/.bin/remark new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/remark_lint_paths/with_bin_path/node_modules/.bin/remark diff --git a/test/command_callback/scala_paths/dummy.scala b/test/command_callback/scala_paths/dummy.scala new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/scala_paths/dummy.scala diff --git a/test/command_callback/test_asm_gcc_command_callbacks.vader b/test/command_callback/test_asm_gcc_command_callbacks.vader index ce8b906a..5ad31186 100644 --- a/test/command_callback/test_asm_gcc_command_callbacks.vader +++ b/test/command_callback/test_asm_gcc_command_callbacks.vader @@ -1,39 +1,18 @@ Before: - Save g:ale_asm_gcc_executable - Save g:ale_asm_gcc_options - - unlet! g:ale_asm_gcc_executable - unlet! b:ale_asm_gcc_executable - unlet! g:ale_asm_gcc_options - unlet! b:ale_asm_gcc_options - - runtime ale_linters/asm/gcc.vim - + call ale#assert#SetUpLinterTest('asm', 'gcc') + call ale#test#SetFilename('test.cpp') let b:command_tail = ' -x assembler -fsyntax-only -iquote' - \ . ' ' . ale#Escape(getcwd()) + \ . ' ' . ale#Escape(g:dir) \ . ' -Wall -' After: - Restore unlet! b:command_tail - unlet! b:ale_asm_gcc_executable - unlet! b:ale_asm_gcc_options - call ale#linter#Reset() - -Execute(The executable should be configurable): - AssertEqual 'gcc', ale_linters#asm#gcc#GetExecutable(bufnr('')) - - let b:ale_asm_gcc_executable = 'foobar' - AssertEqual 'foobar', ale_linters#asm#gcc#GetExecutable(bufnr('')) + call ale#assert#TearDownLinterTest() -Execute(The executable should be used in the command): - AssertEqual - \ ale#Escape('gcc') . b:command_tail, - \ ale_linters#asm#gcc#GetCommand(bufnr('')) +Execute(The executable should be configurable): + AssertLinter 'gcc', ale#Escape('gcc') . b:command_tail let b:ale_asm_gcc_executable = 'foobar' - AssertEqual - \ ale#Escape('foobar') . b:command_tail, - \ ale_linters#asm#gcc#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . b:command_tail diff --git a/test/command_callback/test_brakeman_command_callback.vader b/test/command_callback/test_brakeman_command_callback.vader index 1772c9d6..61be4caf 100644 --- a/test/command_callback/test_brakeman_command_callback.vader +++ b/test/command_callback/test_brakeman_command_callback.vader @@ -1,39 +1,24 @@ Before: - Save g:ale_ruby_brakeman_options - - runtime ale_linters/ruby/brakeman.vim - - let g:ale_ruby_brakeman_options = '' - - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('ruby', 'brakeman') After: - Restore - - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The brakeman command callback should detect absence of a valid Rails app): call ale#test#SetFilename('../ruby_fixtures/not_a_rails_app/test.rb') - AssertEqual - \ '', - \ ale_linters#ruby#brakeman#GetCommand(bufnr('')) + AssertLinter 'brakeman', '' Execute(The brakeman command callback should find a valid Rails app root): call ale#test#SetFilename('../ruby_fixtures/valid_rails_app/db/test.rb') - AssertEqual - \ 'brakeman -f json -q -p ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/../ruby_fixtures/valid_rails_app')), - \ ale_linters#ruby#brakeman#GetCommand(bufnr('')) + AssertLinter 'brakeman', '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): call ale#test#SetFilename('../ruby_fixtures/valid_rails_app/db/test.rb') let g:ale_ruby_brakeman_options = '--combobulate' - AssertEqual - \ 'brakeman -f json -q --combobulate -p ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/../ruby_fixtures/valid_rails_app')), - \ ale_linters#ruby#brakeman#GetCommand(bufnr('')) + AssertLinter 'brakeman', '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_clang_command_callbacks.vader b/test/command_callback/test_c_clang_command_callbacks.vader index d6fc8ca6..7d2ff0bf 100644 --- a/test/command_callback/test_c_clang_command_callbacks.vader +++ b/test/command_callback/test_c_clang_command_callbacks.vader @@ -1,39 +1,20 @@ Before: - Save g:ale_c_clang_executable - Save g:ale_c_clang_options - - unlet! g:ale_c_clang_executable - unlet! b:ale_c_clang_executable - unlet! g:ale_c_clang_options - unlet! b:ale_c_clang_options - - runtime ale_linters/c/clang.vim + Save g:ale_c_parse_makefile + let g:ale_c_parse_makefile = 0 + call ale#assert#SetUpLinterTest('c', 'clang') let b:command_tail = ' -S -x c -fsyntax-only -iquote' \ . ' ' . ale#Escape(getcwd()) \ . ' -std=c11 -Wall -' After: - Restore unlet! b:command_tail - unlet! b:ale_c_clang_executable - unlet! b:ale_c_clang_options - call ale#linter#Reset() -Execute(The executable should be configurable): - AssertEqual 'clang', ale_linters#c#clang#GetExecutable(bufnr('')) + call ale#assert#TearDownLinterTest() - let b:ale_c_clang_executable = 'foobar' - - AssertEqual 'foobar', ale_linters#c#clang#GetExecutable(bufnr('')) - -Execute(The executable should be used in the command): - AssertEqual - \ ale#Escape('clang') . b:command_tail, - \ ale_linters#c#clang#GetCommand(bufnr('')) +Execute(The executable should be configurable): + AssertLinter 'clang', ['', ale#Escape('clang') . b:command_tail] let b:ale_c_clang_executable = 'foobar' - AssertEqual - \ ale#Escape('foobar') . b:command_tail, - \ ale_linters#c#clang#GetCommand(bufnr('')) + AssertLinter 'foobar', ['', ale#Escape('foobar') . b:command_tail] 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 6f75d777..582d4798 100644 --- a/test/command_callback/test_c_clang_tidy_command_callback.vader +++ b/test/command_callback/test_c_clang_tidy_command_callback.vader @@ -1,77 +1,49 @@ Before: - Save g:ale_c_clangtidy_checks - Save g:ale_c_clangtidy_options - Save g:ale_c_build_dir - - unlet! g:ale_c_build_dir - unlet! b:ale_c_build_dir - unlet! g:ale_c_clangtidy_checks - unlet! b:ale_c_clangtidy_checks - unlet! g:ale_c_clangtidy_options - unlet! b:ale_c_clangtidy_options - - runtime ale_linters/c/clangtidy.vim - + call ale#assert#SetUpLinterTest('c', 'clangtidy') call ale#test#SetFilename('test.c') After: - unlet! b:ale_c_build_dir - unlet! b:ale_c_clangtidy_checks - unlet! b:ale_c_clangtidy_options - unlet! b:ale_c_clangtidy_executable - - Restore - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The clangtidy command default should be correct): - AssertEqual - \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('*') . ' %s', - \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s' Execute(You should be able to remove the -checks option for clang-tidy): let b:ale_c_clangtidy_checks = [] - AssertEqual - \ ale#Escape('clang-tidy') - \ . ' %s', - \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' %s' Execute(You should be able to set other checks for clang-tidy): let b:ale_c_clangtidy_checks = ['-*', 'clang-analyzer-*'] - AssertEqual + AssertLinter 'clang-tidy', \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('-*,clang-analyzer-*') . ' %s', - \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + \ . ' -checks=' . ale#Escape('-*,clang-analyzer-*') . ' %s' Execute(You should be able to manually set compiler flags for clang-tidy): let b:ale_c_clangtidy_options = '-Wall' - AssertEqual - \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('*') . ' %s' - \ . ' -- -Wall', - \ ale_linters#c#clangtidy#GetCommand(bufnr('')) - \ + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' + Execute(The build directory should be configurable): let b:ale_c_build_dir = '/foo/bar' - AssertEqual + AssertLinter 'clang-tidy', \ ale#Escape('clang-tidy') \ . ' -checks=' . ale#Escape('*') . ' %s' - \ . ' -p ' . ale#Escape('/foo/bar'), - \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + \ . ' -p ' . ale#Escape('/foo/bar') Execute(The build directory setting should override the options): let b:ale_c_build_dir = '/foo/bar' let b:ale_c_clangtidy_options = '-Wall' - AssertEqual + AssertLinter 'clang-tidy', \ ale#Escape('clang-tidy') \ . ' -checks=' . ale#Escape('*') . ' %s' - \ . ' -p ' . ale#Escape('/foo/bar'), - \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + \ . ' -p ' . ale#Escape('/foo/bar') Execute(The build directory should be ignored for header files): call ale#test#SetFilename('test.h') @@ -79,24 +51,17 @@ Execute(The build directory should be ignored for header files): let b:ale_c_build_dir = '/foo/bar' let b:ale_c_clangtidy_options = '-Wall' - AssertEqual + AssertLinter 'clang-tidy', \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('*') . ' %s' - \ . ' -- -Wall', - \ ale_linters#c#clangtidy#GetCommand(bufnr('')) - \ + \ . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' + call ale#test#SetFilename('test.h') - AssertEqual - \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('*') . ' %s' - \ . ' -- -Wall', - \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' Execute(The executable should be configurable): let b:ale_c_clangtidy_executable = 'foobar' - AssertEqual - \ ale#Escape('foobar') - \ . ' -checks=' . ale#Escape('*') . ' %s', - \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + AssertLinter 'foobar', + \ ale#Escape('foobar') . ' -checks=' . ale#Escape('*') . ' %s' diff --git a/test/command_callback/test_c_clangd_command_callbacks.vader b/test/command_callback/test_c_clangd_command_callbacks.vader new file mode 100644 index 00000000..c8c10b67 --- /dev/null +++ b/test/command_callback/test_c_clangd_command_callbacks.vader @@ -0,0 +1,32 @@ +Before: + call ale#assert#SetUpLinterTest('c', 'clangd') + + Save &filetype + let &filetype = 'c' + +After: + call ale#assert#TearDownLinterTest() + +Execute(The language string should be correct): + AssertLSPLanguage 'c' + +Execute(The default executable should be correct): + AssertLinter 'clangd', ale#Escape('clangd') + +Execute(The project root should be detected correctly): + AssertLSPProject '' + + call ale#test#SetFilename('clangd_paths/dummy.c') + + AssertLSPProject ale#path#Simplify(g:dir . '/clangd_paths') + +Execute(The executable should be configurable): + let g:ale_c_clangd_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') + +Execute(The options should be configurable): + let b:ale_c_clangd_options = '-compile-commands-dir=foo' + + AssertLinter 'clangd', ale#Escape('clangd') . ' ' . b:ale_c_clangd_options + diff --git a/test/command_callback/test_c_cppcheck_command_callbacks.vader b/test/command_callback/test_c_cppcheck_command_callbacks.vader index 1643e3e0..3fc87a79 100644 --- a/test/command_callback/test_c_cppcheck_command_callbacks.vader +++ b/test/command_callback/test_c_cppcheck_command_callbacks.vader @@ -1,49 +1,24 @@ Before: - Save g:ale_c_cppcheck_executable - Save g:ale_c_cppcheck_options - - unlet! g:ale_c_cppcheck_executable - unlet! b:ale_c_cppcheck_executable - unlet! g:ale_c_cppcheck_options - unlet! b:ale_c_cppcheck_options - - runtime ale_linters/c/cppcheck.vim + call ale#assert#SetUpLinterTest('c', 'cppcheck') let b:command_tail = ' -q --language=c --enable=style %t' - call ale#test#SetDirectory('/testplugin/test/command_callback') - After: - Restore + call ale#assert#TearDownLinterTest() + unlet! b:command_tail - unlet! b:ale_c_cppcheck_executable - unlet! b:ale_c_cppcheck_options - call ale#linter#Reset() - call ale#test#RestoreDirectory() Execute(The executable should be configurable): - AssertEqual 'cppcheck', ale_linters#c#cppcheck#GetExecutable(bufnr('')) - - let b:ale_c_cppcheck_executable = 'foobar' - - AssertEqual 'foobar', ale_linters#c#cppcheck#GetExecutable(bufnr('')) - -Execute(The executable should be used in the command): - AssertEqual - \ ale#Escape('cppcheck') . b:command_tail, - \ ale_linters#c#cppcheck#GetCommand(bufnr('')) + AssertLinter 'cppcheck', ale#Escape('cppcheck') . b:command_tail let b:ale_c_cppcheck_executable = 'foobar' - AssertEqual - \ ale#Escape('foobar') . b:command_tail, - \ ale_linters#c#cppcheck#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . b:command_tail Execute(cppcheck for C++ should detect compile_commands.json files): call ale#test#SetFilename('cppcheck_paths/one/foo.cpp') - AssertEqual + AssertLinter 'cppcheck', \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) . ' && ' \ . ale#Escape('cppcheck') - \ . ' -q --language=c --project=compile_commands.json --enable=style %t', - \ ale_linters#c#cppcheck#GetCommand(bufnr('')) + \ . ' -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 new file mode 100644 index 00000000..38385e2b --- /dev/null +++ b/test/command_callback/test_c_flawfinder_command_callbacks.vader @@ -0,0 +1,24 @@ +Before: + call ale#assert#SetUpLinterTest('c', 'flawfinder') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The flawfinder command should be correct): + AssertLinter 'flawfinder', ale#Escape('flawfinder') . ' -CDQS --minlevel=1 %t' + +Execute(The minlevel of flawfinder should be configurable): + let b:ale_c_flawfinder_minlevel = 8 + + AssertLinter 'flawfinder', ale#Escape('flawfinder') . ' -CDQS --minlevel=8 %t' + +Execute(Additional flawfinder options should be configurable): + let b:ale_c_flawfinder_options = '--foobar' + + AssertLinter 'flawfinder', + \ ale#Escape('flawfinder') . ' -CDQS --foobar --minlevel=1 %t' + +Execute(The flawfinder exectable should be configurable): + let b:ale_c_flawfinder_executable = 'foo/bar' + + AssertLinter 'foo/bar', ale#Escape('foo/bar') . ' -CDQS --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 8038f410..1f51c3bc 100644 --- a/test/command_callback/test_c_gcc_command_callbacks.vader +++ b/test/command_callback/test_c_gcc_command_callbacks.vader @@ -1,39 +1,21 @@ Before: - Save g:ale_c_gcc_executable - Save g:ale_c_gcc_options + Save g:ale_c_parse_makefile + let g:ale_c_parse_makefile = 0 - unlet! g:ale_c_gcc_executable - unlet! b:ale_c_gcc_executable - unlet! g:ale_c_gcc_options - unlet! b:ale_c_gcc_options - - runtime ale_linters/c/gcc.vim + call ale#assert#SetUpLinterTest('c', 'gcc') let b:command_tail = ' -S -x c -fsyntax-only -iquote' \ . ' ' . ale#Escape(getcwd()) \ . ' -std=c11 -Wall -' After: - Restore + call ale#assert#TearDownLinterTest() + unlet! b:command_tail - unlet! b:ale_c_gcc_executable - unlet! b:ale_c_gcc_options - call ale#linter#Reset() Execute(The executable should be configurable): - AssertEqual 'gcc', ale_linters#c#gcc#GetExecutable(bufnr('')) - - let b:ale_c_gcc_executable = 'foobar' - - AssertEqual 'foobar', ale_linters#c#gcc#GetExecutable(bufnr('')) - -Execute(The executable should be used in the command): - AssertEqual - \ ale#Escape('gcc') . b:command_tail, - \ ale_linters#c#gcc#GetCommand(bufnr('')) + AssertLinter 'gcc', ['', ale#Escape('gcc') . b:command_tail] let b:ale_c_gcc_executable = 'foobar' - AssertEqual - \ ale#Escape('foobar') . b:command_tail, - \ ale_linters#c#gcc#GetCommand(bufnr('')) + AssertLinter 'foobar', ['', ale#Escape('foobar') . b:command_tail] diff --git a/test/command_callback/test_c_import_paths.vader b/test/command_callback/test_c_import_paths.vader new file mode 100644 index 00000000..80fff57b --- /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') + \ . ' -checks=' . ale#Escape('*') . ' %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 9c06f27d..ac8846b0 100644 --- a/test/command_callback/test_cargo_command_callbacks.vader +++ b/test/command_callback/test_cargo_command_callbacks.vader @@ -1,164 +1,130 @@ Before: - Save g:ale_rust_cargo_use_check - Save g:ale_rust_cargo_check_all_targets - Save g:ale_rust_cargo_default_feature_behavior - Save g:ale_rust_cargo_include_features - - unlet! g:ale_rust_cargo_use_check - unlet! g:ale_cargo_check_all_targets - unlet! g:ale_rust_cargo_default_feature_behavior - unlet! g:ale_rust_cargo_include_features - - runtime ale_linters/rust/cargo.vim - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('rust', 'cargo') let g:suffix = ' --frozen --message-format=json -q' + " Test with version 0.22.0 by default. + WithChainResults ['cargo 0.22.0 (3423351a5 2017-10-06)'] + After: - Restore + call ale#assert#TearDownLinterTest() unlet! g:suffix - call ale#test#RestoreDirectory() - call ale#linter#Reset() - call ale#semver#ResetVersionCache() - -Execute(An empty string should be returned for the cargo executable when there's no Cargo.toml file): - AssertEqual - \ '', - \ ale_linters#rust#cargo#GetCargoExecutable(bufnr('')) +Execute(The linter should not be executed when there's no Cargo.toml file): + AssertLinterNotExecuted -Execute(The executable should be returned when there is a Cargo.toml file): +Execute(The linter should be executed when there is a Cargo.toml file): call ale#test#SetFilename('cargo_paths/test.rs') - AssertEqual - \ 'cargo', - \ ale_linters#rust#cargo#GetCargoExecutable(bufnr('')) - -Execute(The VersionCheck function should return the --version command): - AssertEqual - \ 'cargo --version', - \ ale_linters#rust#cargo#VersionCheck(bufnr('')) + WithChainResults [] + AssertLinter 'cargo', + \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/cargo_paths')) . ' && ' + \ . 'cargo build --frozen --message-format=json -q' Execute(The default command should be correct): - AssertEqual - \ 'cargo build' . g:suffix, - \ ale_linters#rust#cargo#GetCommand(bufnr(''), []) + WithChainResults [] + AssertLinter '', ['cargo --version', 'cargo build' . g:suffix] Execute(`cargo check` should be used when the version is new enough): - AssertEqual - \ 'cargo check' . g:suffix, - \ ale_linters#rust#cargo#GetCommand(bufnr(''), [ - \ 'cargo 0.17.0 (3423351a5 2017-10-06)', - \ ]) + WithChainResults ['cargo 0.17.0 (3423351a5 2017-10-06)'] + AssertLinter '', ['cargo --version', 'cargo check' . g:suffix] " We should cache the version check - AssertEqual - \ 'cargo check' . g:suffix, - \ ale_linters#rust#cargo#GetCommand(bufnr(''), []) - - AssertEqual '', ale_linters#rust#cargo#VersionCheck(bufnr('')) + WithChainResults [] + AssertLinter '', ['', 'cargo check' . g:suffix] Execute(`cargo build` should be used when cargo is too old): - AssertEqual - \ 'cargo build' . g:suffix, - \ ale_linters#rust#cargo#GetCommand(bufnr(''), [ - \ 'cargo 0.16.0 (3423351a5 2017-10-06)', - \ ]) + WithChainResults ['cargo 0.16.0 (3423351a5 2017-10-06)'] + AssertLinter '', ['cargo --version', 'cargo build' . g:suffix] - " We should cache the version check - AssertEqual - \ 'cargo build' . g:suffix, - \ ale_linters#rust#cargo#GetCommand(bufnr(''), []) - - AssertEqual '', ale_linters#rust#cargo#VersionCheck(bufnr('')) + WithChainResults [] + AssertLinter '', ['', 'cargo build' . g:suffix] Execute(`cargo build` should be used when g:ale_rust_cargo_use_check is set to 0): let g:ale_rust_cargo_use_check = 0 - AssertEqual - \ 'cargo build' . g:suffix, - \ ale_linters#rust#cargo#GetCommand(bufnr(''), [ - \ 'cargo 0.24.0 (3423351a5 2017-10-06)', - \ ]) + WithChainResults ['cargo 0.24.0 (3423351a5 2017-10-06)'] + AssertLinter '', ['cargo --version', 'cargo build' . g:suffix] " We should cache the version check - AssertEqual - \ 'cargo build' . g:suffix, - \ ale_linters#rust#cargo#GetCommand(bufnr(''), []) - - AssertEqual '', ale_linters#rust#cargo#VersionCheck(bufnr('')) + WithChainResults [] + AssertLinter '', ['', 'cargo build' . g:suffix] Execute(`cargo check` should be used when the version is new enough): - AssertEqual - \ 'cargo check' . g:suffix, - \ ale_linters#rust#cargo#GetCommand(bufnr(''), [ - \ 'cargo 0.22.0 (3423351a5 2017-10-06)', - \ ]) + AssertLinter '', ['cargo --version', 'cargo check' . g:suffix] " We should cache the version check - AssertEqual - \ 'cargo check' . g:suffix, - \ ale_linters#rust#cargo#GetCommand(bufnr(''), []) - - AssertEqual '', ale_linters#rust#cargo#VersionCheck(bufnr('')) + WithChainResults [] + AssertLinter '', ['', 'cargo check' . g:suffix] Execute(--all-targets should be used when g:ale_rust_cargo_check_all_targets is set to 1): let g:ale_rust_cargo_check_all_targets = 1 - AssertEqual - \ 'cargo check --all-targets' . g:suffix, - \ ale_linters#rust#cargo#GetCommand(bufnr(''), [ - \ 'cargo 0.22.0 (3423351a5 2017-10-06)', - \ ]) + AssertLinter '', ['cargo --version', 'cargo check --all-targets' . g:suffix] " We should cache the version check - AssertEqual - \ 'cargo check --all-targets' . g:suffix, - \ ale_linters#rust#cargo#GetCommand(bufnr(''), []) + WithChainResults [] + AssertLinter '', ['', 'cargo check --all-targets' . g:suffix] + +Execute(--tests should be used when g:ale_rust_cargo_check_tests is set to 1): + let g:ale_rust_cargo_check_tests = 1 - AssertEqual '', ale_linters#rust#cargo#VersionCheck(bufnr('')) + AssertLinter '', ['cargo --version', 'cargo check --tests' . g:suffix] + + " We should cache the version check + WithChainResults [] + AssertLinter '', ['', 'cargo check --tests' . g:suffix] + +Execute(--examples should be used when g:ale_rust_cargo_check_examples is set to 1): + let g:ale_rust_cargo_check_examples = 1 + + AssertLinter '', ['cargo --version', 'cargo check --examples' . g:suffix] + + " We should cache the version check + WithChainResults [] + AssertLinter '', ['', 'cargo check --examples' . g:suffix] Execute(--no-default-features should be used when g:ale_rust_cargo_default_feature_behavior is none): - let g:ale_rust_cargo_default_feature_behavior = 'none' + let b:ale_rust_cargo_default_feature_behavior = 'none' - AssertEqual - \ 'cargo check' . g:suffix . ' --no-default-features', - \ ale_linters#rust#cargo#GetCommand(bufnr(''), [ - \ 'cargo 0.22.0 (3423351a5 2017-10-06)', - \ ]) + AssertLinter '', ['cargo --version', 'cargo check --frozen --message-format=json -q --no-default-features'] Execute(g:ale_rust_cargo_include_features added when g:ale_rust_cargo_default_feature_behavior is none): - let g:ale_rust_cargo_default_feature_behavior = 'none' - let g:ale_rust_cargo_include_features = 'foo bar' + let b:ale_rust_cargo_default_feature_behavior = 'none' + let b:ale_rust_cargo_include_features = 'foo bar' - AssertEqual - \ 'cargo check' . g:suffix . ' --no-default-features --features ' . - \ (fnamemodify(&shell, ':t') is? 'cmd.exe' ? '"foo bar"' : "'foo bar'"), - \ ale_linters#rust#cargo#GetCommand(bufnr(''), [ - \ 'cargo 0.22.0 (3423351a5 2017-10-06)', - \ ]) + AssertLinter '', ['cargo --version', 'cargo check --frozen --message-format=json -q --no-default-features --features ' . ale#Escape('foo bar')] Execute(g:ale_rust_cargo_include_features added and escaped): - let g:ale_rust_cargo_default_feature_behavior = 'default' - let g:ale_rust_cargo_include_features = "foo bar baz" + let b:ale_rust_cargo_default_feature_behavior = 'default' + let b:ale_rust_cargo_include_features = "foo bar baz" - AssertEqual - \ 'cargo check' . g:suffix . ' --features ' . - \ (fnamemodify(&shell, ':t') is? 'cmd.exe' ? '"foo bar baz"' : "'foo bar baz'"), - \ ale_linters#rust#cargo#GetCommand(bufnr(''), [ - \ 'cargo 0.22.0 (3423351a5 2017-10-06)', - \ ]) + AssertLinter '', ['cargo --version', 'cargo check --frozen --message-format=json -q --features ' . ale#Escape('foo bar baz')] Execute(--all-features should be used when g:ale_rust_cargo_default_feature_behavior is all): - let g:ale_rust_cargo_default_feature_behavior = 'all' - + let b:ale_rust_cargo_default_feature_behavior = 'all' " When all features are enabled we should ignore extra features to add " since it won't do anything - let g:ale_rust_cargo_include_features = 'foo bar' + let b:ale_rust_cargo_include_features = 'foo bar' - AssertEqual - \ 'cargo check' . g:suffix . ' --all-features', - \ ale_linters#rust#cargo#GetCommand(bufnr(''), [ - \ 'cargo 0.22.0 (3423351a5 2017-10-06)', - \ ]) + WithChainResults ['cargo 0.22.0 (3423351a5 2017-10-06)'] + AssertLinter '', ['cargo --version', 'cargo check --frozen --message-format=json -q --all-features'] + +Execute(When a crate belongs to a workspace we should cd into the crate): + call ale#test#SetFilename('cargo_workspace_paths/subpath/test.rs') + + AssertLinter 'cargo', [ + \ 'cargo --version', + \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/cargo_workspace_paths/subpath')) . ' && ' + \ . 'cargo check --frozen --message-format=json -q', + \] + +Execute(When a crate belongs to a workspace we chdir into the crate, unless we disabled it): + let g:ale_rust_cargo_avoid_whole_workspace = 0 + call ale#test#SetFilename('cargo_workspace_paths/subpath/test.rs') + + AssertLinter 'cargo', [ + \ '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 f82efffe..f28609ee 100644 --- a/test/command_callback/test_clang_tidy_command_callback.vader +++ b/test/command_callback/test_clang_tidy_command_callback.vader @@ -1,74 +1,46 @@ Before: - Save g:ale_cpp_clangtidy_checks - Save g:ale_cpp_clangtidy_options - Save g:ale_c_build_dir - - unlet! g:ale_c_build_dir - unlet! b:ale_c_build_dir - unlet! g:ale_cpp_clangtidy_checks - unlet! b:ale_cpp_clangtidy_checks - unlet! g:ale_cpp_clangtidy_options - unlet! b:ale_cpp_clangtidy_options - - runtime ale_linters/cpp/clangtidy.vim - + call ale#assert#SetUpLinterTest('cpp', 'clangtidy') call ale#test#SetFilename('test.cpp') After: - unlet! b:ale_c_build_dir - unlet! b:ale_cpp_clangtidy_checks - unlet! b:ale_cpp_clangtidy_options - unlet! b:ale_cpp_clangtidy_executable - - Restore - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The clangtidy command default should be correct): - AssertEqual - \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('*') . ' %s', - \ ale_linters#cpp#clangtidy#GetCommand(bufnr('')) + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s' Execute(You should be able to remove the -checks option for clang-tidy): let b:ale_cpp_clangtidy_checks = [] - AssertEqual - \ ale#Escape('clang-tidy') - \ . ' %s', - \ ale_linters#cpp#clangtidy#GetCommand(bufnr('')) + 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-*'] - AssertEqual + AssertLinter 'clang-tidy', \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('-*,clang-analyzer-*') . ' %s', - \ ale_linters#cpp#clangtidy#GetCommand(bufnr('')) + \ . ' -checks=' . ale#Escape('-*,clang-analyzer-*') . ' %s' Execute(You should be able to manually set compiler flags for clang-tidy): let b:ale_cpp_clangtidy_options = '-Wall' - AssertEqual - \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('*') . ' %s -- -Wall', - \ ale_linters#cpp#clangtidy#GetCommand(bufnr('')) + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' \ Execute(The build directory should be configurable): let b:ale_c_build_dir = '/foo/bar' - AssertEqual + AssertLinter 'clang-tidy', \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('*') . ' %s -p ' . ale#Escape('/foo/bar'), - \ ale_linters#cpp#clangtidy#GetCommand(bufnr('')) + \ . ' -checks=' . ale#Escape('*') . ' %s -p ' . ale#Escape('/foo/bar') Execute(The build directory setting should override the options): let b:ale_c_build_dir = '/foo/bar' let b:ale_cpp_clangtidy_options = '-Wall' - AssertEqual + AssertLinter 'clang-tidy', \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('*') . ' %s -p ' . ale#Escape('/foo/bar'), - \ ale_linters#cpp#clangtidy#GetCommand(bufnr('')) + \ . ' -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') @@ -76,22 +48,16 @@ Execute(The build directory should be ignored for header files): let b:ale_c_build_dir = '/foo/bar' let b:ale_cpp_clangtidy_options = '-Wall' - AssertEqual - \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('*') . ' %s -- -Wall', - \ ale_linters#cpp#clangtidy#GetCommand(bufnr('')) - \ + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' + call ale#test#SetFilename('test.hpp') - AssertEqual - \ ale#Escape('clang-tidy') - \ . ' -checks=' . ale#Escape('*') . ' %s -- -Wall', - \ ale_linters#cpp#clangtidy#GetCommand(bufnr('')) + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' Execute(The executable should be configurable): let b:ale_cpp_clangtidy_executable = 'foobar' - AssertEqual - \ ale#Escape('foobar') - \ . ' -checks=' . ale#Escape('*') . ' %s', - \ ale_linters#cpp#clangtidy#GetCommand(bufnr('')) + AssertLinter 'foobar', + \ ale#Escape('foobar') . ' -checks=' . ale#Escape('*') . ' %s' diff --git a/test/command_callback/test_cpp_clang_command_callbacks.vader b/test/command_callback/test_cpp_clang_command_callbacks.vader index 67d6898c..e96fd8e7 100644 --- a/test/command_callback/test_cpp_clang_command_callbacks.vader +++ b/test/command_callback/test_cpp_clang_command_callbacks.vader @@ -1,39 +1,19 @@ Before: - Save g:ale_cpp_clang_executable - Save g:ale_cpp_clang_options - - unlet! g:ale_cpp_clang_executable - unlet! b:ale_cpp_clang_executable - unlet! g:ale_cpp_clang_options - unlet! b:ale_cpp_clang_options - - runtime ale_linters/cpp/clang.vim + Save g:ale_c_parse_makefile + let g:ale_c_parse_makefile = 0 + call ale#assert#SetUpLinterTest('cpp', 'clang') let b:command_tail = ' -S -x c++ -fsyntax-only -iquote' \ . ' ' . ale#Escape(getcwd()) \ . ' -std=c++14 -Wall -' After: - Restore unlet! b:command_tail - unlet! b:ale_cpp_clang_executable - unlet! b:ale_cpp_clang_options - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The executable should be configurable): - AssertEqual 'clang++', ale_linters#cpp#clang#GetExecutable(bufnr('')) - - let b:ale_cpp_clang_executable = 'foobar' - - AssertEqual 'foobar', ale_linters#cpp#clang#GetExecutable(bufnr('')) - -Execute(The executable should be used in the command): - AssertEqual - \ ale#Escape('clang++') . b:command_tail, - \ ale_linters#cpp#clang#GetCommand(bufnr('')) + AssertLinter 'clang++', ale#Escape('clang++') . b:command_tail let b:ale_cpp_clang_executable = 'foobar' - AssertEqual - \ ale#Escape('foobar') . b:command_tail, - \ ale_linters#cpp#clang#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . b:command_tail diff --git a/test/command_callback/test_cpp_clangcheck_command_callbacks.vader b/test/command_callback/test_cpp_clangcheck_command_callbacks.vader index f708c52d..7aa09eed 100644 --- a/test/command_callback/test_cpp_clangcheck_command_callbacks.vader +++ b/test/command_callback/test_cpp_clangcheck_command_callbacks.vader @@ -1,63 +1,35 @@ Before: - Save g:ale_cpp_clangcheck_executable - Save g:ale_cpp_clangcheck_options - - unlet! g:ale_cpp_clangcheck_executable - unlet! b:ale_cpp_clangcheck_executable - unlet! g:ale_cpp_clangcheck_options - unlet! b:ale_cpp_clangcheck_options - - runtime ale_linters/cpp/clangcheck.vim + call ale#assert#SetUpLinterTest('cpp', 'clangcheck') After: - Restore - unlet! b:command_tail - unlet! b:ale_cpp_clangcheck_executable - unlet! b:ale_cpp_clangcheck_options - unlet! b:ale_c_build_dir - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The executable should be configurable): - AssertEqual 'clang-check', ale_linters#cpp#clangcheck#GetExecutable(bufnr('')) - - let b:ale_cpp_clangcheck_executable = 'foobar' - - AssertEqual 'foobar', ale_linters#cpp#clangcheck#GetExecutable(bufnr('')) - -Execute(The executable should be used in the command): - AssertEqual + AssertLinter 'clang-check', \ ale#Escape('clang-check') - \ . ' -analyze %s' - \ . ' -extra-arg -Xclang -extra-arg -analyzer-output=text', - \ ale_linters#cpp#clangcheck#GetCommand(bufnr('')) + \ . ' -analyze %s -extra-arg -Xclang -extra-arg -analyzer-output=text' let b:ale_cpp_clangcheck_executable = 'foobar' " The extra arguments in the command are used to prevent .plist files from " being generated. - AssertEqual + AssertLinter 'foobar', \ ale#Escape('foobar') - \ . ' -analyze %s' - \ . ' -extra-arg -Xclang -extra-arg -analyzer-output=text', - \ ale_linters#cpp#clangcheck#GetCommand(bufnr('')) + \ . ' -analyze %s -extra-arg -Xclang -extra-arg -analyzer-output=text' Execute(The options should be configurable): let b:ale_cpp_clangcheck_options = '--something' - AssertEqual + AssertLinter 'clang-check', \ ale#Escape('clang-check') \ . ' -analyze %s' \ . ' -extra-arg -Xclang -extra-arg -analyzer-output=text' - \ . ' --something', - \ ale_linters#cpp#clangcheck#GetCommand(bufnr('')) + \ . ' --something' Execute(The build directory should be used when set): let b:ale_cpp_clangcheck_options = '--something' let b:ale_c_build_dir = '/foo/bar' - AssertEqual + AssertLinter 'clang-check', \ ale#Escape('clang-check') - \ . ' -analyze %s ' - \ . '--something -p ' - \ . ale#Escape('/foo/bar'), - \ ale_linters#cpp#clangcheck#GetCommand(bufnr('')) + \ . ' -analyze %s --something -p ' . ale#Escape('/foo/bar') 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..f28609ee --- /dev/null +++ b/test/command_callback/test_cpp_clazy_command_callback.vader @@ -0,0 +1,63 @@ +Before: + call ale#assert#SetUpLinterTest('cpp', 'clangtidy') + call ale#test#SetFilename('test.cpp') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The clangtidy command default should be correct): + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %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' + +Execute(You should be able to set other checks for clang-tidy): + let b:ale_cpp_clangtidy_checks = ['-*', 'clang-analyzer-*'] + + AssertLinter 'clang-tidy', + \ ale#Escape('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_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_build_dir = '/foo/bar' + + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') + \ . ' -checks=' . ale#Escape('*') . ' %s -p ' . ale#Escape('/foo/bar') + +Execute(The build directory setting should override the options): + 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') + +Execute(The build directory should be ignored for header files): + call ale#test#SetFilename('test.h') + + 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' + + call ale#test#SetFilename('test.hpp') + + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' + +Execute(The executable should be configurable): + let b:ale_cpp_clangtidy_executable = 'foobar' + + AssertLinter 'foobar', + \ ale#Escape('foobar') . ' -checks=' . ale#Escape('*') . ' %s' diff --git a/test/command_callback/test_cpp_cppcheck_command_callbacks.vader b/test/command_callback/test_cpp_cppcheck_command_callbacks.vader index 2c9d7298..3a7ada2c 100644 --- a/test/command_callback/test_cpp_cppcheck_command_callbacks.vader +++ b/test/command_callback/test_cpp_cppcheck_command_callbacks.vader @@ -1,49 +1,22 @@ Before: - Save g:ale_cpp_cppcheck_executable - Save g:ale_cpp_cppcheck_options - - unlet! g:ale_cpp_cppcheck_executable - unlet! b:ale_cpp_cppcheck_executable - unlet! g:ale_cpp_cppcheck_options - unlet! b:ale_cpp_cppcheck_options - - runtime ale_linters/cpp/cppcheck.vim - + call ale#assert#SetUpLinterTest('cpp', 'cppcheck') let b:command_tail = ' -q --language=c++ --enable=style %t' - call ale#test#SetDirectory('/testplugin/test/command_callback') - After: - Restore unlet! b:command_tail - unlet! b:ale_cpp_cppcheck_executable - unlet! b:ale_cpp_cppcheck_options - call ale#linter#Reset() - call ale#test#RestoreDirectory() + call ale#assert#TearDownLinterTest() Execute(The executable should be configurable): - AssertEqual 'cppcheck', ale_linters#cpp#cppcheck#GetExecutable(bufnr('')) - - let b:ale_cpp_cppcheck_executable = 'foobar' - - AssertEqual 'foobar', ale_linters#cpp#cppcheck#GetExecutable(bufnr('')) - -Execute(The executable should be used in the command): - AssertEqual - \ ale#Escape('cppcheck') . b:command_tail, - \ ale_linters#cpp#cppcheck#GetCommand(bufnr('')) + AssertLinter 'cppcheck', ale#Escape('cppcheck') . b:command_tail let b:ale_cpp_cppcheck_executable = 'foobar' - AssertEqual - \ ale#Escape('foobar') . b:command_tail, - \ ale_linters#cpp#cppcheck#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . b:command_tail Execute(cppcheck for C++ should detect compile_commands.json files): call ale#test#SetFilename('cppcheck_paths/one/foo.cpp') - AssertEqual + AssertLinter 'cppcheck', \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) . ' && ' \ . ale#Escape('cppcheck') - \ . ' -q --language=c++ --project=compile_commands.json --enable=style %t', - \ ale_linters#cpp#cppcheck#GetCommand(bufnr('')) + \ . ' -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 new file mode 100644 index 00000000..682c90d5 --- /dev/null +++ b/test/command_callback/test_cpp_cquery_command_callbacks.vader @@ -0,0 +1,36 @@ +" Author: Ben Falconer <ben@falconers.me.uk> +" Description: A language server for C++ + +Before: + call ale#assert#SetUpLinterTest('cpp', '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.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') + + let b:ale_cpp_cquery_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') + +Execute(The cache directory should be configurable): + AssertLSPOptions {'cacheDirectory': expand('$HOME/.cache/cquery')} + + let b:ale_cpp_cquery_cache_directory = '/foo/bar' + + AssertLSPOptions {'cacheDirectory': '/foo/bar'} diff --git a/test/command_callback/test_cpp_flawfinder_command_callbacks.vader b/test/command_callback/test_cpp_flawfinder_command_callbacks.vader new file mode 100644 index 00000000..3f4067ea --- /dev/null +++ b/test/command_callback/test_cpp_flawfinder_command_callbacks.vader @@ -0,0 +1,26 @@ +Before: + call ale#assert#SetUpLinterTest('cpp', 'flawfinder') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The flawfinder command should be correct): + AssertLinter 'flawfinder', + \ ale#Escape('flawfinder') . ' -CDQS --minlevel=1 %t' + +Execute(The minlevel of flawfinder should be configurable): + let b:ale_cpp_flawfinder_minlevel = 8 + + AssertLinter 'flawfinder', + \ ale#Escape('flawfinder') . ' -CDQS --minlevel=8 %t' + +Execute(Additional flawfinder options should be configurable): + let b:ale_cpp_flawfinder_options = ' --foobar' + + AssertLinter 'flawfinder', + \ ale#Escape('flawfinder') . ' -CDQS --foobar --minlevel=1 %t' + +Execute(The flawfinder exectable should be configurable): + let b:ale_cpp_flawfinder_executable = 'foo/bar' + + AssertLinter 'foo/bar', ale#Escape('foo/bar') . ' -CDQS --minlevel=1 %t' diff --git a/test/command_callback/test_cpp_gcc_command_callbacks.vader b/test/command_callback/test_cpp_gcc_command_callbacks.vader index 9ab4d5cb..0a86df4f 100644 --- a/test/command_callback/test_cpp_gcc_command_callbacks.vader +++ b/test/command_callback/test_cpp_gcc_command_callbacks.vader @@ -1,39 +1,19 @@ Before: - Save g:ale_cpp_gcc_executable - Save g:ale_cpp_gcc_options - - unlet! g:ale_cpp_gcc_executable - unlet! b:ale_cpp_gcc_executable - unlet! g:ale_cpp_gcc_options - unlet! b:ale_cpp_gcc_options - - runtime ale_linters/cpp/gcc.vim + 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()) \ . ' -std=c++14 -Wall -' After: - Restore unlet! b:command_tail - unlet! b:ale_cpp_gcc_executable - unlet! b:ale_cpp_gcc_options - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The executable should be configurable): - AssertEqual 'gcc', ale_linters#cpp#gcc#GetExecutable(bufnr('')) - - let b:ale_cpp_gcc_executable = 'foobar' - - AssertEqual 'foobar', ale_linters#cpp#gcc#GetExecutable(bufnr('')) - -Execute(The executable should be used in the command): - AssertEqual - \ ale#Escape('gcc') . b:command_tail, - \ ale_linters#cpp#gcc#GetCommand(bufnr('')) + AssertLinter 'gcc', ale#Escape('gcc') . b:command_tail let b:ale_cpp_gcc_executable = 'foobar' - AssertEqual - \ ale#Escape('foobar') . b:command_tail, - \ ale_linters#cpp#gcc#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . b:command_tail diff --git a/test/command_callback/test_cpplint_command_callbacks.vader b/test/command_callback/test_cpplint_command_callbacks.vader index 34746a1b..d5fd457b 100644 --- a/test/command_callback/test_cpplint_command_callbacks.vader +++ b/test/command_callback/test_cpplint_command_callbacks.vader @@ -1,42 +1,17 @@ Before: - Save g:ale_cpp_cpplint_executable - Save g:ale_cpp_cpplint_options - - unlet! g:ale_cpp_cpplint_executable - unlet! b:ale_cpp_cpplint_executable - unlet! g:ale_cpp_cpplint_options - unlet! b:ale_cpp_cpplint_options - - runtime ale_linters/cpp/cpplint.vim + call ale#assert#SetUpLinterTest('cpp', 'cpplint') After: - Restore - unlet! b:command_tail - unlet! b:ale_cpp_cpplint_executable - unlet! b:ale_cpp_cpplint_options - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The executable should be configurable): - AssertEqual 'cpplint', ale_linters#cpp#cpplint#GetExecutable(bufnr('')) + AssertLinter 'cpplint', ale#Escape('cpplint') . ' %s' let b:ale_cpp_cpplint_executable = 'foobar' - AssertEqual 'foobar', ale_linters#cpp#cpplint#GetExecutable(bufnr('')) - -Execute(The executable should be used in the command): - AssertEqual - \ ale#Escape('cpplint') . ' %s', - \ ale_linters#cpp#cpplint#GetCommand(bufnr('')) - - let b:ale_cpp_cpplint_executable = 'foobar' + AssertLinter 'foobar', ale#Escape('foobar') . ' %s' - AssertEqual - \ ale#Escape('foobar') . ' %s', - \ ale_linters#cpp#cpplint#GetCommand(bufnr('')) - \ Execute(The options should be configurable): let b:ale_cpp_cpplint_options = '--something' - AssertEqual - \ ale#Escape('cpplint') . ' --something %s', - \ ale_linters#cpp#cpplint#GetCommand(bufnr('')) + AssertLinter 'cpplint', ale#Escape('cpplint') . ' --something %s' diff --git a/test/command_callback/test_cs_mcs_command_callbacks.vader b/test/command_callback/test_cs_mcs_command_callbacks.vader index 30f067ea..dbebd106 100644 --- a/test/command_callback/test_cs_mcs_command_callbacks.vader +++ b/test/command_callback/test_cs_mcs_command_callbacks.vader @@ -1,34 +1,13 @@ Before: - Save g:ale_cs_mcs_options - - unlet! g:ale_cs_mcs_options - - runtime ale_linters/cs/mcs.vim - - let b:command_tail = ' -unsafe --parse' + call ale#assert#SetUpLinterTest('cs', 'mcs') After: - Restore - unlet! b:command_tail - unlet! b:ale_cs_mcs_options - call ale#linter#Reset() - -Execute(Check for proper default command): + call ale#assert#TearDownLinterTest() - let b:command = ale_linters#cs#mcs#GetCommand(bufnr('')) - let b:command = substitute(b:command,'\s\+',' ','g') - - AssertEqual - \ b:command, - \ 'mcs -unsafe --parse %t' +Execute(The default command should be correct): + AssertLinter 'mcs', 'mcs -unsafe --parse %t' Execute(The options should be be used in the command): - let b:ale_cs_mcs_options = '-pkg:dotnet' - let b:command = ale_linters#cs#mcs#GetCommand(bufnr('')) - let b:command = substitute(b:command,'\s\+',' ','g') - - AssertEqual - \ b:command, - \ 'mcs' . b:command_tail . ' ' . b:ale_cs_mcs_options . ' %t', + AssertLinter 'mcs', 'mcs -unsafe --parse -pkg:dotnet %t' diff --git a/test/command_callback/test_cs_mcsc_command_callbacks.vader b/test/command_callback/test_cs_mcsc_command_callbacks.vader index cb52c969..20ddb28b 100644 --- a/test/command_callback/test_cs_mcsc_command_callbacks.vader +++ b/test/command_callback/test_cs_mcsc_command_callbacks.vader @@ -1,93 +1,47 @@ Before: - Save g:ale_cs_mcsc_options - Save g:ale_cs_mcsc_source - Save g:ale_cs_mcsc_assembly_path - Save g:ale_cs_mcsc_assemblies - Save g:ale_buffer_info - - let g:ale_buffer_info = {bufnr(''): {'temporary_file_list': []}} - - unlet! g:ale_cs_mcsc_options - unlet! g:ale_cs_mcsc_source - unlet! g:ale_cs_mcsc_assembly_path - unlet! g:ale_cs_mcsc_assemblies - - let g:prefix = ' -out:TEMP -t:module -recurse:' . ale#Escape('*.cs') - - function! GetCommand() - let l:command = ale_linters#cs#mcsc#GetCommand(bufnr('')) - let l:command = join(split(l:command)) - - return substitute(l:command, ':[^ ]\+ -t:module', ':TEMP -t:module', '') - endfunction - - runtime ale_linters/cs/mcsc.vim + call ale#assert#SetUpLinterTest('cs', 'mcsc') After: - Restore - - unlet! b:ale_cs_mcsc_options - unlet! g:ale_cs_mcsc_source - unlet! g:ale_cs_mcsc_assembly_path - unlet! g:ale_cs_mcsc_assemblies - unlet! g:ale_prefix - - delfunction GetCommand - - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The mcsc linter should return the correct default command): - AssertEqual - \ ale#path#BufferCdString(bufnr('')) - \ . 'mcs -unsafe' . g:prefix, - \ GetCommand() + AssertLinter 'mcs', 'cd ' . ale#Escape(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' - AssertEqual - \ ale#path#BufferCdString(bufnr('')) - \ . 'mcs -unsafe -pkg:dotnet' . g:prefix, - \ GetCommand() + AssertLinter 'mcs', 'cd ' . ale#Escape(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' - AssertEqual - \ 'cd ' . ale#Escape('../foo/bar') . ' && ' - \ . 'mcs -unsafe' . g:prefix, - \ GetCommand() + AssertLinter 'mcs', 'cd ' . ale#Escape('../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'] - AssertEqual - \ ale#path#BufferCdString(bufnr('')) - \ . 'mcs -unsafe' - \ . ' -lib:' . ale#Escape('/usr/lib/mono') . ',' . ale#Escape('../foo/bar') - \ . g:prefix, - \ GetCommand() + AssertLinter 'mcs', 'cd ' . ale#Escape(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 = [] - AssertEqual - \ ale#path#BufferCdString(bufnr('')) - \ . 'mcs -unsafe' . g:prefix, - \ GetCommand() + AssertLinter 'mcs', 'cd ' . ale#Escape(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'] - AssertEqual - \ ale#path#BufferCdString(bufnr('')) - \ . 'mcs -unsafe' - \ . ' -r:' . ale#Escape('foo.dll') . ',' . ale#Escape('bar.dll') - \ . g:prefix, - \ GetCommand() + AssertLinter 'mcs', 'cd ' . ale#Escape(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 = [] - AssertEqual - \ ale#path#BufferCdString(bufnr('')) - \ . 'mcs -unsafe' . g:prefix, - \ GetCommand() + AssertLinter 'mcs', 'cd ' . ale#Escape(g:dir) . ' && ' + \ . 'mcs -unsafe -out:TEMP -t:module -recurse:' . ale#Escape('*.cs') diff --git a/test/command_callback/test_cucumber_command_callback.vader b/test/command_callback/test_cucumber_command_callback.vader new file mode 100644 index 00000000..7a8457fc --- /dev/null +++ b/test/command_callback/test_cucumber_command_callback.vader @@ -0,0 +1,18 @@ +Before: + call ale#assert#SetUpLinterTest('cucumber', 'cucumber') + +After: + call ale#assert#TearDownLinterTest() + +Execute(Should require the nearest features dir, if one is found): + call ale#test#SetFilename('../cucumber_fixtures/features/cuke.feature') + + AssertLinter 'cucumber', + \ 'cucumber --dry-run --quiet --strict --format=json ' + \ . '-r ' . ale#Escape(ale#path#Simplify(g:dir . '/../cucumber_fixtures/features/')) . ' %t' + +Execute(Should require nothing if no features dir is found): + call ale#test#SetFilename('something/without/a/features/dir') + + AssertLinter 'cucumber', + \ 'cucumber --dry-run --quiet --strict --format=json %t' diff --git a/test/command_callback/test_cuda_nvcc_command_callbacks.vader b/test/command_callback/test_cuda_nvcc_command_callbacks.vader index af199d37..4578d052 100644 --- a/test/command_callback/test_cuda_nvcc_command_callbacks.vader +++ b/test/command_callback/test_cuda_nvcc_command_callbacks.vader @@ -1,36 +1,20 @@ Before: - Save g:ale_cuda_nvcc_executable - Save g:ale_cuda_nvcc_options - - unlet! g:ale_cuda_nvcc_executable - unlet! b:ale_cuda_nvcc_executable - unlet! g:ale_cuda_nvcc_options - unlet! b:ale_cuda_nvcc_options - - runtime ale_linters/cuda/nvcc.vim + call ale#assert#SetUpLinterTest('cuda', 'nvcc') After: - Restore - unlet! b:ale_cuda_nvcc_executable - unlet! b:ale_cuda_nvcc_options - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The executable should be configurable): - AssertEqual 'nvcc', ale_linters#cuda#nvcc#GetExecutable(bufnr('')) + AssertLinter 'nvcc', + \ ale#Escape('nvcc') . ' -cuda -std=c++11 %s -o ' . g:ale#util#nul_file let b:ale_cuda_nvcc_executable = 'foobar' - AssertEqual 'foobar', ale_linters#cuda#nvcc#GetExecutable(bufnr('')) + AssertLinter 'foobar', + \ ale#Escape('foobar') . ' -cuda -std=c++11 %s -o ' . g:ale#util#nul_file -Execute(The executable should be used in the command): - AssertEqual - \ ale#Escape('nvcc') . ' -cuda -std=c++11 %s' - \ . ' -o ' . g:ale#util#nul_file, - \ ale_linters#cuda#nvcc#GetCommand(bufnr('')) - - let b:ale_cuda_nvcc_executable = 'foobar' +Execute(The options should be configurable): + let g:ale_cuda_nvcc_options = '--foobar' - AssertEqual - \ ale#Escape('foobar') . ' -cuda -std=c++11 %s' - \ . ' -o ' . g:ale#util#nul_file, - \ ale_linters#cuda#nvcc#GetCommand(bufnr('')) + AssertLinter 'nvcc', + \ ale#Escape('nvcc') . ' -cuda --foobar %s -o ' . g:ale#util#nul_file diff --git a/test/command_callback/test_dartanalyzer_command_callback.vader b/test/command_callback/test_dartanalyzer_command_callback.vader index c7b51396..62b1d636 100644 --- a/test/command_callback/test_dartanalyzer_command_callback.vader +++ b/test/command_callback/test_dartanalyzer_command_callback.vader @@ -1,40 +1,20 @@ Before: - Save g:ale_dart_dartanalyzer_executable - unlet! g:ale_dart_dartanalyzer_executable - - runtime ale_linters/dart/dartanalyzer.vim - - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('dart', 'dartanalyzer') After: - Restore - - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The default command and executable should be correct): - AssertEqual - \ 'dartanalyzer', - \ ale_linters#dart#dartanalyzer#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('dartanalyzer') . ' %s', - \ ale_linters#dart#dartanalyzer#GetCommand(bufnr('')) + AssertLinter 'dartanalyzer', ale#Escape('dartanalyzer') . ' %s' Execute(The executable should be configurable): - let g:ale_dart_dartanalyzer_executable = '/usr/lib/dart/bin/dartanalyzer' + let g:ale_dart_dartanalyzer_executable = 'foobar' - AssertEqual - \ '/usr/lib/dart/bin/dartanalyzer', - \ ale_linters#dart#dartanalyzer#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('/usr/lib/dart/bin/dartanalyzer') . ' %s', - \ ale_linters#dart#dartanalyzer#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . ' %s' Execute(The .packages file should be set if detected): call ale#test#SetFilename('dart_paths/foo') - AssertEqual - \ ale#Escape('dartanalyzer') + AssertLinter 'dartanalyzer', ale#Escape('dartanalyzer') \ . ' --packages ' . ale#Escape(ale#path#Simplify(g:dir . '/dart_paths/.packages')) - \ . ' %s', - \ ale_linters#dart#dartanalyzer#GetCommand(bufnr('')) + \ . ' %s' diff --git a/test/command_callback/test_elixir_mix_command_callbacks.vader b/test/command_callback/test_elixir_mix_command_callbacks.vader new file mode 100644 index 00000000..18fb13ed --- /dev/null +++ b/test/command_callback/test_elixir_mix_command_callbacks.vader @@ -0,0 +1,19 @@ +Before: + call ale#assert#SetUpLinterTest('elixir', 'mix') + + let g:env_prefix = has('win32') + \ ? 'set MIX_BUILD_PATH=' . ale#Escape('TEMP_DIR') . ' && ' + \ : 'MIX_BUILD_PATH=' . ale#Escape('TEMP_DIR') . ' ' + +After: + unlet! g:env_prefix + + call ale#assert#TearDownLinterTest() + +Execute(The default mix command should be correct): + call ale#test#SetFilename('mix_paths/wrapped_project/lib/app.ex') + + AssertLinter 'mix', + \ ale#path#CdString(ale#path#Simplify(g:dir . '/mix_paths/wrapped_project')) + \ . g:env_prefix + \ . 'mix compile %s' 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_erb_command_callback.vader b/test/command_callback/test_erb_command_callback.vader index 481f64f9..c29d9215 100644 --- a/test/command_callback/test_erb_command_callback.vader +++ b/test/command_callback/test_erb_command_callback.vader @@ -1,21 +1,16 @@ Before: - runtime ale_linters/eruby/erb.vim - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('eruby', 'erb') After: - call ale#linter#Reset() - call ale#test#RestoreDirectory() + call ale#assert#TearDownLinterTest() Execute(Executable should not contain any filter code by default): call ale#test#SetFilename('../ruby_fixtures/not_a_rails_app/file.rb') - AssertEqual - \ 'erb -P -T - -x %t | ruby -c', - \ ale_linters#eruby#erb#GetCommand(bufnr('')) + AssertLinter 'erb', 'erb -P -T - -x %t | ruby -c' Execute(Executable should filter invalid eRuby when inside a Rails project): call ale#test#SetFilename('../ruby_fixtures/valid_rails_app/app/views/my_great_view.html.erb') - AssertEqual - \ 'ruby -r erb -e ' . ale#Escape('puts ERB.new($stdin.read.gsub(%{<%=},%{<%}), nil, %{-}).src') . '< %t | ruby -c', - \ ale_linters#eruby#erb#GetCommand(bufnr('')) + AssertLinter 'erb', + \ 'ruby -r erb -e ' . ale#Escape('puts ERB.new($stdin.read.gsub(%{<%=},%{<%}), nil, %{-}).src') . '< %t | ruby -c' diff --git a/test/command_callback/test_erlang_syntaxerl_command_callback.vader b/test/command_callback/test_erlang_syntaxerl_command_callback.vader index a9a1a500..28cff9b9 100644 --- a/test/command_callback/test_erlang_syntaxerl_command_callback.vader +++ b/test/command_callback/test_erlang_syntaxerl_command_callback.vader @@ -1,66 +1,45 @@ Before: - Save g:ale_erlang_syntaxerl_executable - - unlet! g:ale_erlang_syntaxerl_executable - unlet! b:ale_erlang_syntaxerl_executable - - runtime ale_linters/erlang/syntaxerl.vim + call ale#assert#SetUpLinterTest('erlang', 'syntaxerl') After: - Restore - - call ale#linter#Reset() - -Execute (The executable should be correct): - AssertEqual 'syntaxerl', ale_linters#erlang#syntaxerl#GetExecutable(bufnr('')) - - let g:ale_erlang_syntaxerl_executable = '/some/other/syntaxerl' - AssertEqual '/some/other/syntaxerl', ale_linters#erlang#syntaxerl#GetExecutable(bufnr('')) - - let b:ale_erlang_syntaxerl_executable = '/yet/another/syntaxerl' - AssertEqual '/yet/another/syntaxerl', ale_linters#erlang#syntaxerl#GetExecutable(bufnr('')) - + call ale#assert#TearDownLinterTest() -Execute (The executable should be presented in the feature check command): - let g:ale_erlang_syntaxerl_executable = '/some/other/syntaxerl' +Execute (The default commands should be correct): + AssertLinter 'syntaxerl', [ + \ ale#Escape('syntaxerl') . ' -h', + \ ale#Escape('syntaxerl') . ' %t', + \] - AssertEqual - \ ale#Escape('/some/other/syntaxerl') . ' -h', - \ ale_linters#erlang#syntaxerl#FeatureCheck(bufnr('')) +Execute (The executable should be configurable): + let b:ale_erlang_syntaxerl_executable = 'foobar' - let b:ale_erlang_syntaxerl_executable = '/yet/another/syntaxerl' - - AssertEqual - \ ale#Escape('/yet/another/syntaxerl') . ' -h', - \ ale_linters#erlang#syntaxerl#FeatureCheck(bufnr('')) - -Execute (The executable should be presented in the command): - let g:ale_erlang_syntaxerl_executable = '/some/other/syntaxerl' - - AssertEqual - \ ale#Escape('/some/other/syntaxerl') . ' %t', - \ ale_linters#erlang#syntaxerl#GetCommand(bufnr(''), []) - - let b:ale_erlang_syntaxerl_executable = '/yet/another/syntaxerl' - - AssertEqual - \ ale#Escape('/yet/another/syntaxerl') . ' %t', - \ ale_linters#erlang#syntaxerl#GetCommand(bufnr(''), []) + AssertLinter 'foobar', [ + \ ale#Escape('foobar') . ' -h', + \ ale#Escape('foobar') . ' %t', + \] Execute (The -b option should be used when available): - AssertEqual ale#Escape('syntaxerl') . ' %t', ale_linters#erlang#syntaxerl#GetCommand(bufnr(''), [ - \ 'Syntax checker for Erlang (0.14.0)', - \ 'Usage: syntaxerl [-d | --debug] <FILENAME>', - \ ' syntaxerl <-h | --help>', - \ ' -d, --debug Enable debug output', - \ ' -h, --help Show this message', - \ ]) - - AssertEqual ale#Escape('syntaxerl') . ' -b %s %t', ale_linters#erlang#syntaxerl#GetCommand(bufnr(''), [ - \ 'Syntax checker for Erlang (0.14.0)', - \ 'Usage: syntaxerl [-b | --base <FILENAME>] [-d | --debug] <FILENAME>', - \ ' syntaxerl <-h | --help>', - \ ' -b, --base Set original filename', - \ ' -d, --debug Enable debug output', - \ ' -h, --help Show this message', - \ ]) + WithChainResults [ + \ 'Syntax checker for Erlang (0.14.0)', + \ 'Usage: syntaxerl [-d | --debug] <FILENAME>', + \ ' syntaxerl <-h | --help>', + \ ' -d, --debug Enable debug output', + \ ' -h, --help Show this message', + \] + AssertLinter 'syntaxerl', [ + \ ale#Escape('syntaxerl') . ' -h', + \ ale#Escape('syntaxerl') . ' %t', + \] + + WithChainResults [ + \ 'Syntax checker for Erlang (0.14.0)', + \ 'Usage: syntaxerl [-b | --base <FILENAME>] [-d | --debug] <FILENAME>', + \ ' syntaxerl <-h | --help>', + \ ' -b, --base Set original filename', + \ ' -d, --debug Enable debug output', + \ ' -h, --help Show this message', + \] + AssertLinter 'syntaxerl', [ + \ ale#Escape('syntaxerl') . ' -h', + \ ale#Escape('syntaxerl') . ' -b %s %t', + \] diff --git a/test/command_callback/test_erubi_command_callback.vader b/test/command_callback/test_erubi_command_callback.vader index 1953d763..0643efc2 100644 --- a/test/command_callback/test_erubi_command_callback.vader +++ b/test/command_callback/test_erubi_command_callback.vader @@ -1,31 +1,32 @@ Before: - runtime ale_linters/eruby/erubi.vim - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('eruby', 'erubi') After: - call ale#linter#Reset() - call ale#test#RestoreDirectory() + call ale#assert#TearDownLinterTest() Execute(Executable should not contain any filter code by default): call ale#test#SetFilename('../ruby_fixtures/not_a_rails_app/file.rb') - AssertEqual + AssertLinter 'ruby', [ + \ 'ruby -r erubi/capture_end -e ' . ale#Escape('""'), \ 'ruby -r erubi/capture_end -e ' . ale#Escape('puts Erubi::CaptureEndEngine.new($stdin.read).src') . '< %t | ruby -c', - \ ale_linters#eruby#erubi#GetCommand(bufnr(''), []) + \] Execute(Executable should filter invalid eRuby when inside a Rails project): call ale#test#SetFilename('../ruby_fixtures/valid_rails_app/app/views/my_great_view.html.erb') - AssertEqual + AssertLinter 'ruby', [ + \ 'ruby -r erubi/capture_end -e ' . ale#Escape('""'), \ 'ruby -r erubi/capture_end -e ' . ale#Escape('puts Erubi::CaptureEndEngine.new($stdin.read.gsub(%{<%=},%{<%}), nil, %{-}).src') . '< %t | ruby -c', - \ ale_linters#eruby#erubi#GetCommand(bufnr(''), []) + \] -Execute(Command should be blank if the first command in the chain return output): - let output_lines = [ - \ "/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- erubi/capture_end (LoadError)", - \ " from /usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'", +Execute(Command should be blank if the first command in the chain returns output): + WithChainResults [ + \ "/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- erubi/capture_end (LoadError)", + \ " from /usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'", \] - AssertEqual + AssertLinter 'ruby', [ + \ 'ruby -r erubi/capture_end -e ' . ale#Escape('""'), \ '', - \ ale_linters#eruby#erubi#GetCommand(bufnr(''), output_lines) + \] diff --git a/test/command_callback/test_erubis_command_callback.vader b/test/command_callback/test_erubis_command_callback.vader index 574dd684..c9cdb80f 100644 --- a/test/command_callback/test_erubis_command_callback.vader +++ b/test/command_callback/test_erubis_command_callback.vader @@ -1,21 +1,16 @@ Before: - runtime ale_linters/eruby/erubis.vim - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('eruby', 'erubis') After: - call ale#linter#Reset() - call ale#test#RestoreDirectory() + call ale#assert#TearDownLinterTest() Execute(Executable should not contain any filter code by default): call ale#test#SetFilename('../ruby_fixtures/not_a_rails_app/file.rb') - AssertEqual - \ 'erubis -x %t | ruby -c', - \ ale_linters#eruby#erubis#GetCommand(bufnr('')) + AssertLinter 'erubis', 'erubis -x %t | ruby -c' Execute(Executable should filter invalid eRuby when inside a Rails project): call ale#test#SetFilename('../ruby_fixtures/valid_rails_app/app/views/my_great_view.html.erb') - AssertEqual - \ 'ruby -r erubis -e ' . ale#Escape('puts Erubis::Eruby.new($stdin.read.gsub(%{<%=},%{<%})).src') . '< %t | ruby -c', - \ ale_linters#eruby#erubis#GetCommand(bufnr('')) + AssertLinter 'erubis', + \ 'ruby -r erubis -e ' . ale#Escape('puts Erubis::Eruby.new($stdin.read.gsub(%{<%=},%{<%})).src') . '< %t | ruby -c' diff --git a/test/command_callback/test_flake8_command_callback.vader b/test/command_callback/test_flake8_command_callback.vader index 1784b81f..f12b6747 100644 --- a/test/command_callback/test_flake8_command_callback.vader +++ b/test/command_callback/test_flake8_command_callback.vader @@ -1,77 +1,75 @@ Before: - Save g:ale_python_flake8_executable - Save g:ale_python_flake8_options - Save g:ale_python_flake8_use_global - - unlet! g:ale_python_flake8_executable - unlet! g:ale_python_flake8_args - unlet! g:ale_python_flake8_options - unlet! g:ale_python_flake8_use_global - + call ale#assert#SetUpLinterTest('python', 'flake8') let b:bin_dir = has('win32') ? 'Scripts' : 'bin' - runtime ale_linters/python/flake8.vim - call ale#test#SetDirectory('/testplugin/test/command_callback') + WithChainResults ['3.0.0'] After: - Restore - - unlet! g:ale_python_flake8_args - - unlet! b:bin_dir unlet! b:executable - - call ale#test#RestoreDirectory() - call ale#linter#Reset() - call ale#semver#ResetVersionCache() + unlet! b:bin_dir + call ale#assert#TearDownLinterTest() Execute(The flake8 callbacks should return the correct default values): - AssertEqual - \ 'flake8', - \ ale_linters#python#flake8#GetExecutable(bufnr('')) - AssertEqual + AssertLinter 'flake8', [ \ ale#Escape('flake8') . ' --version', - \ ale_linters#python#flake8#VersionCheck(bufnr('')) - AssertEqual - \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -', - \ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.0']) + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('flake8') . ' --format=default --stdin-display-name %s -', + \] + + " The version check should be cached. + WithChainResults [] + AssertLinter 'flake8', [ + \ '', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('flake8') . ' --format=default --stdin-display-name %s -', + \] " Try with older versions. call ale#semver#ResetVersionCache() - AssertEqual - \ ale#Escape('flake8') . ' --format=default -', - \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9']) + WithChainResults ['2.9.9'] + AssertLinter 'flake8', [ + \ ale#Escape('flake8') . ' --version', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('flake8') . ' --format=default -', + \] + +Execute(The option for disabling changing directories should work): + let g:ale_python_flake8_change_directory = 0 + + AssertLinter 'flake8', [ + \ ale#Escape('flake8') . ' --version', + \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -', + \] Execute(The flake8 command callback should let you set options): let g:ale_python_flake8_options = '--some-option' - AssertEqual - \ ale#Escape('flake8') - \ . ' --some-option --format=default' - \ . ' --stdin-display-name %s -', - \ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.4']) + WithChainResults ['3.0.4'] + AssertLinter 'flake8', [ + \ ale#Escape('flake8') . ' --version', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('flake8') . ' --some-option' + \ . ' --format=default --stdin-display-name %s -', + \] call ale#semver#ResetVersionCache() - - AssertEqual - \ ale#Escape('flake8') - \ . ' --some-option --format=default -', - \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9']) + WithChainResults ['2.9.9'] + AssertLinter 'flake8', [ + \ ale#Escape('flake8') . ' --version', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('flake8') . ' --some-option --format=default -', + \] Execute(You should be able to set a custom executable and it should be escaped): let g:ale_python_flake8_executable = 'executable with spaces' - AssertEqual - \ 'executable with spaces', - \ ale_linters#python#flake8#GetExecutable(bufnr('')) - AssertEqual + AssertLinter 'executable with spaces', [ \ ale#Escape('executable with spaces') . ' --version', - \ ale_linters#python#flake8#VersionCheck(bufnr('')) - AssertEqual - \ ale#Escape('executable with spaces') + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('executable with spaces') \ . ' --format=default' \ . ' --stdin-display-name %s -', - \ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.0']) + \] Execute(The flake8 callbacks should detect virtualenv directories): silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') @@ -80,16 +78,13 @@ Execute(The flake8 callbacks should detect virtualenv directories): \ g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/flake8' \) - AssertEqual - \ b:executable, - \ ale_linters#python#flake8#GetExecutable(bufnr('')) - AssertEqual + AssertLinter b:executable, [ \ ale#Escape(b:executable) . ' --version', - \ ale_linters#python#flake8#VersionCheck(bufnr('')) - AssertEqual - \ ale#Escape(b:executable) - \ . ' --format=default --stdin-display-name %s -', - \ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.0']) + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape(b:executable) + \ . ' --format=default' + \ . ' --stdin-display-name %s -', + \] Execute(The FindProjectRoot should detect the project root directory for namespace package via Manifest.in): silent execute 'file ' . fnameescape(g:dir . '/python_paths/namespace_package_manifest/namespace/foo/bar.py') @@ -133,49 +128,32 @@ Execute(Using `python -m flake8` should be supported for running flake8): let g:ale_python_flake8_executable = 'python' let g:ale_python_flake8_options = '-m flake8 --some-option' - AssertEqual - \ 'python', - \ ale_linters#python#flake8#GetExecutable(bufnr('')) - AssertEqual + WithChainResults ['2.9.9'] + AssertLinter 'python', [ \ ale#Escape('python') . ' -m flake8 --version', - \ ale_linters#python#flake8#VersionCheck(bufnr('')) - AssertEqual - \ ale#Escape('python') . ' -m flake8 --some-option --format=default -', - \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9']) + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('python') + \ . ' -m flake8 --some-option --format=default -' + \] call ale#semver#ResetVersionCache() " Leading spaces shouldn't matter let g:ale_python_flake8_options = ' -m flake8 --some-option' - AssertEqual - \ 'python', - \ ale_linters#python#flake8#GetExecutable(bufnr('')) - AssertEqual + WithChainResults ['2.9.9'] + AssertLinter 'python', [ \ ale#Escape('python') . ' -m flake8 --version', - \ ale_linters#python#flake8#VersionCheck(bufnr('')) - AssertEqual - \ ale#Escape('python') . ' -m flake8 --some-option --format=default -', - \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9']) - -Execute(Using `python2 -m flake8` should be supported with the old args option): - let g:ale_python_flake8_executable = 'python2' - let g:ale_python_flake8_args = '-m flake8' - let g:ale_python_flake8_use_global = 0 - - unlet! g:ale_python_flake8_options - - call ale#linter#Reset() - runtime ale_linters/python/flake8.vim - - silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') - - AssertEqual - \ 'python2', - \ ale_linters#python#flake8#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('python2') . ' -m flake8 --version', - \ ale_linters#python#flake8#VersionCheck(bufnr('')) - AssertEqual - \ ale#Escape('python2') . ' -m flake8 --format=default -', - \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9']) + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('python') + \ . ' -m flake8 --some-option --format=default -' + \] + +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. + WithChainResults [] + AssertLinter 'path/to/pipenv', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('path/to/pipenv') . ' run flake8 --format=default -' diff --git a/test/command_callback/test_foodcritic_command_callback.vader b/test/command_callback/test_foodcritic_command_callback.vader index e3ad8a70..c5564cb1 100644 --- a/test/command_callback/test_foodcritic_command_callback.vader +++ b/test/command_callback/test_foodcritic_command_callback.vader @@ -1,44 +1,18 @@ Before: - Save g:ale_chef_foodcritic_executable - Save g:ale_chef_foodcritic_options - - unlet! g:ale_chef_foodcritic_executable - unlet! g:ale_chef_foodcritic_options - - call ale#test#SetDirectory('/testplugin/test') - - runtime ale_linters/chef/foodcritic.vim + call ale#assert#SetUpLinterTest('chef', 'foodcritic') After: - Restore - - unlet! b:ale_chef_foodcritic_executable - unlet! b:ale_chef_foodcritic_options - - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The default command should be correct): - AssertEqual - \ 'foodcritic', - \ ale_linters#chef#foodcritic#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('foodcritic') . ' %s', - \ ale_linters#chef#foodcritic#GetCommand(bufnr('')) + AssertLinter 'foodcritic', ale#Escape('foodcritic') . ' %s' Execute(Extra options should be included with escapeed tildes (~)): let b:ale_chef_foodcritic_options = '-t ~F011' - AssertEqual - \ ale#Escape('foodcritic') . ' -t \~F011 %s', - \ ale_linters#chef#foodcritic#GetCommand(bufnr('')) + AssertLinter 'foodcritic', ale#Escape('foodcritic') . ' -t \~F011 %s' Execute(The executable should be configurable): let b:ale_chef_foodcritic_executable = 'foobar' - AssertEqual - \ 'foobar', - \ ale_linters#chef#foodcritic#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('foobar') . ' %s', - \ ale_linters#chef#foodcritic#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . ' %s' diff --git a/test/command_callback/test_fortran_fortls_callback.vader b/test/command_callback/test_fortran_fortls_callback.vader new file mode 100644 index 00000000..3be7ff4f --- /dev/null +++ b/test/command_callback/test_fortran_fortls_callback.vader @@ -0,0 +1,18 @@ +Before: + call ale#assert#SetUpLinterTest('fortran', 'language_server') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default executable path should be correct): + AssertLinter 'fortls', ale#Escape('fortls') + +Execute(The project root should be detected correctly): + AssertLSPProject '' + + call ale#test#SetFilename('fortran-fortls-project/test.F90') + + AssertLSPProject ale#path#Simplify(g:dir . '/fortran-fortls-project') + +Execute(The language should be correct): + AssertLSPLanguage 'fortran' diff --git a/test/command_callback/test_fsc_command_callback.vader b/test/command_callback/test_fsc_command_callback.vader new file mode 100644 index 00000000..278e7c16 --- /dev/null +++ b/test/command_callback/test_fsc_command_callback.vader @@ -0,0 +1,13 @@ +Before: + call ale#assert#SetUpLinterTest('scala', 'fsc') + +After: + call ale#assert#TearDownLinterTest() + +Given scala(An empty Scala file): +Execute(The default executable and command should be correct): + AssertLinter 'fsc', ale#Escape('fsc') . ' -Ystop-after:parser %t' + +Given scala.sbt(An empty SBT file): +Execute(fsc should not be run for sbt files): + AssertLinterNotExecuted diff --git a/test/command_callback/test_fusionlint_command_callback.vader b/test/command_callback/test_fusionlint_command_callback.vader index 34a44133..1c63b811 100644 --- a/test/command_callback/test_fusionlint_command_callback.vader +++ b/test/command_callback/test_fusionlint_command_callback.vader @@ -1,34 +1,19 @@ Before: - Save g:ale_fuse_fusionlint_options - Save g:ale_fuse_fusionlint_executable - - unlet! g:ale_fuse_fusionlint_options - unlet! g:ale_fuse_fusionlint_executable - - runtime ale_linters/fuse/fusionlint.vim + call ale#assert#SetUpLinterTest('fuse', 'fusionlint') After: - Restore - - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The fuse fusionlint command callback should return the correct default string): - AssertEqual ale#Escape('fusion-lint') . ' --filename %s -i', - \ join(split(ale_linters#fuse#fusionlint#GetCommand(1))) + AssertLinter 'fusion-lint', ale#Escape('fusion-lint') . ' --filename %s -i' Execute(The fuse fusionlint command callback should let you set options): let g:ale_fuse_fusionlint_options = '--example-option argument' - AssertEqual - \ ale#Escape('fusion-lint') - \ . ' --example-option argument --filename %s -i', - \ join(split(ale_linters#fuse#fusionlint#GetCommand(1))) + AssertLinter 'fusion-lint', + \ ale#Escape('fusion-lint') . ' --example-option argument --filename %s -i' Execute(The fusionlint executable should be configurable): - let g:ale_fuse_fusionlint_executable = 'util/linter.fuse' + let g:ale_fuse_fusionlint_executable = 'foobar' - AssertEqual 'util/linter.fuse', ale_linters#fuse#fusionlint#GetExecutable(1) - AssertEqual - \ ale#Escape('util/linter.fuse') - \ . ' --filename %s -i', - \ join(split(ale_linters#fuse#fusionlint#GetCommand(1))) + AssertLinter 'foobar', ale#Escape('foobar') . ' --filename %s -i' diff --git a/test/command_callback/test_gawk_command_callback.vader b/test/command_callback/test_gawk_command_callback.vader new file mode 100644 index 00000000..ba9f59ab --- /dev/null +++ b/test/command_callback/test_gawk_command_callback.vader @@ -0,0 +1,25 @@ +Before: + call ale#assert#SetUpLinterTest('awk', 'gawk') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'gawk', + \ 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 ' . ale#Escape('BEGIN { exit } END { exit 1 }') + \ . ' -f %t --lint /dev/null' + +Execute(The options should be configurable): + let b:ale_awk_gawk_executable = 'gawk' + let b:ale_awk_gawk_options = '--something' + + AssertLinter 'gawk', + \ 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 501e92fd..3e6ef951 100644 --- a/test/command_callback/test_gfortran_command_callback.vader +++ b/test/command_callback/test_gfortran_command_callback.vader @@ -1,31 +1,24 @@ Before: - runtime ale_linters/fortran/gcc.vim + call ale#assert#SetUpLinterTest('fortran', 'gcc') After: - call ale#linter#Reset() - let g:ale_fortran_gcc_options = '-Wall' - let g:ale_fortran_gcc_use_free_form = 1 - let g:ale_fortran_gcc_executable = 'gcc' + call ale#assert#TearDownLinterTest() Execute(The fortran gcc command callback should return the correct default string): - AssertEqual 'gcc -S -x f95 -fsyntax-only -ffree-form -Wall -', - \ join(split(ale_linters#fortran#gcc#GetCommand(1))) + 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' - AssertEqual 'gcc -S -x f95 -fsyntax-only -ffree-form -Wotherthings -', - \ join(split(ale_linters#fortran#gcc#GetCommand(1))) + 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 - AssertEqual 'gcc -S -x f95 -fsyntax-only -ffixed-form -Wall -', - \ join(split(ale_linters#fortran#gcc#GetCommand(1))) + 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' - AssertEqual 'gfortran', ale_linters#fortran#gcc#GetExecutable(1) - AssertEqual 'gfortran -S -x f95 -fsyntax-only -ffree-form -Wall -', - \ join(split(ale_linters#fortran#gcc#GetCommand(1))) + AssertLinter 'gfortran', + \ ale#Escape('gfortran') . ' -S -x f95 -fsyntax-only -ffree-form -Wall -' diff --git a/test/command_callback/test_gitlint_command_callback.vader b/test/command_callback/test_gitlint_command_callback.vader index 6ff95ea9..7927b064 100644 --- a/test/command_callback/test_gitlint_command_callback.vader +++ b/test/command_callback/test_gitlint_command_callback.vader @@ -1,84 +1,43 @@ Before: - Save g:ale_gitcommit_gitlint_executable - Save g:ale_gitcommit_gitlint_options - Save g:ale_gitcommit_gitlint_use_global - - unlet! g:ale_gitcommit_gitlint_executable - unlet! g:ale_gitcommit_gitlint_options - unlet! g:ale_gitcommit_gitlint_use_global - - runtime ale_linters/gitcommit/gitlint.vim - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('gitcommit', 'gitlint') let b:bin_dir = has('win32') ? 'Scripts' : 'bin' - let b:command_tail = ' lint' After: - Restore - - call ale#test#RestoreDirectory() - call ale#linter#Reset() - unlet! b:bin_dir unlet! b:executable + call ale#assert#TearDownLinterTest() + Execute(The gitlint callbacks should return the correct default values): - AssertEqual - \ 'gitlint', - \ ale_linters#gitcommit#gitlint#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('gitlint') . b:command_tail, - \ ale_linters#gitcommit#gitlint#GetCommand(bufnr('')) + AssertLinter 'gitlint', ale#Escape('gitlint') . ' lint' Execute(The gitlint executable should be configurable, and escaped properly): let g:ale_gitcommit_gitlint_executable = 'executable with spaces' - AssertEqual - \ 'executable with spaces', - \ ale_linters#gitcommit#gitlint#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('executable with spaces') . b:command_tail, - \ ale_linters#gitcommit#gitlint#GetCommand(bufnr('')) + AssertLinter 'executable with spaces', + \ ale#Escape('executable with spaces') . ' lint' Execute(The gitlint command callback should let you set options): let g:ale_gitcommit_gitlint_options = '--some-option' - AssertEqual - \ ale#Escape('gitlint') . ' --some-option' . b:command_tail, - \ ale_linters#gitcommit#gitlint#GetCommand(bufnr('')) + AssertLinter 'gitlint', ale#Escape('gitlint') . ' --some-option lint' Execute(The gitlint callbacks shouldn't detect virtualenv directories where they don't exist): - silent execute 'file ' . fnameescape(g:dir . '/python_paths/no_virtualenv/subdir/foo/COMMIT_EDITMSG') + call ale#test#SetFilename('python_paths/no_virtualenv/subdir/foo/COMMIT_EDITMSG') - AssertEqual - \ 'gitlint', - \ ale_linters#gitcommit#gitlint#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('gitlint') . b:command_tail, - \ ale_linters#gitcommit#gitlint#GetCommand(bufnr('')) + AssertLinter 'gitlint', ale#Escape('gitlint') . ' lint' Execute(The gitlint callbacks should detect virtualenv directories): - silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/COMMIT_EDITMSG') - + call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/COMMIT_EDITMSG') let b:executable = ale#path#Simplify( \ g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/gitlint' \) - AssertEqual - \ b:executable, - \ ale_linters#gitcommit#gitlint#GetExecutable(bufnr('')) - - AssertEqual - \ ale#Escape(b:executable) . b:command_tail, - \ ale_linters#gitcommit#gitlint#GetCommand(bufnr('')) + AssertLinter b:executable, ale#Escape(b:executable) . ' lint' Execute(You should able able to use the global gitlint instead): - silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/COMMIT_EDITMSG') + call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/COMMIT_EDITMSG') let g:ale_gitcommit_gitlint_use_global = 1 - AssertEqual - \ 'gitlint', - \ ale_linters#gitcommit#gitlint#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('gitlint') . b:command_tail, - \ ale_linters#gitcommit#gitlint#GetCommand(bufnr('')) + AssertLinter 'gitlint', ale#Escape('gitlint') . ' lint' diff --git a/test/command_callback/test_glslang_command_callback.vader b/test/command_callback/test_glslang_command_callback.vader index 1b1722a4..980406af 100644 --- a/test/command_callback/test_glslang_command_callback.vader +++ b/test/command_callback/test_glslang_command_callback.vader @@ -1,40 +1,19 @@ Before: - Save g:ale_glsl_glslang_executable - Save g:ale_glsl_glslang_options - - unlet! g:ale_glsl_glslang_executable - unlet! g:ale_glsl_glslang_options - - runtime ale_linters/glsl/glslang.vim - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('glsl', 'glslang') After: - Restore - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() -Execute(Executable should default to glslangValidator): - AssertEqual - \ 'glslangValidator', - \ ale_linters#glsl#glslang#GetExecutable(bufnr('')) +Execute(The default command should be correct): + AssertLinter 'glslangValidator', ale#Escape('glslangValidator') . ' -C %t' -Execute(Executable should be configurable): - let g:ale_glsl_glslang_executable = 'foobar' - AssertEqual - \ 'foobar', - \ ale_linters#glsl#glslang#GetExecutable(bufnr('')) +Execute(The executable should be configurable): + let b:ale_glsl_glslang_executable = 'foobar' -Execute(Command should use executable): - AssertEqual - \ 'glslangValidator -C %t', - \ ale_linters#glsl#glslang#GetCommand(bufnr('')) - - let g:ale_glsl_glslang_executable = 'foobar' - AssertEqual - \ 'foobar -C %t', - \ ale_linters#glsl#glslang#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . ' -C %t' Execute(Options should work): let g:ale_glsl_glslang_options = '--test' - AssertEqual - \ 'glslangValidator --test -C %t', - \ ale_linters#glsl#glslang#GetCommand(bufnr('')) + + AssertLinter 'glslangValidator', + \ ale#Escape('glslangValidator') . ' --test -C %t' diff --git a/test/command_callback/test_glslls_command_callback.vader b/test/command_callback/test_glslls_command_callback.vader index e64c2352..133c2a2f 100644 --- a/test/command_callback/test_glslls_command_callback.vader +++ b/test/command_callback/test_glslls_command_callback.vader @@ -1,37 +1,19 @@ Before: - Save g:ale_glsl_glslls_executable - Save g:ale_glsl_glslls_logfile - - unlet! g:ale_glsl_glslls_executable - unlet! g:ale_glsl_glslls_logfile - - runtime ale_linters/glsl/glslls.vim - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('glsl', 'glslls') After: - Restore - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() -Execute(Executable should default to 'glslls'): - AssertEqual - \ 'glslls', - \ ale_linters#glsl#glslls#GetExecutable(bufnr('')) +Execute(The default command should be correct): + AssertLinter 'glslls', ale#Escape('glslls') . ' --stdin' Execute(Executable should be configurable): - let g:ale_glsl_glslls_executable = 'foobar' - AssertEqual - \ 'foobar', - \ ale_linters#glsl#glslls#GetExecutable(bufnr('')) + let b:ale_glsl_glslls_executable = 'foobar' -Execute(Command should use executable): - let command1 = ale_linters#glsl#glslls#GetCommand(bufnr('')) - AssertEqual command1, ale#Escape('glslls') . ' --stdin' - - let g:ale_glsl_glslls_executable = 'foobar' - let command2 = ale_linters#glsl#glslls#GetCommand(bufnr('')) - AssertEqual command2, ale#Escape('foobar') . ' --stdin' + AssertLinter 'foobar', ale#Escape('foobar') . ' --stdin' Execute(Setting logfile should work): - let g:ale_glsl_glslls_logfile = '/tmp/test.log' - let command = ale_linters#glsl#glslls#GetCommand(bufnr('')) - AssertEqual command, ale#Escape('glslls') . ' --verbose -l /tmp/test.log --stdin' + let b:ale_glsl_glslls_logfile = '/tmp/test.log' + + AssertLinter 'glslls', + \ ale#Escape('glslls') . ' --verbose -l /tmp/test.log --stdin' diff --git a/test/command_callback/test_gobuild_command_callback.vader b/test/command_callback/test_gobuild_command_callback.vader new file mode 100644 index 00000000..f9673213 --- /dev/null +++ b/test/command_callback/test_gobuild_command_callback.vader @@ -0,0 +1,19 @@ +Before: + call ale#assert#SetUpLinterTest('go', 'gobuild') + + WithChainResults ['/foo/bar', '/foo/baz'] + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default commands should be correct): + AssertLinter 'go', + \ 'cd ' . ale#Escape(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', + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . 'go test --foo-bar -c -o /dev/null ./' diff --git a/test/command_callback/test_gometalinter_command_callback.vader b/test/command_callback/test_gometalinter_command_callback.vader index 93a541c8..d788c5bd 100644 --- a/test/command_callback/test_gometalinter_command_callback.vader +++ b/test/command_callback/test_gometalinter_command_callback.vader @@ -1,61 +1,38 @@ Before: - Save b:ale_go_gometalinter_executable - Save b:ale_go_gometalinter_options - Save b:ale_go_gometalinter_lint_package - - let b:ale_go_gometalinter_executable = 'gometalinter' - let b:ale_go_gometalinter_options = '' - let b:ale_go_gometalinter_lint_package = 0 - - runtime ale_linters/go/gometalinter.vim - - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('go', 'gometalinter') call ale#test#SetFilename('test.go') After: - Restore - - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() -Execute(The gometalinter callback should return the right defaults): - AssertEqual - \ 'gometalinter', - \ ale_linters#go#gometalinter#GetExecutable(bufnr('')) - AssertEqual +Execute(The gometalinter defaults should be correct): + AssertLinter 'gometalinter', \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' \ . ale#Escape('gometalinter') \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t'))) - \ . ' .', - \ ale_linters#go#gometalinter#GetCommand(bufnr('')) + \ . ' .' Execute(The gometalinter callback should use a configured executable): let b:ale_go_gometalinter_executable = 'something else' - AssertEqual - \ 'something else', - \ ale_linters#go#gometalinter#GetExecutable(bufnr('')) - AssertEqual + AssertLinter 'something else', \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' \ . ale#Escape('something else') \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t'))) - \ . ' .', - \ ale_linters#go#gometalinter#GetCommand(bufnr('')) + \ . ' .' Execute(The gometalinter callback should use configured options): let b:ale_go_gometalinter_options = '--foobar' - AssertEqual + AssertLinter 'gometalinter', \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' \ . ale#Escape('gometalinter') \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t'))) - \ . ' --foobar' . ' .', - \ ale_linters#go#gometalinter#GetCommand(bufnr('')) + \ . ' --foobar' . ' .' Execute(The gometalinter `lint_package` option should use the correct command): let b:ale_go_gometalinter_lint_package = 1 - AssertEqual + AssertLinter 'gometalinter', \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' - \ . ale#Escape('gometalinter') . ' .', - \ ale_linters#go#gometalinter#GetCommand(bufnr('')) + \ . ale#Escape('gometalinter') . ' .' diff --git a/test/command_callback/test_gosimple_command_callback.vader b/test/command_callback/test_gosimple_command_callback.vader new file mode 100644 index 00000000..7b8c66ae --- /dev/null +++ b/test/command_callback/test_gosimple_command_callback.vader @@ -0,0 +1,10 @@ +Before: + call ale#assert#SetUpLinterTest('go', 'gosimple') + call ale#test#SetFilename('../go_files/testfile2.go') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default gosimple command should be correct): + AssertLinter 'gosimple', + \ 'cd ' . ale#Escape(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 f95e8423..da9ceaf3 100644 --- a/test/command_callback/test_gotype_command_callback.vader +++ b/test/command_callback/test_gotype_command_callback.vader @@ -1,19 +1,15 @@ Before: - runtime ale_linters/go/gotype.vim + call ale#assert#SetUpLinterTest('go', 'gotype') call ale#test#SetFilename('../go_files/testfile2.go') After: - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() - -Execute(The gotype callback should include other files from the directory but exclude the file itself): - let dir = expand('#' . bufnr('') . ':p:h') - AssertEqual - \ "gotype %t ". ale#Escape(ale#path#Simplify(dir . "/testfile.go")), - \ ale_linters#go#gotype#GetCommand(bufnr('')) +Execute(The default gotype command should be correct): + AssertLinter 'gotype', + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && gotype .' Execute(The gotype callback should ignore test files): call ale#test#SetFilename('bla_test.go') - AssertEqual - \ 0, - \ ale_linters#go#gotype#GetCommand(bufnr('')) + + AssertLinter 'gotype', '' diff --git a/test/command_callback/test_govet_command_callback.vader b/test/command_callback/test_govet_command_callback.vader new file mode 100644 index 00000000..3718e0a7 --- /dev/null +++ b/test/command_callback/test_govet_command_callback.vader @@ -0,0 +1,12 @@ +Before: + call ale#assert#SetUpLinterTest('go', 'govet') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'go', 'cd ' . ale#Escape(expand('%:p:h')) . ' && go vet .' + +Execute(Extra options should be supported): + let g:ale_go_govet_options = '--foo-bar' + AssertLinter 'go', 'cd ' . ale#Escape(expand('%:p:h')) . ' && go vet . --foo-bar' diff --git a/test/command_callback/test_haml_hamllint_command_callback.vader b/test/command_callback/test_haml_hamllint_command_callback.vader index 0d9b1e06..a59446ca 100644 --- a/test/command_callback/test_haml_hamllint_command_callback.vader +++ b/test/command_callback/test_haml_hamllint_command_callback.vader @@ -1,72 +1,37 @@ Before: - runtime ale_linters/haml/hamllint.vim + call ale#assert#SetUpLinterTest('haml', 'hamllint') let g:default_command = 'haml-lint %t' - call ale#test#SetDirectory('/testplugin/test/command_callback') After: - Restore - - unlet! g:default_command unlet! b:conf + unlet! b:conf_hamllint + unlet! b:conf_rubocop - call ale#linter#Reset() - call ale#test#RestoreDirectory() + call ale#assert#TearDownLinterTest() Execute(The default command should be correct): - AssertEqual g:default_command, ale_linters#haml#hamllint#GetCommand(bufnr('')) + AssertLinter 'haml-lint', 'haml-lint %t' Execute(The command should have the .rubocop.yml prepended as an env var if one exists): call ale#test#SetFilename('../hamllint-test-files/rubocop-yml/subdir/file.haml') let b:conf = ale#path#Simplify(g:dir . '/../hamllint-test-files/rubocop-yml/.rubocop.yml') - if has('win32') - " Windows uses 'set var=... && command' - AssertEqual - \ 'set HAML_LINT_RUBOCOP_CONF=' - \ . ale#Escape(b:conf) - \ . ' && ' . g:default_command, - \ ale_linters#haml#hamllint#GetCommand(bufnr('')) - else - " Unix uses 'var=... command' - AssertEqual - \ 'HAML_LINT_RUBOCOP_CONF=' - \ . ale#Escape(b:conf) - \ . ' ' . g:default_command, - \ ale_linters#haml#hamllint#GetCommand(bufnr('')) - endif + AssertLinter 'haml-lint', + \ ale#Env('HAML_LINT_RUBOCOP_CONF', b:conf) . 'haml-lint %t' Execute(The command should have the nearest .haml-lint.yml set as --config if it exists): call ale#test#SetFilename('../hamllint-test-files/haml-lint-yml/subdir/file.haml') let b:conf = ale#path#Simplify(g:dir . '/../hamllint-test-files/haml-lint-yml/.haml-lint.yml') - AssertEqual - \ 'haml-lint --config ' - \ . ale#Escape(b:conf) - \ . ' %t', - \ ale_linters#haml#hamllint#GetCommand(bufnr('')) + AssertLinter 'haml-lint', + \ 'haml-lint --config ' . ale#Escape(b:conf) . ' %t', Execute(The command should include a .rubocop.yml and a .haml-lint if both are found): call ale#test#SetFilename('../hamllint-test-files/haml-lint-and-rubocop/subdir/file.haml') let b:conf_hamllint = ale#path#Simplify(g:dir . '/../hamllint-test-files/haml-lint-and-rubocop/.haml-lint.yml') let b:conf_rubocop = ale#path#Simplify(g:dir . '/../hamllint-test-files/haml-lint-and-rubocop/.rubocop.yml') - if has('win32') - " Windows uses 'set var=... && command' - AssertEqual - \ 'set HAML_LINT_RUBOCOP_CONF=' - \ . ale#Escape(b:conf_rubocop) - \ . ' && haml-lint --config ' - \ . ale#Escape(b:conf_hamllint) - \ . ' %t', - \ ale_linters#haml#hamllint#GetCommand(bufnr('')) - else - " Unix uses 'var=... command' - AssertEqual - \ 'HAML_LINT_RUBOCOP_CONF=' - \ . ale#Escape(b:conf_rubocop) - \ . ' haml-lint --config ' - \ . ale#Escape(b:conf_hamllint) - \ . ' %t', - \ ale_linters#haml#hamllint#GetCommand(bufnr('')) - endif + AssertLinter 'haml-lint', + \ ale#Env('HAML_LINT_RUBOCOP_CONF', b:conf_rubocop) + \ . 'haml-lint --config ' . ale#Escape(b:conf_hamllint) . ' %t' diff --git a/test/command_callback/test_haskell_cabal_ghc_command_callbacks.vader b/test/command_callback/test_haskell_cabal_ghc_command_callbacks.vader new file mode 100644 index 00000000..650aefa3 --- /dev/null +++ b/test/command_callback/test_haskell_cabal_ghc_command_callbacks.vader @@ -0,0 +1,23 @@ +Before: + Save g:ale_haskell_cabal_ghc_options + + unlet! g:ale_haskell_cabal_ghc_options + unlet! b:ale_haskell_cabal_ghc_options + + runtime ale_linters/haskell/cabal_ghc.vim + +After: + Restore + unlet! b:ale_haskell_cabal_ghc_options + call ale#linter#Reset() + +Execute(The options should be used in the command): + AssertEqual + \ 'cabal exec -- ghc -fno-code -v0 %t', + \ ale_linters#haskell#cabal_ghc#GetCommand(bufnr('')) + + let b:ale_haskell_cabal_ghc_options = 'foobar' + + AssertEqual + \ 'cabal exec -- ghc foobar %t', + \ ale_linters#haskell#cabal_ghc#GetCommand(bufnr('')) diff --git a/test/command_callback/test_haskell_ghc_command_callbacks.vader b/test/command_callback/test_haskell_ghc_command_callbacks.vader index edaf2b98..2f33477d 100644 --- a/test/command_callback/test_haskell_ghc_command_callbacks.vader +++ b/test/command_callback/test_haskell_ghc_command_callbacks.vader @@ -1,23 +1,12 @@ Before: - Save g:ale_haskell_ghc_options - - unlet! g:ale_haskell_ghc_options - unlet! b:ale_haskell_ghc_options - - runtime ale_linters/haskell/ghc.vim + call ale#assert#SetUpLinterTest('haskell', 'ghc') After: - Restore - unlet! b:ale_haskell_ghc_options - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The options should be used in the command): - AssertEqual - \ 'ghc -fno-code -v0 %t', - \ ale_linters#haskell#ghc#GetCommand(bufnr('')) + AssertLinter 'ghc', 'ghc -fno-code -v0 %t' let b:ale_haskell_ghc_options = 'foobar' - AssertEqual - \ 'ghc foobar %t', - \ ale_linters#haskell#ghc#GetCommand(bufnr('')) + AssertLinter 'ghc', 'ghc foobar %t' diff --git a/test/command_callback/test_haskell_hdevtools_command_callbacks.vader b/test/command_callback/test_haskell_hdevtools_command_callbacks.vader index c5320c5c..0ef2f0e3 100644 --- a/test/command_callback/test_haskell_hdevtools_command_callbacks.vader +++ b/test/command_callback/test_haskell_hdevtools_command_callbacks.vader @@ -1,37 +1,16 @@ Before: - Save g:ale_haskell_hdevtools_executable - Save g:ale_haskell_hdevtools_options - - unlet! g:ale_haskell_hdevtools_executable - unlet! b:ale_haskell_hdevtools_executable - unlet! g:ale_haskell_hdevtools_options - unlet! b:ale_haskell_hdevtools_options - - runtime ale_linters/haskell/hdevtools.vim + call ale#assert#SetUpLinterTest('haskell', 'hdevtools') let b:command_tail = ' check -g -Wall -p %s %t' After: - Restore unlet! b:command_tail - unlet! b:ale_haskell_hdevtools_executable - unlet! b:ale_haskell_hdevtools_options - call ale#linter#Reset() -Execute(The executable should be configurable): - AssertEqual 'hdevtools', ale_linters#haskell#hdevtools#GetExecutable(bufnr('')) + call ale#assert#TearDownLinterTest() - let b:ale_haskell_hdevtools_executable = 'foobar' - - AssertEqual 'foobar', ale_linters#haskell#hdevtools#GetExecutable(bufnr('')) - -Execute(The executable should be used in the command): - AssertEqual - \ ale#Escape('hdevtools') . b:command_tail, - \ ale_linters#haskell#hdevtools#GetCommand(bufnr('')) +Execute(The executable should be configurable): + AssertLinter 'hdevtools', ale#Escape('hdevtools') . b:command_tail let b:ale_haskell_hdevtools_executable = 'foobar' - AssertEqual - \ ale#Escape('foobar') . b:command_tail, - \ ale_linters#haskell#hdevtools#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . b:command_tail 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_htmlhint_command_callback.vader b/test/command_callback/test_htmlhint_command_callback.vader new file mode 100644 index 00000000..d3f209f8 --- /dev/null +++ b/test/command_callback/test_htmlhint_command_callback.vader @@ -0,0 +1,51 @@ +Before: + call ale#assert#SetUpLinterTest('html', 'htmlhint') + call ale#test#SetFilename('htmlhint_paths/test.html') + + let g:node_executable = ale#path#Simplify( + \ g:dir . '/htmlhint_paths/node_modules/.bin/htmlhint' + \) + let g:config_path = ale#path#Simplify( + \ g:dir . '/htmlhint_paths/with_config/.htmlhintrc' + \) + +After: + unlet! g:node_executable + unlet! g:config_path + + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter g:node_executable, + \ ale#Escape(g:node_executable) . ' --format=unix %t' + +Execute(The global executable should be uesd if the option is set): + let g:ale_html_htmlhint_executable = 'foo' + let g:ale_html_htmlhint_use_global = 1 + + AssertLinter 'foo', ale#Escape('foo') . ' --format=unix %t', + +" This is so old configurations which might include this still work. +Execute(--format=unix should be removed from the options if added): + let g:ale_html_htmlhint_options = '--format=unix' + + AssertLinter g:node_executable, + \ ale#Escape(g:node_executable) . ' --format=unix %t' + +Execute(The configuration file should be automatically detected): + call ale#test#SetFilename('htmlhint_paths/with_config/test.html') + + AssertLinter g:node_executable, + \ ale#Escape(g:node_executable) + \ . ' --config ' . ale#Escape(g:config_path) + \ . ' --format=unix %t' + +" This is so old configurations which might include the config will work. +Execute(The configuration file should be configurable through the options variable): + call ale#test#SetFilename('htmlhint_paths/with_config/test.html') + let g:ale_html_htmlhint_options = '--config=/foo/bar/.htmlhintrc' + + AssertLinter g:node_executable, + \ ale#Escape(g:node_executable) + \ . ' --config=/foo/bar/.htmlhintrc' + \ . ' --format=unix %t' diff --git a/test/command_callback/test_idris_command_callbacks.vader b/test/command_callback/test_idris_command_callbacks.vader index 03a69f39..ce7cd270 100644 --- a/test/command_callback/test_idris_command_callbacks.vader +++ b/test/command_callback/test_idris_command_callbacks.vader @@ -1,42 +1,21 @@ Before: - Save g:ale_idris_idris_executable - Save g:ale_idris_idris_options - - unlet! g:ale_idris_idris_executable - unlet! b:ale_idris_idris_executable - unlet! g:ale_idris_idris_options - unlet! b:ale_idris_idris_options - - runtime ale_linters/idris/idris.vim + call ale#assert#SetUpLinterTest('idris', 'idris') After: - Restore unlet! b:command_tail - unlet! b:ale_idris_idris_executable - unlet! b:ale_idris_idris_options - call ale#linter#Reset() - -Execute(The executable should be configurable): - AssertEqual 'idris', ale_linters#idris#idris#GetExecutable(bufnr('')) - - let b:ale_idris_idris_executable = 'foobar' - AssertEqual 'foobar', ale_linters#idris#idris#GetExecutable(bufnr('')) + call ale#assert#TearDownLinterTest() Execute(The executable should be used in the command): - AssertEqual - \ ale#Escape('idris') . ' --total --warnpartial --warnreach --warnipkg --check %s', - \ ale_linters#idris#idris#GetCommand(bufnr('')) + AssertLinter 'idris', + \ ale#Escape('idris') . ' --total --warnpartial --warnreach --warnipkg --check %s' let b:ale_idris_idris_executable = 'foobar' - AssertEqual - \ ale#Escape('foobar') . ' --total --warnpartial --warnreach --warnipkg --check %s', - \ ale_linters#idris#idris#GetCommand(bufnr('')) + AssertLinter 'foobar', + \ ale#Escape('foobar') . ' --total --warnpartial --warnreach --warnipkg --check %s' Execute(The options should be configurable): let b:ale_idris_idris_options = '--something' - AssertEqual - \ ale#Escape('idris') . ' --something --check %s', - \ ale_linters#idris#idris#GetCommand(bufnr('')) + AssertLinter 'idris', ale#Escape('idris') . ' --something --check %s' diff --git a/test/command_callback/test_iverilog_command_callback.vader b/test/command_callback/test_iverilog_command_callback.vader index 2c633178..d7a29f05 100644 --- a/test/command_callback/test_iverilog_command_callback.vader +++ b/test/command_callback/test_iverilog_command_callback.vader @@ -1,24 +1,14 @@ Before: - Save g:ale_verilog_iverilog_options - - unlet! g:ale_verilog_iverilog_options - - runtime ale_linters/verilog/iverilog.vim + call ale#assert#SetUpLinterTest('verilog', 'iverilog') After: - Restore - - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The default iverilog command should be correct): - AssertEqual - \ 'iverilog -t null -Wall %t', - \ ale_linters#verilog#iverilog#GetCommand(bufnr('')) + AssertLinter 'iverilog', 'iverilog -t null -Wall %t' Execute(iverilog options should be configurable): " Additional args for the linter let g:ale_verilog_iverilog_options = '-y.' - AssertEqual - \ 'iverilog -t null -Wall -y. %t', - \ ale_linters#verilog#iverilog#GetCommand(bufnr('')) + AssertLinter 'iverilog', 'iverilog -t null -Wall -y. %t' diff --git a/test/command_callback/test_javac_command_callback.vader b/test/command_callback/test_javac_command_callback.vader index 7823d030..07a0794a 100644 --- a/test/command_callback/test_javac_command_callback.vader +++ b/test/command_callback/test_javac_command_callback.vader @@ -1,13 +1,10 @@ Before: - call ale#test#SetDirectory('/testplugin/test/command_callback') - - Save g:ale_java_javac_options - Save g:ale_java_javac_classpath - - unlet! g:ale_java_javac_options - unlet! g:ale_java_javac_classpath + call ale#assert#SetUpLinterTest('java', 'javac') + call ale#test#SetFilename('dummy.java') let g:cp_sep = has('unix') ? ':' : ';' + let g:prefix = 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape('javac') . ' -Xlint' function! GetCommand(previous_output) abort let l:command = ale_linters#java#javac#GetCommand( @@ -23,57 +20,58 @@ Before: return join(l:split_command) endfunction - runtime ale_linters/java/javac.vim - call ale#engine#InitBufferInfo(bufnr('')) - - call ale#test#SetFilename('dummy.java') - - let g:prefix = 'cd ' . ale#Escape(expand('%:p:h')) . ' && javac -Xlint' - After: - call ale#test#RestoreDirectory() - - Restore - unlet! g:cp_sep unlet! g:prefix delfunction GetCommand - call ale#linter#Reset() - " We need to clean up the buffer to remove the temporary directories created - " for the command. - call ale#engine#Cleanup(bufnr('')) + call ale#assert#TearDownLinterTest() Execute(The javac callback should return the correct default value): - AssertEqual g:prefix . ' -d TEMP %t', GetCommand([]) + AssertLinter 'javac', g:prefix . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' Execute(The javac callback should use g:ale_java_javac_classpath correctly): let g:ale_java_javac_classpath = 'foo.jar' - AssertEqual + AssertLinter 'javac', \ g:prefix \ . ' -cp ' . ale#Escape('foo.jar') - \ . ' -d TEMP %t', - \ GetCommand([]) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' + +Execute(The executable should be configurable): + let g:ale_java_javac_executable = 'foobar' + + AssertLinter 'foobar', + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape('foobar') . ' -Xlint' + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' Execute(The javac callback should include discovered classpaths): - AssertEqual + WithChainResults [ + \ '[DEBUG] Ignore this.', + \ '[INFO] Something we should ignore.', + \ '/foo/bar.jar', + \ '/xyz/abc.jar', + \] + + AssertLinter 'javac', \ g:prefix \ . ' -cp ' \ . ale#Escape(join(['/foo/bar.jar', '/xyz/abc.jar'], g:cp_sep)) - \ . ' -d TEMP %t', - \ GetCommand([ - \ '[DEBUG] Ignore this.', - \ '[INFO] Something we should ignore.', - \ '/foo/bar.jar', - \ '/xyz/abc.jar', - \ ]) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' Execute(The javac callback should combine discovered classpaths and manual ones): let g:ale_java_javac_classpath = 'configured.jar' - AssertEqual + WithChainResults [ + \ '[DEBUG] Ignore this.', + \ '[INFO] Something we should ignore.', + \ '/foo/bar.jar', + \ '/xyz/abc.jar', + \] + + AssertLinter 'javac', \ g:prefix \ . ' -cp ' \ . ale#Escape(join( @@ -84,17 +82,11 @@ Execute(The javac callback should combine discovered classpaths and manual ones) \ ], \ g:cp_sep \ )) - \ . ' -d TEMP %t', - \ GetCommand([ - \ '[DEBUG] Ignore this.', - \ '[INFO] Something we should ignore.', - \ '/foo/bar.jar', - \ '/xyz/abc.jar', - \ ]) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' let g:ale_java_javac_classpath = 'configured.jar' . g:cp_sep . 'configured2.jar' - AssertEqual + AssertLinter 'javac', \ g:prefix \ . ' -cp ' \ . ale#Escape(join( @@ -106,55 +98,46 @@ Execute(The javac callback should combine discovered classpaths and manual ones) \ ], \ g:cp_sep \ )) - \ . ' -d TEMP %t', - \ GetCommand([ - \ '[DEBUG] Ignore this.', - \ '[INFO] Something we should ignore.', - \ '/foo/bar.jar', - \ '/xyz/abc.jar', - \ ]) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' Execute(The javac callback should detect source directories): call ale#engine#Cleanup(bufnr('')) noautocmd e! java_paths/src/main/java/com/something/dummy call ale#engine#InitBufferInfo(bufnr('')) - AssertEqual - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && javac -Xlint' + AssertLinter 'javac', + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' . ale#Escape('javac') . ' -Xlint' \ . ' -sourcepath ' . ale#Escape( \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/') \ ) - \ . ' -d TEMP %t', - \ GetCommand([]) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' Execute(The javac callback should combine detected source directories and classpaths): call ale#engine#Cleanup(bufnr('')) call ale#test#SetFilename('java_paths/src/main/java/com/something/dummy.java') call ale#engine#InitBufferInfo(bufnr('')) - AssertEqual - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && javac -Xlint' + WithChainResults [ + \ '[DEBUG] Ignore this.', + \ '[INFO] Something we should ignore.', + \ '/foo/bar.jar', + \ '/xyz/abc.jar', + \] + AssertLinter 'javac', + \ 'cd ' . ale#Escape(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/') \ ) - \ . ' -d TEMP %t', - \ GetCommand([ - \ '[DEBUG] Ignore this.', - \ '[INFO] Something we should ignore.', - \ '/foo/bar.jar', - \ '/xyz/abc.jar', - \ ]) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' Execute(The javac callback should use g:ale_java_javac_options correctly): let g:ale_java_javac_options = '--anything --else' let b:command = ale_linters#java#javac#GetCommand(bufnr(''), []) - AssertEqual - \ g:prefix - \ . ' -d TEMP --anything --else %t', - \ GetCommand([]) + AssertLinter 'javac', + \ g:prefix . ' -d ' . ale#Escape('TEMP_DIR') . ' --anything --else %t' Execute(The javac callback should include src/test/java for test paths): call ale#engine#Cleanup(bufnr('')) @@ -163,25 +146,23 @@ Execute(The javac callback should include src/test/java for test paths): noautocmd e! java_paths/src/test/java/com/something/dummy call ale#engine#InitBufferInfo(bufnr('')) - AssertEqual - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && javac -Xlint' + AssertLinter 'javac', + \ 'cd ' . ale#Escape(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/'), \ ], g:cp_sep)) - \ . ' -d TEMP %t', - \ GetCommand([]) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' Execute(The javac callback should include src/main/jaxb when available): call ale#engine#Cleanup(bufnr('')) noautocmd e! java_paths_with_jaxb/src/main/java/com/something/dummy call ale#engine#InitBufferInfo(bufnr('')) - AssertEqual - \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && javac -Xlint' + AssertLinter 'javac', + \ 'cd ' . ale#Escape(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/'), \ ], g:cp_sep)) - \ . ' -d TEMP %t', - \ GetCommand([]) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' 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_jscs_command_callback.vader b/test/command_callback/test_jscs_command_callback.vader index f118c039..7cdf5467 100644 --- a/test/command_callback/test_jscs_command_callback.vader +++ b/test/command_callback/test_jscs_command_callback.vader @@ -1,25 +1,15 @@ Before: - runtime ale_linters/javascript/jscs.vim + call ale#assert#SetUpLinterTest('javascript', 'jscs') After: - call ale#linter#Reset() - let g:ale_javascript_jscs_executable = 'jscs' + call ale#assert#TearDownLinterTest() Execute(Should return the correct default values): - AssertEqual - \ 'jscs', - \ ale_linters#javascript#jscs#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('jscs') . ' --reporter inline --no-colors -', - \ ale_linters#javascript#jscs#GetCommand(bufnr('')) - + AssertLinter 'jscs', + \ ale#Escape('jscs') . ' --reporter inline --no-colors -' Execute(Should allow using a custom executable): let g:ale_javascript_jscs_executable = 'foobar' - AssertEqual - \ 'foobar', - \ ale_linters#javascript#jscs#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('foobar') . ' --reporter inline --no-colors -', - \ ale_linters#javascript#jscs#GetCommand(bufnr('')) + AssertLinter 'foobar', + \ ale#Escape('foobar') . ' --reporter inline --no-colors -' 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_less_stylelint_command_callback.vader b/test/command_callback/test_less_stylelint_command_callback.vader index a5912ecf..8d23deb6 100644 --- a/test/command_callback/test_less_stylelint_command_callback.vader +++ b/test/command_callback/test_less_stylelint_command_callback.vader @@ -1,31 +1,10 @@ Before: - Save g:ale_less_stylelint_executable - Save g:ale_less_stylelint_use_global - Save g:ale_less_stylelint_options - + call ale#assert#SetUpLinterTest('less', 'stylelint') unlet! b:executable - unlet! g:ale_less_stylelint_executable - unlet! g:ale_less_stylelint_use_global - unlet! g:ale_less_stylelint_options - - call ale#test#SetDirectory('/testplugin/test/command_callback') - call ale#test#SetFilename('testfile.less') - - runtime ale_linters/less/stylelint.vim - After: - Restore - unlet! b:executable - unlet! b:ale_less_stylelint_executable - unlet! b:ale_less_stylelint_use_global - unlet! b:ale_less_stylelint_options - - call ale#test#SetFilename('test.txt') - - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(node_modules directories should be discovered): call ale#test#SetFilename('stylelint_paths/nested/testfile.less') @@ -35,10 +14,7 @@ Execute(node_modules directories should be discovered): \ . '/stylelint_paths/node_modules/.bin/stylelint' \) - AssertEqual b:executable, ale_linters#less#stylelint#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape(b:executable) . ' --stdin-filename %s', - \ ale_linters#less#stylelint#GetCommand(bufnr('')) + AssertLinter b:executable, ale#Escape(b:executable) . ' --stdin-filename %s' Execute(The global override should work): let b:ale_less_stylelint_executable = 'foobar' @@ -46,15 +22,10 @@ Execute(The global override should work): call ale#test#SetFilename('stylelint_paths/nested/testfile.less') - AssertEqual 'foobar', ale_linters#less#stylelint#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('foobar') . ' --stdin-filename %s', - \ ale_linters#less#stylelint#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . ' --stdin-filename %s' Execute(Extra options should be configurable): let b:ale_less_stylelint_options = '--whatever' - AssertEqual 'stylelint', ale_linters#less#stylelint#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('stylelint') . ' --whatever --stdin-filename %s', - \ ale_linters#less#stylelint#GetCommand(bufnr('')) + AssertLinter 'stylelint', + \ ale#Escape('stylelint') . ' --whatever --stdin-filename %s' diff --git a/test/command_callback/test_lessc_command_callback.vader b/test/command_callback/test_lessc_command_callback.vader index ec2899d1..79f57d06 100644 --- a/test/command_callback/test_lessc_command_callback.vader +++ b/test/command_callback/test_lessc_command_callback.vader @@ -1,31 +1,13 @@ Before: - Save g:ale_less_lessc_executable - Save g:ale_less_lessc_use_global - Save g:ale_less_lessc_options - - unlet! b:executable - - unlet! g:ale_less_lessc_executable - unlet! g:ale_less_lessc_use_global - unlet! g:ale_less_lessc_options - - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('less', 'lessc') call ale#test#SetFilename('testfile.less') - runtime ale_linters/less/lessc.vim + unlet! b:executable After: - Restore - unlet! b:executable - unlet! b:ale_less_lessc_executable - unlet! b:ale_less_lessc_use_global - unlet! b:ale_less_lessc_options - - call ale#test#SetFilename('test.txt') - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(node_modules directories should be discovered): call ale#test#SetFilename('lessc_paths/nested/testfile.less') @@ -35,17 +17,11 @@ Execute(node_modules directories should be discovered): \ . '/lessc_paths/node_modules/.bin/lessc' \) - AssertEqual - \ b:executable, - \ ale_linters#less#lessc#GetExecutable(bufnr('')) - - AssertEqual - \ ale#Escape(b:executable) - \ . ' --no-color --lint' - \ . ' --include-path=' - \ . ale#Escape(ale#path#Simplify(g:dir . '/lessc_paths/nested')) - \ . ' -', - \ ale_linters#less#lessc#GetCommand(bufnr('')) + AssertLinter b:executable, ale#Escape(b:executable) + \ . ' --no-color --lint' + \ . ' --include-path=' + \ . ale#Escape(ale#path#Simplify(g:dir . '/lessc_paths/nested')) + \ . ' -' Execute(The global override should work): let b:ale_less_lessc_executable = 'foobar' @@ -53,30 +29,18 @@ Execute(The global override should work): call ale#test#SetFilename('lessc_paths/nested/testfile.less') - AssertEqual - \ 'foobar', - \ ale_linters#less#lessc#GetExecutable(bufnr('')) - - AssertEqual - \ ale#Escape('foobar') - \ . ' --no-color --lint' - \ . ' --include-path=' - \ . ale#Escape(ale#path#Simplify(g:dir . '/lessc_paths/nested')) - \ . ' -', - \ ale_linters#less#lessc#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') + \ . ' --no-color --lint' + \ . ' --include-path=' + \ . ale#Escape(ale#path#Simplify(g:dir . '/lessc_paths/nested')) + \ . ' -' Execute(Extra options should be configurable): let b:ale_less_lessc_options = '--whatever' - AssertEqual - \ 'lessc', - \ ale_linters#less#lessc#GetExecutable(bufnr('')) - - AssertEqual - \ ale#Escape('lessc') - \ . ' --no-color --lint' - \ . ' --include-path=' - \ . ale#Escape(ale#path#Simplify(g:dir)) - \ . ' --whatever' - \ . ' -', - \ ale_linters#less#lessc#GetCommand(bufnr('')) + AssertLinter 'lessc', ale#Escape('lessc') + \ . ' --no-color --lint' + \ . ' --include-path=' + \ . ale#Escape(ale#path#Simplify(g:dir)) + \ . ' --whatever' + \ . ' -' diff --git a/test/command_callback/test_lintr_command_callback.vader b/test/command_callback/test_lintr_command_callback.vader index 3199b498..8a0e6c1c 100644 --- a/test/command_callback/test_lintr_command_callback.vader +++ b/test/command_callback/test_lintr_command_callback.vader @@ -1,34 +1,36 @@ Before: - Save g:ale_r_lintr_options - - unlet! g:ale_r_lintr_options - unlet! b:ale_r_lintr_options - - runtime ale_linters/r/lintr.vim + call ale#assert#SetUpLinterTest('r', 'lintr') After: - Restore - - unlet! b:ale_r_lintr_options - - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The default lintr command should be correct): - AssertEqual + AssertLinter 'Rscript', \ 'cd ' . ale#Escape(getcwd()) . ' && ' - \ . 'Rscript -e ' - \ . ale#Escape('lintr::lint(commandArgs(TRUE)[1], eval(parse(text = commandArgs(TRUE)[2])))') - \ . ' %t ' - \ . ale#Escape('lintr::with_defaults()'), - \ ale_linters#r#lintr#GetCommand(bufnr('')) + \ . 'Rscript --vanilla -e ' + \ . ale#Escape('suppressPackageStartupMessages(library(lintr));' + \ . 'lint(cache = FALSE, commandArgs(TRUE), ' + \ . 'with_defaults())') + \ . ' %t' Execute(The lintr options should be configurable): - let b:ale_r_lintr_options = 'lintr::with_defaults(object_usage_linter = NULL)' + let b:ale_r_lintr_options = 'with_defaults(object_usage_linter = NULL)' + + AssertLinter 'Rscript', + \ 'cd ' . ale#Escape(getcwd()) . ' && ' + \ . 'Rscript --vanilla -e ' + \ . ale#Escape('suppressPackageStartupMessages(library(lintr));' + \ . 'lint(cache = FALSE, commandArgs(TRUE), ' + \ . 'with_defaults(object_usage_linter = NULL))') + \ . ' %t' + +Execute(If the lint_package flag is set, lintr::lint_package should be called): + let b:ale_r_lintr_lint_package = 1 - AssertEqual + AssertLinter 'Rscript', \ 'cd ' . ale#Escape(getcwd()) . ' && ' - \ . 'Rscript -e ' - \ . ale#Escape('lintr::lint(commandArgs(TRUE)[1], eval(parse(text = commandArgs(TRUE)[2])))') - \ . ' %t ' - \ . ale#Escape('lintr::with_defaults(object_usage_linter = NULL)'), - \ ale_linters#r#lintr#GetCommand(bufnr('')) + \ . 'Rscript --vanilla -e ' + \ . ale#Escape('suppressPackageStartupMessages(library(lintr));' + \ . 'lint_package(cache = FALSE, ' + \ . 'linters = with_defaults())') + \ . ' %t' diff --git a/test/command_callback/test_llc_command_callback.vader b/test/command_callback/test_llc_command_callback.vader index 296b277a..a0caaa48 100644 --- a/test/command_callback/test_llc_command_callback.vader +++ b/test/command_callback/test_llc_command_callback.vader @@ -1,10 +1,5 @@ Before: - Save g:ale_llvm_llc_executable - - unlet! g:ale_llvm_llc_executable - unlet! b:ale_llvm_llc_executable - - runtime ale_linters/llvm/llc.vim + call ale#assert#SetUpLinterTest('llvm', 'llc') function! AssertHasPrefix(str, prefix) abort let msg = printf("'%s' is expected to be prefixed with '%s'", a:str, a:prefix) @@ -12,28 +7,15 @@ Before: endfunction After: - unlet! g:ale_llvm_llc_executable - unlet! b:ale_llvm_llc_executable delfunction AssertHasPrefix - Restore -Execute(llc command is customizable): - let cmd = ale_linters#llvm#llc#GetCommand(bufnr('')) - call AssertHasPrefix(cmd, ale#Escape('llc')) + call ale#assert#TearDownLinterTest() - let g:ale_llvm_llc_executable = 'llc-5.0' - let cmd = ale_linters#llvm#llc#GetCommand(bufnr('')) - call AssertHasPrefix(cmd, ale#Escape('llc-5.0')) +Execute(The llc command should be customizable): + AssertLinter 'llc', + \ ale#Escape('llc') . ' -filetype=null -o=' . g:ale#util#nul_file - let b:ale_llvm_llc_executable = 'llc-4.0' - let cmd = ale_linters#llvm#llc#GetCommand(bufnr('')) - call AssertHasPrefix(cmd, ale#Escape('llc-4.0')) - -Execute(GetCommand() escapes the returned path): - let b:ale_llvm_llc_executable = '/path/space contained/llc' - let cmd = ale_linters#llvm#llc#GetCommand(bufnr('')) - call AssertHasPrefix(cmd, ale#Escape('/path/space contained/llc')) + let g:ale_llvm_llc_executable = 'llc-5.0' -Execute(GetExecutable() does not escape the returned path): - let b:ale_llvm_llc_executable = '/path/space contained/llc' - AssertEqual ale_linters#llvm#llc#GetExecutable(bufnr('')), '/path/space contained/llc' + AssertLinter 'llc-5.0', + \ ale#Escape('llc-5.0') . ' -filetype=null -o=' . g:ale#util#nul_file diff --git a/test/command_callback/test_luac_command_callback.vader b/test/command_callback/test_luac_command_callback.vader index f9eb4d3f..55f39cba 100644 --- a/test/command_callback/test_luac_command_callback.vader +++ b/test/command_callback/test_luac_command_callback.vader @@ -1,16 +1,13 @@ Before: - runtime ale_linters/lua/luac.vim + call ale#assert#SetUpLinterTest('lua', 'luac') After: - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The default command should be correct): - AssertEqual ale#Escape('luac') . ' -p -', - \ join(split(ale_linters#lua#luac#GetCommand(1))) + AssertLinter 'luac', ale#Escape('luac') . ' -p -' Execute(The luac executable should be configurable): let g:ale_lua_luac_executable = 'luac.sh' - AssertEqual 'luac.sh', ale_linters#lua#luac#GetExecutable(1) - AssertEqual ale#Escape('luac.sh') . ' -p -', - \ join(split(ale_linters#lua#luac#GetCommand(1))) + 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 6f7f3a00..f0ef221c 100644 --- a/test/command_callback/test_luacheck_command_callback.vader +++ b/test/command_callback/test_luacheck_command_callback.vader @@ -1,24 +1,23 @@ Before: - runtime ale_linters/lua/luacheck.vim + call ale#assert#SetUpLinterTest('lua', 'luacheck') After: - call ale#linter#Reset() - let g:ale_lua_luacheck_options = '' - let g:ale_lua_luacheck_executable = 'luacheck' + call ale#assert#TearDownLinterTest() Execute(The lua luacheck command callback should return the correct default string): - AssertEqual ale#Escape('luacheck') . ' --formatter plain --codes --filename %s -', - \ join(split(ale_linters#lua#luacheck#GetCommand(1))) + AssertLinter 'luacheck', + \ 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' - AssertEqual ale#Escape('luacheck') . ' --config filename --formatter plain --codes --filename %s -', - \ join(split(ale_linters#lua#luacheck#GetCommand(1))) + AssertLinter 'luacheck', + \ ale#Escape('luacheck') + \ . ' --config filename' + \ . ' --formatter plain --codes --filename %s -' Execute(The luacheck executable should be configurable): let g:ale_lua_luacheck_executable = 'luacheck.sh' - AssertEqual 'luacheck.sh', ale_linters#lua#luacheck#GetExecutable(1) - AssertEqual ale#Escape('luacheck.sh') . ' --formatter plain --codes --filename %s -', - \ join(split(ale_linters#lua#luacheck#GetCommand(1))) + AssertLinter 'luacheck.sh', + \ ale#Escape('luacheck.sh') . ' --formatter plain --codes --filename %s -' diff --git a/test/command_callback/test_markdown_mdl_command_callback.vader b/test/command_callback/test_markdown_mdl_command_callback.vader new file mode 100644 index 00000000..e029bf9b --- /dev/null +++ b/test/command_callback/test_markdown_mdl_command_callback.vader @@ -0,0 +1,19 @@ +Before: + call ale#assert#SetUpLinterTest('markdown', 'mdl') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'mdl', ale#Escape('mdl') + +Execute(The executable and options should be configurable): + let g:ale_markdown_mdl_executable = 'foo bar' + let g:ale_markdown_mdl_options = '--wat' + + AssertLinter 'foo bar', ale#Escape('foo bar') . ' --wat' + +Execute(Setting bundle appends 'exec mdl'): + let g:ale_markdown_mdl_executable = 'path to/bundle' + + AssertLinter 'path to/bundle', ale#Escape('path to/bundle') . ' exec mdl' diff --git a/test/command_callback/test_mercury_mmc_command_callback.vader b/test/command_callback/test_mercury_mmc_command_callback.vader new file mode 100644 index 00000000..ab61fddf --- /dev/null +++ b/test/command_callback/test_mercury_mmc_command_callback.vader @@ -0,0 +1,25 @@ +Before: + call ale#assert#SetUpLinterTest('mercury', 'mmc') + call ale#test#SetFilename('dummy') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'mmc', + \ ale#path#BufferCdString(bufnr('')) + \ . 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('')) + \ . 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('')) + \ . 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 6a0add52..988dfb1b 100644 --- a/test/command_callback/test_mypy_command_callback.vader +++ b/test/command_callback/test_mypy_command_callback.vader @@ -1,97 +1,71 @@ Before: - Save g:ale_python_mypy_executable - Save g:ale_python_mypy_options - Save g:ale_python_mypy_use_global - - unlet! g:ale_python_mypy_executable - unlet! g:ale_python_mypy_options - unlet! g:ale_python_mypy_use_global + call ale#assert#SetUpLinterTest('python', 'mypy') + call ale#test#SetFilename('test.py') let b:bin_dir = has('win32') ? 'Scripts' : 'bin' - runtime ale_linters/python/mypy.vim - - call ale#test#SetDirectory('/testplugin/test/command_callback') - call ale#test#SetFilename('test.py') - After: - Restore - unlet! b:bin_dir unlet! b:executable - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The mypy callbacks should return the correct default values): - AssertEqual - \ 'mypy', - \ ale_linters#python#mypy#GetExecutable(bufnr('')) - AssertEqual + AssertLinter 'mypy', \ 'cd ' . ale#Escape(g:dir) . ' && ' . ale#Escape('mypy') \ . ' --show-column-numbers ' - \ . '--shadow-file %s %t %s', - \ ale_linters#python#mypy#GetCommand(bufnr('')) + \ . '--shadow-file %s %t %s' Execute(The mypy executable should be configurable, and escaped properly): let g:ale_python_mypy_executable = 'executable with spaces' - AssertEqual - \ 'executable with spaces', - \ ale_linters#python#mypy#GetExecutable(bufnr('')) - AssertEqual + AssertLinter 'executable with spaces', \ 'cd ' . ale#Escape(g:dir) . ' && ' . ale#Escape('executable with spaces') \ . ' --show-column-numbers ' - \ . '--shadow-file %s %t %s', - \ ale_linters#python#mypy#GetCommand(bufnr('')) + \ . '--shadow-file %s %t %s' Execute(The mypy command callback should let you set options): let g:ale_python_mypy_options = '--some-option' - AssertEqual + AssertLinter 'mypy', \ 'cd ' . ale#Escape(g:dir) . ' && ' . ale#Escape('mypy') \ . ' --show-column-numbers --some-option ' - \ . '--shadow-file %s %t %s', - \ ale_linters#python#mypy#GetCommand(bufnr('')) + \ . '--shadow-file %s %t %s' 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') - AssertEqual - \ 'mypy', - \ ale_linters#python#mypy#GetExecutable(bufnr('')) - AssertEqual + AssertLinter 'mypy', \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/no_virtualenv/subdir')) \ . ' && ' . ale#Escape('mypy') \ . ' --show-column-numbers ' - \ . '--shadow-file %s %t %s', - \ ale_linters#python#mypy#GetCommand(bufnr('')) + \ . '--shadow-file %s %t %s' Execute(The mypy callbacks should detect virtualenv directories and switch to the project root): silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') let b:executable = ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/mypy') - AssertEqual - \ b:executable, - \ ale_linters#python#mypy#GetExecutable(bufnr('')) - AssertEqual + AssertLinter b:executable, \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/subdir')) \ . ' && ' . ale#Escape(b:executable) \ . ' --show-column-numbers ' - \ . '--shadow-file %s %t %s', - \ ale_linters#python#mypy#GetCommand(bufnr('')) + \ . '--shadow-file %s %t %s' Execute(You should able able to use the global mypy instead): silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') let g:ale_python_mypy_use_global = 1 - AssertEqual - \ 'mypy', - \ ale_linters#python#mypy#GetExecutable(bufnr('')) - AssertEqual + AssertLinter 'mypy', \ 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/subdir')) \ . ' && ' . ale#Escape('mypy') \ . ' --show-column-numbers ' - \ . '--shadow-file %s %t %s', - \ ale_linters#python#mypy#GetCommand(bufnr('')) + \ . '--shadow-file %s %t %s' + +Execute(Setting executable to 'pipenv' appends 'run mypy'): + let g:ale_python_mypy_executable = 'path/to/pipenv' + + AssertLinter 'path/to/pipenv', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('path/to/pipenv') . ' run mypy' + \ . ' --show-column-numbers --shadow-file %s %t %s' diff --git a/test/command_callback/test_nagelfar_command_callbacks.vader b/test/command_callback/test_nagelfar_command_callbacks.vader index 5c6be7f1..94bb1d53 100644 --- a/test/command_callback/test_nagelfar_command_callbacks.vader +++ b/test/command_callback/test_nagelfar_command_callbacks.vader @@ -1,42 +1,19 @@ Before: - Save g:ale_tcl_nagelfar_executable - Save g:ale_tcl_nagelfar_options - - unlet! g:ale_tcl_nagelfar_executable - unlet! b:ale_tcl_nagelfar_executable - unlet! g:ale_tcl_nagelfar_options - unlet! b:ale_tcl_nagelfar_options - - runtime ale_linters/tcl/nagelfar.vim + call ale#assert#SetUpLinterTest('tcl', 'nagelfar') After: - Restore unlet! b:command_tail - unlet! b:ale_tcl_nagelfar_executable - unlet! b:ale_tcl_nagelfar_options - call ale#linter#Reset() -Execute(The executable should be configurable): - AssertEqual 'nagelfar.tcl', ale_linters#tcl#nagelfar#GetExecutable(bufnr('')) + call ale#assert#TearDownLinterTest() - let b:ale_tcl_nagelfar_executable = 'foobar' - - AssertEqual 'foobar', ale_linters#tcl#nagelfar#GetExecutable(bufnr('')) - -Execute(The executable should be used in the command): - AssertEqual - \ ale#Escape('nagelfar.tcl') . ' %s', - \ ale_linters#tcl#nagelfar#GetCommand(bufnr('')) +Execute(The executable should be configurable): + AssertLinter 'nagelfar.tcl', ale#Escape('nagelfar.tcl') . ' %s' let b:ale_tcl_nagelfar_executable = 'foobar' - AssertEqual - \ ale#Escape('foobar') . ' %s', - \ ale_linters#tcl#nagelfar#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . ' %s' Execute(The options should be configurable): let b:ale_tcl_nagelfar_options = '--something' - AssertEqual - \ ale#Escape('nagelfar.tcl') . ' --something %s', - \ ale_linters#tcl#nagelfar#GetCommand(bufnr('')) + AssertLinter 'nagelfar.tcl', ale#Escape('nagelfar.tcl') . ' --something %s' diff --git a/test/command_callback/test_nasm_nasm_command_callbacks.vader b/test/command_callback/test_nasm_nasm_command_callbacks.vader new file mode 100644 index 00000000..0d3e572a --- /dev/null +++ b/test/command_callback/test_nasm_nasm_command_callbacks.vader @@ -0,0 +1,31 @@ +Before: + call ale#assert#SetUpLinterTest('nasm', 'nasm') + + let b:command_tail = + \ ' -X gnu -I ' . ale#Escape(getcwd() . (has('win32') ? '\' : '/')) . ' %s' + let b:command_tail_opt = + \ ' -X gnu -I ' . ale#Escape(getcwd() . (has('win32') ? '\' : '/')) . ' -w+orphan-labels %s' + +After: + unlet! b:command_tail + unlet! b:command_tail_opt + + call ale#assert#TearDownLinterTest() + +Execute(The executable should be configurable): + AssertLinter 'nasm', ale#Escape('nasm') . b:command_tail, + + let b:ale_nasm_nasm_executable = '~/nasm' + + AssertLinter '~/nasm', ale#Escape('~/nasm') . b:command_tail + +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' + +Execute(The options should be used in command): + let b:ale_nasm_nasm_options = '-w+orphan-labels' + + AssertLinter 'nasm', ale#Escape('nasm') . b:command_tail_opt diff --git a/test/command_callback/test_ocaml_ols_callbacks.vader b/test/command_callback/test_ocaml_ols_callbacks.vader index d10898fa..c77e2909 100644 --- a/test/command_callback/test_ocaml_ols_callbacks.vader +++ b/test/command_callback/test_ocaml_ols_callbacks.vader @@ -1,54 +1,40 @@ Before: - Save &filetype - Save g:ale_ocaml_ols_executable - Save g:ale_ocaml_ols_use_global + call ale#assert#SetUpLinterTest('ocaml', 'ols') + Save &filetype let &filetype = 'ocaml' - unlet! g:ale_ocaml_ols_executable - unlet! g:ale_ocaml_ols_use_global - - runtime ale_linters/ocaml/ols.vim - - call ale#test#SetDirectory('/testplugin/test/command_callback') After: - Restore - - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The language string should be correct): - AssertEqual 'ocaml', ale#handlers#ols#GetLanguage(bufnr('')) + AssertLSPLanguage 'ocaml' Execute(The default executable should be correct): - AssertEqual 'ocaml-language-server', ale#handlers#ols#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('ocaml-language-server') . ' --stdio', - \ ale#handlers#ols#GetCommand(bufnr('')) + AssertLinter 'ocaml-language-server', + \ ale#Escape('ocaml-language-server') . ' --stdio' Execute(The project root should be detected correctly): - AssertEqual '', ale#handlers#ols#GetProjectRoot(bufnr('')) + AssertLSPProject '' call ale#test#SetFilename('ols_paths/file.ml') - AssertEqual - \ ale#path#Simplify(g:dir . '/ols_paths'), - \ ale#handlers#ols#GetProjectRoot(bufnr('')) + AssertLSPProject ale#path#Simplify(g:dir . '/ols_paths') Execute(The local executable should be used when available): call ale#test#SetFilename('ols_paths/file.ml') - AssertEqual - \ ale#path#Simplify(g:dir . '/ols_paths/node_modules/.bin/ocaml-language-server'), - \ ale#handlers#ols#GetExecutable(bufnr('')) + AssertLinter ale#path#Simplify(g:dir . '/ols_paths/node_modules/.bin/ocaml-language-server'), + \ ale#Escape(ale#path#Simplify(g:dir . '/ols_paths/node_modules/.bin/ocaml-language-server')) . ' --stdio' Execute(The gloabl executable should always be used when use_global is set): let g:ale_ocaml_ols_use_global = 1 call ale#test#SetFilename('ols_paths/file.ml') - AssertEqual 'ocaml-language-server', ale#handlers#ols#GetExecutable(bufnr('')) + AssertLinter 'ocaml-language-server', + \ ale#Escape('ocaml-language-server') . ' --stdio' Execute(The executable should be configurable): let g:ale_ocaml_ols_executable = 'foobar' - AssertEqual 'foobar', ale#handlers#ols#GetExecutable(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . ' --stdio' diff --git a/test/command_callback/test_perl_command_callback.vader b/test/command_callback/test_perl_command_callback.vader index ba85e53b..3c4b661c 100644 --- a/test/command_callback/test_perl_command_callback.vader +++ b/test/command_callback/test_perl_command_callback.vader @@ -1,37 +1,14 @@ Before: - Save g:ale_perl_perl_executable - Save g:ale_perl_perl_options - - unlet! g:ale_perl_perl_executable - unlet! g:ale_perl_perl_options - - runtime ale_linters/perl/perl.vim + call ale#assert#SetUpLinterTest('perl', 'perl') After: - Restore - - unlet! b:ale_perl_perl_executable - unlet! b:ale_perl_perl_options - - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The default Perl command callback should be correct): - AssertEqual - \ 'perl', - \ ale_linters#perl#perl#GetExecutable(bufnr('')) - - AssertEqual - \ ale#Escape('perl') . ' -c -Mwarnings -Ilib %t', - \ ale_linters#perl#perl#GetCommand(bufnr('')) + AssertLinter 'perl', ale#Escape('perl') . ' -c -Mwarnings -Ilib %t' Execute(Overriding the executable and command should work): let b:ale_perl_perl_executable = 'foobar' let b:ale_perl_perl_options = '-w' - AssertEqual - \ 'foobar', - \ ale_linters#perl#perl#GetExecutable(bufnr('')) - - AssertEqual - \ ale#Escape('foobar') . ' -w %t', - \ ale_linters#perl#perl#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . ' -w %t' diff --git a/test/command_callback/test_perlcritic_command_callback.vader b/test/command_callback/test_perlcritic_command_callback.vader index 6507868b..0f1e2856 100644 --- a/test/command_callback/test_perlcritic_command_callback.vader +++ b/test/command_callback/test_perlcritic_command_callback.vader @@ -1,59 +1,36 @@ Before: - Save g:ale_perl_perlcritic_profile - Save g:ale_perl_perlcritic_options - Save g:ale_perl_perlcritic_executable - Save g:ale_perl_perlcritic_showrules - - unlet! g:ale_perl_perlcritic_options - unlet! g:ale_perl_perlcritic_executable - unlet! g:ale_perl_perlcritic_showrules - let g:ale_perl_perlcritic_profile = '' - - runtime ale_linters/perl/perlcritic.vim - - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('perl', 'perlcritic') call ale#test#SetFilename('test.pl') + let g:ale_perl_perlcritic_profile = '' After: - Restore - - unlet! b:ale_perl_perlcritic_profile - unlet! b:ale_perl_perlcritic_options - unlet! b:ale_perl_perlcritic_executable - unlet! b:ale_perl_perlcritic_showrules unlet! b:readme_path - - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The command should be correct with g:ale_perl_perlcritic_showrules off): let b:ale_perl_perlcritic_showrules = 0 - AssertEqual - \ ale#Escape('perlcritic') . ' --verbose ''%l:%c %m\n'' --nocolor', - \ ale_linters#perl#perlcritic#GetCommand(bufnr('')) + AssertLinter 'perlcritic', ale#Escape('perlcritic') + \ . ' --verbose ' . ale#Escape('%l:%c %m\n') . ' --nocolor' Execute(The command should be correct with g:ale_perl_perlcritic_showrules on): let b:ale_perl_perlcritic_showrules = 1 - AssertEqual - \ ale#Escape('perlcritic') . ' --verbose ''%l:%c %m [%p]\n'' --nocolor', - \ ale_linters#perl#perlcritic#GetCommand(bufnr('')) + AssertLinter 'perlcritic', ale#Escape('perlcritic') + \ . ' --verbose ' . ale#Escape('%l:%c %m [%p]\n') . ' --nocolor' Execute(The command search for the profile file when set): let b:ale_perl_perlcritic_profile = 'README.md' let b:readme_path = ale#path#Simplify(expand('%:p:h:h:h') . '/README.md') - AssertEqual - \ ale#Escape('perlcritic') . ' --verbose ''%l:%c %m\n'' --nocolor' - \ . ' --profile ' . ale#Escape(b:readme_path), - \ ale_linters#perl#perlcritic#GetCommand(bufnr('')) + AssertLinter 'perlcritic', ale#Escape('perlcritic') + \ . ' --verbose ' . ale#Escape('%l:%c %m\n') . ' --nocolor' + \ . ' --profile ' . ale#Escape(b:readme_path) Execute(Extra options should be set appropriately): let b:ale_perl_perlcritic_options = 'beep boop' - AssertEqual - \ ale#Escape('perlcritic') . ' --verbose ''%l:%c %m\n'' --nocolor' - \ . ' beep boop', - \ ale_linters#perl#perlcritic#GetCommand(bufnr('')) + AssertLinter 'perlcritic', ale#Escape('perlcritic') + \ . ' --verbose ' . ale#Escape('%l:%c %m\n') . ' --nocolor' + \ . ' beep boop' diff --git a/test/command_callback/test_php_langserver_callbacks.vader b/test/command_callback/test_php_langserver_callbacks.vader index 0dc30630..3b0a427e 100644 --- a/test/command_callback/test_php_langserver_callbacks.vader +++ b/test/command_callback/test_php_langserver_callbacks.vader @@ -1,52 +1,29 @@ Before: - Save g:ale_php_langserver_executable - Save g:ale_php_langserver_config_path - Save g:ale_php_langserver_use_global - - unlet! g:ale_php_langserver_executable - unlet! g:ale_php_langserver_config_path - unlet! g:ale_php_langserver_use_global - - runtime ale_linters/php/langserver.vim - - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('php', 'langserver') After: - Restore - if isdirectory(g:dir . '/.git') call delete(g:dir . '/.git', 'd') endif - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The default executable path should be correct): - AssertEqual - \ 'php-language-server.php', - \ ale_linters#php#langserver#GetExecutable(bufnr('')) - AssertEqual - \ 'php ' . ale#Escape('php-language-server.php'), - \ ale_linters#php#langserver#GetCommand(bufnr('')) + AssertLinter 'php-language-server.php', + \ 'php ' . ale#Escape('php-language-server.php') Execute(Vendor executables should be detected): call ale#test#SetFilename('php-langserver-project/test.php') - AssertEqual + AssertLinter \ ale#path#Simplify(g:dir . '/php-langserver-project/vendor/bin/php-language-server.php'), - \ ale_linters#php#langserver#GetExecutable(bufnr('')) - AssertEqual \ 'php ' . ale#Escape(ale#path#Simplify( \ g:dir \ . '/php-langserver-project/vendor/bin/php-language-server.php' - \ )), - \ ale_linters#php#langserver#GetCommand(bufnr('')) - -Execute(The language string should be correct): - AssertEqual 'php', ale_linters#php#langserver#GetLanguage(bufnr('')) + \ )) Execute(The project path should be correct for .git directories): call ale#test#SetFilename('php-langserver-project/test.php') call mkdir(g:dir . '/.git') - AssertEqual g:dir, ale_linters#php#langserver#GetProjectRoot(bufnr('')) + AssertLSPProject g:dir 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_phpmd_command_callbacks.vader b/test/command_callback/test_phpmd_command_callbacks.vader index 928b9771..64922820 100644 --- a/test/command_callback/test_phpmd_command_callbacks.vader +++ b/test/command_callback/test_phpmd_command_callbacks.vader @@ -1,20 +1,12 @@ Before: - Save g:ale_php_phpmd_executable - - unlet! g:ale_php_phpmd_executable - - runtime ale_linters/php/phpmd.vim + call ale#assert#SetUpLinterTest('php', 'phpmd') After: - Restore - - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(Custom executables should be used for the executable and command): let g:ale_php_phpmd_executable = 'phpmd_test' - AssertEqual 'phpmd_test', ale_linters#php#phpmd#GetExecutable(bufnr('')) - AssertEqual + AssertLinter 'phpmd_test', \ ale#Escape('phpmd_test') - \ . ' %s text cleancode,codesize,controversial,design,naming,unusedcode --ignore-violations-on-exit %t', - \ ale_linters#php#phpmd#GetCommand(bufnr('')) + \ . ' %s text cleancode,codesize,controversial,design,naming,unusedcode --ignore-violations-on-exit %t' diff --git a/test/command_callback/test_phpstan_command_callbacks.vader b/test/command_callback/test_phpstan_command_callbacks.vader index 169c5bb7..c7db587a 100644 --- a/test/command_callback/test_phpstan_command_callbacks.vader +++ b/test/command_callback/test_phpstan_command_callbacks.vader @@ -1,38 +1,24 @@ Before: - Save g:ale_php_phpstan_executable - Save g:ale_php_phpstan_level - Save g:ale_php_phpstan_configuration - - unlet! g:ale_php_phpstan_executable - unlet! g:ale_php_phpstan_level - unlet! g:ale_php_phpstan_configuration - - runtime ale_linters/php/phpstan.vim + call ale#assert#SetUpLinterTest('php', 'phpstan') After: - Restore - - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(Custom executables should be used for the executable and command): let g:ale_php_phpstan_executable = 'phpstan_test' - AssertEqual 'phpstan_test', ale_linters#php#phpstan#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('phpstan_test') . ' analyze -l4 --errorFormat raw %s', - \ ale_linters#php#phpstan#GetCommand(bufnr('')) + AssertLinter 'phpstan_test', + \ ale#Escape('phpstan_test') . ' analyze -l4 --errorFormat raw %s' Execute(project with level set to 3): call ale#test#SetFilename('phpstan-test-files/foo/test.php') let g:ale_php_phpstan_level = 3 - AssertEqual - \ ale#Escape('phpstan') . ' analyze -l3 --errorFormat raw %s', - \ ale_linters#php#phpstan#GetCommand(bufnr('')) + AssertLinter 'phpstan', + \ ale#Escape('phpstan') . ' analyze -l3 --errorFormat raw %s' Execute(Custom phpstan configuration file): let g:ale_php_phpstan_configuration = 'phpstan_config' - AssertEqual - \ ale#Escape('phpstan') . ' analyze -l4 --errorFormat raw -c phpstan_config %s', - \ ale_linters#php#phpstan#GetCommand(bufnr('')) + AssertLinter 'phpstan', + \ ale#Escape('phpstan') . ' analyze -l4 --errorFormat raw -c phpstan_config %s' diff --git a/test/command_callback/test_pony_ponyc_command_callbacks.vader b/test/command_callback/test_pony_ponyc_command_callbacks.vader new file mode 100644 index 00000000..3a3b32ec --- /dev/null +++ b/test/command_callback/test_pony_ponyc_command_callbacks.vader @@ -0,0 +1,12 @@ +Before: + call ale#assert#SetUpLinterTest('pony', 'ponyc') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The options should be used in the command): + AssertLinter 'ponyc', ale#Escape('ponyc') . ' --pass paint' + + let b:ale_pony_ponyc_options = 'foobar' + + AssertLinter 'ponyc', ale#Escape('ponyc') . ' foobar' diff --git a/test/command_callback/test_prospector_command_callback.vader b/test/command_callback/test_prospector_command_callback.vader new file mode 100644 index 00000000..316b9883 --- /dev/null +++ b/test/command_callback/test_prospector_command_callback.vader @@ -0,0 +1,12 @@ +Before: + call ale#assert#SetUpLinterTest('python', 'prospector') + +After: + call ale#assert#TearDownLinterTest() + +Execute(Setting executable to 'pipenv' appends 'run prospector'): + let g:ale_python_prospector_executable = 'path/to/pipenv' + + AssertLinter 'path/to/pipenv', + \ ale#Escape('path/to/pipenv') . ' run prospector' + \ . ' --messages-only --absolute-paths --zero-exit --output-format json %s' diff --git a/test/command_callback/test_proto_command_callback.vader b/test/command_callback/test_proto_command_callback.vader index 76050c61..726588c0 100644 --- a/test/command_callback/test_proto_command_callback.vader +++ b/test/command_callback/test_proto_command_callback.vader @@ -1,21 +1,16 @@ Before: + call ale#assert#SetUpLinterTest('proto', 'protoc_gen_lint') call ale#test#SetFilename('test.proto') After: - Restore - - unlet! b:ale_proto_protoc_gen_lint_options - - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The default command should be correct): - AssertEqual - \ 'protoc' . ' -I ' . ale#Escape(getcwd()) . ' --lint_out=. ' . '%s', - \ ale_linters#proto#protoc_gen_lint#GetCommand(bufnr('')) + AssertLinter 'protoc', + \ 'protoc' . ' -I ' . ale#Escape(getcwd()) . ' --lint_out=. ' . '%s' Execute(The callback should include any additional options): let b:ale_proto_protoc_gen_lint_options = '--some-option' - AssertEqual - \ 'protoc' . ' -I ' . ale#Escape(getcwd()) . ' --some-option --lint_out=. ' . '%s', - \ ale_linters#proto#protoc_gen_lint#GetCommand(bufnr('')) + AssertLinter 'protoc', + \ 'protoc' . ' -I ' . ale#Escape(getcwd()) . ' --some-option --lint_out=. ' . '%s' diff --git a/test/command_callback/test_puglint_command_callback.vader b/test/command_callback/test_puglint_command_callback.vader index f9b4a856..69c86b25 100644 --- a/test/command_callback/test_puglint_command_callback.vader +++ b/test/command_callback/test_puglint_command_callback.vader @@ -1,71 +1,48 @@ Before: - Save g:ale_pug_puglint_options - Save g:ale_pug_puglint_executable - Save g:ale_pug_puglint_use_global - - let g:ale_pug_puglint_options = '' - let g:ale_pug_puglint_executable = 'pug-lint' - let g:ale_pug_puglint_use_global = 0 - - call ale#test#SetDirectory('/testplugin/test/command_callback') - - runtime ale_linters/pug/puglint.vim + call ale#assert#SetUpLinterTest('pug', 'puglint') After: - Restore - - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(puglint should detect local executables and package.json): call ale#test#SetFilename('puglint_project/test.pug') - AssertEqual + AssertLinter \ ale#path#Simplify(g:dir . '/puglint_project/node_modules/.bin/pug-lint'), - \ ale_linters#pug#puglint#GetExecutable(bufnr('')) - - AssertEqual \ ale#Escape(ale#path#Simplify(g:dir . '/puglint_project/node_modules/.bin/pug-lint')) \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/puglint_project/package.json')) - \ . ' -r inline %t', - \ ale_linters#pug#puglint#GetCommand(bufnr('')) + \ . ' -r inline %t' Execute(puglint should use global executables if configured): let g:ale_pug_puglint_use_global = 1 call ale#test#SetFilename('puglint_project/test.pug') - AssertEqual 'pug-lint', ale_linters#pug#puglint#GetExecutable(bufnr('')) - - AssertEqual + AssertLinter 'pug-lint', \ ale#Escape('pug-lint') \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/puglint_project/package.json')) - \ . ' -r inline %t', - \ ale_linters#pug#puglint#GetCommand(bufnr('')) + \ . ' -r inline %t' Execute(puglint should detect .pug-lintrc): call ale#test#SetFilename('puglint_project/puglint_rc_dir/subdir/test.pug') - AssertEqual + AssertLinter ale#path#Simplify(g:dir . '/puglint_project/node_modules/.bin/pug-lint'), \ ale#Escape(ale#path#Simplify(g:dir . '/puglint_project/node_modules/.bin/pug-lint')) \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/puglint_project/puglint_rc_dir/.pug-lintrc')) - \ . ' -r inline %t', - \ ale_linters#pug#puglint#GetCommand(bufnr('')) + \ . ' -r inline %t' Execute(puglint should detect .pug-lintrc.js): call ale#test#SetFilename('puglint_project/puglint_rc_js_dir/subdir/test.pug') - AssertEqual + AssertLinter ale#path#Simplify(g:dir . '/puglint_project/node_modules/.bin/pug-lint'), \ ale#Escape(ale#path#Simplify(g:dir . '/puglint_project/node_modules/.bin/pug-lint')) \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/puglint_project/puglint_rc_js_dir/.pug-lintrc.js')) - \ . ' -r inline %t', - \ ale_linters#pug#puglint#GetCommand(bufnr('')) + \ . ' -r inline %t' Execute(puglint should detect .pug-lintrc.json): call ale#test#SetFilename('puglint_project/puglint_rc_json_dir/subdir/test.pug') - AssertEqual + AssertLinter ale#path#Simplify(g:dir . '/puglint_project/node_modules/.bin/pug-lint'), \ ale#Escape(ale#path#Simplify(g:dir . '/puglint_project/node_modules/.bin/pug-lint')) \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/puglint_project/puglint_rc_json_dir/.pug-lintrc.json')) - \ . ' -r inline %t', - \ ale_linters#pug#puglint#GetCommand(bufnr('')) + \ . ' -r inline %t' diff --git a/test/command_callback/test_pycodestyle_command_callback.vader b/test/command_callback/test_pycodestyle_command_callback.vader index 5b309e19..851eede9 100644 --- a/test/command_callback/test_pycodestyle_command_callback.vader +++ b/test/command_callback/test_pycodestyle_command_callback.vader @@ -1,27 +1,26 @@ Before: - Save g:ale_python_pycodestyle_executable - Save g:ale_python_pycodestyle_options - Save g:ale_python_pycodestyle_use_global - - runtime ale_linters/python/pycodestyle.vim + call ale#assert#SetUpLinterTest('python', 'pycodestyle') After: - Restore - - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The pycodestyle command callback should return default string): - AssertEqual ale#Escape('pycodestyle') . ' -', - \ ale_linters#python#pycodestyle#GetCommand(bufnr('')) + AssertLinter 'pycodestyle', ale#Escape('pycodestyle') . ' -' Execute(The pycodestyle command callback should allow options): let g:ale_python_pycodestyle_options = '--exclude=test*.py' - AssertEqual ale#Escape('pycodestyle') . ' --exclude=test*.py -', - \ ale_linters#python#pycodestyle#GetCommand(bufnr('')) + AssertLinter 'pycodestyle', + \ ale#Escape('pycodestyle') . ' --exclude=test*.py -' Execute(The pycodestyle executable should be configurable): let g:ale_python_pycodestyle_executable = '~/.local/bin/pycodestyle' - AssertEqual ale#Escape('~/.local/bin/pycodestyle') . ' -', - \ ale_linters#python#pycodestyle#GetCommand(bufnr('')) + AssertLinter '~/.local/bin/pycodestyle', + \ ale#Escape('~/.local/bin/pycodestyle') . ' -' + +Execute(Setting executable to 'pipenv' appends 'run pycodestyle'): + let g:ale_python_pycodestyle_executable = 'path/to/pipenv' + + AssertLinter 'path/to/pipenv', + \ ale#Escape('path/to/pipenv') . ' run pycodestyle -' diff --git a/test/command_callback/test_pyflakes_command_callback.vader b/test/command_callback/test_pyflakes_command_callback.vader index e8486ca8..efc925fe 100644 --- a/test/command_callback/test_pyflakes_command_callback.vader +++ b/test/command_callback/test_pyflakes_command_callback.vader @@ -1,34 +1,20 @@ Before: - Save g:ale_python_pyflakes_executable - Save g:ale_python_pyflakes_use_global - - unlet! g:ale_python_pyflakes_executable - unlet! g:ale_python_pyflakes_use_global - + call ale#assert#SetUpLinterTest('python', 'pyflakes') let b:bin_dir = has('win32') ? 'Scripts' : 'bin' - call ale#test#SetDirectory('/testplugin/test/command_callback') - - runtime ale_linters/python/pyflakes.vim - After: - Restore - unlet! b:bin_dir unlet! b:executable - - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The pyflakes command callback should return default string): - AssertEqual ale#Escape('pyflakes') . ' %t', - \ ale_linters#python#pyflakes#GetCommand(bufnr('')) + AssertLinter 'pyflakes', ale#Escape('pyflakes') . ' %t' Execute(The pyflakes executable should be configurable): let g:ale_python_pyflakes_executable = '~/.local/bin/pyflakes' - AssertEqual ale#Escape('~/.local/bin/pyflakes') . ' %t', - \ ale_linters#python#pyflakes#GetCommand(bufnr('')) + AssertLinter '~/.local/bin/pyflakes', + \ ale#Escape('~/.local/bin/pyflakes') . ' %t' Execute(The pyflakes executable should be run from the virtualenv path): call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py') @@ -37,13 +23,17 @@ Execute(The pyflakes executable should be run from the virtualenv path): \ g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/pyflakes' \) - AssertEqual ale#Escape(b:executable) . ' %t', - \ ale_linters#python#pyflakes#GetCommand(bufnr('')) + AssertLinter b:executable, ale#Escape(b:executable) . ' %t' Execute(You should be able to override the pyflakes virtualenv lookup): call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py') let g:ale_python_pyflakes_use_global = 1 - AssertEqual ale#Escape('pyflakes') . ' %t', - \ ale_linters#python#pyflakes#GetCommand(bufnr('')) + AssertLinter 'pyflakes', ale#Escape('pyflakes') . ' %t' + +Execute(Setting executable to 'pipenv' appends 'run pyflakes'): + let g:ale_python_pyflakes_executable = 'path/to/pipenv' + + AssertLinter 'path/to/pipenv', + \ ale#Escape('path/to/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 1ff8e354..be2908f9 100644 --- a/test/command_callback/test_pylint_command_callback.vader +++ b/test/command_callback/test_pylint_command_callback.vader @@ -1,62 +1,46 @@ Before: - Save g:ale_python_pylint_executable - Save g:ale_python_pylint_options - Save g:ale_python_pylint_use_global - - unlet! g:ale_python_pylint_executable - unlet! g:ale_python_pylint_options - unlet! g:ale_python_pylint_use_global - - runtime ale_linters/python/pylint.vim - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('python', 'pylint') let b:bin_dir = has('win32') ? 'Scripts' : 'bin' - let b:command_tail = ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n %s' After: - Restore - - call ale#test#RestoreDirectory() - call ale#linter#Reset() - unlet! b:bin_dir unlet! b:executable + unlet! b:command_tail + + call ale#assert#TearDownLinterTest() Execute(The pylint callbacks should return the correct default values): - AssertEqual - \ 'pylint', - \ ale_linters#python#pylint#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('pylint') . ' ' . b:command_tail, - \ ale_linters#python#pylint#GetCommand(bufnr('')) + AssertLinter 'pylint', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('pylint') . ' ' . b:command_tail + +Execute(The option for disabling changing directories should work): + let g:ale_python_pylint_change_directory = 0 + + AssertLinter 'pylint', ale#Escape('pylint') . ' ' . b:command_tail Execute(The pylint executable should be configurable, and escaped properly): let g:ale_python_pylint_executable = 'executable with spaces' - AssertEqual - \ 'executable with spaces', - \ ale_linters#python#pylint#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('executable with spaces') . ' ' . b:command_tail, - \ ale_linters#python#pylint#GetCommand(bufnr('')) + AssertLinter 'executable with spaces', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('executable with spaces') . ' ' . b:command_tail Execute(The pylint command callback should let you set options): let g:ale_python_pylint_options = '--some-option' - AssertEqual - \ ale#Escape('pylint') . ' --some-option' . b:command_tail, - \ ale_linters#python#pylint#GetCommand(bufnr('')) + AssertLinter 'pylint', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('pylint') . ' --some-option' . b:command_tail Execute(The pylint callbacks shouldn't detect virtualenv directories where they don't exist): silent execute 'file ' . fnameescape(g:dir . '/python_paths/no_virtualenv/subdir/foo/bar.py') - AssertEqual - \ 'pylint', - \ ale_linters#python#pylint#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('pylint') . ' ' . b:command_tail, - \ ale_linters#python#pylint#GetCommand(bufnr('')) + AssertLinter 'pylint', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('pylint') . ' ' . b:command_tail Execute(The pylint callbacks should detect virtualenv directories): silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') @@ -65,21 +49,22 @@ Execute(The pylint callbacks should detect virtualenv directories): \ g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/pylint' \) - AssertEqual - \ b:executable, - \ ale_linters#python#pylint#GetExecutable(bufnr('')) - - AssertEqual - \ ale#Escape(b:executable) . ' ' . b:command_tail, - \ ale_linters#python#pylint#GetCommand(bufnr('')) + AssertLinter b:executable, + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape(b:executable) . ' ' . b:command_tail Execute(You should able able to use the global pylint instead): silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') let g:ale_python_pylint_use_global = 1 - AssertEqual - \ 'pylint', - \ ale_linters#python#pylint#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('pylint') . ' ' . b:command_tail, - \ ale_linters#python#pylint#GetCommand(bufnr('')) + AssertLinter 'pylint', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('pylint') . ' ' . b:command_tail + +Execute(Setting executable to 'pipenv' appends 'run pylint'): + let g:ale_python_pylint_executable = 'path/to/pipenv' + + AssertLinter 'path/to/pipenv', + \ ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('path/to/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 06ea718f..53bf3000 100644 --- a/test/command_callback/test_pyls_command_callback.vader +++ b/test/command_callback/test_pyls_command_callback.vader @@ -1,34 +1,21 @@ Before: - Save g:ale_python_pyls_executable - Save g:ale_python_pyls_use_global - - unlet! g:ale_python_pyls_executable - unlet! g:ale_python_pyls_use_global + call ale#assert#SetUpLinterTest('python', 'pyls') let b:bin_dir = has('win32') ? 'Scripts' : 'bin' - call ale#test#SetDirectory('/testplugin/test/command_callback') - - runtime ale_linters/python/pyls.vim - After: - Restore - unlet! b:bin_dir unlet! b:executable - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The pyls command callback should return default string): - AssertEqual ale#Escape('pyls'), - \ ale_linters#python#pyls#GetCommand(bufnr('')) + AssertLinter 'pyls', ale#Escape('pyls') Execute(The pyls executable should be configurable): let g:ale_python_pyls_executable = '~/.local/bin/pyls' - AssertEqual ale#Escape('~/.local/bin/pyls'), - \ ale_linters#python#pyls#GetCommand(bufnr('')) + AssertLinter '~/.local/bin/pyls' , ale#Escape('~/.local/bin/pyls') Execute(The pyls executable should be run from the virtualenv path): call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py') @@ -45,5 +32,9 @@ Execute(You should be able to override the pyls virtualenv lookup): let g:ale_python_pyls_use_global = 1 - AssertEqual ale#Escape('pyls'), - \ ale_linters#python#pyls#GetCommand(bufnr('')) + AssertLinter 'pyls', ale#Escape('pyls') + +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' diff --git a/test/command_callback/test_pyre_command_callback.vader b/test/command_callback/test_pyre_command_callback.vader new file mode 100644 index 00000000..6ad19b56 --- /dev/null +++ b/test/command_callback/test_pyre_command_callback.vader @@ -0,0 +1,39 @@ +Before: + call ale#assert#SetUpLinterTest('python', 'pyre') + let b:bin_dir = has('win32') ? 'Scripts' : 'bin' + +After: + unlet! b:bin_dir + unlet! b:executable + call ale#assert#TearDownLinterTest() + +Execute(The pyre command callback should return default string): + AssertLinter 'pyre', ale#Escape('pyre') . ' persistent' + +Execute(The pyre executable should be configurable): + let g:ale_python_pyre_executable = '~/.local/bin/pyre' + + AssertLinter '~/.local/bin/pyre', + \ ale#Escape('~/.local/bin/pyre') . ' persistent' + +Execute(The pyre executable should be run from the virtualenv path): + call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py') + + let b:executable = ale#path#Simplify( + \ g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/pyre' + \) + + AssertLinter b:executable, ale#Escape(b:executable) . ' persistent' + +Execute(You should be able to override the pyre virtualenv lookup): + call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py') + + let g:ale_python_pyre_use_global = 1 + + AssertLinter 'pyre', ale#Escape('pyre') . ' persistent' + +Execute(Setting executable to 'pipenv' appends 'run pyre'): + let g:ale_python_pyre_executable = 'path/to/pipenv' + + AssertLinter 'path/to/pipenv', + \ ale#Escape('path/to/pipenv') . ' run pyre persistent' diff --git a/test/command_callback/test_pyrex_cython_command_callback.vader b/test/command_callback/test_pyrex_cython_command_callback.vader new file mode 100644 index 00000000..b9020f11 --- /dev/null +++ b/test/command_callback/test_pyrex_cython_command_callback.vader @@ -0,0 +1,30 @@ +Before: + call ale#assert#SetUpLinterTest('pyrex', 'cython') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default cython command should be correct): + AssertLinter 'cython', ale#Escape('cython') + \ . ' --working ' . ale#Escape(g:dir) + \ . ' --include-dir ' . ale#Escape(g:dir) + \ . ' --warning-extra' + \ . ' --output-file ' . g:ale#util#nul_file . ' %t' + +Execute(The cython executable should be configurable): + let b:ale_pyrex_cython_executable = 'cython_foobar' + + AssertLinter 'cython_foobar', ale#Escape('cython_foobar') + \ . ' --working ' . ale#Escape(g:dir) + \ . ' --include-dir ' . ale#Escape(g:dir) + \ . ' --warning-extra' + \ . ' --output-file ' . g:ale#util#nul_file . ' %t' + +Execute(Additional cython options should be configurable): + let b:ale_pyrex_cython_options = '--foobar' + + AssertLinter 'cython', ale#Escape('cython') + \ . ' --working ' . ale#Escape(g:dir) + \ . ' --include-dir ' . ale#Escape(g:dir) + \ . ' --foobar' + \ . ' --output-file ' . g:ale#util#nul_file . ' %t' diff --git a/test/command_callback/test_qmlfmt_command_callback.vader b/test/command_callback/test_qmlfmt_command_callback.vader new file mode 100644 index 00000000..53502f4d --- /dev/null +++ b/test/command_callback/test_qmlfmt_command_callback.vader @@ -0,0 +1,13 @@ +Before: + call ale#assert#SetUpLinterTest('qml', 'qmlfmt') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The qml qmlfmt command callback should return the correct default string): + AssertLinter 'qmlfmt', ale#Escape('qmlfmt') . ' -e', + +Execute(The qmlfmt executable should be configurable): + let g:ale_qml_qmlfmt_executable = '~/.local/bin/qmlfmt' + + AssertLinter '~/.local/bin/qmlfmt', ale#Escape('~/.local/bin/qmlfmt') . ' -e' diff --git a/test/command_callback/test_rails_best_practices_command_callback.vader b/test/command_callback/test_rails_best_practices_command_callback.vader index b4d2e82d..bc7c8e85 100644 --- a/test/command_callback/test_rails_best_practices_command_callback.vader +++ b/test/command_callback/test_rails_best_practices_command_callback.vader @@ -1,10 +1,5 @@ Before: - Save g:ale_ruby_rails_best_practices_executable - - let g:ale_ruby_rails_best_practices_executable = 'rails_best_practices' - - runtime ale_linters/ruby/rails_best_practices.vim - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('ruby', 'rails_best_practices') call ale#test#SetFilename('../ruby_fixtures/valid_rails_app/db/test.rb') let b:args = '--silent -f json' @@ -13,45 +8,35 @@ Before: let b:suffix = has('win32') ? '; type %t' : '' After: - Restore - unlet! b:args unlet! b:app_path unlet! b:suffix - - call ale#test#RestoreDirectory() + call ale#assert#TearDownLinterTest() Execute(Executable should default to rails_best_practices): - AssertEqual - \ ale#Escape('rails_best_practices') + AssertLinter 'rails_best_practices', ale#Escape('rails_best_practices') \ . ' ' . b:args \ . ' ' . ale#Escape(b:app_path) - \ . b:suffix, - \ ale_linters#ruby#rails_best_practices#GetCommand(bufnr('')) + \ . b:suffix Execute(Should be able to set a custom executable): let g:ale_ruby_rails_best_practices_executable = 'bin/rails_best_practices' - AssertEqual - \ ale#Escape('bin/rails_best_practices') + AssertLinter 'bin/rails_best_practices', ale#Escape('bin/rails_best_practices') \ . ' ' . b:args \ . ' ' . ale#Escape(b:app_path) - \ . b:suffix, - \ ale_linters#ruby#rails_best_practices#GetCommand(bufnr('')) + \ . b:suffix Execute(Setting bundle appends 'exec rails_best_practices'): let g:ale_ruby_rails_best_practices_executable = 'path to/bundle' - AssertEqual - \ ale#Escape('path to/bundle') . ' exec rails_best_practices' + AssertLinter 'path to/bundle', ale#Escape('path to/bundle') + \ . ' exec rails_best_practices' \ . ' ' . b:args \ . ' ' . ale#Escape(b:app_path) - \ . b:suffix, - \ ale_linters#ruby#rails_best_practices#GetCommand(bufnr('')) + \ . b:suffix Execute(Command callback should be empty when not in a valid Rails app): call ale#test#SetFilename('../ruby_fixtures/not_a_rails_app/test.rb') - AssertEqual - \ '', - \ ale_linters#ruby#rails_best_practices#GetCommand(bufnr('')) + AssertLinter 'rails_best_practices', '' diff --git a/test/command_callback/test_reason_ols_callbacks.vader b/test/command_callback/test_reason_ols_callbacks.vader index 5fb39afe..53ef7fab 100644 --- a/test/command_callback/test_reason_ols_callbacks.vader +++ b/test/command_callback/test_reason_ols_callbacks.vader @@ -1,54 +1,41 @@ Before: - Save &filetype - Save g:ale_reason_ols_executable - Save g:ale_reason_ols_use_global + call ale#assert#SetUpLinterTest('reason', 'ols') + Save &filetype let &filetype = 'reason' - unlet! g:ale_reason_ols_executable - unlet! g:ale_reason_ols_use_global - - runtime ale_linters/reason/ols.vim - - call ale#test#SetDirectory('/testplugin/test/command_callback') After: - Restore - - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The language string should be correct): - AssertEqual 'reason', ale#handlers#ols#GetLanguage(bufnr('')) + AssertLSPLanguage 'reason' Execute(The default executable should be correct): - AssertEqual 'ocaml-language-server', ale#handlers#ols#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('ocaml-language-server') . ' --stdio', - \ ale#handlers#ols#GetCommand(bufnr('')) + AssertLinter 'ocaml-language-server', + \ ale#Escape('ocaml-language-server') . ' --stdio' Execute(The project root should be detected correctly): - AssertEqual '', ale#handlers#ols#GetProjectRoot(bufnr('')) + AssertLSPProject '' call ale#test#SetFilename('ols_paths/file.re') - AssertEqual - \ ale#path#Simplify(g:dir . '/ols_paths'), - \ ale#handlers#ols#GetProjectRoot(bufnr('')) + AssertLSPProject ale#path#Simplify(g:dir . '/ols_paths') Execute(The local executable should be used when available): call ale#test#SetFilename('ols_paths/file.re') - AssertEqual + AssertLinter \ ale#path#Simplify(g:dir . '/ols_paths/node_modules/.bin/ocaml-language-server'), - \ ale#handlers#ols#GetExecutable(bufnr('')) + \ ale#Escape(ale#path#Simplify(g:dir . '/ols_paths/node_modules/.bin/ocaml-language-server')) . ' --stdio' Execute(The gloabl executable should always be used when use_global is set): let g:ale_reason_ols_use_global = 1 call ale#test#SetFilename('ols_paths/file.re') - AssertEqual 'ocaml-language-server', ale#handlers#ols#GetExecutable(bufnr('')) + AssertLinter 'ocaml-language-server', + \ ale#Escape('ocaml-language-server') . ' --stdio' Execute(The executable should be configurable): let g:ale_reason_ols_executable = 'foobar' - AssertEqual 'foobar', ale#handlers#ols#GetExecutable(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . ' --stdio' diff --git a/test/command_callback/test_reek_command_callback.vader b/test/command_callback/test_reek_command_callback.vader new file mode 100644 index 00000000..059e5e36 --- /dev/null +++ b/test/command_callback/test_reek_command_callback.vader @@ -0,0 +1,34 @@ +Before: + call ale#assert#SetUpLinterTest('ruby', 'reek') + +After: + call ale#assert#TearDownLinterTest() + +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', + \] + + " Try with older versions. + call ale#semver#ResetVersionCache() + + WithChainResults ['reek 4.8.2'] + AssertLinter 'reek', [ + \ 'reek --version', + \ 'reek -f json --no-progress --no-color', + \] + +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', + \] + + WithChainResults [] + AssertLinter 'reek', [ + \ '', + \ 'reek -f json --no-progress --no-color --stdin-filename %s', + \] diff --git a/test/command_callback/test_remark_lint_command_callbacks.vader b/test/command_callback/test_remark_lint_command_callbacks.vader new file mode 100644 index 00000000..f3ab7550 --- /dev/null +++ b/test/command_callback/test_remark_lint_command_callbacks.vader @@ -0,0 +1,37 @@ +Before: + " This is just one language for the linter. + call ale#assert#SetUpLinterTest('markdown', 'remark_lint') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'remark', + \ ale#Escape('remark') . ' --no-stdout --no-color' + +Execute(The executable should be configurable): + let b:ale_markdown_remark_lint_executable = 'foobar' + + AssertLinter 'foobar', + \ ale#Escape('foobar') . ' --no-stdout --no-color' + +Execute(The options should be configurable): + let b:ale_markdown_remark_lint_options = '--something' + + AssertLinter 'remark', + \ ale#Escape('remark') . ' --something --no-stdout --no-color' + +Execute(The local executable from .bin should be used if available): + call ale#test#SetFilename('remark_lint_paths/with_bin_path/foo.md') + + AssertLinter + \ ale#path#Simplify(g:dir . '/remark_lint_paths/with_bin_path/node_modules/.bin/remark'), + \ ale#Escape(ale#path#Simplify(g:dir . '/remark_lint_paths/with_bin_path/node_modules/.bin/remark')) + \ . ' --no-stdout --no-color' + +Execute(The global executable should be uesd if the option is set): + let b:ale_markdown_remark_lint_use_global = 1 + call ale#test#SetFilename('remark_lint_paths/with_bin_path/foo.md') + + AssertLinter 'remark', ale#Escape('remark') + \ . ' --no-stdout --no-color' diff --git a/test/command_callback/test_rubocop_command_callback.vader b/test/command_callback/test_rubocop_command_callback.vader index f0aa194f..7f42a8c0 100644 --- a/test/command_callback/test_rubocop_command_callback.vader +++ b/test/command_callback/test_rubocop_command_callback.vader @@ -1,39 +1,29 @@ Before: - Save g:ale_ruby_rubocop_executable + call ale#assert#SetUpLinterTest('ruby', 'rubocop') + call ale#test#SetFilename('dummy.rb') let g:ale_ruby_rubocop_executable = 'rubocop' - - runtime ale_linters/ruby/rubocop.vim - call ale#test#SetDirectory('/testplugin/test/command_callback') - call ale#test#SetFilename('dummy.rb') + let g:ale_ruby_rubocop_options = '' After: - Restore - - call ale#linter#Reset() - call ale#test#RestoreDirectory() + call ale#assert#TearDownLinterTest() Execute(Executable should default to rubocop): - AssertEqual - \ ale#Escape('rubocop') + AssertLinter 'rubocop', ale#Escape('rubocop') \ . ' --format json --force-exclusion --stdin ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb')), - \ ale_linters#ruby#rubocop#GetCommand(bufnr('')) + \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb')) Execute(Should be able to set a custom executable): let g:ale_ruby_rubocop_executable = 'bin/rubocop' - AssertEqual - \ ale#Escape('bin/rubocop') + AssertLinter 'bin/rubocop' , ale#Escape('bin/rubocop') \ . ' --format json --force-exclusion --stdin ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb')), - \ ale_linters#ruby#rubocop#GetCommand(bufnr('')) + \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb')) Execute(Setting bundle appends 'exec rubocop'): let g:ale_ruby_rubocop_executable = 'path to/bundle' - AssertEqual - \ ale#Escape('path to/bundle') . ' exec rubocop' + AssertLinter 'path to/bundle', ale#Escape('path to/bundle') + \ . ' exec rubocop' \ . ' --format json --force-exclusion --stdin ' - \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb')), - \ ale_linters#ruby#rubocop#GetCommand(bufnr('')) + \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb')) diff --git a/test/command_callback/test_ruby_command_callback.vader b/test/command_callback/test_ruby_command_callback.vader index 3813d56b..b6bac14f 100644 --- a/test/command_callback/test_ruby_command_callback.vader +++ b/test/command_callback/test_ruby_command_callback.vader @@ -1,25 +1,13 @@ Before: - Save g:ale_ruby_ruby_executable - - unlet! g:ale_ruby_ruby_executable - - runtime ale_linters/ruby/ruby.vim + call ale#assert#SetUpLinterTest('ruby', 'ruby') After: - Restore - - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The default command should be correct): - AssertEqual 'ruby', ale_linters#ruby#ruby#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('ruby') . ' -w -c -T1 %t', - \ ale_linters#ruby#ruby#GetCommand(bufnr('')) + AssertLinter 'ruby', ale#Escape('ruby') . ' -w -c -T1 %t' Execute(The executable should be configurable): let g:ale_ruby_ruby_executable = 'foobar' - AssertEqual 'foobar', ale_linters#ruby#ruby#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('foobar') . ' -w -c -T1 %t', - \ ale_linters#ruby#ruby#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . ' -w -c -T1 %t' diff --git a/test/command_callback/test_rust_rls_callbacks.vader b/test/command_callback/test_rust_rls_callbacks.vader index 693d6e9f..a710161d 100644 --- a/test/command_callback/test_rust_rls_callbacks.vader +++ b/test/command_callback/test_rust_rls_callbacks.vader @@ -1,41 +1,25 @@ Before: - Save g:ale_rust_rls_executable - Save g:ale_rust_rls_toolchain - - unlet! g:ale_rust_rls_executable - unlet! g:ale_rust_rls_toolchain - - runtime ale_linters/rust/rls.vim - - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('rust', 'rls') After: - Restore - - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The default executable path should be correct): - AssertEqual 'rls', ale_linters#rust#rls#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('rls') . ' +' . ale#Escape('nightly'), - \ ale_linters#rust#rls#GetCommand(bufnr('')) + AssertLinter 'rls', ale#Escape('rls') . ' +' . ale#Escape('nightly') Execute(The toolchain should be configurable): let g:ale_rust_rls_toolchain = 'stable' - AssertEqual - \ ale#Escape('rls') . ' +' . ale#Escape('stable'), - \ ale_linters#rust#rls#GetCommand(bufnr('')) + AssertLinter 'rls', ale#Escape('rls') . ' +' . ale#Escape('stable') + +Execute(The toolchain should be ommitted if not given): + let g:ale_rust_rls_toolchain = '' -Execute(The language string should be correct): - AssertEqual 'rust', ale_linters#rust#rls#GetLanguage(bufnr('')) + AssertLinter 'rls', ale#Escape('rls') Execute(The project root should be detected correctly): - AssertEqual '', ale_linters#rust#rls#GetProjectRoot(bufnr('')) + AssertLSPProject '' call ale#test#SetFilename('rust-rls-project/test.rs') - AssertEqual - \ ale#path#Simplify(g:dir . '/rust-rls-project'), - \ ale_linters#rust#rls#GetProjectRoot(bufnr('')) + AssertLSPProject ale#path#Simplify(g:dir . '/rust-rls-project') diff --git a/test/command_callback/test_rustc_command_callback.vader b/test/command_callback/test_rustc_command_callback.vader index fe46c9ad..f765e725 100644 --- a/test/command_callback/test_rustc_command_callback.vader +++ b/test/command_callback/test_rustc_command_callback.vader @@ -1,37 +1,21 @@ Before: - Save g:ale_rust_rustc_options - - unlet! g:ale_rust_rustc_options - - runtime ale_linters/rust/rustc.vim - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('rust', 'rustc') After: - Restore - - unlet! b:ale_rust_rustc_options - - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The default command should be correct): - AssertEqual - \ 'rustc --error-format=json -Z no-trans -', - \ ale_linters#rust#rustc#RustcCommand(bufnr('')) + AssertLinter 'rustc', 'rustc --error-format=json -Z no-codegen -' Execute(The options should be configurable): let b:ale_rust_rustc_options = '--foo' - AssertEqual - \ 'rustc --error-format=json --foo -', - \ ale_linters#rust#rustc#RustcCommand(bufnr('')) + AssertLinter 'rustc', 'rustc --error-format=json --foo -' Execute(Some default paths should be included when the project is a Cargo project): call ale#test#SetFilename('cargo_paths/test.rs') - AssertEqual - \ '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')) - \ . ' -', - \ ale_linters#rust#rustc#RustcCommand(bufnr('')) + \ . ' -' diff --git a/test/command_callback/test_sasslint_command_callback.vader b/test/command_callback/test_sasslint_command_callback.vader new file mode 100644 index 00000000..4d7cc4c7 --- /dev/null +++ b/test/command_callback/test_sasslint_command_callback.vader @@ -0,0 +1,11 @@ +Before: + call ale#assert#SetUpLinterTest('sass', 'sasslint') + call ale#test#SetFilename('test.sass') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default sasslint command should be correct): + AssertLinter 'sass-lint', + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape('sass-lint') . ' -v -q -f compact %t' diff --git a/test/command_callback/test_scalac_command_callback.vader b/test/command_callback/test_scalac_command_callback.vader new file mode 100644 index 00000000..ea5ae109 --- /dev/null +++ b/test/command_callback/test_scalac_command_callback.vader @@ -0,0 +1,13 @@ +Before: + call ale#assert#SetUpLinterTest('scala', 'scalac') + +After: + call ale#assert#TearDownLinterTest() + +Given scala(An empty Scala file): +Execute(The default executable and command should be correct): + AssertLinter 'scalac', ale#Escape('scalac') . ' -Ystop-after:parser %t' + +Given scala.sbt(An empty SBT file): +Execute(scalac should not be run for sbt files): + AssertLinterNotExecuted diff --git a/test/command_callback/test_scalastyle_command_callback.vader b/test/command_callback/test_scalastyle_command_callback.vader index 953d57b3..3c28f7a3 100644 --- a/test/command_callback/test_scalastyle_command_callback.vader +++ b/test/command_callback/test_scalastyle_command_callback.vader @@ -1,36 +1,34 @@ Before: - Save g:ale_scala_scalastyle_options - Save g:ale_scalastyle_config_loc - - unlet! g:ale_scala_scalastyle_options - unlet! g:ale_scalastyle_config_loc - - runtime ale_linters/scala/scalastyle.vim + call ale#assert#SetUpLinterTest('scala', 'scalastyle') After: - Restore - + unlet! g:ale_scalastyle_config_loc call ale#linter#Reset() Execute(Should return the correct default command): - AssertEqual - \ 'scalastyle %t', - \ ale_linters#scala#scalastyle#GetCommand(bufnr('')) + AssertLinter 'scalastyle', 'scalastyle %t' Execute(Should allow using a custom config file): + let b:ale_scala_scalastyle_config = '/dooper/config.xml' + + AssertLinter 'scalastyle', 'scalastyle' + \ . ' --config ' . ale#Escape('/dooper/config.xml') + \ . ' %t' + +Execute(Should support a legacy option for the scalastyle config): + unlet! g:ale_scala_scalastyle_config let g:ale_scalastyle_config_loc = '/dooper/config.xml' - AssertEqual - \ 'scalastyle' - \ . ' --config ' . ale#Escape('/dooper/config.xml') - \ . ' %t', - \ ale_linters#scala#scalastyle#GetCommand(bufnr('')) + call ale#linter#Reset() + runtime ale_linters/scala/scalastyle.vim + + AssertLinter 'scalastyle', 'scalastyle' + \ . ' --config ' . ale#Escape('/dooper/config.xml') + \ . ' %t' Execute(Should allow using custom options): - let g:ale_scala_scalastyle_options = '--warnings false --quiet true' + let b:ale_scala_scalastyle_options = '--warnings false --quiet true' - AssertEqual - \ 'scalastyle' + AssertLinter 'scalastyle', 'scalastyle' \ . ' --warnings false --quiet true' - \ . ' %t', - \ ale_linters#scala#scalastyle#GetCommand(bufnr('')) + \ . ' %t' diff --git a/test/command_callback/test_shellcheck_command_callback.vader b/test/command_callback/test_shellcheck_command_callback.vader index 68694b67..23684026 100644 --- a/test/command_callback/test_shellcheck_command_callback.vader +++ b/test/command_callback/test_shellcheck_command_callback.vader @@ -1,129 +1,95 @@ Before: - Save g:ale_sh_shellcheck_exclusions - Save g:ale_sh_shellcheck_executable - Save g:ale_sh_shellcheck_options - - unlet! g:ale_sh_shellcheck_exclusions - unlet! g:ale_sh_shellcheck_executable - unlet! g:ale_sh_shellcheck_options - - runtime ale_linters/sh/shellcheck.vim - - call ale#test#SetDirectory('/testplugin/test/command_callback') + 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:suffix = ' -f gcc -' After: - Restore - - unlet! b:ale_sh_shellcheck_exclusions - unlet! b:ale_sh_shellcheck_executable - unlet! b:ale_sh_shellcheck_options unlet! b:is_bash unlet! b:prefix - - call ale#test#RestoreDirectory() - - call ale#linter#Reset() + unlet! b:suffix + call ale#assert#TearDownLinterTest() Execute(The default shellcheck command should be correct): - AssertEqual - \ b:prefix . ale#Escape('shellcheck') . b:suffix, - \ ale_linters#sh#shellcheck#GetCommand(bufnr(''), []) + AssertLinter 'shellcheck', b:prefix . ale#Escape('shellcheck') . b:suffix Execute(The shellcheck command should accept options): let b:ale_sh_shellcheck_options = '--foobar' - AssertEqual - \ b:prefix . ale#Escape('shellcheck') . ' --foobar' . b:suffix, - \ ale_linters#sh#shellcheck#GetCommand(bufnr(''), []) + AssertLinter 'shellcheck', + \ b:prefix . ale#Escape('shellcheck') . ' --foobar' . b:suffix Execute(The shellcheck command should accept options and exclusions): let b:ale_sh_shellcheck_options = '--foobar' let b:ale_sh_shellcheck_exclusions = 'foo,bar' - AssertEqual - \ b:prefix . ale#Escape('shellcheck') . ' --foobar -e foo,bar' . b:suffix, - \ ale_linters#sh#shellcheck#GetCommand(bufnr(''), []) + AssertLinter 'shellcheck', + \ b:prefix . ale#Escape('shellcheck') . ' --foobar -e foo,bar' . b:suffix Execute(The shellcheck command should include the dialect): let b:is_bash = 1 - AssertEqual - \ b:prefix . ale#Escape('shellcheck') . ' -s bash' . b:suffix, - \ ale_linters#sh#shellcheck#GetCommand(bufnr(''), []) + AssertLinter 'shellcheck', + \ b:prefix . ale#Escape('shellcheck') . ' -s bash' . b:suffix Execute(The shellcheck command should include the dialect before options and exclusions): let b:is_bash = 1 let b:ale_sh_shellcheck_options = '--foobar' let b:ale_sh_shellcheck_exclusions = 'foo,bar' - AssertEqual - \ b:prefix - \ . ale#Escape('shellcheck') + AssertLinter 'shellcheck', b:prefix . ale#Escape('shellcheck') \ . ' -s bash --foobar -e foo,bar' - \ . b:suffix, - \ ale_linters#sh#shellcheck#GetCommand(bufnr(''), []) + \ . b:suffix -Execute(The VersionCheck function should return the --version command): - AssertEqual +Execute(The -x option should be added when the version is new enough): + AssertLinter 'shellcheck', [ \ ale#Escape('shellcheck') . ' --version', - \ ale_linters#sh#shellcheck#VersionCheck(bufnr('')) - - let g:ale_sh_shellcheck_executable = 'foobar' - - AssertEqual - \ ale#Escape('foobar') . ' --version', - \ ale_linters#sh#shellcheck#VersionCheck(bufnr('')) + \ b:prefix . ale#Escape('shellcheck') . b:suffix, + \] -Execute(The -x option should be added when the version is new enough): - AssertEqual + WithChainResults [ + \ 'ShellCheck - shell script analysis tool', + \ 'version: 0.4.4', + \ 'license: GNU General Public License, version 3', + \ 'website: http://www.shellcheck.net', + \] + AssertLinter 'shellcheck', [ + \ ale#Escape('shellcheck') . ' --version', \ b:prefix . ale#Escape('shellcheck') . ' -x' . b:suffix, - \ ale_linters#sh#shellcheck#GetCommand(bufnr(''), [ - \ 'ShellCheck - shell script analysis tool', - \ 'version: 0.4.4', - \ 'license: GNU General Public License, version 3', - \ 'website: http://www.shellcheck.net', - \ ]) + \] " We should cache the version check - AssertEqual + WithChainResults [] + AssertLinter 'shellcheck', [ + \ '', \ b:prefix . ale#Escape('shellcheck') . ' -x' . b:suffix, - \ ale_linters#sh#shellcheck#GetCommand(bufnr(''), []) - - AssertEqual '', ale_linters#sh#shellcheck#VersionCheck(bufnr('')) + \] -Execute(The version check shouldn't be run again for new versions): - call ale_linters#sh#shellcheck#GetCommand(bufnr(''), [ +Execute(The -x option should not be added when the version is too old): + WithChainResults [ \ 'ShellCheck - shell script analysis tool', - \ 'version: 0.4.4', + \ 'version: 0.3.9', \ 'license: GNU General Public License, version 3', \ 'website: http://www.shellcheck.net', - \]) - -Execute(The -x option should not be added when the version is too old): - AssertEqual - \ b:prefix . ale#Escape('shellcheck') . b:suffix, - \ ale_linters#sh#shellcheck#GetCommand(bufnr(''), [ - \ 'ShellCheck - shell script analysis tool', - \ 'version: 0.3.9', - \ 'license: GNU General Public License, version 3', - \ 'website: http://www.shellcheck.net', - \ ]) - - " We should cache the version check - AssertEqual + \] + AssertLinter 'shellcheck', [ + \ ale#Escape('shellcheck') . ' --version', \ b:prefix . ale#Escape('shellcheck') . b:suffix, - \ ale_linters#sh#shellcheck#GetCommand(bufnr(''), []) + \] Execute(The version check shouldn't be run again for old versions): - call ale_linters#sh#shellcheck#GetCommand(bufnr(''), [ + WithChainResults [ \ 'ShellCheck - shell script analysis tool', \ 'version: 0.3.9', \ 'license: GNU General Public License, version 3', \ 'website: http://www.shellcheck.net', - \]) - - AssertEqual '', ale_linters#sh#shellcheck#VersionCheck(bufnr('')) + \] + AssertLinter 'shellcheck', [ + \ ale#Escape('shellcheck') . ' --version', + \ b:prefix . ale#Escape('shellcheck') . b:suffix, + \] + AssertLinter 'shellcheck', [ + \ '', + \ b:prefix . ale#Escape('shellcheck') . b:suffix, + \] diff --git a/test/command_callback/test_slimlint_command_callback.vader b/test/command_callback/test_slimlint_command_callback.vader index 38588a1f..3522c2fa 100644 --- a/test/command_callback/test_slimlint_command_callback.vader +++ b/test/command_callback/test_slimlint_command_callback.vader @@ -1,39 +1,19 @@ Before: - runtime ale_linters/slim/slimlint.vim - + call ale#assert#SetUpLinterTest('slim', 'slimlint') let g:default_command = 'slim-lint %t' - call ale#test#SetDirectory('/testplugin/test/command_callback') - After: - Restore - - unlet! g:default_command - unlet! b:conf - - call ale#linter#Reset() - call ale#test#RestoreDirectory() + call ale#assert#TearDownLinterTest() Execute(The default command should be correct): - AssertEqual g:default_command, ale_linters#slim#slimlint#GetCommand(bufnr('')) + AssertLinter 'slim-lint', 'slim-lint %t' Execute(The command should have the .rubocop.yml prepended as an env var if one exists): call ale#test#SetFilename('../slimlint-test-files/subdir/file.slim') - let b:conf = ale#path#Simplify(g:dir . '/../slimlint-test-files/.rubocop.yml') - - if has('win32') - " Windows uses 'set var=... && command' - AssertEqual - \ 'set SLIM_LINT_RUBOCOP_CONF=' - \ . ale#Escape(b:conf) - \ . ' && ' . g:default_command, - \ ale_linters#slim#slimlint#GetCommand(bufnr('')) - else - " Unix uses 'var=... command' - AssertEqual - \ 'SLIM_LINT_RUBOCOP_CONF=' - \ . ale#Escape(b:conf) - \ . ' ' . g:default_command, - \ ale_linters#slim#slimlint#GetCommand(bufnr('')) - endif + AssertLinter 'slim-lint', + \ ale#Env( + \ 'SLIM_LINT_RUBOCOP_CONF', + \ ale#path#Simplify(g:dir . '/../slimlint-test-files/.rubocop.yml') + \ ) + \ . 'slim-lint %t' diff --git a/test/command_callback/test_standard_command_callback.vader b/test/command_callback/test_standard_command_callback.vader index 3dee2856..a47e2ec9 100644 --- a/test/command_callback/test_standard_command_callback.vader +++ b/test/command_callback/test_standard_command_callback.vader @@ -1,28 +1,10 @@ Before: - Save g:ale_javascript_standard_executable - Save g:ale_javascript_standard_use_global - Save g:ale_javascript_standard_options - - unlet! b:executable - unlet! g:ale_javascript_standard_executable - unlet! b:ale_javascript_standard_executable - unlet! g:ale_javascript_standard_use_global - unlet! g:ale_javascript_standard_options - - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('javascript', 'standard') call ale#test#SetFilename('testfile.js') - - runtime ale_linters/javascript/standard.vim - -After: - Restore - unlet! b:executable - call ale#test#SetFilename('test.txt') - - call ale#test#RestoreDirectory() - call ale#linter#Reset() +After: + call ale#assert#TearDownLinterTest() Execute(bin/cmd.js paths should be preferred): call ale#test#SetFilename('standard-test-files/with-cmd/testfile.js') @@ -32,15 +14,10 @@ Execute(bin/cmd.js paths should be preferred): \ . '/standard-test-files/with-cmd/node_modules/standard/bin/cmd.js' \) - AssertEqual - \ b:executable, - \ ale_linters#javascript#standard#GetExecutable(bufnr('')) - - AssertEqual + AssertLinter b:executable, \ (has('win32') ? 'node.exe ' : '') \ . ale#Escape(b:executable) - \ . ' --stdin %s', - \ ale_linters#javascript#standard#GetCommand(bufnr('')) + \ . ' --stdin %s' Execute(.bin directories should be used too): call ale#test#SetFilename('standard-test-files/with-bin/testfile.js') @@ -50,38 +27,17 @@ Execute(.bin directories should be used too): \ . '/standard-test-files/with-bin/node_modules/.bin/standard' \) - AssertEqual - \ b:executable, - \ ale_linters#javascript#standard#GetExecutable(bufnr('')) - - AssertEqual - \ ale#Escape(b:executable) - \ . ' --stdin %s', - \ ale_linters#javascript#standard#GetCommand(bufnr('')) + AssertLinter b:executable, ale#Escape(b:executable) . ' --stdin %s' Execute(The global executable should be used otherwise): - AssertEqual - \ 'standard', - \ ale_linters#javascript#standard#GetExecutable(bufnr('')) - - AssertEqual - \ ale#Escape('standard') . ' --stdin %s', - \ ale_linters#javascript#standard#GetCommand(bufnr('')) + AssertLinter 'standard', ale#Escape('standard') . ' --stdin %s' Execute(The global executable should be configurable): let b:ale_javascript_standard_executable = 'foobar' - AssertEqual - \ 'foobar', - \ ale_linters#javascript#standard#GetExecutable(bufnr('')) - - AssertEqual - \ ale#Escape('foobar') . ' --stdin %s', - \ ale_linters#javascript#standard#GetCommand(bufnr('')) + AssertLinter 'foobar', ale#Escape('foobar') . ' --stdin %s' Execute(The options should be configurable): let b:ale_javascript_standard_options = '--wat' - AssertEqual - \ ale#Escape('standard') . ' --wat --stdin %s', - \ ale_linters#javascript#standard#GetCommand(bufnr('')) + AssertLinter 'standard', ale#Escape('standard') . ' --wat --stdin %s' diff --git a/test/command_callback/test_staticcheck_command_callback.vader b/test/command_callback/test_staticcheck_command_callback.vader new file mode 100644 index 00000000..918c12a0 --- /dev/null +++ b/test/command_callback/test_staticcheck_command_callback.vader @@ -0,0 +1,26 @@ +Before: + call ale#assert#SetUpLinterTest('go', 'staticcheck') + call ale#test#SetFilename('test.go') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The staticcheck callback should return the right defaults): + AssertLinter 'staticcheck', + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . 'staticcheck ' + \ . ale#Escape(expand('%' . ':t')) + +Execute(The staticcheck callback should use configured options): + let b:ale_go_staticcheck_options = '-test' + + AssertLinter 'staticcheck', + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . 'staticcheck ' + \ . '-test ' . ale#Escape(expand('%' . ':t')) + +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 .', diff --git a/test/command_callback/test_swaglint_command_callback.vader b/test/command_callback/test_swaglint_command_callback.vader index 51a10094..68fb1406 100644 --- a/test/command_callback/test_swaglint_command_callback.vader +++ b/test/command_callback/test_swaglint_command_callback.vader @@ -1,43 +1,29 @@ Before: - runtime ale_linters/yaml/swaglint.vim - - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('yaml', 'swaglint') After: - let g:ale_yaml_swaglint_executable = 'swaglint' - let g:ale_yaml_swaglint_use_global = 0 - - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The yaml swaglint command callback should return the correct default string): - AssertEqual 'swaglint', - \ ale_linters#yaml#swaglint#GetExecutable(bufnr('')) - AssertEqual 'swaglint -r compact --stdin', - \ ale_linters#yaml#swaglint#GetCommand(bufnr('')) + 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' - AssertEqual '~/.local/bin/swaglint', - \ ale_linters#yaml#swaglint#GetExecutable(bufnr('')) - AssertEqual '~/.local/bin/swaglint -r compact --stdin', - \ ale_linters#yaml#swaglint#GetCommand(bufnr('')) + + AssertLinter '~/.local/bin/swaglint', + \ 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 - AssertEqual '/usr/local/bin/swaglint', - \ ale_linters#yaml#swaglint#GetExecutable(bufnr('')) - AssertEqual '/usr/local/bin/swaglint -r compact --stdin', - \ ale_linters#yaml#swaglint#GetCommand(bufnr('')) + + AssertLinter '/usr/local/bin/swaglint', + \ 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') - AssertEqual + AssertLinter \ ale#path#Simplify(g:dir . '/swaglint_paths/node_modules/.bin/swaglint'), - \ ale_linters#yaml#swaglint#GetExecutable(bufnr('')) - - AssertEqual - \ ale#path#Simplify(g:dir . '/swaglint_paths/node_modules/.bin/swaglint') - \ . ' -r compact --stdin', - \ ale_linters#yaml#swaglint#GetCommand(bufnr('')) + \ 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 a4ae56b0..0cef0176 100644 --- a/test/command_callback/test_terraform_tflint_command_callback.vader +++ b/test/command_callback/test_terraform_tflint_command_callback.vader @@ -1,30 +1,28 @@ Before: - Save g:ale_terraform_tflint_executable - Save g:ale_terraform_tflint_options - - runtime ale_linters/terraform/tflint.vim + call ale#assert#SetUpLinterTest('terraform', 'tflint') After: - Restore + call ale#assert#TearDownLinterTest() - call ale#linter#Reset() +Execute(The default command should be correct): + AssertLinter 'tflint', ale#Escape('tflint') . ' -f json %t' Execute(The default executable should be configurable): - AssertEqual 'tflint', ale_linters#terraform#tflint#GetExecutable(bufnr('')) - - let g:ale_terraform_tflint_executable = 'asdf' - - AssertEqual 'asdf', ale_linters#terraform#tflint#GetExecutable(bufnr('')) + let b:ale_terraform_tflint_executable = 'asdf' -Execute(The default command should be good): - let g:ale_terraform_tflint_executable = 'tflint' - AssertEqual - \ ale#Escape('tflint') . ' -f json %t', - \ ale_linters#terraform#tflint#GetCommand(bufnr('')) + AssertLinter 'asdf', ale#Escape('asdf') . ' -f json %t' -Execute(Overriding things should work): +Execute(Overriding options should work): let g:ale_terraform_tflint_executable = 'fnord' let g:ale_terraform_tflint_options = '--whatever' - AssertEqual - \ ale#Escape('fnord') . ' --whatever -f json %t', - \ ale_linters#terraform#tflint#GetCommand(bufnr('')) + + 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_textlint_command_callbacks.vader b/test/command_callback/test_textlint_command_callbacks.vader new file mode 100644 index 00000000..794c7fde --- /dev/null +++ b/test/command_callback/test_textlint_command_callbacks.vader @@ -0,0 +1,65 @@ +" Author: januswel, w0rp + +Before: + " This is just one language for the linter. + call ale#assert#SetUpLinterTest('markdown', 'textlint') + + " The configuration is shared between many languages. + Save g:ale_textlint_executable + Save g:ale_textlint_use_global + Save g:ale_textlint_options + + let g:ale_textlint_executable = 'textlint' + let g:ale_textlint_use_global = 0 + let g:ale_textlint_options = '' + + unlet! b:ale_textlint_executable + unlet! b:ale_textlint_use_global + unlet! b:ale_textlint_options + +After: + unlet! b:command_tail + unlet! b:ale_textlint_executable + unlet! b:ale_textlint_use_global + unlet! b:ale_textlint_options + + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'textlint', + \ ale#Escape('textlint') . ' -f json --stdin --stdin-filename %s' + +Execute(The executable should be configurable): + let b:ale_textlint_executable = 'foobar' + + AssertLinter 'foobar', + \ ale#Escape('foobar') . ' -f json --stdin --stdin-filename %s' + +Execute(The options should be configurable): + let b:ale_textlint_options = '--something' + + AssertLinter 'textlint', + \ ale#Escape('textlint') . ' --something -f json --stdin --stdin-filename %s' + +Execute(The local executable from .bin should be used if available): + call ale#test#SetFilename('textlint_paths/with_bin_path/foo.txt') + + AssertLinter + \ ale#path#Simplify(g:dir . '/textlint_paths/with_bin_path/node_modules/.bin/textlint'), + \ ale#Escape(ale#path#Simplify(g:dir . '/textlint_paths/with_bin_path/node_modules/.bin/textlint')) + \ . ' -f json --stdin --stdin-filename %s' + +Execute(The local executable from textlint/bin should be used if available): + call ale#test#SetFilename('textlint_paths/with_textlint_bin_path/foo.txt') + + if has('win32') + AssertLinter + \ ale#path#Simplify(g:dir . '/textlint_paths/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'), + \ ale#Escape('node.exe') . ' ' . ale#Escape(ale#path#Simplify(g:dir . '/textlint_paths/with_textlint_bin_path/node_modules/textlint/bin/textlint.js')) + \ . ' -f json --stdin --stdin-filename %s' + else + AssertLinter + \ ale#path#Simplify(g:dir . '/textlint_paths/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'), + \ ale#Escape(ale#path#Simplify(g:dir . '/textlint_paths/with_textlint_bin_path/node_modules/textlint/bin/textlint.js')) + \ . ' -f json --stdin --stdin-filename %s' + endif diff --git a/test/command_callback/test_thrift_command_callback.vader b/test/command_callback/test_thrift_command_callback.vader index 7d4e436c..ea217259 100644 --- a/test/command_callback/test_thrift_command_callback.vader +++ b/test/command_callback/test_thrift_command_callback.vader @@ -1,13 +1,6 @@ Before: - Save g:ale_thrift_thrift_executable - Save g:ale_thrift_thrift_generators - Save g:ale_thrift_thrift_includes - Save g:ale_thrift_thrift_options - - unlet! b:ale_thrift_thrift_executable - unlet! b:ale_thrift_thrift_generators - unlet! b:ale_thrift_thrift_includes - unlet! b:ale_thrift_thrift_options + call ale#assert#SetUpLinterTest('thrift', 'thrift') + let b:suffix = ' -out ' . ale#Escape('TEMP_DIR') . ' %t' function! GetCommand(buffer) abort call ale#engine#InitBufferInfo(a:buffer) @@ -24,62 +17,37 @@ Before: return join(l:split_command) endfunction - runtime ale_linters/thrift/thrift.vim - After: - Restore - + unlet! b:suffix delfunction GetCommand - unlet! b:ale_thrift_thrift_executable - unlet! b:ale_thrift_thrift_generators - unlet! b:ale_thrift_thrift_includes - unlet! b:ale_thrift_thrift_options - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() -Execute(The executable should be configurable): - AssertEqual 'thrift', ale_linters#thrift#thrift#GetExecutable(bufnr('')) +Execute(The default command should be correct): + AssertLinter 'thrift', ale#Escape('thrift') . ' --gen cpp -strict' . b:suffix +Execute(The executable should be configurable): let b:ale_thrift_thrift_executable = 'foobar' - AssertEqual 'foobar', ale_linters#thrift#thrift#GetExecutable(bufnr('')) - -Execute(The executable should be used in the command): - AssertEqual - \ ale#Escape('thrift') . ' --gen cpp -strict -out TEMP %t', - \ GetCommand(bufnr('%')) - let b:ale_thrift_thrift_executable = 'foobar' - AssertEqual - \ ale#Escape('foobar') . ' --gen cpp -strict -out TEMP %t', - \ GetCommand(bufnr('%')) + AssertLinter 'foobar', ale#Escape('foobar') . ' --gen cpp -strict' . b:suffix Execute(The list of generators should be configurable): let b:ale_thrift_thrift_generators = ['java', 'py:dynamic'] - AssertEqual - \ ale#Escape('thrift') . ' --gen java --gen py:dynamic -strict -out TEMP %t', - \ GetCommand(bufnr('%')) + AssertLinter 'thrift', ale#Escape('thrift') + \ . ' --gen java --gen py:dynamic -strict' . b:suffix let b:ale_thrift_thrift_generators = [] - AssertEqual - \ ale#Escape('thrift') . ' --gen cpp -strict -out TEMP %t', - \ GetCommand(bufnr('%')) + AssertLinter 'thrift', ale#Escape('thrift') . ' --gen cpp -strict' . b:suffix Execute(The list of include paths should be configurable): let b:ale_thrift_thrift_includes = ['included/path'] - AssertEqual - \ ale#Escape('thrift') - \ . ' --gen cpp' - \ . ' -I included/path' - \ . ' -strict -out TEMP %t', - \ GetCommand(bufnr('%')) + AssertLinter 'thrift', ale#Escape('thrift') + \ . ' --gen cpp -I included/path -strict' . b:suffix Execute(The string of compiler options should be configurable): let b:ale_thrift_thrift_options = '-strict --allow-64bit-consts' - AssertEqual - \ ale#Escape('thrift') - \ . ' --gen cpp -strict --allow-64bit-consts' - \ . ' -out TEMP %t', - \ GetCommand(bufnr('%')) + AssertLinter 'thrift', ale#Escape('thrift') + \ . ' --gen cpp -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 4ad42fa5..bd8a12ec 100644 --- a/test/command_callback/test_tslint_command_callback.vader +++ b/test/command_callback/test_tslint_command_callback.vader @@ -1,39 +1,27 @@ Before: - Save g:ale_typescript_tslint_executable - Save g:ale_typescript_tslint_config_path - Save g:ale_typescript_tslint_rules_dir - Save g:ale_typescript_tslint_use_global - - unlet! g:ale_typescript_tslint_executable - unlet! g:ale_typescript_tslint_config_path - unlet! g:ale_typescript_tslint_rules_dir - unlet! g:ale_typescript_tslint_use_global - - runtime ale_linters/typescript/tslint.vim - - call ale#test#SetDirectory('/testplugin/test/command_callback') + call ale#assert#SetUpLinterTest('typescript', 'tslint') call ale#test#SetFilename('test.ts') After: - Restore - - unlet! b:ale_typescript_tslint_rules_dir - - call ale#test#RestoreDirectory() - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The default tslint command should be correct): - AssertEqual + AssertLinter 'tslint', \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' - \ . 'tslint --format json %t', - \ ale_linters#typescript#tslint#GetCommand(bufnr('')) + \ . ale#Escape('tslint') . ' --format json %t' Execute(The rules directory option should be included if set): let b:ale_typescript_tslint_rules_dir = '/foo/bar' - AssertEqual + AssertLinter 'tslint', \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' - \ . 'tslint --format json' + \ . ale#Escape('tslint') . ' --format json' \ . ' -r ' . ale#Escape('/foo/bar') - \ . ' %t', - \ ale_linters#typescript#tslint#GetCommand(bufnr('')) + \ . ' %t' + +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#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_vint_command_callback.vader b/test/command_callback/test_vint_command_callback.vader new file mode 100644 index 00000000..e0051f26 --- /dev/null +++ b/test/command_callback/test_vint_command_callback.vader @@ -0,0 +1,23 @@ +Before: + call ale#assert#SetUpLinterTest('vim', 'vint') + let b:command_tail = (has('nvim') ? ' --enable-neovim' : '') + \ . ' -f "{file_path}:{line_number}:{column_number}: {severity}: {description} (see {reference})" %t' + +After: + unlet! b:bin_dir + unlet! b:executable + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'vint', [ + \ ale#Escape('vint') .' --version', + \ ale#Escape('vint') .' -s --no-color' . b:command_tail, + \] + +Execute(The executable should be configurable): + let g:ale_vim_vint_executable = 'foobar' + + AssertLinter 'foobar', [ + \ ale#Escape('foobar') .' --version', + \ ale#Escape('foobar') .' -s --no-color' . b:command_tail, + \] diff --git a/test/command_callback/test_write_good_command_callback.vader b/test/command_callback/test_write_good_command_callback.vader index 8d9e9a00..9ffa39bd 100644 --- a/test/command_callback/test_write_good_command_callback.vader +++ b/test/command_callback/test_write_good_command_callback.vader @@ -1,4 +1,8 @@ Before: + " This is just one example of a language using the linter. + call ale#assert#SetUpLinterTest('markdown', 'writegood') + + " The options are shared between many languages. Save g:ale_writegood_options Save g:ale_writegood_executable Save g:ale_writegood_use_global @@ -7,51 +11,40 @@ Before: unlet! g:ale_writegood_executable unlet! g:ale_writegood_use_global - call ale#test#SetDirectory('/testplugin/test/command_callback') call ale#test#SetFilename('testfile.txt') - call ale#handlers#writegood#ResetOptions() After: - Restore - - call ale#test#RestoreDirectory() + call ale#assert#TearDownLinterTest() Execute(The global executable should be used when the local one cannot be found): - AssertEqual 'write-good', ale#handlers#writegood#GetExecutable(bufnr('')) - AssertEqual + AssertLinter + \ 'write-good', \ ale#Escape('write-good') . ' %t', - \ ale#handlers#writegood#GetCommand(bufnr('')) Execute(The options should be used in the command): let g:ale_writegood_options = '--foo --bar' - AssertEqual + AssertLinter + \ 'write-good', \ ale#Escape('write-good') . ' --foo --bar %t', - \ ale#handlers#writegood#GetCommand(bufnr('')) Execute(Should use the node_modules/.bin executable, if available): call ale#test#SetFilename('write-good-node-modules/test.txt') - AssertEqual + AssertLinter \ ale#path#Simplify(g:dir . '/write-good-node-modules/node_modules/.bin/write-good'), - \ ale#handlers#writegood#GetExecutable(bufnr('')) - AssertEqual \ ale#Escape(ale#path#Simplify(g:dir . '/write-good-node-modules/node_modules/.bin/write-good')) \ . ' %t', - \ ale#handlers#writegood#GetCommand(bufnr('')) Execute(Should use the node_modules/write-good executable, if available): call ale#test#SetFilename('write-good-node-modules-2/test.txt') - AssertEqual + AssertLinter \ ale#path#Simplify(g:dir . '/write-good-node-modules-2/node_modules/write-good/bin/write-good.js'), - \ ale#handlers#writegood#GetExecutable(bufnr('')) - AssertEqual \ (has('win32') ? 'node.exe ' : '') \ . ale#Escape(ale#path#Simplify(g:dir . '/write-good-node-modules-2/node_modules/write-good/bin/write-good.js')) \ . ' %t', - \ ale#handlers#writegood#GetCommand(bufnr('')) Execute(Should let users configure a global executable and override local paths): call ale#test#SetFilename('write-good-node-modules-2/test.txt') @@ -59,7 +52,4 @@ Execute(Should let users configure a global executable and override local paths) let g:ale_writegood_executable = 'foo-bar' let g:ale_writegood_use_global = 1 - AssertEqual 'foo-bar', ale#handlers#writegood#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('foo-bar') . ' %t', - \ ale#handlers#writegood#GetCommand(bufnr('')) + AssertLinter 'foo-bar', ale#Escape('foo-bar') . ' %t' diff --git a/test/command_callback/test_xmllint_command_callback.vader b/test/command_callback/test_xmllint_command_callback.vader index 12ca15de..5a2377c2 100644 --- a/test/command_callback/test_xmllint_command_callback.vader +++ b/test/command_callback/test_xmllint_command_callback.vader @@ -1,25 +1,20 @@ Before: - runtime ale_linters/xml/xmllint.vim + call ale#assert#SetUpLinterTest('xml', 'xmllint') After: - let g:ale_xml_xmllint_options = '' - let g:ale_xml_xmllint_executable = 'xmllint' - - call ale#linter#Reset() + call ale#assert#TearDownLinterTest() Execute(The xml xmllint command callback should return the correct default string): - AssertEqual ale#Escape('xmllint') . ' --noout -', - \ join(split(ale_linters#xml#xmllint#GetCommand(1))) + AssertLinter 'xmllint', ale#Escape('xmllint') . ' --noout -' Execute(The xml xmllint command callback should let you set options): let g:ale_xml_xmllint_options = '--xinclude --postvalid' - AssertEqual ale#Escape('xmllint') . ' --xinclude --postvalid --noout -', - \ join(split(ale_linters#xml#xmllint#GetCommand(1))) + AssertLinter 'xmllint', + \ ale#Escape('xmllint') . ' --xinclude --postvalid --noout -' Execute(The xmllint executable should be configurable): let g:ale_xml_xmllint_executable = '~/.local/bin/xmllint' - AssertEqual '~/.local/bin/xmllint', ale_linters#xml#xmllint#GetExecutable(1) - AssertEqual ale#Escape('~/.local/bin/xmllint') . ' --noout -', - \ join(split(ale_linters#xml#xmllint#GetCommand(1))) + AssertLinter '~/.local/bin/xmllint', + \ ale#Escape('~/.local/bin/xmllint') . ' --noout -' 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/command_callback/textlint_paths/with_bin_path/node_modules/.bin/textlint b/test/command_callback/textlint_paths/with_bin_path/node_modules/.bin/textlint new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/textlint_paths/with_bin_path/node_modules/.bin/textlint diff --git a/test/command_callback/textlint_paths/with_textlint_bin_path/node_modules/textlint/bin/textlint.js b/test/command_callback/textlint_paths/with_textlint_bin_path/node_modules/textlint/bin/textlint.js new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/textlint_paths/with_textlint_bin_path/node_modules/textlint/bin/textlint.js diff --git a/test/command_callback/tidy_paths/.tidyrc b/test/command_callback/tidy_paths/.tidyrc new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/tidy_paths/.tidyrc diff --git a/test/command_callback/tidy_paths/test.html b/test/command_callback/tidy_paths/test.html new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/tidy_paths/test.html diff --git a/test/command_callback/tidy_paths/tidy b/test/command_callback/tidy_paths/tidy new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/tidy_paths/tidy diff --git a/test/command_callback/tidy_paths/tidy.exe b/test/command_callback/tidy_paths/tidy.exe new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/tidy_paths/tidy.exe diff --git a/test/completion/test_completion_events.vader b/test/completion/test_completion_events.vader index 49d485f6..3f0bfa70 100644 --- a/test/completion/test_completion_events.vader +++ b/test/completion/test_completion_events.vader @@ -2,20 +2,25 @@ Before: Save g:ale_completion_enabled Save g:ale_completion_delay Save g:ale_completion_max_suggestions - Save g:ale_completion_experimental_lsp_support Save &l:omnifunc Save &l:completeopt - unlet! g:ale_completion_experimental_lsp_support - let g:ale_completion_enabled = 1 let g:get_completions_called = 0 let g:feedkeys_calls = [] + let g:fake_mode = 'i' + + let &l:completeopt = 'menu,menuone,preview,noselect,noinsert' runtime autoload/ale/util.vim - function! ale#util#FeedKeys(string, mode) abort - call add(g:feedkeys_calls, [a:string, a:mode]) + function! ale#util#FeedKeys(string) abort + call add(g:feedkeys_calls, [a:string]) + endfunction + + " Pretend we're in insert mode for most tests. + function! ale#util#Mode(...) abort + return g:fake_mode endfunction function! CheckCompletionCalled(expect_success) abort @@ -27,8 +32,16 @@ Before: endfunction let g:ale_completion_delay = 0 - call ale#completion#Queue() - sleep 1m + + " Run this check a few times, as it can fail randomly. + for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1) + call ale#completion#Queue() + sleep 1m + + if g:get_completions_called is a:expect_success + break + endif + endfor AssertEqual a:expect_success, g:get_completions_called endfunction @@ -36,6 +49,8 @@ Before: After: Restore + unlet! g:output + unlet! g:fake_mode unlet! g:get_completions_called unlet! b:ale_old_omnifunc unlet! b:ale_old_completopt @@ -43,7 +58,6 @@ After: unlet! b:ale_completion_response unlet! b:ale_completion_parser unlet! b:ale_complete_done_time - unlet! g:ale_completion_experimental_lsp_support delfunction CheckCompletionCalled @@ -51,6 +65,12 @@ After: " This stops the tests from failing randomly. call ale#completion#StopTimer() + " Reset the function. The runtime command below should fix this, but doesn't + " seem to fix it. + function! ale#util#Mode(...) abort + return call('mode', a:000) + endfunction + runtime autoload/ale/completion.vim runtime autoload/ale/util.vim @@ -80,6 +100,22 @@ Execute(ale#completion#GetCompletions should not be called when the cursor posit Assert !g:get_completions_called +Execute(ale#completion#GetCompletions should not be called if you switch to normal mode): + let &l:completeopt = 'menu,preview' + let g:fake_mode = 'n' + + " We just want to check if the function is called. + function! ale#completion#GetCompletions() + let g:get_completions_called = 1 + endfunction + + let g:ale_completion_delay = 0 + call ale#completion#Queue() + + sleep 1m + + Assert !g:get_completions_called + Execute(Completion should not be done shortly after the CompleteDone function): call CheckCompletionCalled(1) call ale#completion#Done() @@ -93,26 +129,69 @@ 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' call ale#completion#Show('Response', 'Parser') 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' + + call ale#completion#Show('Response', 'Parser') + + 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' call ale#completion#OmniFunc(0, '') AssertEqual 'menu', b:ale_old_completopt + AssertEqual 'menu,menuone,noselect,noinsert', &l:completeopt + +Execute(ale#completion#OmniFunc() should set the preview option if it's set): + let &l:completeopt = 'menu,preview' + + call ale#completion#OmniFunc(0, '') + + AssertEqual 'menu,preview', b:ale_old_completopt AssertEqual 'menu,menuone,preview,noselect,noinsert', &l:completeopt Execute(ale#completion#Show() should make the correct feedkeys() call): call ale#completion#Show('Response', 'Parser') - AssertEqual [["\<C-x>\<C-o>", 'n']], g:feedkeys_calls + 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): + let &l:completeopt = 'menu,preview' + let g:fake_mode = 'n' + + call ale#completion#Show('Response', 'Parser') + + AssertEqual 'menu,preview', &l:completeopt + Assert !exists('b:ale_old_omnifunc') + Assert !exists('b:ale_old_completopt') + Assert !exists('b:ale_completion_response') + Assert !exists('b:ale_completion_parser') + AssertEqual [], g:feedkeys_calls Execute(ale#completion#Show() should set up the response and parser): call ale#completion#Show('Response', 'Parser') @@ -131,7 +210,6 @@ Execute(ale#completion#Done() should restore old omnifunc values): Execute(ale#completion#Done() should restore the old completeopt setting): let b:ale_old_completopt = 'menu' - let &l:completeopt = 'menu,menuone,preview,noselect,noinsert' call ale#completion#Done() @@ -170,3 +248,28 @@ Execute(b:ale_completion_info should be set up correctly when requesting complet \ 'prefix': 'ab', \ }, \ b:ale_completion_info + +Execute(The correct keybinds should be configured): + redir => g:output + silent map <Plug>(ale_show_completion_menu) + redir END + + AssertEqual + \ [ + \ 'n <Plug>(ale_show_completion_menu) * :call ale#completion#RestoreCompletionOptions()<CR>', + \ 'o <Plug>(ale_show_completion_menu) * <Nop>', + \ 'v <Plug>(ale_show_completion_menu) * <Nop>', + \ ], + \ sort(split(g:output, "\n")) + +Execute(Running the normal mode <Plug> keybind should reset the settings): + let b:ale_old_omnifunc = 'FooBar' + let b:ale_old_completopt = 'menu' + + " We can't run the keybind, but we can call the function. + call ale#completion#RestoreCompletionOptions() + + AssertEqual 'FooBar', &l:omnifunc + AssertEqual 'menu', &l:completeopt + Assert !has_key(b:, 'ale_old_omnifunc') + Assert !has_key(b:, 'ale_old_completopt') diff --git a/test/completion/test_completion_filtering.vader b/test/completion/test_completion_filtering.vader index 3e461aef..ae91a952 100644 --- a/test/completion/test_completion_filtering.vader +++ b/test/completion/test_completion_filtering.vader @@ -1,15 +1,27 @@ +Before: + Save g:ale_completion_excluded_words + + let g:ale_completion_excluded_words = [] + +After: + Restore + + unlet! b:ale_completion_excluded_words + unlet! b:suggestions + Execute(Prefix filtering should work for Lists of strings): AssertEqual \ ['FooBar', 'foo'], - \ ale#completion#Filter(['FooBar', 'FongBar', 'baz', 'foo'], 'foo') + \ ale#completion#Filter(bufnr(''), ['FooBar', 'FongBar', 'baz', 'foo'], 'foo') AssertEqual \ ['FooBar', 'FongBar', 'baz', 'foo'], - \ ale#completion#Filter(['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'}, @@ -18,6 +30,7 @@ Execute(Prefix filtering should work for completion items): \ ], \ 'foo' \ ) + AssertEqual \ [ \ {'word': 'FooBar'}, @@ -26,6 +39,7 @@ Execute(Prefix filtering should work for completion items): \ {'word': 'foo'}, \ ], \ ale#completion#Filter( + \ bufnr(''), \ [ \ {'word': 'FooBar'}, \ {'word': 'FongBar'}, @@ -34,3 +48,61 @@ Execute(Prefix filtering should work for completion items): \ ], \ '.' \ ) + +Execute(Excluding words from completion results should work): + let b:ale_completion_excluded_words = ['it', 'describe'] + + AssertEqual + \ [{'word': 'Italian'}], + \ ale#completion#Filter( + \ bufnr(''), + \ [ + \ {'word': 'Italian'}, + \ {'word': 'it'}, + \ ], + \ 'it' + \ ) + + AssertEqual + \ [{'word': 'Deutsch'}], + \ ale#completion#Filter( + \ bufnr(''), + \ [ + \ {'word': 'describe'}, + \ {'word': 'Deutsch'}, + \ ], + \ 'de' + \ ) + + AssertEqual + \ [{'word': 'Deutsch'}], + \ ale#completion#Filter( + \ bufnr(''), + \ [ + \ {'word': 'describe'}, + \ {'word': 'Deutsch'}, + \ ], + \ '.' + \ ) + +Execute(Excluding words from completion results should work with lists of Strings): + let b:ale_completion_excluded_words = ['it', 'describe'] + + AssertEqual + \ ['Italian'], + \ ale#completion#Filter(bufnr(''), ['Italian', 'it'], 'it') + AssertEqual + \ ['Deutsch'], + \ ale#completion#Filter(bufnr(''), ['describe', 'Deutsch'], 'de') + AssertEqual + \ ['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 b:suggestions, [{'word': 'describe'}] + AssertEqual [], ale#completion#Filter(bufnr(''), b:suggestions, 'de') + AssertEqual b:suggestions, [{'word': 'describe'}] diff --git a/test/completion/test_completion_prefixes.vader b/test/completion/test_completion_prefixes.vader index 8ac29326..0b2cfeaf 100644 --- a/test/completion/test_completion_prefixes.vader +++ b/test/completion/test_completion_prefixes.vader @@ -2,6 +2,8 @@ Given typescript(): let abc = y. let foo = ab let foo = (ab) + let string1 = ' + let string2 = " Execute(Completion should be done after dots in TypeScript): AssertEqual '.', ale#completion#GetPrefix(&filetype, 1, 13) @@ -15,5 +17,29 @@ Execute(Completion should be done after words in parens in TypeScript): Execute(Completion should not be done after parens in TypeScript): AssertEqual '', ale#completion#GetPrefix(&filetype, 3, 15) +Execute(Completion should be done after strings in TypeScript): + AssertEqual '''', ale#completion#GetPrefix(&filetype, 4, 16) + AssertEqual '"', ale#completion#GetPrefix(&filetype, 5, 16) + +Execute(Completion prefixes should work for other filetypes): + AssertEqual 'ab', ale#completion#GetPrefix('xxxyyyzzz', 3, 14) + Execute(Completion prefixes should work for other filetypes): AssertEqual 'ab', ale#completion#GetPrefix('xxxyyyzzz', 3, 14) + +Given rust(): + let abc = y. + let abc = String:: + let foo = (ab) + +Execute(Completion should be done after dots in Rust): + AssertEqual '.', ale#completion#GetPrefix(&filetype, 1, 13) + +Execute(Completion should be done after colons in Rust): + AssertEqual '::', ale#completion#GetPrefix(&filetype, 2, 19) + +Execute(Completion should be done after words in parens in Rust): + AssertEqual 'ab', ale#completion#GetPrefix(&filetype, 3, 14) + +Execute(Completion should not be done after parens in Rust): + AssertEqual '', ale#completion#GetPrefix(&filetype, 3, 15) diff --git a/test/completion/test_lsp_completion_messages.vader b/test/completion/test_lsp_completion_messages.vader index f21acfb9..130f31b9 100644 --- a/test/completion/test_lsp_completion_messages.vader +++ b/test/completion/test_lsp_completion_messages.vader @@ -2,12 +2,9 @@ Before: Save g:ale_completion_delay Save g:ale_completion_max_suggestions Save g:ale_completion_info - Save g:ale_completion_experimental_lsp_support Save &l:omnifunc Save &l:completeopt - unlet! g:ale_completion_experimental_lsp_support - let g:ale_completion_enabled = 1 call ale#test#SetDirectory('/testplugin/test/completion') @@ -16,26 +13,55 @@ Before: runtime autoload/ale/lsp.vim let g:message_list = [] + let g:capability_checked = '' + let g:conn_id = v:null let g:Callback = '' + let g:wait_callback_list = [] - function! ale#linter#StartLSP(buffer, linter, callback) abort - let g:Callback = a:callback + 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 { - \ 'connection_id': 347, + \ 'buffer': a:buffer, + \ 'connection_id': g:conn_id, \ 'project_root': '/foo/bar', + \ 'language_id': 'python', \} endfunction + " Pretend we're in insert mode for most tests. + function! ale#util#Mode(...) abort + return 'i' + endfunction + + function! ale#lsp#WaitForCapability(conn_id, capability, callback) abort + let g:capability_checked = a:capability + call add(g:wait_callback_list, a:callback) + endfunction + + function! ale#lsp#RegisterCallback(conn_id, callback) abort + let g:Callback = a:callback + endfunction + " Replace the Send function for LSP, so we can monitor calls to it. - function! ale#lsp#Send(conn_id, message, ...) abort + function! ale#lsp#Send(conn_id, message) abort call add(g:message_list, a:message) + + return 1 endfunction After: Restore + if g:conn_id isnot v:null + call ale#lsp#RemoveConnectionWithID(g:conn_id) + endif + unlet! g:message_list + unlet! g:capability_checked + unlet! g:wait_callback_list + unlet! g:conn_id unlet! g:Callback unlet! b:ale_old_omnifunc unlet! b:ale_old_completopt @@ -44,7 +70,12 @@ After: unlet! b:ale_completion_parser unlet! b:ale_complete_done_time unlet! b:ale_linters - unlet! g:ale_completion_experimental_lsp_support + unlet! b:ale_tsserver_completion_names + + " Reset the function. + function! ale#util#Mode(...) abort + return call('mode', a:000) + endfunction call ale#test#RestoreDirectory() call ale#linter#Reset() @@ -55,6 +86,7 @@ After: runtime autoload/ale/completion.vim runtime autoload/ale/lsp.vim + runtime autoload/ale/lsp_linter.vim Given typescript(Some typescript file): foo @@ -69,6 +101,13 @@ Execute(The right message should be sent for the initial tsserver request): call ale#completion#GetCompletions() + " We shouldn't register the callback yet. + AssertEqual '''''', string(g:Callback) + + AssertEqual 1, len(g:wait_callback_list) + AssertEqual 'completion', g:capability_checked + call map(g:wait_callback_list, 'v:val([g:conn_id, ''/foo/bar''])') + " We should send the right callback. AssertEqual \ 'function(''ale#completion#HandleTSServerResponse'')', @@ -81,9 +120,9 @@ Execute(The right message should be sent for the initial tsserver request): AssertEqual \ { \ 'line_length': 3, - \ 'conn_id': 0, + \ 'conn_id': g:conn_id, \ 'column': 3, - \ 'request_id': 0, + \ 'request_id': 1, \ 'line': 1, \ 'prefix': 'fo', \ }, @@ -116,6 +155,12 @@ Execute(The right message sent to the tsserver LSP when the first completion mes \ ], \}) + " We should save the names we got in the buffer, as TSServer doesn't return + " details for every name. + AssertEqual + \ ['Foo', 'FooBar', 'frazzle'], + \ get(b:, 'ale_tsserver_completion_names', []) + " The entry details messages should have been sent. AssertEqual \ [[ @@ -136,8 +181,6 @@ Given python(Some Python file): bazxyzxyzxyz Execute(The right message should be sent for the initial LSP request): - let g:ale_completion_experimental_lsp_support = 1 - runtime ale_linters/python/pyls.vim let b:ale_linters = ['pyls'] " The cursor position needs to match what was saved before. @@ -145,6 +188,13 @@ Execute(The right message should be sent for the initial LSP request): call ale#completion#GetCompletions() + " We shouldn't register the callback yet. + AssertEqual '''''', string(g:Callback) + + AssertEqual 1, len(g:wait_callback_list) + AssertEqual 'completion', g:capability_checked + call map(g:wait_callback_list, 'v:val([g:conn_id, ''/foo/bar''])') + " We should send the right callback. AssertEqual \ 'function(''ale#completion#HandleLSPResponse'')', @@ -173,10 +223,58 @@ Execute(The right message should be sent for the initial LSP request): AssertEqual \ { \ 'line_length': 3, - \ 'conn_id': 0, + \ 'conn_id': g:conn_id, \ 'column': 3, - \ 'request_id': 0, + \ 'request_id': 1, \ 'line': 1, \ 'prefix': 'fo', + \ 'completion_filter': 'ale#completion#python#CompletionItemFilter', \ }, \ get(b:, 'ale_completion_info', {}) + +Execute(Two completion requests shouldn't be sent in a row): + call ale#linter#PreventLoading('python') + call ale#linter#Define('python', { + \ 'name': 'foo', + \ 'lsp': 'stdio', + \ 'executable': 'foo', + \ 'command': 'foo', + \ 'project_root_callback': {-> '/foo/bar'}, + \}) + call ale#linter#Define('python', { + \ 'name': 'bar', + \ 'lsp': 'stdio', + \ 'executable': 'foo', + \ 'command': 'foo', + \ 'project_root_callback': {-> '/foo/bar'}, + \}) + let b:ale_linters = ['foo', 'bar'] + + " The cursor position needs to match what was saved before. + call setpos('.', [bufnr(''), 1, 5, 0]) + + call ale#completion#GetCompletions() + + " We shouldn't register the callback yet. + AssertEqual '''''', string(g:Callback) + + AssertEqual 2, len(g:wait_callback_list) + AssertEqual 'completion', g:capability_checked + call map(g:wait_callback_list, 'v:val([347, ''/foo/bar''])') + + " We should only send one completion message for two LSP servers. + AssertEqual + \ [ + \ [1, 'textDocument/didChange', { + \ 'textDocument': { + \ 'uri': ale#path#ToURI(expand('%:p')), + \ 'version': g:ale_lsp_next_version_id - 1, + \ }, + \ 'contentChanges': [{'text': join(getline(1, '$'), "\n") . "\n"}] + \ }], + \ [0, 'textDocument/completion', { + \ 'textDocument': {'uri': ale#path#ToURI(expand('%:p'))}, + \ 'position': {'line': 0, 'character': 3}, + \ }], + \ ], + \ g:message_list diff --git a/test/completion/test_lsp_completion_parsing.vader b/test/completion/test_lsp_completion_parsing.vader new file mode 100644 index 00000000..d5a45b54 --- /dev/null +++ b/test/completion/test_lsp_completion_parsing.vader @@ -0,0 +1,449 @@ +After: + unlet! b:ale_completion_info + +Execute(Should handle Rust completion results correctly): + AssertEqual + \ [ + \ {'word': 'new', 'menu': 'pub fn new() -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'with_capacity', 'menu': 'pub fn with_capacity(capacity: usize) -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from_utf8', 'menu': 'pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error>', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from_utf8_lossy', 'menu': 'pub fn from_utf8_lossy<''a>(v: &''a [u8]) -> Cow<''a, str>', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from_utf16', 'menu': 'pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error>', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from_utf16_lossy', 'menu': 'pub fn from_utf16_lossy(v: &[u16]) -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from_raw_parts', 'menu': 'pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from_utf8_unchecked', 'menu': 'pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = &''a char>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = &''a str>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = Cow<''a, str>>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Searcher', 'menu': 'type Searcher = <&''b str as Pattern<''a>>::Searcher;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'default', 'menu': 'fn default() -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = String;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Target', 'menu': 'type Target = str;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Err', 'menu': 'type Err = ParseError;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from_str', 'menu': 'fn from_str(s: &str) -> Result<String, ParseError>', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from', 'menu': 'fn from(s: &''a str) -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from', 'menu': 'fn from(s: Box<str>) -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'from', 'menu': 'fn from(s: Cow<''a, str>) -> String', 'info': '', 'kind': 'f', 'icase': 1}, + \], + \ ale#completion#ParseLSPCompletions({ + \ "jsonrpc":"2.0", + \ "id":65, + \ "result":[ + \ { + \ "label":"new", + \ "kind":3, + \ "detail":"pub fn new() -> String" + \ }, + \ { + \ "label":"with_capacity", + \ "kind":3, + \ "detail":"pub fn with_capacity(capacity: usize) -> String" + \ }, + \ { + \ "label":"from_utf8", + \ "kind":3, + \ "detail":"pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error>" + \ }, + \ { + \ "label":"from_utf8_lossy", + \ "kind":3, + \ "detail":"pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str>" + \ }, + \ { + \ "label":"from_utf16", + \ "kind":3, + \ "detail":"pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error>" + \ }, + \ { + \ "label":"from_utf16_lossy", + \ "kind":3, + \ "detail":"pub fn from_utf16_lossy(v: &[u16]) -> String" + \ }, + \ { + \ "label":"from_raw_parts", + \ "kind":3, + \ "detail":"pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String" + \ }, + \ { + \ "label":"from_utf8_unchecked", + \ "kind":3, + \ "detail":"pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String" + \ }, + \ { + \ "label":"from_iter", + \ "kind":3, + \ "detail":"fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> String" + \ }, + \ { + \ "label":"from_iter", + \ "kind":3, + \ "detail":"fn from_iter<I: IntoIterator<Item = &'a char>>(iter: I) -> String" + \ }, + \ { + \ "label":"from_iter", + \ "kind":3, + \ "detail":"fn from_iter<I: IntoIterator<Item = &'a str>>(iter: I) -> String" + \ }, + \ { + \ "label":"from_iter", + \ "kind":3, + \ "detail":"fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> String" + \ }, + \ { + \ "label":"from_iter", + \ "kind":3, + \ "detail":"fn from_iter<I: IntoIterator<Item = Cow<'a, str>>>(iter: I) -> String" + \ }, + \ { + \ "label":"Searcher", + \ "kind":8, + \ "detail":"type Searcher = <&'b str as Pattern<'a>>::Searcher;" + \ }, + \ { + \ "label":"default", + \ "kind":3, + \ "detail":"fn default() -> String" + \ }, + \ { + \ "label":"Output", + \ "kind":8, + \ "detail":"type Output = String;" + \ }, + \ { + \ "label":"Output", + \ "kind":8, + \ "detail":"type Output = str;" + \ }, + \ { + \ "label":"Output", + \ "kind":8, + \ "detail":"type Output = str;" + \ }, + \ { + \ "label":"Output", + \ "kind":8, + \ "detail":"type Output = str;" + \ }, + \ { + \ "label":"Output", + \ "kind":8, + \ "detail":"type Output = str;" + \ }, + \ { + \ "label":"Output", + \ "kind":8, + \ "detail":"type Output = str;" + \ }, + \ { + \ "label":"Output", + \ "kind":8, + \ "detail":"type Output = str;" + \ }, + \ { + \ "label":"Target", + \ "kind":8, + \ "detail":"type Target = str;" + \ }, + \ { + \ "label":"Err", + \ "kind":8, + \ "detail":"type Err = ParseError;" + \ }, + \ { + \ "label":"from_str", + \ "kind":3, + \ "detail":"fn from_str(s: &str) -> Result<String, ParseError>" + \ }, + \ { + \ "label":"from", + \ "kind":3, + \ "detail":"fn from(s: &'a str) -> String" + \ }, + \ { + \ "label":"from", + \ "kind":3, + \ "detail":"fn from(s: Box<str>) -> String" + \ }, + \ { + \ "label":"from", + \ "kind":3, + \ "detail":"fn from(s: Cow<'a, str>) -> String" + \ } + \ ] + \ }) + +Execute(Should handle Python completion results correctly): + let b:ale_completion_info = { + \ 'completion_filter': 'ale#completion#python#CompletionItemFilter', + \} + + AssertEqual + \ [ + \ {'word': 'what', 'menu': 'example-python-project.bar.Bar', 'info': "what()\n\n", 'kind': 'f', 'icase': 1}, + \ ], + \ ale#completion#ParseLSPCompletions({ + \ "jsonrpc":"2.0", + \ "id":6, + \ "result":{ + \ "isIncomplete":v:false, + \ "items":[ + \ { + \ "label":"what()", + \ "kind":3, + \ "detail":"example-python-project.bar.Bar", + \ "documentation":"what()\n\n", + \ "sortText":"awhat", + \ "insertText":"what" + \ }, + \ { + \ "label":"__class__", + \ "kind":7, + \ "detail":"object", + \ "documentation":"type(object_or_name, bases, dict)\ntype(object) -> the object's type\ntype(name, bases, dict) -> a new type", + \ "sortText":"z__class__", + \ "insertText":"__class__" + \ }, + \ { + \ "label":"__delattr__(name)", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Implement delattr(self, name).", + \ "sortText":"z__delattr__", + \ "insertText":"__delattr__" + \ }, + \ { + \ "label":"__dir__()", + \ "kind":3, + \ "detail":"object", + \ "documentation":"__dir__() -> list\ndefault dir() implementation", + \ "sortText":"z__dir__", + \ "insertText":"__dir__" + \ }, + \ { + \ "label":"__doc__", + \ "kind":18, + \ "detail":"object", + \ "documentation":"str(object='') -> str\nstr(bytes_or_buffer[, encoding[, errors]]) -> str\n\nCreate a new string object from the given object. If encoding or\nerrors is specified, then the object must expose a data buffer\nthat will be decoded using the given encoding and error handler.\nOtherwise, returns the result of object.__str__() (if defined)\nor repr(object).\nencoding defaults to sys.getdefaultencoding().\nerrors defaults to 'strict'.", + \ "sortText":"z__doc__", + \ "insertText":"__doc__" + \ }, + \ { + \ "label":"__eq__(value)", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Return self==value.", + \ "sortText":"z__eq__", + \ "insertText":"__eq__" + \ }, + \ { + \ "label":"__format__()", + \ "kind":3, + \ "detail":"object", + \ "documentation":"default object formatter", + \ "sortText":"z__format__", + \ "insertText":"__format__" + \ }, + \ { + \ "label":"__ge__(value)", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Return self>=value.", + \ "sortText":"z__ge__", + \ "insertText":"__ge__" + \ }, + \ { + \ "label":"__getattribute__(name)", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Return getattr(self, name).", + \ "sortText":"z__getattribute__", + \ "insertText":"__getattribute__" + \ }, + \ { + \ "label":"__gt__(value)", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Return self>value.", + \ "sortText":"z__gt__", + \ "insertText":"__gt__" + \ }, + \ { + \ "label":"__hash__()", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Return hash(self).", + \ "sortText":"z__hash__", + \ "insertText":"__hash__" + \ }, + \ { + \ "label":"__init__(args, kwargs)", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Initialize self.\u00a0\u00a0See help(type(self)) for accurate signature.", + \ "sortText":"z__init__", + \ "insertText":"__init__" + \ }, + \ { + \ "label":"__init_subclass__()", + \ "kind":3, + \ "detail":"object", + \ "documentation":"This method is called when a class is subclassed.\n\nThe default implementation does nothing. It may be\noverridden to extend subclasses.", + \ "sortText":"z__init_subclass__", + \ "insertText":"__init_subclass__" + \ }, + \ { + \ "label":"__le__(value)", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Return self<=value.", + \ "sortText":"z__le__", + \ "insertText":"__le__" + \ }, + \ { + \ "label":"__lt__(value)", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Return self<value.", + \ "sortText":"z__lt__", + \ "insertText":"__lt__" + \ }, + \ { + \ "label":"__ne__(value)", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Return self!=value.", + \ "sortText":"z__ne__", + \ "insertText":"__ne__" + \ }, + \ { + \ "label":"__new__(kwargs)", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Create and return a new object.\u00a0\u00a0See help(type) for accurate signature.", + \ "sortText":"z__new__", + \ "insertText":"__new__" + \ }, + \ { + \ "label":"__reduce__()", + \ "kind":3, + \ "detail":"object", + \ "documentation":"helper for pickle", + \ "sortText":"z__reduce__", + \ "insertText":"__reduce__" + \ }, + \ { + \ "label":"__reduce_ex__()", + \ "kind":3, + \ "detail":"object", + \ "documentation":"helper for pickle", + \ "sortText":"z__reduce_ex__", + \ "insertText":"__reduce_ex__" + \ }, + \ { + \ "label":"__repr__()", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Return repr(self).", + \ "sortText":"z__repr__", + \ "insertText":"__repr__" + \ }, + \ { + \ "label":"__setattr__(name, value)", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Implement setattr(self, name, value).", + \ "sortText":"z__setattr__", + \ "insertText":"__setattr__" + \ }, + \ { + \ "label":"__sizeof__()", + \ "kind":3, + \ "detail":"object", + \ "documentation":"__sizeof__() -> int\nsize of object in memory, in bytes", + \ "sortText":"z__sizeof__", + \ "insertText":"__sizeof__" + \ }, + \ { + \ "label":"__str__()", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Return str(self).", + \ "sortText":"z__str__", + \ "insertText":"__str__" + \ }, + \ { + \ "label":"__subclasshook__()", + \ "kind":3, + \ "detail":"object", + \ "documentation":"Abstract classes can override this to customize issubclass().\n\nThis is invoked early on by abc.ABCMeta.__subclasscheck__().\nIt should return True, False or NotImplemented.\u00a0\u00a0If it returns\nNotImplemented, the normal algorithm is used.\u00a0\u00a0Otherwise, it\noverrides the normal algorithm (and the outcome is cached).", + \ "sortText":"z__subclasshook__", + \ "insertText":"__subclasshook__" + \ } + \ ] + \ } + \ }) + +Execute(Should handle Python completion results correctly): + let b:ale_completion_info = { + \ 'completion_filter': 'ale#completion#python#CompletionItemFilter', + \ 'prefix': 'mig', + \} + + AssertEqual + \ [ + \ {'word': 'migrations', 'menu': 'xxx', 'info': 'migrations', 'kind': 'f', 'icase': 1}, + \ {'word': 'MigEngine', 'menu': 'xxx', 'info': 'mig engine', 'kind': 'f', 'icase': 1}, + \ ], + \ ale#completion#ParseLSPCompletions({ + \ 'jsonrpc': '2.0', + \ 'id': 6, + \ 'result': { + \ 'isIncomplete': v:false, + \ 'items': [ + \ { + \ 'label': 'migrations', + \ 'kind': 3, + \ 'detail': 'xxx', + \ 'documentation': 'migrations', + \ }, + \ { + \ 'label': 'MigEngine', + \ 'kind': 3, + \ 'detail': 'xxx', + \ 'documentation': 'mig engine', + \ }, + \ { + \ 'label': 'ignore me', + \ 'kind': 3, + \ 'detail': 'nope', + \ 'documentation': 'nope', + \ }, + \ ] + \ } + \ }) + +Execute(Should handle missing keys): + AssertEqual + \ [ + \ {'word': 'x', 'menu': '', 'info': '', 'kind': 'v', 'icase': 1}, + \ ], + \ ale#completion#ParseLSPCompletions({ + \ 'jsonrpc': '2.0', + \ 'id': 6, + \ 'result': { + \ 'isIncomplete': v:false, + \ 'items': [ + \ { + \ 'label': 'x', + \ }, + \ ] + \ } + \ }) diff --git a/test/completion/test_tsserver_completion_parsing.vader b/test/completion/test_tsserver_completion_parsing.vader index b663ef40..c8e2c993 100644 --- a/test/completion/test_tsserver_completion_parsing.vader +++ b/test/completion/test_tsserver_completion_parsing.vader @@ -1,3 +1,6 @@ +After: + unlet! b:ale_tsserver_completion_names + Execute(TypeScript completions responses should be parsed correctly): AssertEqual [], \ ale#completion#ParseTSServerCompletions({ @@ -73,3 +76,74 @@ Execute(TypeScript completion details responses should be parsed correctly): \ }, \ ], \}) + +Execute(Entries without details should be included in the responses): + let b:ale_tsserver_completion_names = ['xyz'] + + AssertEqual + \ [ + \ { + \ 'word': 'abc', + \ 'menu': '(property) Foo.abc: number', + \ 'info': '', + \ 'kind': 'f', + \ 'icase': 1, + \ }, + \ { + \ 'word': 'def', + \ 'menu': '(property) Foo.def: number', + \ 'info': 'foo bar baz', + \ 'kind': 'f', + \ 'icase': 1, + \ }, + \ { + \ 'word': 'xyz', + \ 'menu': '', + \ 'info': '', + \ 'kind': 'v', + \ 'icase': 1, + \ }, + \ ], + \ ale#completion#ParseTSServerCompletionEntryDetails({ + \ 'body': [ + \ { + \ 'name': 'abc', + \ 'kind': 'parameterName', + \ 'displayParts': [ + \ {'text': '('}, + \ {'text': 'property'}, + \ {'text': ')'}, + \ {'text': ' '}, + \ {'text': 'Foo'}, + \ {'text': '.'}, + \ {'text': 'abc'}, + \ {'text': ':'}, + \ {'text': ' '}, + \ {'text': 'number'}, + \ ], + \ }, + \ { + \ 'name': 'def', + \ 'kind': 'parameterName', + \ 'displayParts': [ + \ {'text': '('}, + \ {'text': 'property'}, + \ {'text': ')'}, + \ {'text': ' '}, + \ {'text': 'Foo'}, + \ {'text': '.'}, + \ {'text': 'def'}, + \ {'text': ':'}, + \ {'text': ' '}, + \ {'text': 'number'}, + \ ], + \ 'documentation': [ + \ {'text': 'foo'}, + \ {'text': ' '}, + \ {'text': 'bar'}, + \ {'text': ' '}, + \ {'text': 'baz'}, + \ ], + \ }, + \ ], + \}) diff --git a/test/cucumber_fixtures/features/cuke.feature b/test/cucumber_fixtures/features/cuke.feature new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/cucumber_fixtures/features/cuke.feature diff --git a/test/cucumber_fixtures/features/step_definitions/base_steps.rb b/test/cucumber_fixtures/features/step_definitions/base_steps.rb new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/cucumber_fixtures/features/step_definitions/base_steps.rb diff --git a/test/dart_files/testfile.dart b/test/dart_files/testfile.dart new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/dart_files/testfile.dart diff --git a/test/dumb_tcp_client.py b/test/dumb_tcp_client.py new file mode 100644 index 00000000..3a728b02 --- /dev/null +++ b/test/dumb_tcp_client.py @@ -0,0 +1,33 @@ +""" +This is just a script for testing that the dumb TCP server actually works +correctly, for verifying that problems with tests are in Vim. Pass the +same port number given to the test server to check that it's working. +""" +import socket +import sys + + +def main(): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + result = sock.connect_ex(('127.0.0.1', int(sys.argv[1]))) + + if result: + sock.close() + sys.exit("Couldn't connect to the socket!") + + data_sent = 'x' * 1024 + + sock.send(data_sent) + data_received = sock.recv(1024) + + if data_sent != data_received: + sock.close() + sys.exit("Data sent didn't match data received.") + + sock.close() + + print("Everything was just fine.") + + +if __name__ == "__main__": + main() diff --git a/test/dumb_tcp_server.py b/test/dumb_tcp_server.py new file mode 100644 index 00000000..c15db65e --- /dev/null +++ b/test/dumb_tcp_server.py @@ -0,0 +1,40 @@ +""" +This Python script creates a TCP server that does nothing but send its input +back to the client that connects to it. Only one argument must be given, a port +to bind to. +""" +import os +import socket +import sys + + +def main(): + if len(sys.argv) < 2 or not sys.argv[1].isdigit(): + sys.exit('You must specify a port number') + + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind(('127.0.0.1', int(sys.argv[1]))) + sock.listen(0) + + pid = os.fork() + + if pid: + print(pid) + sys.exit() + + while True: + connection = sock.accept()[0] + connection.settimeout(5) + + while True: + try: + connection.send(connection.recv(1024)) + except socket.timeout: + break + + connection.close() + + +if __name__ == "__main__": + main() diff --git a/test/elm-test-files/app/node_modules/.bin/elm b/test/elm-test-files/app/node_modules/.bin/elm new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/elm-test-files/app/node_modules/.bin/elm diff --git a/test/fix/test_ale_fix.vader b/test/fix/test_ale_fix.vader index 817c243d..67b8b212 100644 --- a/test/fix/test_ale_fix.vader +++ b/test/fix/test_ale_fix.vader @@ -17,12 +17,21 @@ Before: \ 'testft': [], \} + let g:pre_success = 0 + let g:post_success = 0 + augroup VaderTest + autocmd! + autocmd User ALEFixPre let g:pre_success = 1 + autocmd User ALEFixPost let g:post_success = 1 + augroup end + if !has('win32') let &shell = '/bin/bash' endif call ale#test#SetDirectory('/testplugin/test') call ale#test#SetFilename('test.txt') + call ale#linter#PreventLoading('testft') function AddCarets(buffer, lines) abort " map() is applied to the original lines here. @@ -171,6 +180,7 @@ After: unlet! g:ale_emulate_job_failure unlet! b:ale_fixers unlet! b:ale_fix_on_save + augroup! VaderTest delfunction AddCarets delfunction AddDollars delfunction DoNothing @@ -248,6 +258,25 @@ Expect(Only the second function should be applied): $b $c +Execute(The * fixers shouldn't be used if an empty list is set for fixers): + let g:ale_fixers.testft = [] + let g:ale_fixers['*'] = ['AddDollars'] + ALEFix + +Expect(Nothing should be changed): + a + b + c + +Execute(* fixers should be used if no filetype is matched): + let g:ale_fixers = {'*': ['AddDollars']} + ALEFix + +Expect(The file should be changed): + $a + $b + $c + Execute(ALEFix should allow commands to be run): if has('win32') " Just skip this test on Windows, we can't run it. @@ -263,6 +292,15 @@ Expect(An extra line should be added): c d +Execute(ALEFix should use fixers passed in commandline when provided): + let g:ale_fixers.testft = ['RemoveLastLine'] + ALEFix AddCarets AddDollars + +Expect(Only fixers passed via command line should be run): + $^a + $^b + $^c + Execute(ALEFix should allow temporary files to be read): if has('win32') " Just skip this test on Windows, we can't run it. @@ -420,7 +458,7 @@ Execute(ALEFix should save files on the save event): \ 'nr': -1, \ 'pattern': '', \ 'valid': 1, - \}], getloclist(0) + \}], ale#test#GetLoclistWithoutModule() endif Expect(The buffer should be modified): @@ -459,7 +497,7 @@ Execute(ALEFix should still lint with no linters to be applied): \ 'nr': -1, \ 'pattern': '', \ 'valid': 1, - \}], getloclist(0) + \}], ale#test#GetLoclistWithoutModule() endif Expect(The buffer should be the same): @@ -493,7 +531,7 @@ Execute(ALEFix should still lint when nothing was fixed on save): \ 'nr': -1, \ 'pattern': '', \ 'valid': 1, - \}], getloclist(0) + \}], ale#test#GetLoclistWithoutModule() endif Expect(The buffer should be the same): @@ -514,8 +552,6 @@ Execute(ale#fix#InitBufferData() should set up the correct data): AssertEqual { \ bufnr(''): { \ 'temporary_directory_list': [], - \ 'vars': b:, - \ 'filename': ale#path#Simplify(getcwd() . '/fix_test_file'), \ 'done': 0, \ 'lines_before': ['a', 'b', 'c'], \ 'should_save': 1, @@ -574,6 +610,16 @@ Execute(ALE should print a message telling you something isn't a valid fixer whe AssertEqual 'There is no fixer named `invalidname`. Check :ALEFixSuggest', GetLastMessage() +Execute(ALE should complain about invalid fixers with minuses in the name): + let g:ale_fixers.testft = ['foo-bar'] + ALEFix + + AssertEqual 'There is no fixer named `foo-bar`. Check :ALEFixSuggest', GetLastMessage() + +Execute(ALE should tolerate valid fixers with minuses in the name): + let g:ale_fixers.testft = ['prettier-standard'] + ALEFix + Execute(Test fixing with chained callbacks): let g:ale_fixers.testft = ['FirstChainCallback'] ALEFix @@ -654,3 +700,9 @@ Expect(The lines in the JSON should be used): x y z + +Execute(ALEFix should apply autocmds): + let g:ale_fixers.testft = ['AddCarets'] + ALEFix + AssertEqual g:pre_success, 1 + AssertEqual g:post_success, 1 diff --git a/test/fix/test_ale_fix_completion.vader b/test/fix/test_ale_fix_completion.vader new file mode 100644 index 00000000..6c38bb8d --- /dev/null +++ b/test/fix/test_ale_fix_completion.vader @@ -0,0 +1,23 @@ +Execute (List of available fixers is empty): + call ale#fix#registry#Clear() + +Then (List of applicable fixers for python file is empty): + AssertEqual [], ale#fix#registry#GetApplicableFixers('python') + +Execute (Add ruby fixer): + call ale#fix#registry#Add('ruby_fixer', 'fixer_fun', ['ruby'], 'ruby fixer') + +Then (List of applicable fixers for python file is still empty): + AssertEqual [], ale#fix#registry#GetApplicableFixers('python') + +Execute (Add generic fixer): + call ale#fix#registry#Add('generic_fixer', 'fixer_fun', [], 'generic fixer') + +Then (Generic fixer should be returned as applicable for python file): + AssertEqual ['generic_fixer'], ale#fix#registry#GetApplicableFixers('python') + +Execute (Add python fixer): + call ale#fix#registry#Add('python_fixer', 'fixer_func', ['python'], 'python fixer') + +Then (List of fixers should contain both generic and python fixers): + AssertEqual ['generic_fixer', 'python_fixer'], ale#fix#registry#GetApplicableFixers('python') diff --git a/test/fix/test_ale_fix_completion_filter.vader b/test/fix/test_ale_fix_completion_filter.vader new file mode 100644 index 00000000..536b7138 --- /dev/null +++ b/test/fix/test_ale_fix_completion_filter.vader @@ -0,0 +1,14 @@ +Before: + call ale#fix#registry#Clear() + call ale#test#SetFilename('test.js') + call ale#fix#registry#Add('prettier', '', ['javascript'], 'prettier') + call ale#fix#registry#Add('eslint', '', ['javascript'], 'eslint') + setfiletype javascript + +Execute(completeFixers returns all of the applicable fixers without an arglead): + AssertEqual ['eslint', 'prettier'], + \ ale#fix#registry#CompleteFixers('', 'ALEFix ', 7) + +Execute(completeFixers returns all of the applicable fixers without an arglead): + AssertEqual ['prettier'], + \ ale#fix#registry#CompleteFixers('pre', 'ALEFix ', 10) diff --git a/test/fixers/test_black_fixer_callback.vader b/test/fixers/test_black_fixer_callback.vader new file mode 100644 index 00000000..365b0fa6 --- /dev/null +++ b/test/fixers/test_black_fixer_callback.vader @@ -0,0 +1,39 @@ +Before: + Save g:ale_python_black_executable + Save g:ale_python_black_options + + " Use an invalid global executable, so we don't match it. + let g:ale_python_black_executable = 'xxxinvalid' + let g:ale_python_black_options = '' + + call ale#test#SetDirectory('/testplugin/test/fixers') + silent cd .. + silent cd command_callback + let g:dir = getcwd() + + let b:bin_dir = has('win32') ? 'Scripts' : 'bin' + +After: + Restore + + unlet! b:bin_dir + + call ale#test#RestoreDirectory() + +Execute(The black callback should return the correct default values): + AssertEqual + \ 0, + \ ale#fixers#black#Fix(bufnr('')) + + silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') + AssertEqual + \ {'command': ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/black')) . ' -'}, + \ ale#fixers#black#Fix(bufnr('')) + +Execute(The black callback should include options): + let g:ale_python_black_options = '--some-option' + + silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') + AssertEqual + \ {'command': ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/black')) . ' --some-option -' }, + \ ale#fixers#black#Fix(bufnr('')) diff --git a/test/fixers/test_brittany_fixer_callback.vader b/test/fixers/test_brittany_fixer_callback.vader index a0182b52..073e368c 100644 --- a/test/fixers/test_brittany_fixer_callback.vader +++ b/test/fixers/test_brittany_fixer_callback.vader @@ -18,6 +18,7 @@ Execute(The brittany callback should return the correct default values): \ { \ 'read_temporary_file': 1, \ 'command': ale#Escape('xxxinvalid') + \ . ' --write-mode inplace' \ . ' %t', \ }, \ ale#fixers#brittany#Fix(bufnr('')) diff --git a/test/fixers/test_dartfmt_fixer_callback.vader b/test/fixers/test_dartfmt_fixer_callback.vader new file mode 100644 index 00000000..79c40eff --- /dev/null +++ b/test/fixers/test_dartfmt_fixer_callback.vader @@ -0,0 +1,40 @@ +Before: + Save g:ale_dart_dartfmt_executable + Save g:ale_dart_dartfmt_options + + " Use an invalid global executable, so we don't match it. + let g:ale_dart_dartfmt_executable = 'xxxinvalid' + let g:ale_dart_dartfmt_options = '' + + call ale#test#SetDirectory('/testplugin/test/fixers') + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The dartfmt callback should return the correct default values): + call ale#test#SetFilename('../dart_files/testfile.dart') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('xxxinvalid') + \ . ' -w' + \ . ' %t', + \ }, + \ ale#fixers#dartfmt#Fix(bufnr('')) + +Execute(The dartfmt callback should include custom dartfmt options): + let g:ale_dart_dartfmt_options = "-l 80" + call ale#test#SetFilename('../dart_files/testfile.dart') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('xxxinvalid') + \ . ' -w' + \ . ' ' . g:ale_dart_dartfmt_options + \ . ' %t', + \ }, + \ ale#fixers#dartfmt#Fix(bufnr('')) diff --git a/test/fixers/test_elm_format_fixer_callback.vader b/test/fixers/test_elm_format_fixer_callback.vader index d613aa84..682c22ca 100644 --- a/test/fixers/test_elm_format_fixer_callback.vader +++ b/test/fixers/test_elm_format_fixer_callback.vader @@ -18,7 +18,7 @@ Execute(The elm-format command should have default params): \ ale#Escape(ale#path#Simplify(g:dir . '/../elm-test-files/node_modules/.bin/elm-format')) \ . ' %t --yes', \ }, - \ ale#fixers#format#Fix(bufnr('')) + \ ale#fixers#elm_format#Fix(bufnr('')) Execute(The elm-format command should manage use_global = 1 param): call ale#test#SetFilename('../elm-test-files/src/subdir/testfile.elm') @@ -31,7 +31,7 @@ Execute(The elm-format command should manage use_global = 1 param): \ ale#Escape('elm-format') \ . ' %t --yes', \ }, - \ ale#fixers#format#Fix(bufnr('')) + \ ale#fixers#elm_format#Fix(bufnr('')) Execute(The elm-format command should manage executable param): call ale#test#SetFilename('../elm-test-files/src/subdir/testfile.elm') @@ -45,7 +45,7 @@ Execute(The elm-format command should manage executable param): \ ale#Escape('elmformat') \ . ' %t --yes', \ }, - \ ale#fixers#format#Fix(bufnr('')) + \ ale#fixers#elm_format#Fix(bufnr('')) Execute(The elm-format command should manage empty options): call ale#test#SetFilename('../elm-test-files/src/subdir/testfile.elm') @@ -58,7 +58,7 @@ Execute(The elm-format command should manage empty options): \ ale#Escape(ale#path#Simplify(g:dir . '/../elm-test-files/node_modules/.bin/elm-format')) \ . ' %t', \ }, - \ ale#fixers#format#Fix(bufnr('')) + \ ale#fixers#elm_format#Fix(bufnr('')) Execute(The elm-format command should manage custom options): call ale#test#SetFilename('../elm-test-files/src/subdir/testfile.elm') @@ -71,4 +71,4 @@ Execute(The elm-format command should manage custom options): \ ale#Escape(ale#path#Simplify(g:dir . '/../elm-test-files/node_modules/.bin/elm-format')) \ . ' %t --param1 --param2', \ }, - \ ale#fixers#format#Fix(bufnr('')) + \ ale#fixers#elm_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..48f26c7c --- /dev/null +++ b/test/fixers/test_hlint_fixer_callback.vader @@ -0,0 +1,25 @@ +Before: + Save g:ale_haskell_hlint_executable + + " Use an invalid global executable, so we don't match it. + let g:ale_haskell_hlint_executable = 'xxxinvalid' + + 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('xxxinvalid') + \ . ' --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 503057bb..56c08d26 100644 --- a/test/fixers/test_isort_fixer_callback.vader +++ b/test/fixers/test_isort_fixer_callback.vader @@ -1,5 +1,6 @@ Before: Save g:ale_python_isort_executable + Save g:ale_python_isort_options " Use an invalid global executable, so we don't match it. let g:ale_python_isort_executable = 'xxxinvalid' @@ -25,5 +26,24 @@ Execute(The isort callback should return the correct default values): silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') AssertEqual - \ {'command': ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/isort')) . ' -' }, + \ { + \ 'command': 'cd ' . ale#Escape(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('')) + +Execute(The isort callback should respect custom options): + let g:ale_python_isort_options = '--multi-line=3 --trailing-comma' + + AssertEqual + \ 0, + \ ale#fixers#isort#Fix(bufnr('')) + + 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')) . ' && ' + \ . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/isort')) + \ . ' --multi-line=3 --trailing-comma -', + \ }, \ ale#fixers#isort#Fix(bufnr('')) diff --git a/test/fixers/test_jq_fixer_callback.vader b/test/fixers/test_jq_fixer_callback.vader new file mode 100644 index 00000000..2e32bf8e --- /dev/null +++ b/test/fixers/test_jq_fixer_callback.vader @@ -0,0 +1,14 @@ +Before: + Save g:ale_json_jq_executable + Save g:ale_json_jq_options + +After: + Restore + +Execute(The jq fixer should use the options you set): + let g:ale_json_jq_executable = 'foo' + let g:ale_json_jq_options = '--bar' + + AssertEqual + \ {'command': ale#Escape('foo') . ' . --bar'}, + \ ale#fixers#jq#Fix(bufnr('')) diff --git a/test/fixers/test_mix_format_fixer_callback.vader b/test/fixers/test_mix_format_fixer_callback.vader index c6c97c57..365fbecf 100644 --- a/test/fixers/test_mix_format_fixer_callback.vader +++ b/test/fixers/test_mix_format_fixer_callback.vader @@ -1,10 +1,15 @@ Before: - call ale#test#SetDirectory('/testplugin/test/fixers') Save g:ale_elixir_mix_executable + Save g:ale_elixir_mix_format_options let g:ale_elixir_mix_executable = 'xxxinvalid' + let g:ale_elixir_mix_format_options = '' + + call ale#test#SetDirectory('/testplugin/test/fixers') After: + Restore + call ale#test#RestoreDirectory() Execute(The mix_format callback should return the correct default values): @@ -18,3 +23,14 @@ Execute(The mix_format callback should return the correct default values): \ }, \ ale#fixers#mix_format#Fix(bufnr('')) +Execute(The mix_format callback should include the correct format options): + let g:ale_elixir_mix_format_options = 'invalid_options' + call ale#test#SetFilename('../elixir-test-files/testfile.ex') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('xxxinvalid') + \ . ' format invalid_options %t', + \ }, + \ ale#fixers#mix_format#Fix(bufnr('')) diff --git a/test/fixers/test_perltidy_fixer_callback.vader b/test/fixers/test_perltidy_fixer_callback.vader new file mode 100644 index 00000000..c7430bfa --- /dev/null +++ b/test/fixers/test_perltidy_fixer_callback.vader @@ -0,0 +1,40 @@ +Before: + Save g:ale_perl_perltidy_executable + Save g:ale_perl_perltidy_options + + " Use an invalid global executable, so we don't match it. + let g:ale_perl_perltidy_executable = 'xxxinvalid' + let g:ale_perl_perltidy_options = '' + + call ale#test#SetDirectory('/testplugin/test/fixers') + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The perltidy callback should return the correct default values): + call ale#test#SetFilename('../pl_files/testfile.pl') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('xxxinvalid') + \ . ' -b' + \ . ' %t', + \ }, + \ ale#fixers#perltidy#Fix(bufnr('')) + +Execute(The perltidy callback should include custom perltidy options): + let g:ale_perl_perltidy_options = "-r '(a) -> a'" + call ale#test#SetFilename('../pl_files/testfile.pl') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('xxxinvalid') + \ . ' -b' + \ . ' ' . g:ale_perl_perltidy_options + \ . ' %t', + \ }, + \ ale#fixers#perltidy#Fix(bufnr('')) diff --git a/test/fixers/test_php_cs_fixer.vader b/test/fixers/test_php_cs_fixer.vader new file mode 100644 index 00000000..b47c190c --- /dev/null +++ b/test/fixers/test_php_cs_fixer.vader @@ -0,0 +1,65 @@ +Before: + Save g:ale_php_cs_fixer_executable + Save g:ale_php_cs_fixer_options + let g:ale_php_cs_fixer_executable = 'php-cs-fixer' + let g:ale_php_cs_fixer_options = '' + + call ale#test#SetDirectory('/testplugin/test/fixers') + silent cd .. + silent cd command_callback + let g:dir = getcwd() + +After: + Restore + + call ale#test#RestoreDirectory() + + +Execute(project with php-cs-fixer should use local by default): + call ale#test#SetFilename('php_paths/project-with-php-cs-fixer/test.php') + + AssertEqual + \ ale#path#Simplify(g:dir . '/php_paths/project-with-php-cs-fixer/vendor/bin/php-cs-fixer'), + \ ale#fixers#php_cs_fixer#GetExecutable(bufnr('')) + +Execute(use-global should override local detection): + let g:ale_php_cs_fixer_use_global = 1 + call ale#test#SetFilename('php_paths/project-with-php-cs-fixer/test.php') + + AssertEqual + \ 'php-cs-fixer', + \ ale#fixers#php_cs_fixer#GetExecutable(bufnr('')) + +Execute(project without php-cs-fixer should use global): + call ale#test#SetFilename('php_paths/project-without-php-cs-fixer/test.php') + + AssertEqual + \ 'php-cs-fixer', + \ ale#fixers#php_cs_fixer#GetExecutable(bufnr('')) + + + + +Execute(The php-cs-fixer callback should return the correct default values): + call ale#test#SetFilename('php_paths/project-without-php-cs-fixer/foo/test.php') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('php-cs-fixer') + \ . ' ' . g:ale_php_cs_fixer_options + \ . ' fix %t' + \ }, + \ ale#fixers#php_cs_fixer#Fix(bufnr('')) + +Execute(The php-cs-fixer callback should include custom php-cs-fixer options): + let g:ale_php_cs_fixer_options = '--config="$HOME/.php_cs"' + call ale#test#SetFilename('php_paths/project-without-php-cs-fixer/test.php') + + AssertEqual + \ { + \ 'command': ale#Escape(g:ale_php_cs_fixer_executable) + \ . ' --config="$HOME/.php_cs" fix %t', + \ 'read_temporary_file': 1, + \ }, + \ ale#fixers#php_cs_fixer#Fix(bufnr('')) diff --git a/test/fixers/test_prettier_fixer_callback.vader b/test/fixers/test_prettier_fixer_callback.vader index c4f36f52..44245630 100644 --- a/test/fixers/test_prettier_fixer_callback.vader +++ b/test/fixers/test_prettier_fixer_callback.vader @@ -95,3 +95,175 @@ Execute(The version number should be cached): \ . ' --stdin-filepath %s --stdin', \ }, \ ale#fixers#prettier#ApplyFixForVersion(bufnr(''), []) + +Execute(Should set --parser based on filetype, TypeScript): + call ale#test#SetFilename('../prettier-test-files/testfile') + + set filetype=typescript + + AssertEqual + \ { + \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape(g:ale_javascript_prettier_executable) + \ . ' --parser typescript' + \ . ' --stdin-filepath %s --stdin', + \ }, + \ ale#fixers#prettier#ApplyFixForVersion(bufnr(''), ['1.6.0']) + +Execute(Should set --parser based on filetype, CSS): + call ale#test#SetFilename('../prettier-test-files/testfile') + + set filetype=css + + AssertEqual + \ { + \ 'command': 'cd ' . ale#Escape(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(Should set --parser based on filetype, LESS): + call ale#test#SetFilename('../prettier-test-files/testfile') + + set filetype=less + + AssertEqual + \ { + \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape(g:ale_javascript_prettier_executable) + \ . ' --parser less' + \ . ' --stdin-filepath %s --stdin', + \ }, + \ ale#fixers#prettier#ApplyFixForVersion(bufnr(''), ['1.6.0']) + +Execute(Should set --parser based on filetype, SCSS): + call ale#test#SetFilename('../prettier-test-files/testfile') + + set filetype=scss + + AssertEqual + \ { + \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape(g:ale_javascript_prettier_executable) + \ . ' --parser scss' + \ . ' --stdin-filepath %s --stdin', + \ }, + \ ale#fixers#prettier#ApplyFixForVersion(bufnr(''), ['1.6.0']) + +Execute(Should set --parser based on filetype, JSON): + call ale#test#SetFilename('../prettier-test-files/testfile') + + set filetype=json + + AssertEqual + \ { + \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape(g:ale_javascript_prettier_executable) + \ . ' --parser json' + \ . ' --stdin-filepath %s --stdin', + \ }, + \ ale#fixers#prettier#ApplyFixForVersion(bufnr(''), ['1.6.0']) + +Execute(Should set --parser based on filetype, JSON5): + call ale#test#SetFilename('../prettier-test-files/testfile') + + set filetype=json5 + + AssertEqual + \ { + \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape(g:ale_javascript_prettier_executable) + \ . ' --parser json5' + \ . ' --stdin-filepath %s --stdin', + \ }, + \ ale#fixers#prettier#ApplyFixForVersion(bufnr(''), ['1.6.0']) + +Execute(Should set --parser based on filetype, GraphQL): + call ale#test#SetFilename('../prettier-test-files/testfile') + + set filetype=graphql + + AssertEqual + \ { + \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape(g:ale_javascript_prettier_executable) + \ . ' --parser graphql' + \ . ' --stdin-filepath %s --stdin', + \ }, + \ ale#fixers#prettier#ApplyFixForVersion(bufnr(''), ['1.6.0']) + +Execute(Should set --parser based on filetype, Markdown): + call ale#test#SetFilename('../prettier-test-files/testfile') + + set filetype=markdown + + AssertEqual + \ { + \ 'command': 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape(g:ale_javascript_prettier_executable) + \ . ' --parser markdown' + \ . ' --stdin-filepath %s --stdin', + \ }, + \ ale#fixers#prettier#ApplyFixForVersion(bufnr(''), ['1.6.0']) + +Execute(Should set --parser based on filetype, Vue): + call ale#test#SetFilename('../prettier-test-files/testfile') + + set filetype=vue + + AssertEqual + \ { + \ 'command': 'cd ' . ale#Escape(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': 'cd ' . ale#Escape(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 first filetype of multiple filetypes): + call ale#test#SetFilename('../prettier-test-files/testfile') + + set filetype=css.scss + + AssertEqual + \ { + \ 'command': 'cd ' . ale#Escape(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_qmlfmt_fixer_callback.vader b/test/fixers/test_qmlfmt_fixer_callback.vader new file mode 100644 index 00000000..e216f2e1 --- /dev/null +++ b/test/fixers/test_qmlfmt_fixer_callback.vader @@ -0,0 +1,12 @@ +Before: + Save g:ale_qml_qmlfmt_executable + +After: + Restore + +Execute(The qmlfmt fixer should use the options you set): + let g:ale_qml_qmlfmt_executable = 'foo-exe' + + AssertEqual + \ {'command': ale#Escape('foo-exe')}, + \ ale#fixers#qmlfmt#Fix(bufnr('')) diff --git a/test/fixers/test_rufo_fixer_callback.vader b/test/fixers/test_rufo_fixer_callback.vader new file mode 100644 index 00000000..a0828406 --- /dev/null +++ b/test/fixers/test_rufo_fixer_callback.vader @@ -0,0 +1,33 @@ +Before: + Save g:ale_ruby_rufo_executable + + " Use an invalid global executable, so we don't match it. + let g:ale_ruby_rufo_executable = 'xxxinvalid' + + call ale#test#SetDirectory('/testplugin/test/fixers') + silent cd .. + silent cd command_callback + let g:dir = getcwd() + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The rufo command should contain `bundle exec` when executable is `bundle`): + let g:ale_ruby_rufo_executable = 'bundle' + call ale#test#SetFilename('ruby_paths/dummy.rb') + + AssertEqual + \ ale#Escape('bundle') . ' exec rufo %t', + \ ale#fixers#rufo#GetCommand(bufnr('')) + +Execute(The rufo callback should return the correct default values): + call ale#test#SetFilename('ruby_paths/dummy.rb') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('xxxinvalid') . ' %t' + \ }, + \ ale#fixers#rufo#Fix(bufnr('')) diff --git a/test/fixers/test_scalafmt_fixer_callback.vader b/test/fixers/test_scalafmt_fixer_callback.vader new file mode 100644 index 00000000..d82fda43 --- /dev/null +++ b/test/fixers/test_scalafmt_fixer_callback.vader @@ -0,0 +1,69 @@ +Before: + Save g:ale_scala_scalafmt_executable + Save g:ale_scala_scalafmt_options + + " Use an invalid global executable, so we don't match it. + let g:ale_scala_scalafmt_executable = 'xxxinvalid' + let g:ale_scala_scalafmt_options = '' + + call ale#test#SetDirectory('/testplugin/test/fixers') + silent cd .. + silent cd command_callback + let g:dir = getcwd() + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The scalafmt callback should return the correct default values): + call ale#test#SetFilename('scala_paths/dummy.scala') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape(g:ale_scala_scalafmt_executable) + \ . ' %t', + \ }, + \ ale#fixers#scalafmt#Fix(bufnr('')) + +Execute(The scalafmt callback should use ng with scalafmt automatically): + let g:ale_scala_scalafmt_executable = 'ng' + call ale#test#SetFilename('scala_paths/dummy.scala') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('ng') + \ . ' scalafmt' + \ . ' %t', + \ }, + \ ale#fixers#scalafmt#Fix(bufnr('')) + +Execute(The scalafmt callback should include custom scalafmt options): + let g:ale_scala_scalafmt_options = '--diff' + call ale#test#SetFilename('scala_paths/dummy.scala') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape(g:ale_scala_scalafmt_executable) + \ . ' --diff' + \ . ' %t', + \ }, + \ ale#fixers#scalafmt#Fix(bufnr('')) + +Execute(The scalafmt callback should include custom scalafmt options and use ng with scalafmt): + let g:ale_scala_scalafmt_options = '--diff' + let g:ale_scala_scalafmt_executable = 'ng' + call ale#test#SetFilename('scala_paths/dummy.scala') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('ng') + \ . ' scalafmt' + \ . ' --diff' + \ . ' %t', + \ }, + \ ale#fixers#scalafmt#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_tidy_fixer_callback.vader b/test/fixers/test_tidy_fixer_callback.vader new file mode 100644 index 00000000..5677d8fd --- /dev/null +++ b/test/fixers/test_tidy_fixer_callback.vader @@ -0,0 +1,29 @@ +Before: + Save g:ale_html_tidy_executable + + let g:ale_html_tidy_executable = 'tidy_paths/tidy' + + 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 tidy callback should return 0 if tidy not found): + let g:ale_html_tidy_executable = 'xxxinvalidpath' + AssertEqual + \ 0, + \ ale#fixers#tidy#Fix(bufnr('')) + +Execute(The tidy callback should return the correct default command): + AssertEqual + \ { + \ 'command': ale#Escape('tidy_paths/tidy') + \ . ' -q --tidy-mark no --show-errors 0 --show-warnings 0' + \ }, + \ ale#fixers#tidy#Fix(bufnr('')) diff --git a/test/fixers/test_tslint_fixer_callback.vader b/test/fixers/test_tslint_fixer_callback.vader index 5bfafe24..aa9c0322 100644 --- a/test/fixers/test_tslint_fixer_callback.vader +++ b/test/fixers/test_tslint_fixer_callback.vader @@ -2,13 +2,16 @@ Before: Save g:ale_typescript_tslint_executable Save g:ale_typescript_tslint_config_path - let g:ale_typescript_tslint_executable = 'xxxinvalid' - let g:ale_typescript_tslint_config_path = 'tslint.json' + unlet! g:ale_typescript_tslint_executable + unlet! g:ale_typescript_tslint_config_path + unlet! b:ale_typescript_tslint_executable + unlet! b:ale_typescript_tslint_config_path + + call ale#handlers#tslint#InitVariables() - call ale#test#SetDirectory('/testplugin/test/fixers') + call ale#test#SetDirectory('/testplugin/test/command_callback') silent cd .. silent cd command_callback - let g:dir = getcwd() After: Restore @@ -16,12 +19,13 @@ After: call ale#test#RestoreDirectory() Execute(The tslint callback should return the correct default values): + let g:ale_typescript_tslint_config_path = 'tslint.json' call ale#test#SetFilename('../prettier-test-files/testfile.ts') AssertEqual \ { \ 'read_temporary_file': 1, - \ 'command': ale#Escape(g:ale_typescript_tslint_executable) + \ 'command': ale#Escape('tslint') \ . ' -c ' . ale#Escape('tslint.json') \ . ' --fix %t', \ }, @@ -34,8 +38,8 @@ Execute(The tslint callback should include custom tslint config option): AssertEqual \ { \ 'read_temporary_file': 1, - \ 'command': ale#Escape(g:ale_typescript_tslint_executable) - \ . ' -c ' . ale#Escape(g:ale_typescript_tslint_config_path) + \ 'command': ale#Escape('tslint') + \ . ' -c ' . ale#Escape('.tslintrc') \ . ' --fix %t', \ }, \ ale#fixers#tslint#Fix(bufnr('')) diff --git a/test/handler/test_cfn_python_lint_handler.vader b/test/handler/test_cfn_python_lint_handler.vader new file mode 100644 index 00000000..2c7ddc62 --- /dev/null +++ b/test/handler/test_cfn_python_lint_handler.vader @@ -0,0 +1,33 @@ +Before: + runtime! ale_linters/cloudformation/cfn_python_lint.vim + call ale#test#SetFilename('sample.template.yaml') + +After: + call ale#linter#Reset() + +Execute(The cfn_python_lint handler should parse items correctly): + AssertEqual + \ [ + \ { + \ 'lnum': '96', + \ 'col': '7', + \ 'end_lnum': '96', + \ 'end_col': '15', + \ 'text': 'Property Resources/Sample/Properties/FromPort should be of type Integer', + \ 'code': 'E3012', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': '97', + \ 'col': '7', + \ 'end_lnum': '97', + \ 'end_col': '15', + \ 'text': 'AllowedPattern and/or AllowedValues for Parameter should be specified at Parameters/SampleIpAddress. Example for AllowedPattern "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$"', + \ 'code': 'W2509', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#cloudformation#cfn_python_lint#Handle(bufnr(''), [ + \ fnamemodify(tempname(), ':h') . '/sample.template.yaml:96:7:96:15:E3012:Property Resources/Sample/Properties/FromPort should be of type Integer', + \ fnamemodify(tempname(), ':h') . '/sample.template.yaml:97:7:97:15:W2509:AllowedPattern and/or AllowedValues for Parameter should be specified at Parameters/SampleIpAddress. Example for AllowedPattern "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-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_cucumber_handler.vader b/test/handler/test_cucumber_handler.vader new file mode 100644 index 00000000..2b69a784 --- /dev/null +++ b/test/handler/test_cucumber_handler.vader @@ -0,0 +1,18 @@ +Before: + runtime ale_linters/cucumber/cucumber.vim + +After: + call ale#linter#Reset() + +Execute(The cucumber handler parses JSON correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 13, + \ 'code': 'E', + \ 'text': 'Undefined step' + \ } + \ ], + \ ale_linters#cucumber#cucumber#Handle(bufnr(''), [ + \ '[{"elements": [{"steps": [{"result": {"status": "undefined"},"match": {"location": "features/cuke.feature:13"},"line": 13,"name": "Something undefined","keyword": "Given "},{"result": {"status": "skipped"},"match": {"location": "/var/lib/gems/2.3.0/gems/cucumber-3.1.0/lib/cucumber/step_match.rb:103"},"line": 14,"name": "I visit the profile page for Alice","keyword": "When "}],"type": "scenario","line": 12,"description": "","name": "Another scenario","keyword": "Scenario","id": "a-user-can-view-another-users-profile;another-scenario"}],"line": 1,"description": "","name": "A user can view another users profile","keyword": "Feature","id": "a-user-can-view-another-users-profile","uri": "features/cuke.feature"}]' + \ ]) diff --git a/test/handler/test_elmmake_handler.vader b/test/handler/test_elmmake_handler.vader index f3424b4b..f5906a8b 100644 --- a/test/handler/test_elmmake_handler.vader +++ b/test/handler/test_elmmake_handler.vader @@ -1,15 +1,144 @@ Before: - let b:tmp = has('win32') ? substitute($TMP, '\\', '\\\\', 'g') : $TMPDIR - runtime ale_linters/elm/make.vim After: - unlet! b:tmp unlet! g:config_error_lines call ale#linter#Reset() -Execute(The elm-make handler should parse lines correctly): + +" Elm 0.19 + +Execute(The elm-make handler should parse Elm 0.19 general problems correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'type': 'E', + \ 'text': "error details\n\nstyled details" + \ } + \ ], + \ ale_linters#elm#make#Handle(347, [ + \ json_encode({ + \ 'type': 'error', + \ 'path': ale#util#Tempname() . '/Module.elm', + \ 'title': 'UNKNOWN IMPORT', + \ 'message': ["error details\n\n", { 'string': 'styled details' }] + \ }), + \ ]) + +Execute(The elm-make handler should parse Elm 0.19 compilation errors correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 404, + \ 'col': 1, + \ 'end_lnum': 408, + \ 'end_col': 18, + \ 'type': 'E', + \ 'text': "error details 1\n\nstyled details" + \ }, + \ { + \ 'lnum': 406, + \ 'col': 5, + \ 'end_lnum': 407, + \ 'end_col': 17, + \ 'type': 'E', + \ 'text': 'error details 2', + \ }, + \ { + \ 'lnum': 406, + \ 'col': 5, + \ 'end_lnum': 406, + \ 'end_col': 93, + \ 'type': 'E', + \ 'text': 'error details 3', + \ }, + \ ], + \ ale_linters#elm#make#Handle(347, [ + \ json_encode({ + \ 'type': 'compile-errors', + \ 'errors': [ + \ { + \ 'path': ale#util#Tempname() . '/Module.elm', + \ 'problems': [ + \ { + \ 'title': 'TYPE MISMATCH', + \ 'message': ["error details 1\n\n", { 'string': 'styled details' }], + \ 'region': { 'start': { 'line': 404, 'column': 1 }, 'end': { 'line': 408, 'column': 18 } } + \ }, + \ { + \ 'title': 'TYPE MISMATCH', + \ 'message': ['error details 2'], + \ 'region': { 'start': {'line': 406, 'column': 5}, 'end': {'line': 407, 'column': 17 } } + \ }, + \ { + \ 'title': 'TYPE MISMATCH', + \ 'message': ['error details 3'], + \ 'region': { 'start': { 'line': 406, 'column': 5}, 'end': {'line': 406, 'column': 93 } } + \ } + \ ] + \ } + \ ] + \ }), + \ ]) + +Execute(The elm-make handler should handle errors in Elm 0.19 imported modules): + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'type': 'E', + \ 'text': "src/Module.elm - error details\n\nstyled details", + \ 'detail': "src/Module.elm ----------\n\nerror details\n\nstyled details" + \ }, + \ { + \ 'lnum': 1, + \ 'type': 'E', + \ 'text': "Elm - error details\n\nstyled details", + \ 'detail': "Elm ----------\n\nerror details\n\nstyled details" + \ }, + \ { + \ 'lnum': 1, + \ 'type': 'E', + \ 'text': "src/Module.elm:404 - error details\n\nstyled details", + \ 'detail': "src/Module.elm:404 ----------\n\nerror details\n\nstyled details" + \ }, + \ ], + \ ale_linters#elm#make#Handle(347, [ + \ json_encode({ + \ 'type': 'error', + \ 'path': 'src/Module.elm', + \ 'title': 'UNKNOWN IMPORT', + \ 'message': ["error details\n\n", { 'string': 'styled details' }] + \ }), + \ json_encode({ + \ 'type': 'error', + \ 'path': v:null, + \ 'title': 'UNKNOWN IMPORT', + \ 'message': ["error details\n\n", { 'string': 'styled details' }] + \ }), + \ json_encode({ + \ 'type': 'compile-errors', + \ 'errors': [ + \ { + \ 'path': 'src/Module.elm', + \ 'problems': [ + \ { + \ 'title': 'TYPE MISMATCH', + \ 'message': ["error details\n\n", { 'string': 'styled details' }], + \ 'region': { 'start': { 'line': 404, 'column': 1 }, 'end': { 'line': 408, 'column': 18 } } + \ } + \ ] + \ } + \ ] + \ }), + \ ]) + + +" Elm 0.18 + +Execute(The elm-make handler should parse Elm 0.18 compilation errors correctly): AssertEqual \ [ \ { @@ -50,21 +179,90 @@ Execute(The elm-make handler should parse lines correctly): \ }, \ ], \ ale_linters#elm#make#Handle(347, [ - \ '[{"tag":"unused import","overview":"warning overview","details":"warning details","region":{"start":{"line":33,"column":1},"end":{"line":33,"column":19}},"type":"warning","file":"' . b:tmp . 'Module.elm"}]', - \ '[{"tag":"TYPE MISMATCH","overview":"error overview 1","subregion":{"start":{"line":406,"column":5},"end":{"line":408,"column":18}},"details":"error details 1","region":{"start":{"line":404,"column":1},"end":{"line":408,"column":18}},"type":"error","file":"' . b:tmp . 'Module.elm"},{"tag":"TYPE MISMATCH","overview":"error overview 2","subregion":{"start":{"line":407,"column":12},"end":{"line":407,"column":17}},"details":"error details 2","region":{"start":{"line":406,"column":5},"end":{"line":407,"column":17}},"type":"error","file":"' . b:tmp . 'Module.elm"},{"tag":"TYPE MISMATCH","overview":"error overview 3","subregion":{"start":{"line":406,"column":88},"end":{"line":406,"column":93}},"details":"error details 3","region":{"start":{"line":406,"column":5},"end":{"line":406,"column":93}},"type":"error","file":"' . b:tmp . 'Module.elm"}]' + \ json_encode([ + \ { + \ 'tag': 'unused import', + \ 'overview': 'warning overview', + \ 'details': 'warning details', + \ 'region': {'start': { 'line': 33, 'column': 1 }, 'end': { 'line': 33, 'column': 19 } }, + \ 'type': 'warning', + \ 'file': ale#util#Tempname() . '/Module.elm', + \ } + \ ]), + \ json_encode([ + \ { + \ 'tag': 'TYPE MISMATCH', + \ 'overview': 'error overview 1', + \ 'subregion': { 'start': { 'line': 406, 'column': 5 }, 'end': { 'line': 408, 'column': 18 } }, + \ 'details': 'error details 1', + \ 'region': { 'start': { 'line': 404, 'column': 1 }, 'end': { 'line': 408, 'column': 18 } }, + \ 'type': 'error', + \ 'file': ale#util#Tempname() . '/Module.elm', + \ }, + \ { + \ 'tag': 'TYPE MISMATCH', + \ 'overview': 'error overview 2', + \ 'subregion': { 'start': { 'line': 407, 'column': 12 }, 'end': { 'line': 407, 'column': 17 } }, + \ 'details': 'error details 2', + \ 'region': { 'start': { 'line': 406, 'column': 5}, 'end': { 'line': 407, 'column': 17 } }, + \ 'type':'error', + \ 'file': ale#util#Tempname() . '/Module.elm', + \ }, + \ { + \ 'tag': 'TYPE MISMATCH', + \ 'overview': 'error overview 3', + \ 'subregion': { 'start': { 'line': 406, 'column': 88 }, 'end': { 'line': 406, 'column': 93 } }, + \ 'details': 'error details 3', + \ 'region': { 'start': { 'line': 406, 'column': 5 }, 'end': { 'line': 406, 'column': 93 } }, + \ 'type':'error', + \ 'file': ale#util#Tempname() . '/Module.elm', + \ } + \ ]), \ ]) +Execute(The elm-make handler should handle errors in Elm 0.18 imported modules): + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'type': 'E', + \ 'text': 'src/Module.elm:33 - error overview', + \ 'detail': "src/Module.elm:33 ----------\n\nerror overview\n\nerror details" + \ } + \ ], + \ ale_linters#elm#make#Handle(347, [ + \ json_encode([ + \ { + \ 'tag': 'unused import', + \ 'overview': 'warning overview', + \ 'details': 'warning details', + \ 'region': {'start': { 'line': 33, 'column': 1 }, 'end': { 'line': 33, 'column': 19 } }, + \ 'type': 'warning', + \ 'file': 'src/Module.elm', + \ }, + \ { + \ 'tag': 'type error', + \ 'overview': 'error overview', + \ 'details': 'error details', + \ 'region': {'start': { 'line': 33, 'column': 1 }, 'end': { 'line': 33, 'column': 19 } }, + \ 'type': 'error', + \ 'file': 'src/Module.elm', + \ } + \ ]), + \ ]) + +" Generic + Execute(The elm-make handler should put an error on the first line if a line cannot be parsed): AssertEqual \ [ \ { - \ 'lnum': 33, + \ 'lnum': 404, \ 'col': 1, - \ 'end_lnum': 33, - \ 'end_col': 19, - \ 'type': 'W', - \ 'text': 'warning overview', - \ 'detail': "warning overview\n\nwarning details", + \ 'end_lnum': 408, + \ 'end_col': 18, + \ 'type': 'E', + \ 'text': "error details 1\n\nstyled details" \ }, \ { \ 'lnum': 1, @@ -74,7 +272,28 @@ Execute(The elm-make handler should put an error on the first line if a line can \ }, \ ], \ ale_linters#elm#make#Handle(347, [ - \ '[{"tag":"unused import","overview":"warning overview","details":"warning details","region":{"start":{"line":33,"column":1},"end":{"line":33,"column":19}},"type":"warning","file":"' . b:tmp . 'Module.elm"}]', - \ "Not JSON", - \ "Also not JSON", + \ json_encode({ + \ 'type': 'compile-errors', + \ 'errors': [ + \ { + \ 'path': ale#util#Tempname() . '/Module.elm', + \ 'problems': [ + \ { + \ 'title': 'TYPE MISMATCH', + \ 'message': ["error details 1\n\n", { 'string': 'styled details' }], + \ 'region': { 'start': { 'line': 404, 'column': 1 }, 'end': { 'line': 408, 'column': 18 } } + \ } + \ ] + \ } + \ ] + \ }), + \ 'Not JSON', + \ 'Also not JSON', + \ ]) + +Execute(The elm-make handler should ignore success lines): + AssertEqual + \ [], + \ ale_linters#elm#make#Handle(347, [ + \ 'Successfully generated /dev/null', \ ]) diff --git a/test/handler/test_fish_handler.vader b/test/handler/test_fish_handler.vader index 567952e4..ad3a963c 100644 --- a/test/handler/test_fish_handler.vader +++ b/test/handler/test_fish_handler.vader @@ -37,3 +37,25 @@ Execute(The fish handler should handle basic warnings and syntax errors): \ "abbr --add p 'cd ~/Projects'", \ '^', \ ]) + +Execute(The fish handler should handle problems where the problem before before the line with the line number): + AssertEqual + \ [ + \ { + \ 'lnum': 2, + \ 'col': 23, + \ 'text': 'Unsupported use of ''||''. In fish, please use ''COMMAND; or COMMAND''.', + \ }, + \ { + \ 'lnum': 5, + \ 'col': 1, + \ 'text': 'wat', + \ }, + \ ], + \ ale_linters#fish#fish#Handle(bufnr(''), [ + \ 'Unsupported use of ''||''. In fish, please use ''COMMAND; or COMMAND''.', + \ '/tmp/vLz620o/258/test.fish (line 2): if set -q SSH_CLIENT || set -q SSH_TTY', + \ ' ^', + \ '/tmp/vLz620o/258/test.fish (line 5): wat', + \ ' ^', + \ ]) diff --git a/test/handler/test_flake8_handler.vader b/test/handler/test_flake8_handler.vader index 492941c9..efacdfb2 100644 --- a/test/handler/test_flake8_handler.vader +++ b/test/handler/test_flake8_handler.vader @@ -214,3 +214,33 @@ Execute(Disabling trailing blank line warnings should work): \ ale_linters#python#flake8#Handle(bufnr(''), [ \ 'foo.py:6:1: W391 blank line at end of file', \ ]) + +Execute(F401 should be a warning): + AssertEqual + \ [ + \ { + \ 'lnum': 6, + \ 'col': 1, + \ 'code': 'F401', + \ 'type': 'W', + \ 'text': 'module imported but unused', + \ }, + \ ], + \ ale_linters#python#flake8#Handle(bufnr(''), [ + \ 'foo.py:6:1: F401 module imported but unused', + \ ]) + +Execute(E112 should be a syntax error): + AssertEqual + \ [ + \ { + \ 'lnum': 6, + \ 'col': 1, + \ 'code': 'E112', + \ 'type': 'E', + \ 'text': 'expected an indented block', + \ }, + \ ], + \ ale_linters#python#flake8#Handle(bufnr(''), [ + \ 'foo.py:6:1: E112 expected an indented block', + \ ]) diff --git a/test/handler/test_flawfinder_handler.vader b/test/handler/test_flawfinder_handler.vader new file mode 100644 index 00000000..708bac2a --- /dev/null +++ b/test/handler/test_flawfinder_handler.vader @@ -0,0 +1,57 @@ +Before: + Save g:ale_c_flawfinder_error_severity + + unlet! g:ale_c_flawfinder_error_severity + unlet! b:ale_c_flawfinder_error_severity + + runtime ale_linters/c/flawfinder.vim + +After: + unlet! g:ale_c_flawfinder_error_severity + Restore + +Execute(The Flawfinder handler should ignore other lines of output): + AssertEqual + \ [], + \ ale#handlers#flawfinder#HandleFlawfinderFormat(347, [ + \ 'foo', + \ 'bar', + \ 'baz', + \ ]) + +Execute(The Flawfinder handler should work): + AssertEqual + \ [ + \ { + \ 'lnum': 31, + \ 'col': 4, + \ 'type': 'W', + \ 'text': "(buffer) strncpy: Easily used incorrectly", + \ }, + \ ], + \ ale#handlers#flawfinder#HandleFlawfinderFormat(347, [ + \ "<stdin>:31:4: [1] (buffer) strncpy:Easily used incorrectly", + \ ]) + +Execute(The Flawfinder error severity level should be configurable): + let b:ale_c_flawfinder_error_severity = 2 + + AssertEqual + \ [ + \ { + \ 'lnum': 12, + \ 'col': 4, + \ 'type': 'E', + \ 'text': "(buffer) char: Statically-sized arrays can be bad", + \ }, + \ { + \ 'lnum': 31, + \ 'col': 4, + \ 'type': 'W', + \ 'text': "(buffer) strncpy: Easily used incorrectly", + \ }, + \ ], + \ ale#handlers#flawfinder#HandleFlawfinderFormat(bufnr(''), [ + \ "<stdin>:12:4: [2] (buffer) char:Statically-sized arrays can be bad", + \ "<stdin>:31:4: [1] (buffer) strncpy:Easily used incorrectly", + \ ]) diff --git a/test/handler/test_gawk_handler.vader b/test/handler/test_gawk_handler.vader new file mode 100644 index 00000000..3a7b5457 --- /dev/null +++ b/test/handler/test_gawk_handler.vader @@ -0,0 +1,39 @@ +Before: + runtime ale_linters/awk/gawk.vim + +After: + call ale#linter#Reset() + +Execute(gawk syntax errors should be parsed correctly): + + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'col': 0, + \ 'text': "invalid char ''' in expression", + \ 'code': 0, + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 5, + \ 'col': 0, + \ 'text': 'unterminated string', + \ 'code': 0, + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 10, + \ 'col': 0, + \ 'text': "escape sequence `\u' treated as plain `u'", + \ 'code': 0, + \ 'type': 'W', + \ }, + \ ], + \ ale#handlers#gawk#HandleGawkFormat(347, [ + \ "gawk: something.awk:1: BEGIN { system('touch aaaaaaaaa') }", + \ "gawk: something.awk:1: ^ invalid char ''' in expression", + \ 'gawk: something.awk:5: { x = "aaaaaaaaaaa', + \ 'gawk: something.awk:5: ^ unterminated string', + \ "gawk: something.awk:10: warning: escape sequence `\u' treated as plain `u'", + \ ]) diff --git a/test/handler/test_gcc_handler.vader b/test/handler/test_gcc_handler.vader index 79f17899..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,6 +200,20 @@ 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', \ ]) + +Execute(The GCC handler should handle fatal error messages due to missing files): + AssertEqual + \ [ + \ { + \ 'lnum': 3, + \ 'col': 12, + \ 'type': 'E', + \ 'text': 'foo.h: No such file or directory' + \ }, + \ ], + \ 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 73ee988f..60d632a0 100644 --- a/test/handler/test_gitlint_handler.vader +++ b/test/handler/test_gitlint_handler.vader @@ -1,8 +1,16 @@ Before: - runtime ale_linters/gitcommit/gitlint.vim + Save g:ale_warn_about_trailing_whitespace + + let g:ale_warn_about_trailing_whitespace = 1 + + runtime ale_linters/gitcommit/gitlint.vim After: - call ale#linter#Reset() + Restore + + unlet! b:ale_warn_about_trailing_whitespace + + call ale#linter#Reset() Execute(The gitlint handler should handle basic warnings and syntax errors): AssertEqual @@ -39,3 +47,24 @@ Execute(The gitlint handler should handle basic warnings and syntax errors): \ '8: T1 Title exceeds max length (92>72): "some very long commit subject line where the author can''t wait to explain what he just fixed"' \ ]) +Execute(Disabling trailing whitespace warnings should work): + AssertEqual + \ [ + \ { + \ 'lnum': 8, + \ 'type': 'E', + \ 'text': 'Trailing whitespace', + \ 'code': 'T2', + \ }, + \ ], + \ ale_linters#gitcommit#gitlint#Handle(bufnr(''), [ + \ '8: T2 Trailing whitespace', + \]) + + let b:ale_warn_about_trailing_whitespace = 0 + + AssertEqual + \ [], + \ ale_linters#gitcommit#gitlint#Handle(bufnr(''), [ + \ '8: T2 Trailing whitespace', + \ ]) diff --git a/test/handler/test_go_generic_handler.vader b/test/handler/test_go_generic_handler.vader new file mode 100644 index 00000000..624e56c1 --- /dev/null +++ b/test/handler/test_go_generic_handler.vader @@ -0,0 +1,22 @@ +Execute(The golang handler should return the correct filenames): + AssertEqual + \ [ + \ { + \ 'lnum': 27, + \ 'col': 0, + \ 'text': 'some error', + \ 'type': 'E', + \ 'filename': ale#path#Simplify(expand('%:p:h') . '/test.go'), + \ }, + \ { + \ 'lnum': 27, + \ 'col': 5, + \ 'text': 'some error with a column', + \ 'type': 'E', + \ 'filename': ale#path#Simplify(expand('%:p:h') . '/other.go'), + \ }, + \ ], + \ ale#handlers#go#Handler(bufnr(''), [ + \ 'test.go:27: some error', + \ 'other.go:27:5: some error with a column', + \ ]) diff --git a/test/handler/test_markdownlint_handler.vader b/test/handler/test_markdownlint_handler.vader new file mode 100644 index 00000000..db6acc66 --- /dev/null +++ b/test/handler/test_markdownlint_handler.vader @@ -0,0 +1,24 @@ +Before: + runtime ale_linters/markdown/markdownlint.vim + +After: + call ale#linter#Reset() + +Execute(The Markdownlint handler should parse output correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'text': '(MD002/first-header-h1) First header should be a top level header [Expected: h1; Actual: h2]', + \ 'type': 'W' + \ }, + \ { + \ 'lnum': 298, + \ 'text': '(MD033/no-inline-html) Inline HTML [Element: p]', + \ 'type': 'W' + \ } + \ ], + \ ale#handlers#markdownlint#Handle(0, [ + \ 'README.md: 1: MD002/first-header-h1 First header should be a top level header [Expected: h1; Actual: h2]', + \ 'README.md: 298: MD033/no-inline-html Inline HTML [Element: p]' + \ ]) diff --git a/test/handler/test_mcsc_handler.vader b/test/handler/test_mcsc_handler.vader index ac55ee81..8ae47357 100644 --- a/test/handler/test_mcsc_handler.vader +++ b/test/handler/test_mcsc_handler.vader @@ -3,10 +3,15 @@ Before: unlet! g:ale_cs_mcsc_source + call ale#test#SetDirectory('/testplugin/test/handler') + call ale#test#SetFilename('Test.cs') + runtime ale_linters/cs/mcsc.vim After: unlet! g:ale_cs_mcsc_source + + call ale#test#RestoreDirectory() call ale#linter#Reset() Execute(The mcs handler should work with the default of the buffer's directory): @@ -18,10 +23,10 @@ Execute(The mcs handler should work with the default of the buffer's directory): \ 'text': '; expected', \ 'code': 'CS1001', \ 'type': 'E', - \ 'filename': ale#path#Simplify(expand('%:p:h') . '/Test.cs'), + \ 'filename': ale#path#Simplify(g:dir . '/Test.cs'), \ }, \ ], - \ ale_linters#cs#mcsc#Handle(347, [ + \ ale_linters#cs#mcsc#Handle(bufnr(''), [ \ 'Test.cs(12,29): error CS1001: ; expected', \ 'Compilation failed: 2 error(s), 1 warnings', \ ]) @@ -56,7 +61,7 @@ Execute(The mcs handler should handle cannot find symbol errors): \ 'filename': ale#path#Simplify('/home/foo/project/bar/Test.cs'), \ }, \ ], - \ ale_linters#cs#mcsc#Handle(347, [ + \ ale_linters#cs#mcsc#Handle(bufnr(''), [ \ 'Test.cs(12,29): error CS1001: ; expected', \ 'Test.cs(101,0): error CS1028: Unexpected processor directive (no #if for this #endif)', \ 'Test.cs(10,12): warning CS0123: some warning', diff --git a/test/handler/test_mercury_mmc_handler.vader b/test/handler/test_mercury_mmc_handler.vader new file mode 100644 index 00000000..e862f287 --- /dev/null +++ b/test/handler/test_mercury_mmc_handler.vader @@ -0,0 +1,58 @@ +Before: + runtime ale_linters/mercury/mmc.vim + +After: + call ale#linter#Reset() + +Execute(The mmc handler should handle syntax errors): + AssertEqual + \ [ + \ { + \ 'lnum': 3, + \ 'type': 'E', + \ 'text': "Syntax error at token ',': operator precedence error." + \ } + \ ], + \ ale_linters#mercury#mmc#Handle(1, [ + \ "file_name.m:003: Syntax error at token ',': operator precedence error." + \ ]) + +Execute(The mmc handler should handle warnings): + AssertEqual + \ [ + \ { + \ 'lnum': 10, + \ 'type': 'W', + \ 'text': 'Warning: reference to uninitialized state variable !.X.' + \ }, + \ { + \ 'lnum': 12, + \ 'type': 'W', + \ 'text': 'warning: determinism declaration could be tighter.' + \ } + \ ], + \ ale_linters#mercury#mmc#Handle(1, [ + \ 'file_name.m:010: Warning: reference to uninitialized state variable !.X.', + \ "file_name.m:012: In `some_predicate':", + \ 'file_name.m:012: warning: determinism declaration could be tighter.' + \ ]) + +Execute(The mmc handler should handle semantic errors): + AssertEqual + \ [ + \ { + \ 'lnum': 7, + \ 'type': 'E', + \ 'text': "error: undefined type `bar'/0." + \ }, + \ { + \ 'lnum': 15, + \ 'type': 'E', + \ 'text': "Error: circular equivalence type `file_name.foo'/0." + \ } + \ ], + \ ale_linters#mercury#mmc#Handle(1, [ + \ "file_name.m:007: In clause for predicate `foldit'/4:", + \ "file_name.m:007: error: undefined type `bar'/0.", + \ "file_name.m:015: Error: circular equivalence type `file_name.foo'/0." + \ ]) diff --git a/test/handler/test_mix_handler.vader b/test/handler/test_mix_handler.vader new file mode 100644 index 00000000..a5549b5d --- /dev/null +++ b/test/handler/test_mix_handler.vader @@ -0,0 +1,21 @@ +Before: + runtime ale_linters/elixir/mix.vim + +After: + call ale#linter#Reset() + +Execute(The mix handler should parse lines correctly): + + AssertEqual + \ [ + \ { + \ 'bufnr': 347, + \ 'lnum': 87, + \ 'col': 0, + \ 'text': 'undefined function update_in/4', + \ 'type': 'E', + \ }, + \ ], + \ ale_linters#elixir#mix#Handle(347, [ + \ '** (CompileError) apps/sim/lib/sim/server.ex:87: undefined function update_in/4' + \ ]) diff --git a/test/handler/test_msgfmt_hander.vader b/test/handler/test_msgfmt_hander.vader new file mode 100644 index 00000000..1a67dbc6 --- /dev/null +++ b/test/handler/test_msgfmt_hander.vader @@ -0,0 +1,24 @@ +Before: + runtime ale_linters/po/msgfmt.vim + +After: + call ale#linter#Reset() + +Execute(Duplicate messages should be made easier to navigate): + AssertEqual + \ [ + \ {'lnum': 14, 'col': 0, 'type': 'W', 'text': 'some other thing'}, + \ {'lnum': 1746, 'col': 0, 'type': 'W', 'text': 'duplicate of message at line 262'}, + \ {'lnum': 262, 'col': 0, 'type': 'W', 'text': 'first location of duplicate of message at line 1746'}, + \ {'lnum': 666, 'col': 0, 'type': 'W', 'text': 'duplicate message definition...'}, + \ {'lnum': 888, 'col': 0, 'type': 'W', 'text': 'some other thing'}, + \ {'lnum': 999, 'col': 0, 'type': 'W', 'text': '...this is the location of the first definition'}, + \ ], + \ ale_linters#po#msgfmt#Handle(bufnr(''), [ + \ '/tmp/v6GMUFf/16/foo.po:14: some other thing', + \ '/tmp/v6GMUFf/16/foo.po:1746: duplicate message definition...', + \ '/tmp/v6GMUFf/16/foo.po:262: ...this is the location of the first definition', + \ '/tmp/v6GMUFf/16/foo.po:666: duplicate message definition...', + \ '/tmp/v6GMUFf/16/foo.po:888: some other thing', + \ '/tmp/v6GMUFf/16/foo.po:999: ...this is the location of the first definition', + \ ]) diff --git a/test/handler/test_nasm_handler.vader b/test/handler/test_nasm_handler.vader new file mode 100644 index 00000000..9c7d9650 --- /dev/null +++ b/test/handler/test_nasm_handler.vader @@ -0,0 +1,30 @@ +Before: + runtime ale_linters/nasm/nasm.vim + +After: + call ale#linter#Reset() + +Execute(The nasm handler should parse GCC style output from nasm correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 2, + \ 'text': "label alone on a line without a colon might be in error", + \ 'type': 'W', + \ }, + \ { + \ 'lnum': 4, + \ 'text': "invalid combination of opcode and operands", + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 7, + \ 'text': "unable to open include file `bar.asm'", + \ 'type': 'E', + \ }, + \ ], + \ ale_linters#nasm#nasm#Handle(bufnr(''), [ + \ "tmp.asm:2: warning: label alone on a line without a colon might be in error", + \ "tmp.asm:4: error: invalid combination of opcode and operands", + \ "tmp.asm:7: fatal: unable to open include file `bar.asm'" + \ ]) diff --git a/test/handler/test_perl_handler.vader b/test/handler/test_perl_handler.vader index 75e8f226..c5791d76 100644 --- a/test/handler/test_perl_handler.vader +++ b/test/handler/test_perl_handler.vader @@ -47,3 +47,42 @@ Execute(The Perl linter should complain about failing to locate modules): \ 'Unable to build `ro` accessor for slot `path` in `App::CPANFileUpdate` because the slot cannot be found. at /extlib/Method/Traits.pm line 189.', \ 'BEGIN failed--compilation aborted at - line 10.', \ ]) + +Execute(The Perl linter should not report warnings as errors): + AssertEqual + \ [ + \ {'lnum': '5', 'type': 'W', 'text': '"my" variable $foo masks earlier declaration in same scope'}, + \ ], + \ ale_linters#perl#perl#Handle(bufnr(''), [ + \ '"my" variable $foo masks earlier declaration in same scope at - line 5.', + \ 't.pl syntax OK', + \ ]) + +Execute(The Perl linter does not default to reporting generic error): + AssertEqual + \ [ + \ {'lnum': '8', 'type': 'E', 'text': 'Missing right curly or square bracket'}, + \ ], + \ ale_linters#perl#perl#Handle(bufnr(''), [ + \ 'Missing right curly or square bracket at - line 8, at end of line', + \ 'syntax error at - line 8, at EOF', + \ 'Execution of t.pl aborted due to compilation errors.', + \ ]) + +" The first "error" is actually a warning, but the current implementation +" doesn't have a good way of teasing out the warnings from amongst the +" errors. If we're able to do this in future, then we'll want to switch +" the first "E" to a "W". + +Execute(The Perl linter reports errors even when mixed with warnings): + AssertEqual + \ [ + \ {'lnum': '5', 'type': 'E', 'text': '"my" variable $foo masks earlier declaration in same scope'}, + \ {'lnum': '8', 'type': 'E', 'text': 'Missing right curly or square bracket'}, + \ ], + \ ale_linters#perl#perl#Handle(bufnr(''), [ + \ '"my" variable $foo masks earlier declaration in same scope at - line 5.', + \ 'Missing right curly or square bracket at - line 8, at end of line', + \ 'syntax error at - line 8, at EOF', + \ 'Execution of t.pl aborted due to compilation errors.', + \ ]) diff --git a/test/handler/test_pmd_handler.vader b/test/handler/test_pmd_handler.vader new file mode 100644 index 00000000..0c95fb2a --- /dev/null +++ b/test/handler/test_pmd_handler.vader @@ -0,0 +1,27 @@ +Before: + runtime ale_linters/java/pmd.vim + +After: + call ale#linter#Reset() + +Execute(The pmd handler should parse lines correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 18, + \ 'text': 'Each class should declare at least one constructor', + \ 'code': 'Code Style - AtLeastOneConstructor', + \ 'type': 'W', + \ }, + \ { + \ 'lnum': 36, + \ 'text': 'Local variable ''node'' could be declared final', + \ 'code': 'Code Style - LocalVariableCouldBeFinal', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#java#pmd#Handle(666, [ + \ '"Problem","Package","File","Priority","Line","Description","Rule set","Rule"', + \ '"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"' + \ ]) diff --git a/test/handler/test_pony_handler.vader b/test/handler/test_pony_handler.vader new file mode 100644 index 00000000..25a8254b --- /dev/null +++ b/test/handler/test_pony_handler.vader @@ -0,0 +1,21 @@ +Execute(The pony handler should handle ponyc output): + call ale#test#SetFilename('foo.pony') + + AssertEqual + \ [ + \ { + \ 'filename': '/home/projects/Wombat.pony', + \ 'lnum': 22, + \ 'type': 'E', + \ 'col': 30, + \ 'text': 'can''t lookup private fields from outside the type', + \ }, + \ ], + \ ale#handlers#pony#HandlePonycFormat(bufnr(''), [ + \ 'Building builtin -> /usr/lib/pony/0.21.3/packages/builtin', + \ 'Building . -> /home/projects', + \ 'Error:', + \ '/home/projects/Wombat.pony:22:30: can''t lookup private fields from outside the type', + \ ' env.out.print(defaultWombat._hunger_level)', + \ ' ^', + \ ]) diff --git a/test/handler/test_prospector_handler.vader b/test/handler/test_prospector_handler.vader index 7962f6cd..935c37da 100644 --- a/test/handler/test_prospector_handler.vader +++ b/test/handler/test_prospector_handler.vader @@ -156,3 +156,8 @@ Execute(Ignoring trailing whitespace messages should work): \ ' ]', \ '}', \ ]) + +Execute(The prospector handler should handle empty output): + AssertEqual + \ [], + \ ale_linters#python#prospector#Handle(bufnr(''), []) diff --git a/test/handler/test_puppet_handler.vader b/test/handler/test_puppet_handler.vader index 0d274fd2..e73c9dc7 100644 --- a/test/handler/test_puppet_handler.vader +++ b/test/handler/test_puppet_handler.vader @@ -37,9 +37,15 @@ Execute(The puppet handler should parse lines and column correctly): \ 'lnum': 54, \ 'col': 9, \ 'text': "Syntax error at ':'" - \ } + \ }, + \ { + \ 'lnum': 45, + \ 'col': 12, + \ 'text': "Syntax error at 'parameter1'" + \ }, \ ], \ ale_linters#puppet#puppet#Handle(255, [ \ "Error: Could not parse for environment production: Syntax error at ':' at /root/puppetcode/modules/nginx/manifests/init.pp:43:12", \ "Error: Could not parse for environment production: Syntax error at ':' at C:/puppet/modules/nginx/manifests/init.pp:54:9", + \ "Error: Could not parse for environment production: Syntax error at 'parameter1' (file: /tmp/modules/mariadb/manifests/slave.pp, line: 45, column: 12)", \ ]) diff --git a/test/handler/test_pycodestyle_handler.vader b/test/handler/test_pycodestyle_handler.vader index 0fd885d6..3664455e 100644 --- a/test/handler/test_pycodestyle_handler.vader +++ b/test/handler/test_pycodestyle_handler.vader @@ -137,3 +137,18 @@ Execute(Disabling trailing blank line warnings should work): \ ale_linters#python#pycodestyle#Handle(bufnr(''), [ \ 'foo.py:6:1: W391 blank line at end of file', \ ]) + +Execute(E112 should be a syntax error): + AssertEqual + \ [ + \ { + \ 'lnum': 6, + \ 'col': 1, + \ 'code': 'E112', + \ 'type': 'E', + \ 'text': 'expected an indented block', + \ }, + \ ], + \ ale_linters#python#pycodestyle#Handle(bufnr(''), [ + \ 'foo.py:6:1: E112 expected an indented block', + \ ]) diff --git a/test/handler/test_pylint_handler.vader b/test/handler/test_pylint_handler.vader index aff40845..18f66526 100644 --- a/test/handler/test_pylint_handler.vader +++ b/test/handler/test_pylint_handler.vader @@ -94,3 +94,22 @@ Execute(Ignoring trailing whitespace messages should work): \ '------------------------------------------------------------------', \ 'Your code has been rated at 0.00/10 (previous run: 2.50/10, -2.50)', \ ]) + +Execute(The pylint handler should parse Windows filenames): + AssertEqual + \ [ + \ { + \ 'lnum': 13, + \ 'col': 6, + \ 'text': 'Undefined variable ''x''', + \ 'code': 'undefined-variable', + \ 'type': 'E', + \ }, + \ ], + \ ale_linters#python#pylint#Handle(bufnr(''), [ + \ '************* Module test', + \ 'D:\acm\github\vim\tools\test.py:13:5: E0602 (undefined-variable) Undefined variable ''x''', + \ '', + \ '------------------------------------------------------------------', + \ 'Your code has been rated at 5.83/10 (previous run: 5.83/10, +0.00)', + \ ]) diff --git a/test/handler/test_pyrex_cython_handler.vader b/test/handler/test_pyrex_cython_handler.vader new file mode 100644 index 00000000..fd0f9a8b --- /dev/null +++ b/test/handler/test_pyrex_cython_handler.vader @@ -0,0 +1,26 @@ +Before: + runtime ale_linters/pyrex/cython.vim + +After: + call ale#linter#Reset() + +Execute(The cython handler should handle warnings and errors): + AssertEqual + \ [ + \ { + \ 'lnum': 42, + \ 'col': 7, + \ 'text': 'some warning', + \ 'type': 'W', + \ }, + \ { + \ 'lnum': 777, + \ 'col': 21, + \ 'text': 'some error', + \ 'type': 'E', + \ }, + \ ], + \ ale_linters#pyrex#cython#Handle(347, [ + \ 'warning: file:42:7: some warning', + \ 'file:777:21: some error', + \ ]) diff --git a/test/handler/test_qmlfmt_handler.vader b/test/handler/test_qmlfmt_handler.vader new file mode 100644 index 00000000..fc8ef355 --- /dev/null +++ b/test/handler/test_qmlfmt_handler.vader @@ -0,0 +1,19 @@ +Before: + runtime ale_linters/qml/qmlfmt.vim + +After: + call ale#linter#Reset() + +Execute(The qmlfmt handler should parse error messages correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 22, + \ 'col': 1, + \ 'type': 'E', + \ 'text': 'Expected token ''}''.' + \ } + \ ], + \ ale_linters#qml#qmlfmt#Handle(1, [ + \ 'Error:22:1: Expected token ''}''.' + \ ]) diff --git a/test/handler/test_qmllint_handler.vader b/test/handler/test_qmllint_handler.vader new file mode 100644 index 00000000..fcc65eb5 --- /dev/null +++ b/test/handler/test_qmllint_handler.vader @@ -0,0 +1,19 @@ +Before: + runtime ale_linters/qml/qmllint.vim + +After: + call ale#linter#Reset() + +Execute(The qmllint handler should parse error messages correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 2, + \ 'col': 0, + \ 'type': 'E', + \ 'text': 'Expected token ''}''' + \ } + \ ], + \ ale_linters#qml#qmllint#Handle(1, [ + \ '/tmp/ab34cd56/Test.qml:2 : Expected token ''}''' + \ ]) diff --git a/test/handler/test_redpen_handler.vader b/test/handler/test_redpen_handler.vader index f28d6923..4490bcba 100644 --- a/test/handler/test_redpen_handler.vader +++ b/test/handler/test_redpen_handler.vader @@ -23,6 +23,15 @@ Execute(redpen handler should handle errors output): \ 'type': 'W', \ 'code': 'Spelling', \ }, + \ { + \ 'lnum': 1, + \ 'col': 35, + \ 'end_lnum': 1, + \ 'end_col': 55, + \ 'text': 'Found possibly misspelled word "コードチェック".', + \ 'type': 'W', + \ 'code': 'Spelling', + \ }, \ ], \ ale#handlers#redpen#HandleRedpenOutput(bufnr(''), [ \ '[', @@ -50,6 +59,21 @@ Execute(redpen handler should handle errors output): \ ' "lineNum": 1,', \ ' "sentenceStartColumnNum": 0,', \ ' "message": "Found possibly misspelled word \"NeoVim\"."', + \ ' },', + \ ' {', + \ ' "sentence": "ALEはNeoVimとVim8で非同期のコードチェックを実現するプラグインです。",', + \ ' "endPosition": {', + \ ' "offset": 27,', + \ ' "lineNum": 1', + \ ' },', + \ ' "validator": "Spelling",', + \ ' "lineNum": 1,', + \ ' "sentenceStartColumnNum": 0,', + \ ' "message": "Found possibly misspelled word \"コードチェック\".",', + \ ' "startPosition": {', + \ ' "offset": 20,', + \ ' "lineNum": 1', + \ ' }', \ ' }', \ ' ]', \ ' }', diff --git a/test/handler/test_remark_lint_handler.vader b/test/handler/test_remark_lint_handler.vader index f61da199..0794d51c 100644 --- a/test/handler/test_remark_lint_handler.vader +++ b/test/handler/test_remark_lint_handler.vader @@ -19,12 +19,21 @@ Execute(Warning and error messages should be handled correctly): \ 'type': 'E', \ 'text': 'Incorrect list-item indent: remove 1 space list-item-indent remark-lint', \ }, + \ { + \ 'lnum': 18, + \ 'col': 71, + \ 'end_lnum': 19, + \ 'end_col': 1, + \ 'type': 'E', + \ 'text': 'Missing new line after list item list-item-spacing remark-lint', + \ }, \ ], \ ale_linters#markdown#remark_lint#Handle(1, [ \ 'foo.md', \ ' 1:4 warning Incorrect list-item indent: add 1 space list-item-indent remark-lint', \ ' 3:5 error Incorrect list-item indent: remove 1 space list-item-indent remark-lint', + \ ' 18:71-19:1 error Missing new line after list item list-item-spacing remark-lint', \ '', \ '⚠ 1 warnings', - \ '✘ 1 errors', + \ '✘ 2 errors', \]) diff --git a/test/handler/test_rust_handler.vader b/test/handler/test_rust_handler.vader index 05bd1e94..e3ab3e86 100644 --- a/test/handler/test_rust_handler.vader +++ b/test/handler/test_rust_handler.vader @@ -7,16 +7,16 @@ Execute(The Rust handler should handle rustc output): \ 'lnum': 15, \ 'end_lnum': 15, \ 'type': 'E', - \ 'col': 418, - \ 'end_col': 421, + \ 'col': 5, + \ 'end_col': 8, \ 'text': 'expected one of `.`, `;`, `?`, `}`, or an operator, found `for`', \ }, \ { \ 'lnum': 13, \ 'end_lnum': 13, \ 'type': 'E', - \ 'col': 407, - \ 'end_col': 410, + \ 'col': 7, + \ 'end_col': 10, \ 'text': 'no method named `wat` found for type `std::string::String` in the current scope', \ }, \ ], @@ -83,16 +83,16 @@ Execute(The Rust handler should handle cargo output): \ 'lnum': 15, \ 'end_lnum': 15, \ 'type': 'E', - \ 'col': 11505, - \ 'end_col': 11508, + \ 'col': 5, + \ 'end_col': 8, \ 'text': 'expected one of `.`, `;`, `?`, `}`, or an operator, found `for`', \ }, \ { \ 'lnum': 13, \ 'end_lnum': 13, \ 'type': 'E', - \ 'col': 11494, - \ 'end_col': 11497, + \ 'col': 7, + \ 'end_col': 10, \ 'text': 'no method named `wat` found for type `std::string::String` in the current scope', \ }, \ ], @@ -157,8 +157,8 @@ Execute(The Rust handler should should errors from expansion spans): \ 'lnum': 4, \ 'end_lnum': 4, \ 'type': 'E', - \ 'col': 52, - \ 'end_col': 54, + \ 'col': 21, + \ 'end_col': 23, \ 'text': 'mismatched types: expected bool, found integral variable', \ }, \ ], @@ -207,8 +207,8 @@ Execute(The Rust handler should show detailed errors): \ 'lnum': 4, \ 'end_lnum': 4, \ 'type': 'E', - \ 'col': 52, - \ 'end_col': 54, + \ 'col': 21, + \ 'end_col': 23, \ 'text': 'mismatched types: expected bool, found integral variable', \ }, \ ], diff --git a/test/handler/test_scala_handler.vader b/test/handler/test_scala_handler.vader new file mode 100644 index 00000000..3214bdbc --- /dev/null +++ b/test/handler/test_scala_handler.vader @@ -0,0 +1,32 @@ +After: + call ale#linter#Reset() + +Execute(The handler should return an empty list with empty input): + AssertEqual [], ale#handlers#scala#HandleScalacLintFormat(bufnr(''), []) + +Execute(The handler should correctly parse error messages): + AssertEqual + \ [ + \ { + \ 'lnum': 4, + \ 'col': 8, + \ 'text': ''':'' expected but identifier found.', + \ 'type': 'E' + \ }, + \ { + \ 'lnum': 6, + \ 'col': 2, + \ 'text': 'identifier expected but eof found.', + \ 'type': 'E' + \ } + \ ], + \ ale#handlers#scala#HandleScalacLintFormat(bufnr(''), + \ [ + \ "hi.scala:4: error: ':' expected but identifier found.", + \ " Some stupid scala code", + \ " ^", + \ "hi.scala:6: error: identifier expected but eof found.", + \ ")", + \ " ^", + \ "two errors found", + \ ]) diff --git a/test/handler/test_scalac_handler.vader b/test/handler/test_scalac_handler.vader deleted file mode 100644 index fd222f67..00000000 --- a/test/handler/test_scalac_handler.vader +++ /dev/null @@ -1,18 +0,0 @@ -Before: - runtime ale_linters/scala/scalac.vim - -After: - call ale#linter#Reset() - -Given scala(An empty Scala file): - -Execute(The default executable and command should be correct): - AssertEqual 'scalac', ale_linters#scala#scalac#GetExecutable(bufnr('')) - AssertEqual - \ ale#Escape('scalac') . ' -Ystop-after:parser %t', - \ ale_linters#scala#scalac#GetCommand(bufnr('')) - -Given scala.sbt(An empty SBT file): -Execute(scalac should not be run for sbt files): - AssertEqual '', ale_linters#scala#scalac#GetExecutable(bufnr('')) - AssertEqual '', ale_linters#scala#scalac#GetCommand(bufnr('')) diff --git a/test/handler/test_textlint_handler.vader b/test/handler/test_textlint_handler.vader new file mode 100644 index 00000000..c00d54de --- /dev/null +++ b/test/handler/test_textlint_handler.vader @@ -0,0 +1,41 @@ +Before: + runtime! ale_linters/markdown/textlint.vim + +After: + call ale#linter#Reset() + +Execute(textlint handler should handle errors output): + AssertEqual + \ [ + \ { + \ 'lnum': 16, + \ 'col': 50, + \ 'text': 'Found possibly misspelled word "NeoVim".', + \ 'type': 'W', + \ 'code': 'preset-japanese/no-doubled-joshi', + \ }, + \ ], + \ ale#handlers#textlint#HandleTextlintOutput(bufnr(''), [ + \ '[', + \ ' {', + \ ' "filePath": "test.md",', + \ ' "messages": [', + \ ' {', + \ ' "type": "lint",', + \ ' "ruleId": "preset-japanese/no-doubled-joshi",', + \ ' "index": 1332,', + \ ' "line": 16,', + \ ' "column": 50,', + \ ' "severity": 2,', + \ ' "message": "Found possibly misspelled word \"NeoVim\"."', + \ ' }', + \ ' ]', + \ ' }', + \ ']', + \ ]) + +Execute(textlint handler should no error output): + AssertEqual + \ [], + \ ale#handlers#textlint#HandleTextlintOutput(bufnr(''), [ + \ ]) 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/handler/test_yamllint_handler.vader b/test/handler/test_yamllint_handler.vader new file mode 100644 index 00000000..1aa0b9f5 --- /dev/null +++ b/test/handler/test_yamllint_handler.vader @@ -0,0 +1,59 @@ +Before: + Save g:ale_warn_about_trailing_whitespace + + let g:ale_warn_about_trailing_whitespace = 1 + + runtime! ale_linters/yaml/yamllint.vim + +After: + Restore + + unlet! b:ale_warn_about_trailing_whitespace + + call ale#linter#Reset() + +Execute(Problems should be parsed correctly for yamllint): + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'col': 1, + \ 'type': 'W', + \ 'text': 'missing document start "---"', + \ 'code': 'document-start', + \ }, + \ { + \ 'lnum': 2, + \ 'col': 1, + \ 'type': 'E', + \ 'text': 'syntax error: expected the node content, but found ''<stream end>''', + \ }, + \ ], + \ ale_linters#yaml#yamllint#Handle(bufnr(''), [ + \ 'something.yaml:1:1: [warning] missing document start "---" (document-start)', + \ 'something.yml:2:1: [error] syntax error: expected the node content, but found ''<stream end>''', + \ ]) + +Execute(The yamllint handler should respect ale_warn_about_trailing_whitespace): + AssertEqual + \ [ + \ { + \ 'lnum': 5, + \ 'col': 18, + \ 'type': 'E', + \ 'text': 'trailing spaces', + \ 'code': 'trailing-spaces', + \ }, + \ ], + \ ale_linters#yaml#yamllint#Handle(bufnr(''), [ + \ 'something.yml:5:18: [error] trailing spaces (trailing-spaces)', + \ ]) + + let b:ale_warn_about_trailing_whitespace = 0 + + AssertEqual + \ [ + \ ], + \ ale_linters#yaml#yamllint#Handle(bufnr(''), [ + \ 'something.yml:5:18: [error] trailing spaces (trailing-spaces)', + \ ]) diff --git a/test/lsp/test_did_save_event.vader b/test/lsp/test_did_save_event.vader index 042a3ce2..f8ff8f70 100644 --- a/test/lsp/test_did_save_event.vader +++ b/test/lsp/test_did_save_event.vader @@ -13,8 +13,8 @@ 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 = [] - let g:Callback = '' function! LanguageCallback() abort return 'foobar' @@ -34,26 +34,32 @@ Before: \ }) let g:ale_linters = {'foobar': ['dummy_linter']} - function! ale#linter#StartLSP(buffer, linter, callback) abort - let g:Callback = a:callback + 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 { - \ 'connection_id': 347, + \ 'buffer': a:buffer, + \ '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:Callback unlet! g:message_list delfunction LanguageCallback @@ -68,6 +74,7 @@ After: runtime autoload/ale/completion.vim runtime autoload/ale/lsp.vim + runtime autoload/ale/lsp_linter.vim Given foobar (Some imaginary filetype): <contents> diff --git a/test/lsp/test_lsp_client_messages.vader b/test/lsp/test_lsp_client_messages.vader index 053da803..dc28c2e9 100644 --- a/test/lsp/test_lsp_client_messages.vader +++ b/test/lsp/test_lsp_client_messages.vader @@ -16,9 +16,11 @@ Execute(ale#lsp#message#Initialize() should return correct messages): \ 'processId': getpid(), \ 'rootPath': '/foo/bar', \ 'capabilities': {}, + \ 'initializationOptions': {'foo': 'bar'}, + \ 'rootUri': 'file:///foo/bar', \ } \ ], - \ ale#lsp#message#Initialize('/foo/bar') + \ ale#lsp#message#Initialize('/foo/bar', {'foo': 'bar'}) Execute(ale#lsp#message#Initialized() should return correct messages): AssertEqual [1, 'initialized'], ale#lsp#message#Initialized() @@ -144,6 +146,35 @@ Execute(ale#lsp#message#Definition() should return correct messages): \ ], \ ale#lsp#message#Definition(bufnr(''), 12, 34) +Execute(ale#lsp#message#References() should return correct messages): + AssertEqual + \ [ + \ 0, + \ 'textDocument/references', + \ { + \ 'textDocument': { + \ 'uri': ale#path#ToURI(g:dir . '/foo/bar.ts'), + \ }, + \ 'position': {'line': 11, 'character': 34}, + \ 'context': {'includeDeclaration': v:false}, + \ } + \ ], + \ ale#lsp#message#References(bufnr(''), 12, 34) + +Execute(ale#lsp#message#Hover() should return correct messages): + AssertEqual + \ [ + \ 0, + \ 'textDocument/hover', + \ { + \ 'textDocument': { + \ 'uri': ale#path#ToURI(g:dir . '/foo/bar.ts'), + \ }, + \ 'position': {'line': 11, 'character': 34}, + \ } + \ ], + \ ale#lsp#message#Hover(bufnr(''), 12, 34) + Execute(ale#lsp#tsserver_message#Open() should return correct messages): AssertEqual \ [ @@ -233,3 +264,29 @@ Execute(ale#lsp#tsserver_message#Definition() should return correct messages): \ } \ ], \ ale#lsp#tsserver_message#Definition(bufnr(''), 347, 12) + +Execute(ale#lsp#tsserver_message#References() should return correct messages): + AssertEqual + \ [ + \ 0, + \ 'ts@references', + \ { + \ 'file': ale#path#Simplify(g:dir . '/foo/bar.ts'), + \ 'line': 347, + \ 'offset': 12, + \ } + \ ], + \ ale#lsp#tsserver_message#References(bufnr(''), 347, 12) + +Execute(ale#lsp#tsserver_message#Quickinfo() should return correct messages): + AssertEqual + \ [ + \ 0, + \ 'ts@quickinfo', + \ { + \ 'file': ale#path#Simplify(g:dir . '/foo/bar.ts'), + \ 'line': 347, + \ 'offset': 12, + \ } + \ ], + \ ale#lsp#tsserver_message#Quickinfo(bufnr(''), 347, 12) diff --git a/test/lsp/test_lsp_command_formatting.vader b/test/lsp/test_lsp_command_formatting.vader new file mode 100644 index 00000000..9721f37f --- /dev/null +++ b/test/lsp/test_lsp_command_formatting.vader @@ -0,0 +1,36 @@ +Before: + runtime autoload/ale/lsp.vim + + let g:args = [] + + " Mock the StartProgram function so we can just capture the arguments. + function! ale#lsp#StartProgram(...) abort + let g:args = a:000[1:] + endfunction + +After: + unlet! g:args + + runtime autoload/ale/lsp.vim + +Execute(Command formatting should be applied correctly for LSP linters): + call ale#lsp_linter#StartLSP( + \ bufnr(''), + \ { + \ 'language_callback': {-> 'x'}, + \ 'project_root_callback': {-> '/foo/bar'}, + \ 'lsp': 'stdio', + \ 'executable': has('win32') ? 'cmd': 'true', + \ 'command': '%e --foo', + \ }, + \) + + if has('win32') + AssertEqual + \ ['cmd', 'cmd /s/c "cmd --foo"'], + \ g:args + else + AssertEqual + \ ['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 8651d801..1c2fceab 100644 --- a/test/lsp/test_lsp_connections.vader +++ b/test/lsp/test_lsp_connections.vader @@ -2,6 +2,10 @@ Before: let g:ale_lsp_next_message_id = 1 After: + if exists('b:conn') && has_key(b:conn, 'id') + call ale#lsp#RemoveConnectionWithID(b:conn.id) + endif + unlet! b:data unlet! b:conn @@ -221,51 +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 = {'projects': {}} - - call ale#lsp#RegisterProject(b:conn, '/foo/bar') - - AssertEqual - \ { - \ 'projects': { - \ '/foo/bar': {'initialized': 0, 'message_queue': [], 'init_request_id': 0}, - \ }, - \ }, - \ b:conn - -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 = {'projects': {}} - - call ale#lsp#RegisterProject(b:conn, '') - - AssertEqual - \ { - \ 'projects': { - \ '<<EMPTY>>': {'initialized': 1, 'message_queue': [], 'init_request_id': 0}, - \ }, - \ }, - \ b:conn - -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_lsp_error_parsing.vader b/test/lsp/test_lsp_error_parsing.vader new file mode 100644 index 00000000..44169c80 --- /dev/null +++ b/test/lsp/test_lsp_error_parsing.vader @@ -0,0 +1,74 @@ +Execute(Invalid responses should be handled): + AssertEqual '', ale#lsp#response#GetErrorMessage({}) + AssertEqual '', ale#lsp#response#GetErrorMessage({'error': 0}) + AssertEqual '', ale#lsp#response#GetErrorMessage({'error': {}}) + AssertEqual '', ale#lsp#response#GetErrorMessage({ + \ 'error': { + \ 'code': 0, + \ 'message': 'x', + \ }, + \}) + AssertEqual '', ale#lsp#response#GetErrorMessage({'error': {'code': -32602}}) + AssertEqual '', ale#lsp#response#GetErrorMessage({'error': {'code': -32603}}) + +Execute(Messages without tracebacks should be handled): + AssertEqual 'xyz', ale#lsp#response#GetErrorMessage({ + \ 'error': { + \ 'code': -32602, + \ 'message': 'xyz', + \ }, + \}) + AssertEqual 'abc', ale#lsp#response#GetErrorMessage({ + \ 'error': { + \ 'code': -32603, + \ 'message': 'abc', + \ }, + \}) + +Execute(Invalid traceback data should be tolerated): + AssertEqual 'xyz', ale#lsp#response#GetErrorMessage({ + \ 'error': { + \ 'code': -32602, + \ 'message': 'xyz', + \ 'data': { + \ }, + \ }, + \}) + AssertEqual 'xyz', ale#lsp#response#GetErrorMessage({ + \ 'error': { + \ 'code': -32602, + \ 'message': 'xyz', + \ 'data': { + \ 'traceback': 0, + \ }, + \ }, + \}) + AssertEqual 'xyz', ale#lsp#response#GetErrorMessage({ + \ 'error': { + \ 'code': -32602, + \ 'message': 'xyz', + \ 'data': { + \ 'traceback': [], + \ }, + \ }, + \}) + +Execute(Messages with tracebacks should be handled): + AssertEqual "xyz\n123\n456", ale#lsp#response#GetErrorMessage({ + \ 'error': { + \ 'code': -32602, + \ 'message': 'xyz', + \ 'data': { + \ 'traceback': ['123', '456'], + \ }, + \ }, + \}) + +Execute(Messages with string data should be handled): + AssertEqual "xyz\nUncaught Exception", ale#lsp#response#GetErrorMessage({ + \ 'error': { + \ 'code': -32602, + \ 'message': 'xyz', + \ 'data': 'Uncaught Exception', + \ }, + \}) diff --git a/test/lsp/test_other_initialize_message_handling.vader b/test/lsp/test_other_initialize_message_handling.vader index 3a7c7f62..e29f3358 100644 --- a/test/lsp/test_other_initialize_message_handling.vader +++ b/test/lsp/test_other_initialize_message_handling.vader @@ -1,66 +1,132 @@ 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': {}, + \ 'callback_list': [], \ 'message_queue': [], - \} - - let b:conn = { - \ 'projects': { - \ '/foo/bar': b:project, + \ 'capabilities_queue': [], + \ 'capabilities': { + \ 'hover': 0, + \ 'references': 0, + \ 'completion': 0, + \ 'completion_trigger_characters': [], + \ 'definition': 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'}, +Execute(Messages with no method and capabilities should initialize projects): + call ale#lsp#HandleInitResponse(b:conn, { + \ 'result': {'capabilities': {}}, \}) - AssertEqual - \ { - \ 'initialized': 0, - \ 'init_request_id': 3, - \ 'message_queue': [], - \ }, - \ b:project + AssertEqual 1, b:conn.initialized + +Execute(Other messages should not initialize projects): + call ale#lsp#HandleInitResponse(b:conn, {'method': 'lolwat'}) + + AssertEqual 0, b:conn.initialized - call ale#lsp#HandleOtherInitializeResponses(b:conn, { - \ 'method': 'textDocument/publishDiagnostics', - \ 'params': {'uri': 'file:///foo/bar/baz.txt'}, + call ale#lsp#HandleInitResponse(b:conn, {'result': {'x': {}}}) + + AssertEqual 0, b:conn.initialized + +Execute(Capabilities should bet set up correctly): + call ale#lsp#HandleInitResponse(b:conn, { + \ 'jsonrpc': '2.0', + \ 'id': 1, + \ 'result': { + \ 'capabilities': { + \ 'renameProvider': v:true, + \ 'executeCommandProvider': { + \ 'commands': [], + \ }, + \ 'hoverProvider': v:true, + \ 'documentSymbolProvider': v:true, + \ 'documentRangeFormattingProvider': v:true, + \ 'codeLensProvider': { + \ 'resolveProvider': v:false + \ }, + \ 'referencesProvider': v:true, + \ 'textDocumentSync': 2, + \ 'documentFormattingProvider': v:true, + \ 'codeActionProvider': v:true, + \ 'signatureHelpProvider': { + \ 'triggerCharacters': ['(', ','], + \ }, + \ 'completionProvider': { + \ 'triggerCharacters': ['.'], + \ 'resolveProvider': v:false + \ }, + \ 'definitionProvider': v:true, + \ 'experimental': {}, + \ 'documentHighlightProvider': v:true + \ }, + \ }, \}) + AssertEqual 1, b:conn.initialized AssertEqual \ { - \ 'initialized': 1, - \ 'init_request_id': 3, - \ 'message_queue': [], + \ 'completion_trigger_characters': ['.'], + \ 'completion': 1, + \ 'references': 1, + \ 'hover': 1, + \ 'definition': 1, \ }, - \ b:project + \ b:conn.capabilities -Execute(Messages with no method and capabilities should initialize projects): - call ale#lsp#HandleOtherInitializeResponses(b:conn, { - \ 'result': {'capabilities': {}}, +Execute(Disabled capabilities should be recognised correctly): + call ale#lsp#HandleInitResponse(b:conn, { + \ 'jsonrpc': '2.0', + \ 'id': 1, + \ 'result': { + \ 'capabilities': { + \ 'renameProvider': v:true, + \ 'executeCommandProvider': { + \ 'commands': [], + \ }, + \ 'hoverProvider': v:false, + \ 'documentSymbolProvider': v:true, + \ 'documentRangeFormattingProvider': v:true, + \ 'codeLensProvider': { + \ 'resolveProvider': v:false + \ }, + \ 'referencesProvider': v:false, + \ 'textDocumentSync': 2, + \ 'documentFormattingProvider': v:true, + \ 'codeActionProvider': v:true, + \ 'signatureHelpProvider': { + \ 'triggerCharacters': ['(', ','], + \ }, + \ 'definitionProvider': v:false, + \ 'experimental': {}, + \ 'documentHighlightProvider': v:true + \ }, + \ }, \}) + AssertEqual 1, b:conn.initialized AssertEqual \ { - \ 'initialized': 1, - \ 'init_request_id': 3, - \ 'message_queue': [], + \ 'completion_trigger_characters': [], + \ 'completion': 0, + \ 'references': 0, + \ 'hover': 0, + \ 'definition': 0, \ }, - \ b:project + \ b:conn.capabilities -Execute(Other messages should not initialize projects): - call ale#lsp#HandleOtherInitializeResponses(b:conn, {'method': 'lolwat'}) - - AssertEqual 0, b:project.initialized - - call ale#lsp#HandleOtherInitializeResponses(b:conn, {'result': {'x': {}}}) - - AssertEqual 0, b:project.initialized +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 3e637418..be50fbe8 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': [ @@ -89,6 +89,26 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle messages without codes) \ }, \ ]}}) +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 [ \ { @@ -120,16 +140,79 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle multiple messages): \ }, \ ]}}) -Execute(ale#lsp#response#ReadTSServerDiagnostics() should handle tsserver responses): +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, \ 'end_lnum': 1, \ 'end_col': 17, \ }, - \], + \ ], \ ale#lsp#response#ReadTSServerDiagnostics({"seq":0,"type":"event","event":"semanticDiag","body":{"file":"/bar/foo.ts","diagnostics":[{"start":{"line":1,"offset":11},"end":{"line":1,"offset":17},"text":"Operator ''+'' cannot be applied to types ''3'' and ''{}''.","code":2365}]}}) + +Execute(ale#lsp#response#ReadTSServerDiagnostics() should handle warnings from tsserver): + AssertEqual + \ [ + \ { + \ 'lnum': 27, + \ 'col': 3, + \ 'nr': 2515, + \ 'code': '2515', + \ 'end_lnum': 27, + \ 'type': 'W', + \ 'end_col': 14, + \ 'text': 'Calls to ''console.log'' are not allowed. (no-console)', + \ } + \ ], + \ ale#lsp#response#ReadTSServerDiagnostics({"seq":0,"type":"event","event":"semanticDiag","body":{"file":"<removed>","diagnostics":[{"start":{"line":27,"offset":3},"end":{"line":27,"offset":14},"text":"Calls to 'console.log' are not allowed. (no-console)","code":2515,"category":"warning","source":"tslint"}]}}) + +Execute(ale#lsp#response#ReadTSServerDiagnostics() should handle suggestions from tsserver): + AssertEqual + \ [ + \ { + \ 'lnum': 27, + \ 'col': 3, + \ 'nr': 2515, + \ 'code': '2515', + \ 'end_lnum': 27, + \ 'type': 'I', + \ 'end_col': 14, + \ 'text': 'Some info', + \ } + \ ], + \ ale#lsp#response#ReadTSServerDiagnostics({"seq":0,"type":"event","event":"semanticDiag","body":{"file":"<removed>","diagnostics":[{"start":{"line":27,"offset":3},"end":{"line":27,"offset":14},"text":"Some info","code":2515,"category":"suggestion","source":"tslint"}]}}) diff --git a/test/lsp/test_reset_lsp.vader b/test/lsp/test_reset_lsp.vader new file mode 100644 index 00000000..2bec13dc --- /dev/null +++ b/test/lsp/test_reset_lsp.vader @@ -0,0 +1,90 @@ +Before: + Save g:ale_enabled + 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_enabled = 0 + let g:ale_set_signs = 0 + let g:ale_set_quickfix = 0 + let g:ale_set_loclist = 0 + let g:ale_set_highlights = 0 + let g:ale_echo_cursor = 0 + + function EmptyString() abort + return '' + endfunction + + call ale#engine#InitBufferInfo(bufnr('')) + + call ale#linter#Define('testft', { + \ 'name': 'lsplinter', + \ 'lsp': 'tsserver', + \ 'executable_callback': 'EmptyString', + \ 'command_callback': 'EmptyString', + \ 'project_root_callback': 'EmptyString', + \ 'language_callback': 'EmptyString', + \}) + + call ale#linter#Define('testft', { + \ 'name': 'otherlinter', + \ 'callback': 'TestCallback', + \ 'executable': has('win32') ? 'cmd': 'true', + \ 'command': 'true', + \ 'read_buffer': 0, + \}) + +After: + Restore + + unlet! b:ale_save_event_fired + + delfunction EmptyString + call ale#linter#Reset() + +Given testft(Some file with an imaginary filetype): +Execute(ALEStopAllLSPs should clear the loclist): + let g:ale_buffer_info[bufnr('')].loclist = [ + \ { + \ 'text': 'a', + \ 'lnum': 10, + \ 'col': 0, + \ 'bufnr': bufnr(''), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'lsplinter', + \ }, + \ { + \ 'text': 'a', + \ 'lnum': 10, + \ 'col': 0, + \ 'bufnr': bufnr(''), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'otherlinter', + \ }, + \] + let g:ale_buffer_info[bufnr('')].active_linter_list = ['lsplinter', 'otherlinter'] + + ALEStopAllLSPs + + " The loclist should be updated. + AssertEqual g:ale_buffer_info[bufnr('')].loclist, [ + \ { + \ 'text': 'a', + \ 'lnum': 10, + \ 'col': 0, + \ 'bufnr': bufnr(''), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'otherlinter', + \ }, + \] + + " The LSP linter should be removed from the active linter list. + AssertEqual g:ale_buffer_info[bufnr('')].active_linter_list, ['otherlinter'] diff --git a/test/maven-test-files/maven-kotlin-project/pom.xml b/test/maven-test-files/maven-kotlin-project/pom.xml new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/test/maven-test-files/maven-kotlin-project/pom.xml @@ -0,0 +1 @@ + diff --git a/test/maven-test-files/maven-kotlin-project/src/main/kotlin/dummy.kt b/test/maven-test-files/maven-kotlin-project/src/main/kotlin/dummy.kt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/test/maven-test-files/maven-kotlin-project/src/main/kotlin/dummy.kt @@ -0,0 +1 @@ + diff --git a/test/prettier-test-files/testfile b/test/prettier-test-files/testfile new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/prettier-test-files/testfile diff --git a/test/puppet-test-files/new-style-module/lib/puppet/types/exampletype.rb b/test/puppet-test-files/new-style-module/lib/puppet/types/exampletype.rb new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/puppet-test-files/new-style-module/lib/puppet/types/exampletype.rb diff --git a/test/puppet-test-files/new-style-module/metadata.json b/test/puppet-test-files/new-style-module/metadata.json new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/puppet-test-files/new-style-module/metadata.json diff --git a/test/puppet-test-files/new-style-module/template/template.epp b/test/puppet-test-files/new-style-module/template/template.epp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/puppet-test-files/new-style-module/template/template.epp diff --git a/test/puppet-test-files/old-style-module/manifests/init.pp b/test/puppet-test-files/old-style-module/manifests/init.pp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/puppet-test-files/old-style-module/manifests/init.pp diff --git a/test/puppet-test-files/old-style-module/templates/template.epp b/test/puppet-test-files/old-style-module/templates/template.epp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/puppet-test-files/old-style-module/templates/template.epp diff --git a/test/script/check-supported-tools-tables b/test/script/check-supported-tools-tables index 32cebb2d..220c7427 100755 --- a/test/script/check-supported-tools-tables +++ b/test/script/check-supported-tools-tables @@ -1,4 +1,7 @@ -#!/bin/bash -eu +#!/usr/bin/env bash + +set -e +set -u # This script compares the table of supported tools in both the README file # and the doc/ale.txt file, so we can complain if they don't match up. diff --git a/test/script/check-toc b/test/script/check-toc index cc2d2b9c..8e411589 100755 --- a/test/script/check-toc +++ b/test/script/check-toc @@ -1,4 +1,7 @@ -#!/bin/bash -eu +#!/usr/bin/env bash + +set -e +set -u # This script checks that the table of contents for the supported tools is # sorted, and that the table matches the files. diff --git a/test/script/custom-checks b/test/script/custom-checks index 791053d4..d4027fec 100755 --- a/test/script/custom-checks +++ b/test/script/custom-checks @@ -1,8 +1,10 @@ -#!/bin/bash -eu +#!/usr/bin/env bash + +set -e +set -u exit_code=0 -image=w0rp/ale -docker_flags=(--rm -v "$PWD:/testplugin" -v "$PWD/test:/home" -w /testplugin "$image") +docker_flags=(--rm -v "$PWD:/testplugin" -v "$PWD/test:/home" -w /testplugin "$DOCKER_RUN_IMAGE") echo '========================================' echo 'Running custom linting rules' diff --git a/test/script/custom-linting-rules b/test/script/custom-linting-rules index ef6d792f..7aafe995 100755 --- a/test/script/custom-linting-rules +++ b/test/script/custom-linting-rules @@ -1,4 +1,7 @@ -#!/bin/bash -eu +#!/usr/bin/env bash + +set -e +set -u # This Bash script implements custom sanity checks for scripts beyond what # Vint covers, which are easy to check with regex. @@ -49,12 +52,18 @@ directories=("$@") check_errors() { regex="$1" message="$2" + include_arg='' + + if [ $# -gt 2 ]; then + include_arg="--include $3" + fi for directory in "${directories[@]}"; do + # shellcheck disable=SC2086 while IFS= read -r match; do RETURN_CODE=1 echo "$match $message" - done < <(grep -n "$regex" "$directory"/**/*.vim \ + done < <(grep -n "$regex" $include_arg "$directory"/**/*.vim \ | grep -v 'no-custom-checks' \ | grep -o '^[^:]\+:[0-9]\+' \ | sed 's:^\./::') @@ -69,9 +78,21 @@ 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 +# The arguments are: regex, explanation, [filename_filter] check_errors \ '^function.*) *$' \ 'Function without abort keyword (See :help except-compat)' @@ -84,6 +105,7 @@ check_errors $'\t' 'Use four spaces, not tabs' check_errors 'let g:ale_\w\+_\w\+_args =' 'Name your option g:ale_<filetype>_<lintername>_options instead' check_errors 'shellescape(' 'Use ale#Escape instead of shellescape' check_errors 'simplify(' 'Use ale#path#Simplify instead of simplify' +check_errors 'tempname(' 'Use ale#util#Tempname instead of tempname' check_errors "expand(['\"]%" "Use expand('#' . a:buffer . '...') instead. You might get a filename for the wrong buffer." check_errors 'getcwd()' "Do not use getcwd(), as it could run from the wrong buffer. Use expand('#' . a:buffer . ':p:h') instead." check_errors '==#' "Use 'is#' instead of '==#'. 0 ==# 'foobar' is true" @@ -91,5 +113,17 @@ check_errors '==?' "Use 'is?' instead of '==?'. 0 ==? 'foobar' is true" 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" exit $RETURN_CODE diff --git a/test/script/run-vader-tests b/test/script/run-vader-tests index a10b8baf..c8cdfde4 100755 --- a/test/script/run-vader-tests +++ b/test/script/run-vader-tests @@ -1,13 +1,14 @@ -#!/bin/bash -eu +#!/usr/bin/env bash -image=w0rp/ale -docker_flags=(--rm -v "$PWD:/testplugin" -v "$PWD/test:/home" -w /testplugin "$image") +set -e +set -u + +docker_flags=(--rm -v "$PWD:/testplugin" -v "$PWD/test:/home" -w /testplugin "$DOCKER_RUN_IMAGE") red='\033[0;31m' green='\033[0;32m' nc='\033[0m' verbose=0 quiet=0 -exit_code=0 while [ $# -ne 0 ]; do case $1 in @@ -35,15 +36,27 @@ done vim="$1" tests="$2" +# This file will be used to track if tests ran or not. +# We can't use a variable, because we need to set a value in a sub-shell. +run_file="$(mktemp -t tests_ran.XXXXXXXX)" function filter-vader-output() { + local hit_first_vader_line=0 # When verbose mode is off, suppress output until Vader starts. local start_output="$verbose" local filtered_data='' while read -r; do - if ((!start_output)); then + # Search for the first Vader output line. + # We can try starting tests again if they don't start. + if ((!hit_first_vader_line)); then if [[ "$REPLY" = *'Starting Vader:'* ]]; then + hit_first_vader_line=1 + fi + fi + + if ((!start_output)); then + if ((hit_first_vader_line)); then start_output=1 else continue @@ -70,6 +83,11 @@ function filter-vader-output() { echo "$REPLY" fi done + + # Note that we managed to get the Vader tests started if we did. + if ((hit_first_vader_line)); then + echo 1 > "$run_file" + fi } function color-vader-output() { @@ -106,10 +124,28 @@ echo "Running tests for $vim" echo '========================================' echo -set -o pipefail -docker run -a stderr -e VADER_OUTPUT_FILE=/dev/stderr "${docker_flags[@]}" \ - "/vim-build/bin/$vim" -u test/vimrc \ - "+Vader! $tests" 2>&1 | filter-vader-output | color-vader-output || exit_code=$? -set +o pipefail +tries=0 + +while [ "$tries" -lt 5 ]; do + tries=$((tries + 1)) + + exit_code=0 + set -o pipefail + docker run -a stderr -e VADER_OUTPUT_FILE=/dev/stderr "${docker_flags[@]}" \ + "/vim-build/bin/$vim" -u test/vimrc \ + "+Vader! $tests" 2>&1 | filter-vader-output | color-vader-output || exit_code=$? + set +o pipefail + + if [ -s "$run_file" ]; then + break + fi +done + +if [ "$tries" -gt 1 ]; then + echo + echo "Tried to run tests $tries times" +fi + +rm "$run_file" exit "$exit_code" diff --git a/test/script/run-vint b/test/script/run-vint index e1140307..ce42ad41 100755 --- a/test/script/run-vint +++ b/test/script/run-vint @@ -1,8 +1,10 @@ -#!/bin/bash -eu +#!/usr/bin/env bash + +set -e +set -u exit_code=0 -image=w0rp/ale -docker_flags=(--rm -v "$PWD:/testplugin" -v "$PWD/test:/home" -w /testplugin "$image") +docker_flags=(--rm -v "$PWD:/testplugin" -v "$PWD/test:/home" -w /testplugin "$DOCKER_RUN_IMAGE") echo '========================================' echo 'Running Vint to lint our code' diff --git a/test/sign/test_linting_sets_signs.vader b/test/sign/test_linting_sets_signs.vader index c23b4002..3ccecf45 100644 --- a/test/sign/test_linting_sets_signs.vader +++ b/test/sign/test_linting_sets_signs.vader @@ -3,6 +3,23 @@ Given foobar (Some imaginary filetype): var y = 3 Before: + Save g:ale_buffer_info + Save g:ale_echo_cursor + Save g:ale_run_synchronously + Save g:ale_set_highlights + Save g:ale_set_loclist + Save g:ale_set_quickfix + Save g:ale_set_signs + + let g:ale_buffer_info = {} + let g:ale_run_synchronously = 1 + let g:ale_set_signs = 1 + " Disable features we don't need for these tests. + let g:ale_set_quickfix = 0 + let g:ale_set_loclist = 0 + let g:ale_set_highlights = 0 + let g:ale_echo_cursor = 0 + sign unplace * function! TestCallback(buffer, output) @@ -37,17 +54,14 @@ Before: \ 'command': has('win32') ? 'echo foo bar' : '/bin/sh -c ''echo foo bar''', \}) - After: delfunction TestCallback delfunction CollectSigns sign unplace * - let g:ale_buffer_info = {} call ale#linter#Reset() Execute(The signs should be updated after linting is done): - call ale#Lint() - call ale#engine#WaitForJobs(2000) + ALELint AssertEqual [['1', 'ALEWarningSign'], ['2', 'ALEErrorSign']], CollectSigns() diff --git a/test/sign/test_sign_column_highlighting.vader b/test/sign/test_sign_column_highlighting.vader index 4457a45c..0b506fa7 100644 --- a/test/sign/test_sign_column_highlighting.vader +++ b/test/sign/test_sign_column_highlighting.vader @@ -1,12 +1,13 @@ Before: Save g:ale_change_sign_column_color + Save &verbose function! ParseHighlight(name) abort redir => l:output silent execute 'highlight ' . a:name redir end - return join(split(l:output)[2:]) + return substitute(join(split(l:output)[2:]), ' Last set.*', '', '') endfunction function! SetHighlight(name, syntax) abort @@ -53,3 +54,15 @@ Execute(The SignColumn highlight should be set and reset): call ale#sign#SetSigns(bufnr(''), []) AssertEqual 'links to ALESignColumnWithoutErrors', ParseHighlight('SignColumn') + +Execute(The SignColumn should be correctly parsed when verbose=1): + set verbose=1 + highlight SignColumn ctermfg=246 ctermbg=7 guifg=#839496 guibg=Grey + + call ale#sign#SetUpDefaultColumnWithoutErrorsHighlight() + + AssertEqual + \ has('nvim') + \ ? 'ctermfg=246 ctermbg=7 guifg=#839496 guibg=Grey' + \ : 'term=standout ctermfg=246 ctermbg=7 guifg=#839496 guibg=Grey', + \ ParseHighlight('ALESignColumnWithoutErrors') diff --git a/test/sign/test_sign_placement.vader b/test/sign/test_sign_placement.vader index 36f34e16..e2d95ff0 100644 --- a/test/sign/test_sign_placement.vader +++ b/test/sign/test_sign_placement.vader @@ -1,7 +1,20 @@ Before: + Save g:ale_buffer_info + Save g:ale_echo_cursor + Save g:ale_run_synchronously + Save g:ale_set_highlights + Save g:ale_set_loclist + Save g:ale_set_quickfix Save g:ale_set_signs + let g:ale_buffer_info = {} + let g:ale_run_synchronously = 1 let g:ale_set_signs = 1 + " Disable features we don't need for these tests. + let g:ale_set_quickfix = 0 + let g:ale_set_loclist = 0 + let g:ale_set_highlights = 0 + let g:ale_echo_cursor = 0 call ale#linter#Reset() sign unplace * @@ -120,8 +133,7 @@ Given testft(A file with warnings/errors): fifth line Execute(The current signs should be set for running a job): - call ale#Lint() - call ale#engine#WaitForJobs(2000) + ALELint AssertEqual \ [ diff --git a/test/smoke_test.vader b/test/smoke_test.vader index f6d0be56..2708c86f 100644 --- a/test/smoke_test.vader +++ b/test/smoke_test.vader @@ -33,8 +33,13 @@ Before: After: Restore + unlet! g:i + unlet! g:results + unlet! g:expected_results + delfunction TestCallback delfunction TestCallback2 + call ale#engine#Cleanup(bufnr('')) call ale#linter#Reset() Given foobar (Some imaginary filetype): @@ -45,10 +50,7 @@ Given foobar (Some imaginary filetype): Execute(Linters should run with the default options): AssertEqual 'foobar', &filetype - call ale#Lint() - call ale#engine#WaitForJobs(2000) - - AssertEqual [{ + let g:expected_results = [{ \ 'bufnr': bufnr('%'), \ 'lnum': 2, \ 'vcol': 0, @@ -58,7 +60,22 @@ Execute(Linters should run with the default options): \ 'nr': -1, \ 'pattern': '', \ 'valid': 1, - \ }], getloclist(0) + \ }] + + " 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#engine#WaitForJobs(2000) + + let g:results = ale#test#GetLoclistWithoutModule() + + if g:results == g:expected_results + break + endif + endfor + + AssertEqual g:expected_results, g:results Execute(Linters should run in PowerShell too): if has('win32') @@ -93,7 +110,7 @@ Execute(Linters should run in PowerShell too): \}) call ale#Lint() - call ale#engine#WaitForJobs(2000) + call ale#engine#WaitForJobs(4000) AssertEqual [ \ { @@ -118,7 +135,7 @@ Execute(Linters should run in PowerShell too): \ 'pattern': '', \ 'valid': 1, \ }, - \], getloclist(0) + \], ale#test#GetLoclistWithoutModule() endif Execute(Previous errors should be removed when linters change): @@ -134,17 +151,29 @@ Execute(Previous errors should be removed when linters change): \ 'command': has('win32') ? 'echo baz boz' : '/bin/sh -c ''echo baz boz''', \}) - call ale#Lint() - call ale#engine#WaitForJobs(2000) + let g:expected_results = [{ + \ 'bufnr': bufnr('%'), + \ 'lnum': 3, + \ 'vcol': 0, + \ 'col': 4, + \ 'text': 'baz boz', + \ 'type': 'E', + \ 'nr': -1, + \ 'pattern': '', + \ 'valid': 1, + \}] + + " 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#engine#WaitForJobs(2000) - AssertEqual [{ - \ 'bufnr': bufnr('%'), - \ 'lnum': 3, - \ 'vcol': 0, - \ 'col': 4, - \ 'text': 'baz boz', - \ 'type': 'E', - \ 'nr': -1, - \ 'pattern': '', - \ 'valid': 1, - \ }], getloclist(0) + let g:results = ale#test#GetLoclistWithoutModule() + + if g:results == g:expected_results + break + endif + endfor + + AssertEqual g:expected_results, g:results diff --git a/test/test_ale_info.vader b/test/test_ale_info.vader index e20125a3..39a2a85a 100644 --- a/test/test_ale_info.vader +++ b/test/test_ale_info.vader @@ -1,30 +1,50 @@ Before: Save g:ale_buffer_info Save g:ale_cache_executable_check_failures + Save g:ale_completion_delay Save g:ale_completion_enabled + Save g:ale_completion_max_suggestions Save g:ale_fixers Save g:ale_history_log_output Save g:ale_lint_on_insert_leave Save g:ale_lint_on_text_changed Save g:ale_linters + Save g:ale_lsp_error_messages Save g:ale_maximum_file_size Save g:ale_pattern_options Save g:ale_pattern_options_enabled Save g:ale_set_balloons + Save g:ale_sign_error + Save g:ale_sign_info + Save g:ale_sign_style_error + Save g:ale_sign_style_warning + Save g:ale_sign_warning + Save g:ale_statusline_format + Save g:ale_type_map Save g:ale_warn_about_trailing_whitespace unlet! b:ale_history let g:ale_buffer_info = {} let g:ale_cache_executable_check_failures = 0 + let g:ale_completion_delay = 100 let g:ale_completion_enabled = 0 + let g:ale_completion_max_suggestions = 50 let g:ale_history_log_output = 1 let g:ale_lint_on_insert_leave = 0 let g:ale_lint_on_text_changed = 'always' + let g:ale_lsp_error_messages = {} let g:ale_maximum_file_size = 0 let g:ale_pattern_options = {} let g:ale_pattern_options_enabled = 0 let g:ale_set_balloons = 0 + let g:ale_sign_error = '>>' + let g:ale_sign_info = '--' + let g:ale_sign_style_error = '>>' + let g:ale_sign_style_warning = '--' + let g:ale_sign_warning = '--' + let g:ale_statusline_format = ['%d error(s)', '%d warning(s)', 'OK'] + let g:ale_type_map = {} let g:ale_warn_about_trailing_whitespace = 1 let g:testlinter1 = {'name': 'testlinter1', 'executable': 'testlinter1', 'command': 'testlinter1', 'callback': 'testCB1', 'output_stream': 'stdout'} @@ -32,10 +52,19 @@ Before: call ale#engine#ResetExecutableCache() call ale#linter#Reset() + call ale#linter#PreventLoading('testft') let g:ale_linters = {} let g:ale_fixers = {} let g:ale_linter_aliases = {} let g:ale_buffer_info = {} + let g:fixer_lines = [ + \ ' Suggested Fixers: ', + \ ' ''foo'' - Fix things the foo way', + \] + let g:variables_lines = [ + \ ' Linter Variables:', + \ '', + \] let g:globals_lines = [ \ ' Global Variables:', \ '', @@ -66,6 +95,7 @@ Before: \ '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_loclist_msg_format = ''%code: %%s''', \ 'let g:ale_max_buffer_history_size = 20', \ 'let g:ale_max_signs = -1', @@ -87,6 +117,7 @@ Before: \ 'let g:ale_sign_warning = ''--''', \ '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_warn_about_trailing_blank_lines = 1', \ 'let g:ale_warn_about_trailing_whitespace = 1', \] @@ -104,6 +135,11 @@ Before: AssertEqual a:expected_list, split(l:output, "\n") endfunction + call ale#test#SetDirectory('/testplugin/test') + + call ale#fix#registry#Clear() + call ale#fix#registry#Add('foo', 'x', [], 'Fix things the foo way') + After: Restore @@ -113,6 +149,8 @@ After: unlet! b:ale_history unlet! b:ale_linters unlet! g:output + unlet! g:fixer_lines + unlet! g:variables_lines unlet! g:globals_string unlet! g:command_header unlet! g:ale_testft_testlinter1_foo @@ -122,15 +160,22 @@ After: unlet! g:ale_testft2_testlinter2_bar delfunction CheckInfo + call ale#test#RestoreDirectory() + call ale#fix#registry#ResetToDefaults() + Given nolintersft (Empty buffer with no linters): Execute (ALEInfo with no linters should return the right output): - call CheckInfo([ - \ ' Current Filetype: nolintersft', - \ 'Available Linters: []', - \ ' Enabled Linters: []', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: nolintersft', + \ 'Available Linters: []', + \ ' Enabled Linters: []', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given (Empty buffer with no filetype): Execute (ALEInfo should return buffer-local global ALE settings): @@ -142,48 +187,64 @@ Execute (ALEInfo should return buffer-local global ALE settings): \ index(g:globals_lines, 'let g:ale_linters = {}') + 1 \) - call CheckInfo([ - \ ' Current Filetype: ', - \ 'Available Linters: []', - \ ' Enabled Linters: []', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: ', + \ 'Available Linters: []', + \ ' Enabled Linters: []', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given (Empty buffer with no filetype): Execute (ALEInfo with no filetype should return the right output): - call CheckInfo([ - \ ' Current Filetype: ', - \ 'Available Linters: []', - \ ' Enabled Linters: []', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: ', + \ 'Available Linters: []', + \ ' Enabled Linters: []', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given testft (Empty buffer): Execute (ALEInfo with a single linter should return the right output): call ale#linter#Define('testft', g:testlinter1) - call CheckInfo([ - \ ' Current Filetype: testft', - \ 'Available Linters: [''testlinter1'']', - \ ' Enabled Linters: [''testlinter1'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft', + \ 'Available Linters: [''testlinter1'']', + \ ' Enabled Linters: [''testlinter1'']', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given testft (Empty buffer): Execute (ALEInfo with two linters should return the right output): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft', g:testlinter2) - call CheckInfo([ - \ ' Current Filetype: testft', - \ 'Available Linters: [''testlinter1'', ''testlinter2'']', - \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given testft (Empty buffer): Execute (ALEInfo should calculate enabled linters correctly): @@ -194,39 +255,51 @@ Execute (ALEInfo should calculate enabled linters correctly): let g:globals_lines[index(g:globals_lines, 'let g:ale_linters = {}')] \ = 'let g:ale_linters = {''testft'': [''testlinter2'']}' - call CheckInfo([ - \ ' Current Filetype: testft', - \ 'Available Linters: [''testlinter1'', ''testlinter2'']', - \ ' Enabled Linters: [''testlinter2'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Enabled Linters: [''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given testft (Empty buffer): Execute (ALEInfo should only return linters for current filetype): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ - \ ' Current Filetype: testft', - \ 'Available Linters: [''testlinter1'']', - \ ' Enabled Linters: [''testlinter1'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft', + \ 'Available Linters: [''testlinter1'']', + \ ' Enabled Linters: [''testlinter1'']', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo with compound filetypes should return linters for both of them): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ - \ ' Current Filetype: testft.testft2', - \ 'Available Linters: [''testlinter1'', ''testlinter2'']', - \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft.testft2', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo should return appropriately named global variables): @@ -238,17 +311,58 @@ Execute (ALEInfo should return appropriately named global variables): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ - \ ' Current Filetype: testft.testft2', - \ 'Available Linters: [''testlinter1'', ''testlinter2'']', - \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \ 'let g:ale_testft2_testlinter2_bar = {''x'': ''y''}', - \ 'let g:ale_testft2_testlinter2_foo = 123', - \ 'let g:ale_testft_testlinter1_bar = [''abc'']', - \ 'let g:ale_testft_testlinter1_foo = ''abc''', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft.testft2', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + [ + \ ' Linter Variables:', + \ '', + \ 'let g:ale_testft2_testlinter2_bar = {''x'': ''y''}', + \ 'let g:ale_testft2_testlinter2_foo = 123', + \ 'let g:ale_testft_testlinter1_bar = [''abc'']', + \ 'let g:ale_testft_testlinter1_foo = ''abc''', + \ ] + \ + g:globals_lines + \ + g:command_header + \) + +Execute (ALEInfoToFile should write to a file correctly): + if filereadable(g:dir . '/ale-info-test-file') + call delete(g:dir . '/ale-info-test-file') + endif + + let g:ale_testft_testlinter1_foo = 'abc' + let g:ale_testft_testlinter1_bar = ['abc'] + let g:ale_testft2_testlinter2_foo = 123 + let g:ale_testft2_testlinter2_bar = {'x': 'y'} + + call ale#linter#Define('testft', g:testlinter1) + call ale#linter#Define('testft2', g:testlinter2) + + execute 'ALEInfoToFile ' . fnameescape(g:dir . '/ale-info-test-file') + + AssertEqual + \ [ + \ ' Current Filetype: testft.testft2', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + [ + \ ' Linter Variables:', + \ '', + \ 'let g:ale_testft2_testlinter2_bar = {''x'': ''y''}', + \ 'let g:ale_testft2_testlinter2_foo = 123', + \ 'let g:ale_testft_testlinter1_bar = [''abc'']', + \ 'let g:ale_testft_testlinter1_foo = ''abc''', + \ ] + \ + g:globals_lines + \ + g:command_header, + \ readfile(g:dir . '/ale-info-test-file') Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo should buffer-local linter variables): @@ -258,15 +372,22 @@ Execute (ALEInfo should buffer-local linter variables): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ - \ ' Current Filetype: testft.testft2', - \ 'Available Linters: [''testlinter1'', ''testlinter2'']', - \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \ 'let g:ale_testft2_testlinter2_foo = 123', - \ 'let b:ale_testft2_testlinter2_foo = 456', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft.testft2', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + [ + \ ' Linter Variables:', + \ '', + \ 'let g:ale_testft2_testlinter2_foo = 123', + \ 'let b:ale_testft2_testlinter2_foo = 456', + \ ] + \ + g:globals_lines + \ + g:command_header + \) Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo should output linter aliases): @@ -279,18 +400,25 @@ Execute (ALEInfo should output linter aliases): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ - \ ' Current Filetype: testft.testft2', - \ 'Available Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Aliases:', - \ '''testlinter1'' -> [''testftalias1'', ''testftalias2'']', - \ '''testlinter2'' -> [''testftalias3'', ''testftalias4'']', - \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \ 'let g:ale_testft2_testlinter2_foo = 123', - \ 'let b:ale_testft2_testlinter2_foo = 456', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft.testft2', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Linter Aliases:', + \ '''testlinter1'' -> [''testftalias1'', ''testftalias2'']', + \ '''testlinter2'' -> [''testftalias3'', ''testftalias4'']', + \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + [ + \ ' Linter Variables:', + \ '', + \ 'let g:ale_testft2_testlinter2_foo = 123', + \ 'let b:ale_testft2_testlinter2_foo = 456', + \ ] + \ + g:globals_lines + \ + g:command_header + \) Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo should return command history): @@ -302,17 +430,22 @@ Execute (ALEInfo should return command history): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ + call CheckInfo( + \ [ \ ' Current Filetype: testft.testft2', \ 'Available Linters: [''testlinter1'', ''testlinter2'']', \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header + [ - \ '', - \ '(started) ''first command''', - \ '(started) [''/bin/bash'', ''\c'', ''last command'']', - \]) + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \ + [ + \ '', + \ '(started) ''first command''', + \ '(started) [''/bin/bash'', ''\c'', ''last command'']', + \ ] + \) Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo command history should print exit codes correctly): @@ -324,17 +457,22 @@ Execute (ALEInfo command history should print exit codes correctly): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ + call CheckInfo( + \ [ \ ' Current Filetype: testft.testft2', \ 'Available Linters: [''testlinter1'', ''testlinter2'']', \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header + [ - \ '', - \ '(finished - exit code 0) ''first command''', - \ '(finished - exit code 1) [''/bin/bash'', ''\c'', ''last command'']', - \]) + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \ + [ + \ '', + \ '(finished - exit code 0) ''first command''', + \ '(finished - exit code 1) [''/bin/bash'', ''\c'', ''last command'']', + \ ] + \) Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo command history should print command output if logging is on): @@ -367,31 +505,36 @@ Execute (ALEInfo command history should print command output if logging is on): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ + call CheckInfo( + \ [ \ ' Current Filetype: testft.testft2', \ 'Available Linters: [''testlinter1'', ''testlinter2'']', \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header + [ - \ '', - \ '(finished - exit code 0) ''first command''', - \ '', - \ '<<<OUTPUT STARTS>>>', - \ 'some', - \ 'first command output', - \ '<<<OUTPUT ENDS>>>', - \ '', - \ '(finished - exit code 1) [''/bin/bash'', ''\c'', ''last command'']', - \ '', - \ '<<<OUTPUT STARTS>>>', - \ 'different second command output', - \ '<<<OUTPUT ENDS>>>', - \ '', - \ '(finished - exit code 0) ''command with no output''', - \ '', - \ '<<<NO OUTPUT RETURNED>>>', - \]) + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \ + [ + \ '', + \ '(finished - exit code 0) ''first command''', + \ '', + \ '<<<OUTPUT STARTS>>>', + \ 'some', + \ 'first command output', + \ '<<<OUTPUT ENDS>>>', + \ '', + \ '(finished - exit code 1) [''/bin/bash'', ''\c'', ''last command'']', + \ '', + \ '<<<OUTPUT STARTS>>>', + \ 'different second command output', + \ '<<<OUTPUT ENDS>>>', + \ '', + \ '(finished - exit code 0) ''command with no output''', + \ '', + \ '<<<NO OUTPUT RETURNED>>>', + \ ] + \) Execute (ALEInfo should include executable checks in the history): call ale#linter#Define('testft', g:testlinter1) @@ -400,18 +543,23 @@ Execute (ALEInfo should include executable checks in the history): call ale#engine#IsExecutable(bufnr(''), 'TheresNoWayThisIsExecutable') call ale#engine#IsExecutable(bufnr(''), 'TheresNoWayThisIsExecutable') - call CheckInfo([ + call CheckInfo( + \ [ \ ' Current Filetype: testft.testft2', \ 'Available Linters: [''testlinter1'']', \ ' Enabled Linters: [''testlinter1'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header + [ - \ '', - \ '(executable check - success) ' . (has('win32') ? 'cmd' : 'echo'), - \ '(executable check - failure) TheresNoWayThisIsExecutable', - \ '(executable check - failure) TheresNoWayThisIsExecutable', - \]) + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \ + [ + \ '', + \ '(executable check - success) ' . (has('win32') ? 'cmd' : 'echo'), + \ '(executable check - failure) TheresNoWayThisIsExecutable', + \ '(executable check - failure) TheresNoWayThisIsExecutable', + \ ] + \) Execute (The option for caching failing executable checks should work): let g:ale_cache_executable_check_failures = 1 @@ -424,14 +572,60 @@ Execute (The option for caching failing executable checks should work): call ale#engine#IsExecutable(bufnr(''), 'TheresNoWayThisIsExecutable') call ale#engine#IsExecutable(bufnr(''), 'TheresNoWayThisIsExecutable') - call CheckInfo([ + call CheckInfo( + \ [ \ ' Current Filetype: testft.testft2', \ 'Available Linters: [''testlinter1'']', \ ' Enabled Linters: [''testlinter1'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header + [ - \ '', - \ '(executable check - success) ' . (has('win32') ? 'cmd' : 'echo'), - \ '(executable check - failure) TheresNoWayThisIsExecutable', - \]) + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \ + [ + \ '', + \ '(executable check - success) ' . (has('win32') ? 'cmd' : 'echo'), + \ '(executable check - failure) TheresNoWayThisIsExecutable', + \ ] + \) + +Given testft (Empty buffer): +Execute (LSP errors for a linter should be outputted): + let g:ale_lsp_error_messages = {'testlinter1': ['foo', 'bar']} + call ale#linter#Define('testft', g:testlinter1) + + call CheckInfo( + \ [ + \ ' Current Filetype: testft', + \ 'Available Linters: [''testlinter1'']', + \ ' Enabled Linters: [''testlinter1'']', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + [ + \ ' LSP Error Messages:', + \ '', + \ '(Errors for testlinter1)', + \ 'foo', + \ 'bar', + \ ] + \ + g:command_header + \) + +Given testft (Empty buffer): +Execute (LSP errors for other linters shouldn't appear): + let g:ale_lsp_error_messages = {'testlinter2': ['foo']} + call ale#linter#Define('testft', g:testlinter1) + + call CheckInfo( + \ [ + \ ' Current Filetype: testft', + \ 'Available Linters: [''testlinter1'']', + \ ' Enabled Linters: [''testlinter1'']', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) diff --git a/test/test_ale_lint_command.vader b/test/test_ale_lint_command.vader index d36b2177..bc2ebabe 100644 --- a/test/test_ale_lint_command.vader +++ b/test/test_ale_lint_command.vader @@ -14,13 +14,6 @@ Before: \ 'pattern': '', \ 'valid': 1, \}] - let g:expected_groups = [ - \ 'ALECleanupGroup', - \ 'ALECursorGroup', - \ 'ALEHighlightBufferGroup', - \ 'ALERunOnEnterGroup', - \ 'ALERunOnTextChangedGroup', - \] function! ToggleTestCallback(buffer, output) return [{ @@ -45,11 +38,13 @@ After: Restore unlet! g:expected_loclist - unlet! g:expected_groups + unlet! b:i - let g:ale_buffer_info = {} + call ale#engine#Cleanup(bufnr('')) call ale#linter#Reset() + let g:ale_buffer_info = {} + delfunction ToggleTestCallback Given foobar (Some imaginary filetype): @@ -60,14 +55,21 @@ Given foobar (Some imaginary filetype): Execute(ALELint should run the linters): AssertEqual 'foobar', &filetype - ALELint - call ale#engine#WaitForJobs(2000) + " Try to run the linter a few times, as it fails randomly in NeoVim. + for b:i in range(5) + ALELint + call ale#engine#WaitForJobs(2000) + + if !has('nvim') + " Sleep so the delayed list function can run. + " This breaks the tests in NeoVim for some reason. + sleep 1ms + endif - if !has('nvim') - " Sleep so the delayed list function can run. - " This breaks the tests in NeoVim for some reason. - sleep 1ms - endif + if ale#test#GetLoclistWithoutModule() == g:expected_loclist + break + endif + endfor " Check the loclist - AssertEqual g:expected_loclist, getloclist(0) + AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule() diff --git a/test/test_ale_toggle.vader b/test/test_ale_toggle.vader index d56f8c2b..db891009 100644 --- a/test/test_ale_toggle.vader +++ b/test/test_ale_toggle.vader @@ -5,12 +5,16 @@ Before: Save g:ale_run_synchronously Save g:ale_pattern_options Save g:ale_pattern_options_enabled + Save g:ale_set_balloons let g:ale_set_signs = 1 let g:ale_set_lists_synchronously = 1 let g:ale_run_synchronously = 1 let g:ale_pattern_options = {} let g:ale_pattern_options_enabled = 1 + let g:ale_set_balloons = + \ has('balloon_eval') && has('gui_running') || + \ has('balloon_eval_term') && !has('gui_running') unlet! b:ale_enabled @@ -28,12 +32,8 @@ Before: \}] let g:expected_groups = [ \ 'ALECleanupGroup', - \ 'ALECursorGroup', + \ 'ALEEvents', \ 'ALEHighlightBufferGroup', - \ 'ALERunOnEnterGroup', - \ 'ALERunOnFiletypeChangeGroup', - \ 'ALERunOnSaveGroup', - \ 'ALERunOnTextChangedGroup', \] function! ToggleTestCallback(buffer, output) @@ -56,7 +56,7 @@ Before: let l:results = [] for l:line in split(l:output, "\n") - let l:match = matchlist(l:line, '^ALE[a-zA-Z]\+Group') + let l:match = matchlist(l:line, '^ALE[a-zA-Z]\+') " We don't care about some groups here. if !empty(l:match) @@ -110,16 +110,12 @@ Given foobar (Some imaginary filetype): baz Execute(ALEToggle should reset everything and then run again): - " Run this test asynchrously. - let g:ale_run_synchronously = 0 - AssertEqual 'foobar', &filetype - call ale#Lint() - call ale#engine#WaitForJobs(2000) + ALELint " First check that everything is there... - AssertEqual g:expected_loclist, getloclist(0) + AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule() AssertEqual [0, [[2, 1000001, 'ALEErrorSign']]], ale#sign#FindCurrentSigns(bufnr('%')) AssertEqual \ [{'group': 'ALEError', 'pos1': [2, 3, 1]}], @@ -132,22 +128,15 @@ Execute(ALEToggle should reset everything and then run again): " Everything should be cleared. Assert !has_key(g:ale_buffer_info, bufnr('')), 'The g:ale_buffer_info Dictionary was not removed' - AssertEqual [], getloclist(0), 'The loclist was not cleared' + AssertEqual [], ale#test#GetLoclistWithoutModule(), 'The loclist was not cleared' AssertEqual [0, []], ale#sign#FindCurrentSigns(bufnr('%')), 'The signs were not cleared' AssertEqual [], getmatches(), 'The highlights were not cleared' - AssertEqual - \ [ - \ 'ALECleanupGroup', - \ 'ALEHighlightBufferGroup', - \ 'ALERunOnSaveGroup', - \ ], - \ ParseAuGroups() + AssertEqual g:expected_groups, ParseAuGroups() " Toggle ALE on, everything should be set up and run again. ALEToggle - call ale#engine#WaitForJobs(2000) - AssertEqual g:expected_loclist, getloclist(0) + AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule() AssertEqual [0, [[2, 1000001, 'ALEErrorSign']]], ale#sign#FindCurrentSigns(bufnr('%')) AssertEqual \ [{'group': 'ALEError', 'pos1': [2, 3, 1]}], @@ -156,9 +145,6 @@ Execute(ALEToggle should reset everything and then run again): AssertEqual [{'lnum': 2, 'bufnr': bufnr(''), 'col': 3, 'linter_name': 'testlinter', 'vcol': 0, 'nr': -1, 'type': 'E', 'text': 'foo bar', 'sign_id': 1000001}], g:ale_buffer_info[bufnr('')].loclist Execute(ALEToggle should skip filename keys and preserve them): - " Run this test asynchrously. - let g:ale_run_synchronously = 0 - AssertEqual 'foobar', &filetype let g:ale_buffer_info['/foo/bar/baz.txt'] = { @@ -170,8 +156,7 @@ Execute(ALEToggle should skip filename keys and preserve them): \ 'history': [], \} - call ale#Lint() - call ale#engine#WaitForJobs(2000) + ALELint " Now Toggle ALE off. ALEToggle @@ -189,7 +174,6 @@ Execute(ALEToggle should skip filename keys and preserve them): " Toggle ALE on again. ALEToggle - call ale#engine#WaitForJobs(2000) AssertEqual \ { @@ -203,18 +187,18 @@ Execute(ALEToggle should skip filename keys and preserve them): \ get(g:ale_buffer_info, '/foo/bar/baz.txt', {}) Execute(ALEDisable should reset everything and stay disabled): - call ale#Lint() + ALELint - AssertEqual g:expected_loclist, getloclist(0) + AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule() ALEDisable - AssertEqual [], getloclist(0) + AssertEqual [], ale#test#GetLoclistWithoutModule() AssertEqual 0, g:ale_enabled ALEDisable - AssertEqual [], getloclist(0) + AssertEqual [], ale#test#GetLoclistWithoutModule() AssertEqual 0, g:ale_enabled Execute(ALEEnable should enable ALE and lint again): @@ -222,16 +206,16 @@ Execute(ALEEnable should enable ALE and lint again): ALEEnable - AssertEqual g:expected_loclist, getloclist(0) + AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule() AssertEqual 1, g:ale_enabled Execute(ALEReset should reset everything for a buffer): AssertEqual 'foobar', &filetype - call ale#Lint() + ALELint " First check that everything is there... - AssertEqual g:expected_loclist, getloclist(0) + AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule() AssertEqual [0, [[2, 1000001, 'ALEErrorSign']]], ale#sign#FindCurrentSigns(bufnr('%')) AssertEqual \ [{'group': 'ALEError', 'pos1': [2, 3, 1]}], @@ -243,23 +227,19 @@ Execute(ALEReset should reset everything for a buffer): " Everything should be cleared. Assert !has_key(g:ale_buffer_info, bufnr('')), 'The g:ale_buffer_info Dictionary was not removed' - AssertEqual [], getloclist(0), 'The loclist was not cleared' + AssertEqual [], ale#test#GetLoclistWithoutModule(), 'The loclist was not cleared' AssertEqual [0, []], ale#sign#FindCurrentSigns(bufnr('%')), 'The signs were not cleared' AssertEqual [], getmatches(), 'The highlights were not cleared' AssertEqual 1, g:ale_enabled Execute(ALEToggleBuffer should reset everything and then run again): - " Run this test asynchrously. - let g:ale_run_synchronously = 0 - AssertEqual 'foobar', &filetype - call ale#Lint() - call ale#engine#WaitForJobs(2000) + ALELint " First check that everything is there... - AssertEqual g:expected_loclist, getloclist(0) + AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule() AssertEqual [0, [[2, 1000001, 'ALEErrorSign']]], ale#sign#FindCurrentSigns(bufnr('%')) AssertEqual \ [{'group': 'ALEError', 'pos1': [2, 3, 1]}], @@ -271,15 +251,14 @@ Execute(ALEToggleBuffer should reset everything and then run again): " Everything should be cleared. Assert !has_key(g:ale_buffer_info, bufnr('')), 'The g:ale_buffer_info Dictionary was not removed' - AssertEqual [], getloclist(0), 'The loclist was not cleared' + AssertEqual [], ale#test#GetLoclistWithoutModule(), 'The loclist was not cleared' AssertEqual [0, []], ale#sign#FindCurrentSigns(bufnr('%')), 'The signs were not cleared' AssertEqual [], getmatches(), 'The highlights were not cleared' " Toggle ALE on, everything should be set up and run again. ALEToggleBuffer - call ale#engine#WaitForJobs(2000) - AssertEqual g:expected_loclist, getloclist(0) + AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule() AssertEqual [0, [[2, 1000001, 'ALEErrorSign']]], ale#sign#FindCurrentSigns(bufnr('%')) AssertEqual \ [{'group': 'ALEError', 'pos1': [2, 3, 1]}], @@ -288,13 +267,13 @@ Execute(ALEToggleBuffer should reset everything and then run again): AssertEqual [{'lnum': 2, 'bufnr': bufnr(''), 'col': 3, 'linter_name': 'testlinter', 'vcol': 0, 'nr': -1, 'type': 'E', 'text': 'foo bar', 'sign_id': 1000001}], g:ale_buffer_info[bufnr('')].loclist Execute(ALEDisableBuffer should reset everything and stay disabled): - call ale#Lint() + ALELint - AssertEqual g:expected_loclist, getloclist(0) + AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule() ALEDisableBuffer - AssertEqual [], getloclist(0) + AssertEqual [], ale#test#GetLoclistWithoutModule() AssertEqual 0, b:ale_enabled Execute(ALEEnableBuffer should enable ALE and lint again): @@ -302,7 +281,7 @@ Execute(ALEEnableBuffer should enable ALE and lint again): ALEEnableBuffer - AssertEqual g:expected_loclist, getloclist(0) + AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule() AssertEqual 1, b:ale_enabled Execute(ALEEnableBuffer should complain when ALE is disabled globally): @@ -313,7 +292,7 @@ Execute(ALEEnableBuffer should complain when ALE is disabled globally): ALEEnableBuffer redir END - AssertEqual [], getloclist(0) + AssertEqual [], ale#test#GetLoclistWithoutModule() AssertEqual 0, b:ale_enabled AssertEqual 0, g:ale_enabled AssertEqual @@ -323,10 +302,10 @@ Execute(ALEEnableBuffer should complain when ALE is disabled globally): Execute(ALEResetBuffer should reset everything for a buffer): AssertEqual 'foobar', &filetype - call ale#Lint() + ALELint " First check that everything is there... - AssertEqual g:expected_loclist, getloclist(0) + AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule() AssertEqual [0, [[2, 1000001, 'ALEErrorSign']]], ale#sign#FindCurrentSigns(bufnr('%')) AssertEqual \ [{'group': 'ALEError', 'pos1': [2, 3, 1]}], @@ -338,9 +317,69 @@ Execute(ALEResetBuffer should reset everything for a buffer): " Everything should be cleared. Assert !has_key(g:ale_buffer_info, bufnr('')), 'The g:ale_buffer_info Dictionary was not removed' - AssertEqual [], getloclist(0), 'The loclist was not cleared' + AssertEqual [], ale#test#GetLoclistWithoutModule(), 'The loclist was not cleared' AssertEqual [0, []], ale#sign#FindCurrentSigns(bufnr('%')), 'The signs were not cleared' AssertEqual [], getmatches(), 'The highlights were not cleared' AssertEqual 1, g:ale_enabled AssertEqual 1, get(b:, 'ale_enabled', 1) + +Execute(Disabling ALE should disable balloons): + " These tests won't run in the console, but we can run them manually in GVim. + if has('balloon_eval') && has('gui_running') + \|| (has('balloon_eval_term') && !has('gui_running')) + call ale#linter#Reset() + + " Enable balloons, so we can check the expr value. + call ale#balloon#Enable() + + if has('balloon_eval') && has('gui_running') + AssertEqual 1, &ballooneval + else + AssertEqual 1, &balloonevalterm + endif + + AssertEqual 'ale#balloon#Expr()', &balloonexpr + + " Toggle ALE off. + ALEToggle + + " The balloon settings should be reset. + if has('balloon_eval') && has('gui_running') + AssertEqual 0, &ballooneval + else + AssertEqual 0, &balloonevalterm + endif + + AssertEqual '', &balloonexpr + endif + +Execute(Enabling ALE should enable balloons if the setting is on): + if has('balloon_eval') && has('gui_running') + \|| (has('balloon_eval_term') && !has('gui_running')) + call ale#linter#Reset() + call ale#balloon#Disable() + ALEDisable + let g:ale_set_balloons = 0 + ALEEnable + + if has('balloon_eval') && has('gui_running') + AssertEqual 0, &ballooneval + else + AssertEqual 0, &balloonevalterm + endif + + AssertEqual '', &balloonexpr + + ALEDisable + let g:ale_set_balloons = 1 + ALEEnable + + if has('balloon_eval') && has('gui_running') + AssertEqual 1, &ballooneval + else + AssertEqual 1, &balloonevalterm + endif + + AssertEqual 'ale#balloon#Expr()', &balloonexpr + endif diff --git a/test/test_ale_var.vader b/test/test_ale_var.vader index fb674d93..419a9983 100644 --- a/test/test_ale_var.vader +++ b/test/test_ale_var.vader @@ -5,8 +5,6 @@ After: unlet! g:ale_some_variable unlet! b:undefined_variable_name - let g:ale_fix_buffer_data = {} - Execute(ale#Var should return global variables): AssertEqual 'abc', ale#Var(bufnr(''), 'some_variable') @@ -24,18 +22,3 @@ Execute(ale#Var should throw exceptions for undefined variables): let b:undefined_variable_name = 'def' AssertThrows call ale#Var(bufnr(''), 'undefined_variable_name') - -Execute(ale#Var return variables from deleted buffers, saved for fixing things): - let g:ale_fix_buffer_data[1347347] = {'vars': {'ale_some_variable': 'def'}} - - AssertEqual 'def', ale#Var(1347347, 'some_variable') - -Execute(ale#Var should return the global variable for unknown variables): - let g:ale_fix_buffer_data = {} - - AssertEqual 'abc', ale#Var(1347347, 'some_variable') - -Execute(ale#Var should return the global variables when the ALE fix variable is undefined): - unlet! g:ale_fix_buffer_data - - AssertEqual 'abc', ale#Var(1347347, 'some_variable') diff --git a/test/test_alejobstarted_autocmd.vader b/test/test_alejobstarted_autocmd.vader new file mode 100644 index 00000000..388e5439 --- /dev/null +++ b/test/test_alejobstarted_autocmd.vader @@ -0,0 +1,45 @@ +Before: + Save g:ale_buffer_info + + let g:job_started_success = 0 + let g:ale_run_synchronously = 1 + + unlet! b:ale_linted + + function! TestCallback(buffer, output) + return [] + endfunction + + call ale#linter#PreventLoading('testft') + call ale#linter#Define('testft', { + \ 'name': 'testlinter', + \ 'callback': 'TestCallback', + \ 'executable': has('win32') ? 'cmd' : 'true', + \ 'command': 'true', + \}) + +After: + Restore + + let g:ale_run_synchronously = 0 + + try + augroup! VaderTest + catch + endtry + + unlet! g:job_started_success + + delfunction TestCallback + call ale#linter#Reset() + +Given testft (An empty file): +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 + + ALELint + + AssertEqual g:job_started_success, 1 diff --git a/test/test_alelint_autocmd.vader b/test/test_alelint_autocmd.vader index b19e6b4e..5af1cd47 100644 --- a/test/test_alelint_autocmd.vader +++ b/test/test_alelint_autocmd.vader @@ -3,12 +3,19 @@ Before: let g:post_success = 0 let g:ale_run_synchronously = 1 + unlet! b:ale_linted + After: let g:ale_run_synchronously = 0 let g:ale_buffer_info = {} - augroup! VaderTest -Execute (Run a lint cycle, and check that a variable is set in the autocmd): + try + augroup! VaderTest + catch + endtry + +Given foobar(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 @@ -19,3 +26,14 @@ Execute (Run a lint cycle, and check that a variable is set in the autocmd): AssertEqual g:pre_success, 1 AssertEqual g:post_success, 1 + +Execute(b:ale_linted should be increased after each lint cycle): + AssertEqual get(b:, 'ale_linted'), 0 + + call ale#Lint() + + AssertEqual get(b:, 'ale_linted'), 1 + + call ale#Lint() + + AssertEqual get(b:, 'ale_linted'), 2 diff --git a/test/test_autocmd_commands.vader b/test/test_autocmd_commands.vader index c03e8fb7..8d5048f0 100644 --- a/test/test_autocmd_commands.vader +++ b/test/test_autocmd_commands.vader @@ -1,6 +1,6 @@ Before: function! CheckAutocmd(group) - call ale#toggle#InitAuGroups() + call ale#events#Init() redir => l:output execute 'silent! autocmd ' . a:group @@ -26,8 +26,9 @@ Before: " for the one matching the current buffer. if l:line =~# '<buffer=' . bufnr('') . '>' let l:header .= ' <buffer>' - else + elseif l:line[:0] is# ' ' call add(l:matches, join(split(l:header . l:line))) + else let l:header = '' endif endif @@ -38,16 +39,28 @@ Before: return l:matches endfunction + Save g:ale_completion_enabled + Save g:ale_echo_cursor Save g:ale_enabled - Save g:ale_lint_on_text_changed - Save g:ale_lint_on_insert_leave - Save g:ale_pattern_options_enabled + Save g:ale_fix_on_save Save g:ale_lint_on_enter Save g:ale_lint_on_filetype_changed + Save g:ale_lint_on_insert_leave Save g:ale_lint_on_save - Save g:ale_echo_cursor - Save g:ale_fix_on_save - Save g:ale_completion_enabled + Save g:ale_lint_on_text_changed + Save g:ale_pattern_options_enabled + + " Turn everything on by defaul for these tests. + let g:ale_completion_enabled = 1 + let g:ale_echo_cursor = 1 + let g:ale_enabled = 1 + let g:ale_fix_on_save = 1 + let g:ale_lint_on_enter = 1 + let g:ale_lint_on_filetype_changed = 1 + let g:ale_lint_on_insert_leave = 1 + let g:ale_lint_on_save = 1 + let g:ale_lint_on_text_changed = 1 + let g:ale_pattern_options_enabled = 1 After: delfunction CheckAutocmd @@ -59,100 +72,95 @@ After: call ale#completion#Disable() endif - call ale#toggle#InitAuGroups() + call ale#events#Init() -Execute (g:ale_lint_on_text_changed = 0 should bind no events): +Execute (All events should be set up when everything is on): + let g:ale_echo_cursor = 1 + + AssertEqual + \ [ + \ 'BufEnter * call ale#events#ReadOrEnterEvent(str2nr(expand(''<abuf>'')))', + \ 'BufReadPost * call ale#events#ReadOrEnterEvent(str2nr(expand(''<abuf>'')))', + \ 'BufWinEnter * call ale#events#LintOnEnter(str2nr(expand(''<abuf>'')))', + \ 'BufWritePost * call ale#events#SaveEvent(str2nr(expand(''<abuf>'')))', + \ 'CursorHold * if exists(''*ale#engine#Cleanup'') | call ale#cursor#EchoCursorWarningWithDelay() | endif', + \ 'CursorMoved * if exists(''*ale#engine#Cleanup'') | call ale#cursor#EchoCursorWarningWithDelay() | endif', + \ 'FileChangedShellPost * call ale#events#FileChangedEvent(str2nr(expand(''<abuf>'')))', + \ 'FileType * call ale#events#FileTypeEvent( str2nr(expand(''<abuf>'')), expand(''<amatch>''))', + \ 'InsertLeave * call ale#Queue(0)', + \ 'InsertLeave if exists(''*ale#engine#Cleanup'') | call ale#cursor#EchoCursorWarning() | endif', + \ 'TextChanged * call ale#Queue(g:ale_lint_delay)', + \ 'TextChangedI * call ale#Queue(g:ale_lint_delay)', + \ ], + \ CheckAutocmd('ALEEvents') + +Execute (Only the required events should be bound even if various settings are off): + let g:ale_completion_enabled = 0 + let g:ale_echo_cursor = 0 + let g:ale_enabled = 0 + let g:ale_fix_on_save = 0 + let g:ale_lint_on_enter = 0 + let g:ale_lint_on_filetype_changed = 0 + let g:ale_lint_on_insert_leave = 0 + let g:ale_lint_on_save = 0 let g:ale_lint_on_text_changed = 0 + let g:ale_pattern_options_enabled = 0 - AssertEqual [], CheckAutocmd('ALERunOnTextChangedGroup') + AssertEqual + \ [ + \ 'BufEnter * call ale#events#ReadOrEnterEvent(str2nr(expand(''<abuf>'')))', + \ 'BufReadPost * call ale#events#ReadOrEnterEvent(str2nr(expand(''<abuf>'')))', + \ 'BufWritePost * call ale#events#SaveEvent(str2nr(expand(''<abuf>'')))', + \ ], + \ CheckAutocmd('ALEEvents') Execute (g:ale_lint_on_text_changed = 1 bind both events): let g:ale_lint_on_text_changed = 1 - AssertEqual [ - \ 'TextChanged * call ale#Queue(g:ale_lint_delay)', - \ 'TextChangedI * call ale#Queue(g:ale_lint_delay)' - \], CheckAutocmd('ALERunOnTextChangedGroup') + AssertEqual + \ [ + \ 'TextChanged * call ale#Queue(g:ale_lint_delay)', + \ 'TextChangedI * call ale#Queue(g:ale_lint_delay)', + \ ], + \ filter(CheckAutocmd('ALEEvents'), 'v:val =~ ''^TextChanged''') Execute (g:ale_lint_on_text_changed = 'always' should bind both events): let g:ale_lint_on_text_changed = 'always' - AssertEqual [ - \ 'TextChanged * call ale#Queue(g:ale_lint_delay)', - \ 'TextChangedI * call ale#Queue(g:ale_lint_delay)' - \], CheckAutocmd('ALERunOnTextChangedGroup') + AssertEqual + \ [ + \ 'TextChanged * call ale#Queue(g:ale_lint_delay)', + \ 'TextChangedI * call ale#Queue(g:ale_lint_delay)', + \ ], + \ filter(CheckAutocmd('ALEEvents'), 'v:val =~ ''^TextChanged''') Execute (g:ale_lint_on_text_changed = 'normal' should bind only TextChanged): let g:ale_lint_on_text_changed = 'normal' - AssertEqual [ - \ 'TextChanged * call ale#Queue(g:ale_lint_delay)', - \], CheckAutocmd('ALERunOnTextChangedGroup') + AssertEqual + \ [ + \ 'TextChanged * call ale#Queue(g:ale_lint_delay)', + \ ], + \ filter(CheckAutocmd('ALEEvents'), 'v:val =~ ''^TextChanged''') Execute (g:ale_lint_on_text_changed = 'insert' should bind only TextChangedI): let g:ale_lint_on_text_changed = 'insert' - AssertEqual [ - \ 'TextChangedI * call ale#Queue(g:ale_lint_delay)', - \], CheckAutocmd('ALERunOnTextChangedGroup') + AssertEqual + \ [ + \ 'TextChangedI * call ale#Queue(g:ale_lint_delay)', + \ ], + \ filter(CheckAutocmd('ALEEvents'), 'v:val =~ ''^TextChanged''') Execute (g:ale_lint_on_insert_leave = 1 should bind InsertLeave): let g:ale_lint_on_insert_leave = 1 - - AssertEqual [ - \ 'InsertLeave * call ale#Queue(0)', - \], CheckAutocmd('ALERunOnInsertLeave') - -Execute (g:ale_lint_on_insert_leave = 0 should bind no events): - let g:ale_lint_on_insert_leave = 0 - - AssertEqual [], CheckAutocmd('ALERunOnInsertLeave') - -Execute (g:ale_pattern_options_enabled = 1 should bind BufReadPost and BufEnter): - let g:ale_pattern_options_enabled = 1 - - AssertEqual [ - \ 'BufEnter * call ale#pattern_options#SetOptions(str2nr(expand(''<abuf>'')))', - \ 'BufReadPost * call ale#pattern_options#SetOptions(str2nr(expand(''<abuf>'')))', - \], CheckAutocmd('ALEPatternOptionsGroup') - -Execute (g:ale_pattern_options_enabled = 0 should still bind events): - let g:ale_pattern_options_enabled = 0 - - AssertEqual [ - \ 'BufEnter * call ale#pattern_options#SetOptions(str2nr(expand(''<abuf>'')))', - \ 'BufReadPost * call ale#pattern_options#SetOptions(str2nr(expand(''<abuf>'')))', - \], CheckAutocmd('ALEPatternOptionsGroup') - -Execute (g:ale_enabled = 0 should still bind pattern events): - let g:ale_enabled = 0 - - AssertEqual [ - \ 'BufEnter * call ale#pattern_options#SetOptions(str2nr(expand(''<abuf>'')))', - \ 'BufReadPost * call ale#pattern_options#SetOptions(str2nr(expand(''<abuf>'')))', - \], CheckAutocmd('ALEPatternOptionsGroup') - -Execute (g:ale_lint_on_enter = 0 should bind only the BufEnter event): - let g:ale_lint_on_enter = 0 + let g:ale_echo_cursor = 0 AssertEqual - \ ['BufEnter * call ale#events#EnterEvent(str2nr(expand(''<abuf>'')))'], - \ CheckAutocmd('ALERunOnEnterGroup') - -Execute (g:ale_lint_on_enter = 1 should bind the required events): - let g:ale_lint_on_enter = 1 - - AssertEqual [ - \ 'BufEnter * call ale#events#EnterEvent(str2nr(expand(''<abuf>'')))', - \ 'BufReadPost * call ale#Queue(0, ''lint_file'', str2nr(expand(''<abuf>'')))', - \ 'BufWinEnter * call ale#Queue(0, ''lint_file'', str2nr(expand(''<abuf>'')))', - \ 'FileChangedShellPost * call ale#events#FileChangedEvent(str2nr(expand(''<abuf>'')))', - \], CheckAutocmd('ALERunOnEnterGroup') - -Execute (g:ale_lint_on_filetype_changed = 0 should bind no events): - let g:ale_lint_on_filetype_changed = 0 - - AssertEqual [], CheckAutocmd('ALERunOnFiletypeChangeGroup') + \ [ + \ 'InsertLeave * call ale#Queue(0)', + \ ], + \ filter(CheckAutocmd('ALEEvents'), 'v:val =~ ''^InsertLeave''') Execute (g:ale_lint_on_filetype_changed = 1 should bind the FileType event): let g:ale_lint_on_filetype_changed = 1 @@ -164,34 +172,11 @@ Execute (g:ale_lint_on_filetype_changed = 1 should bind the FileType event): \ . 'expand(''<amatch>'')' \ . ')', \ ], - \ CheckAutocmd('ALERunOnFiletypeChangeGroup') - -Execute (The SaveEvent should always be bound): - let g:ale_enabled = 0 - let g:ale_lint_on_save = 0 - let g:ale_fix_on_save = 0 - - AssertEqual [ - \ 'BufWritePost * call ale#events#SaveEvent(str2nr(expand(''<abuf>'')))', - \], CheckAutocmd('ALERunOnSaveGroup') - -Execute (g:ale_echo_cursor = 0 should bind no events): - let g:ale_echo_cursor = 0 - - AssertEqual [], CheckAutocmd('ALECursorGroup') - -Execute (g:ale_echo_cursor = 1 should bind cursor events): - let g:ale_echo_cursor = 1 - - AssertEqual [ - \ 'CursorHold * call ale#cursor#EchoCursorWarningWithDelay()', - \ 'CursorMoved * call ale#cursor#EchoCursorWarningWithDelay()', - \ 'InsertLeave * call ale#cursor#EchoCursorWarning()', - \], CheckAutocmd('ALECursorGroup') + \ filter(CheckAutocmd('ALEEvents'), 'v:val =~ ''\v^FileType''') Execute (ALECleanupGroup should include the right commands): AssertEqual [ - \ 'BufDelete * call ale#engine#Cleanup(str2nr(expand(''<abuf>'')))', + \ 'BufDelete * if exists(''*ale#engine#Cleanup'') | call ale#engine#Cleanup(str2nr(expand(''<abuf>''))) | endif', \ 'QuitPre * call ale#events#QuitEvent(str2nr(expand(''<abuf>'')))', \], CheckAutocmd('ALECleanupGroup') diff --git a/test/test_balloon_messages.vader b/test/test_balloon_messages.vader index ec09fe29..d0724c21 100644 --- a/test/test_balloon_messages.vader +++ b/test/test_balloon_messages.vader @@ -1,21 +1,34 @@ Before: Save g:ale_buffer_info + Save g:ale_enabled + Save g:ale_set_balloons - let g:ale_buffer_info[347] = {'loclist': [ + let g:ale_set_balloons = 1 + + let g:ale_buffer_info[bufnr('')] = {'loclist': [ + \ { + \ 'bufnr': bufnr('%'), + \ 'lnum': 1, + \ 'col': 10, + \ 'linter_name': 'eslint', + \ 'type': 'W', + \ 'text': 'Ignore me.', + \ }, \ { - \ 'bufnr': 347, + \ 'bufnr': bufnr(''), \ 'lnum': 1, \ 'col': 10, \ 'text': 'Missing semicolon. (semi)', + \ 'type': 'E', \ }, \ { - \ 'bufnr': 347, + \ 'bufnr': bufnr(''), \ 'lnum': 2, \ 'col': 10, \ 'text': 'Infix operators must be spaced. (space-infix-ops)' \ }, \ { - \ 'bufnr': 347, + \ 'bufnr': bufnr(''), \ 'lnum': 2, \ 'col': 15, \ 'text': 'Missing radix parameter (radix)' @@ -25,17 +38,50 @@ Before: After: Restore + unlet! b:ale_enabled + unlet! b:ale_set_balloons + Execute(Balloon messages should be shown for the correct lines): AssertEqual \ 'Missing semicolon. (semi)', - \ ale#balloon#MessageForPos(347, 1, 1) + \ ale#balloon#MessageForPos(bufnr(''), 1, 1) Execute(Balloon messages should be shown for earlier columns): AssertEqual \ 'Infix operators must be spaced. (space-infix-ops)', - \ ale#balloon#MessageForPos(347, 2, 1) + \ ale#balloon#MessageForPos(bufnr(''), 2, 1) Execute(Balloon messages should be shown for later columns): AssertEqual \ 'Missing radix parameter (radix)', - \ ale#balloon#MessageForPos(347, 2, 16) + \ ale#balloon#MessageForPos(bufnr(''), 2, 16) + +Execute(Balloon messages should be disabled if ALE is disabled globally): + let g:ale_enabled = 0 + " Enabling the buffer should not make a difference. + let b:ale_enabled = 1 + + AssertEqual '', ale#balloon#MessageForPos(bufnr(''), 1, 1) + +Execute(Balloon messages should be disabled if ALE is disabled for a buffer): + let b:ale_enabled = 0 + + AssertEqual '', ale#balloon#MessageForPos(bufnr(''), 1, 1) + +Execute(Balloon messages should be disabled if the global setting is off): + let g:ale_set_balloons = 0 + + AssertEqual '', ale#balloon#MessageForPos(bufnr(''), 1, 1) + +Execute(Balloon messages should be disabled if the buffer setting is off): + let b:ale_set_balloons = 0 + + AssertEqual '', ale#balloon#MessageForPos(bufnr(''), 1, 1) + +Execute(The balloon buffer setting should override the global one): + let g:ale_set_balloons = 0 + let b:ale_set_balloons = 1 + + AssertEqual + \ 'Missing semicolon. (semi)', + \ ale#balloon#MessageForPos(bufnr(''), 1, 1) diff --git a/test/test_c_flag_parsing.vader b/test/test_c_flag_parsing.vader new file mode 100644 index 00000000..a4e00452 --- /dev/null +++ b/test/test_c_flag_parsing.vader @@ -0,0 +1,163 @@ +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 ' + \ . '-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(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 6080779f..00000000 --- a/test/test_c_import_paths.vader +++ /dev/null @@ -1,281 +0,0 @@ -Before: - 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_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() - -" Run this only once for this series of tests. The cleanup Execute step -" will run at the bottom of this file. -" -" We need to move .git/HEAD away so we don't match it, as we need to test -" functions which look for .git/HEAD. -Execute(Move .git/HEAD to a temp dir): - let g:temp_head_filename = tempname() - let g:head_filename = findfile('.git/HEAD', ';') - - if !empty(g:head_filename) - call writefile(readfile(g:head_filename, 'b'), g:temp_head_filename, 'b') - call delete(g:head_filename) - endif - -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++ Clang handler shoud use the include directory based on the .git location): - runtime! ale_linters/cpp/clang.vim - - if !isdirectory(g:dir . '/test_c_projects/git_and_nested_makefiles/.git') - call mkdir(g:dir . '/test_c_projects/git_and_nested_makefiles/.git') - endif - - if !filereadable(g:dir . '/test_c_projects/git_and_nested_makefiles/.git/HEAD') - call writefile([], g:dir . '/test_c_projects/git_and_nested_makefiles/.git/HEAD') - endif - - call ale#test#SetFilename('test_c_projects/git_and_nested_makefiles/src/file.cpp') - - AssertEqual - \ ale#Escape('clang++') - \ . ' -S -x c++ -fsyntax-only ' - \ . '-iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/git_and_nested_makefiles/src')) . ' ' - \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/git_and_nested_makefiles/include')) . ' ' - \ . ' -' - \ , 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('')) - -Execute(Move .git/HEAD back): - if !empty(g:head_filename) - call writefile(readfile(g:temp_head_filename, 'b'), g:head_filename, 'b') - call delete(g:temp_head_filename) - endif - - unlet! g:temp_head_filename - unlet! g:head_filename diff --git a/test/test_c_projects/makefile_project/subdir/file.c b/test/test_c_projects/makefile_project/subdir/file.c new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/test_c_projects/makefile_project/subdir/file.c diff --git a/test/test_checkingbuffer_autocmd.vader b/test/test_checkingbuffer_autocmd.vader new file mode 100644 index 00000000..9e3a8188 --- /dev/null +++ b/test/test_checkingbuffer_autocmd.vader @@ -0,0 +1,57 @@ +Before: + Save g:ale_run_synchronously + Save g:ale_buffer_info + + let g:ale_run_synchronously = 1 + let g:ale_buffer_info = {} + + let g:checking_buffer = 0 + + unlet! b:ale_linted + + function! TestCallback(buffer, output) + return [] + endfunction + + call ale#linter#PreventLoading('testft') + call ale#linter#Define('testft', { + \ 'name': 'testlinter', + \ 'callback': 'TestCallback', + \ 'executable': has('win32') ? 'cmd' : 'true', + \ 'command': 'true', + \}) + +After: + Restore + + unlet! g:checking_buffer + + delfunction TestCallback + call ale#linter#Reset() + + augroup VaderTest + autocmd! + augroup end + + augroup! VaderTest + +Given testft (An empty file): +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 + + ALELint + + AssertEqual g:checking_buffer, 0 + +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 + + ALELint + + AssertEqual g:checking_buffer, 1 diff --git a/test/test_conflicting_plugin_warnings.vader b/test/test_conflicting_plugin_warnings.vader deleted file mode 100644 index 08a4c412..00000000 --- a/test/test_conflicting_plugin_warnings.vader +++ /dev/null @@ -1,74 +0,0 @@ -Execute(The after file should have been loaded for real): - " FIXME: Fix these tests in NeoVim. - if !has('nvim') - Assert has_key(g:, 'loaded_ale_after'), 'g:loaded_ale_after was not set!' - Assert g:loaded_ale_after - endif - -Before: - silent! cd /testplugin/test - cd .. - unlet! g:loaded_ale_after - -After: - cd test - let g:loaded_ale_after = 1 - let g:ale_emit_conflict_warnings = 1 - unlet! g:loaded_syntastic_plugin - unlet! g:loaded_neomake - unlet! g:loaded_validator_plugin - -Execute(ALE should not warn when nothing extra is installed): - " Nothing should be thrown when loading the after file. - source after/plugin/ale.vim - -Execute(ALE should warn users when Syntastic is installed): - let g:loaded_syntastic_plugin = 1 - - AssertThrows source after/plugin/ale.vim - AssertEqual - \ 'ALE conflicts with Syntastic' - \ . '. Uninstall it, or disable this warning with ' - \ . '`let g:ale_emit_conflict_warnings = 0` in your vimrc file, ' - \ . '*before* plugins are loaded.', - \ g:vader_exception - -Execute(ALE should not warn about Syntastic when the flag is set): - let g:loaded_syntastic_plugin = 1 - let g:ale_emit_conflict_warnings = 0 - - source after/plugin/ale.vim - -Execute(ALE should warn users when Neomake is installed): - let g:loaded_neomake = 1 - - AssertThrows source after/plugin/ale.vim - AssertEqual - \ 'ALE conflicts with Neomake' - \ . '. Uninstall it, or disable this warning with ' - \ . '`let g:ale_emit_conflict_warnings = 0` in your vimrc file, ' - \ . '*before* plugins are loaded.', - \ g:vader_exception - -Execute(ALE should not warn about Neomake when the flag is set): - let g:loaded_neomake = 1 - let g:ale_emit_conflict_warnings = 0 - - source after/plugin/ale.vim - -Execute(ALE should warn users when Validator is installed): - let g:loaded_validator_plugin = 1 - - AssertThrows source after/plugin/ale.vim - AssertEqual - \ 'ALE conflicts with Validator' - \ . '. Uninstall it, or disable this warning with ' - \ . '`let g:ale_emit_conflict_warnings = 0` in your vimrc file, ' - \ . '*before* plugins are loaded.', - \ g:vader_exception - -Execute(ALE should not warn about Validator when the flag is set): - let g:loaded_validator_plugin = 1 - let g:ale_emit_conflict_warnings = 0 - - source after/plugin/ale.vim diff --git a/test/test_cursor_warnings.vader b/test/test_cursor_warnings.vader index 19592217..24652909 100644 --- a/test/test_cursor_warnings.vader +++ b/test/test_cursor_warnings.vader @@ -2,6 +2,7 @@ Before: Save g:ale_echo_msg_format Save g:ale_echo_cursor + " We should prefer the error message at column 10 instead of the warning. let g:ale_buffer_info = { \ bufnr('%'): { \ 'loclist': [ @@ -12,6 +13,17 @@ Before: \ 'vcol': 0, \ 'linter_name': 'eslint', \ 'nr': -1, + \ 'type': 'W', + \ 'code': 'semi', + \ 'text': 'Ignore me.', + \ }, + \ { + \ 'lnum': 1, + \ 'col': 10, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'linter_name': 'eslint', + \ 'nr': -1, \ 'type': 'E', \ 'code': 'semi', \ 'text': 'Missing semicolon.', diff --git a/test/test_dockerfile_hadolint_linter.vader b/test/test_dockerfile_hadolint_linter.vader index 7262c5b0..3edbb2b6 100644 --- a/test/test_dockerfile_hadolint_linter.vader +++ b/test/test_dockerfile_hadolint_linter.vader @@ -55,7 +55,7 @@ Execute(command is correct when using docker): let b:ale_dockerfile_hadolint_use_docker = 'always' AssertEqual - \ "docker run --rm -i lukasmartinelli/hadolint", + \ "docker run --rm -i hadolint/hadolint", \ ale_linters#dockerfile#hadolint#GetCommand(bufnr('')) @@ -66,4 +66,25 @@ Execute(command is correct when not docker): \ "hadolint -", \ ale_linters#dockerfile#hadolint#GetCommand(bufnr('')) +Execute(test warnings from hadolint): + AssertEqual + \ [{'lnum': 10, 'col': 0, 'type': 'W', 'text': 'Using latest is prone to errors', 'detail': "DL3007 ( https://github.com/hadolint/hadolint/wiki/DL3007 )\n\nUsing latest is prone to errors"}], + \ ale_linters#dockerfile#hadolint#Handle(bufnr(''), [ + \ '/dev/stdin:10 DL3007 Using latest is prone to errors', + \ ]) + +Execute(test warnings from shellcheck): + AssertEqual + \ [{'lnum': 3, 'col': 0, 'type': 'W', 'text': 'bar is referenced but not assigned.', 'detail': "SC2154 ( https://github.com/koalaman/shellcheck/wiki/SC2154 )\n\nbar is referenced but not assigned."}], + \ ale_linters#dockerfile#hadolint#Handle(bufnr(''), [ + \ '/dev/stdin:3 SC2154 bar is referenced but not assigned.', + \ ]) + +Execute(test errors from dockerfile parser): + AssertEqual + \ [{'lnum': 3, 'col': 4, 'type': 'E', 'text': 'unexpected "A" expecting at least one space after ''RUN''', 'detail': 'unexpected "A" expecting at least one space after ''RUN'''}], + \ ale_linters#dockerfile#hadolint#Handle(bufnr(''), [ + \ "/dev/stdin:3:4 unexpected \"A\" expecting at least one space after 'RUN'", + \ ]) + " fin... diff --git a/test/test_elm_executable_detection.vader b/test/test_elm_executable_detection.vader deleted file mode 100644 index 4227cbfa..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-make'), - \ 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-make', - \ 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-make' - let g:ale_elm_make_use_global = 1 - - call ale#test#SetFilename('elm-test-files/app/testfile.elm') - - AssertEqual - \ 'other-elm-make', - \ 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 b3a45b14..818659db 100644 --- a/test/test_engine_lsp_response_handling.vader +++ b/test/test_engine_lsp_response_handling.vader @@ -1,5 +1,9 @@ Before: Save g:ale_buffer_info + Save g:ale_lsp_error_messages + + unlet! g:ale_lsp_error_messages + call ale#test#SetDirectory('/testplugin/test') After: @@ -7,7 +11,9 @@ After: call ale#test#RestoreDirectory() call ale#linter#Reset() + call ale#lsp_linter#ClearLSPData() +Given foobar(An empty file): Execute(tsserver syntax error responses should be handled correctly): runtime ale_linters/typescript/tsserver.vim call ale#test#SetFilename('filename.ts') @@ -15,7 +21,7 @@ Execute(tsserver syntax error responses should be handled correctly): " When we get syntax errors and no semantic errors, we should keep the " syntax errors. - call ale#engine#HandleLSPResponse(1, { + call ale#lsp_linter#HandleLSPResponse(1, { \ 'seq': 0, \ 'type': 'event', \ 'event': 'syntaxDiag', @@ -37,7 +43,7 @@ Execute(tsserver syntax error responses should be handled correctly): \ ], \ }, \}) - call ale#engine#HandleLSPResponse(1, { + call ale#lsp_linter#HandleLSPResponse(1, { \ 'seq': 0, \ 'type': 'event', \ 'event': 'semanticDiag', @@ -57,15 +63,15 @@ Execute(tsserver syntax error responses should be handled correctly): \ 'vcol': 0, \ 'nr': 1005, \ 'type': 'E', - \ 'text': ''','' expected.', + \ 'text': '1005: '','' expected.', \ 'valid': 1, \ 'pattern': '', \ }, \ ], - \ getloclist(0) + \ ale#test#GetLoclistWithoutModule() " After we get empty syntax errors, we should clear them. - call ale#engine#HandleLSPResponse(1, { + call ale#lsp_linter#HandleLSPResponse(1, { \ 'seq': 0, \ 'type': 'event', \ 'event': 'syntaxDiag', @@ -79,7 +85,7 @@ Execute(tsserver syntax error responses should be handled correctly): AssertEqual \ [ \ ], - \ getloclist(0) + \ ale#test#GetLoclistWithoutModule() Execute(tsserver semantic error responses should be handled correctly): runtime ale_linters/typescript/tsserver.vim @@ -88,7 +94,7 @@ Execute(tsserver semantic error responses should be handled correctly): " When we get syntax errors and no semantic errors, we should keep the " syntax errors. - call ale#engine#HandleLSPResponse(1, { + call ale#lsp_linter#HandleLSPResponse(1, { \ 'seq': 0, \ 'type': 'event', \ 'event': 'syntaxDiag', @@ -98,7 +104,7 @@ Execute(tsserver semantic error responses should be handled correctly): \ ], \ }, \}) - call ale#engine#HandleLSPResponse(1, { + call ale#lsp_linter#HandleLSPResponse(1, { \ 'seq': 0, \ 'type': 'event', \ 'event': 'semanticDiag', @@ -130,15 +136,15 @@ 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': '', \ }, \ ], - \ getloclist(0) + \ ale#test#GetLoclistWithoutModule() " After we get empty syntax errors, we should clear them. - call ale#engine#HandleLSPResponse(1, { + call ale#lsp_linter#HandleLSPResponse(1, { \ 'seq': 0, \ 'type': 'event', \ 'event': 'semanticDiag', @@ -152,4 +158,21 @@ Execute(tsserver semantic error responses should be handled correctly): AssertEqual \ [ \ ], - \ getloclist(0) + \ ale#test#GetLoclistWithoutModule() + +Execute(LSP errors should be logged in the history): + call ale#lsp_linter#SetLSPLinterMap({'347': 'foobar'}) + call ale#lsp_linter#HandleLSPResponse(347, { + \ 'jsonrpc': '2.0', + \ 'error': { + \ 'code': -32602, + \ 'message': 'xyz', + \ 'data': { + \ 'traceback': ['123', '456'], + \ }, + \ }, + \}) + + AssertEqual + \ {'foobar': ["xyz\n123\n456"]}, + \ get(g:, 'ale_lsp_error_messages', {}) diff --git a/test/test_env_function.vader b/test/test_env_function.vader new file mode 100644 index 00000000..856a3f57 --- /dev/null +++ b/test/test_env_function.vader @@ -0,0 +1,8 @@ +Execute(ale#Env should produce the correct syntax): + if has('win32') + AssertEqual 'set name=xxx && ', ale#Env('name', 'xxx') + AssertEqual 'set name="foo bar" && ', ale#Env('name', 'foo bar') + else + AssertEqual 'name=''xxx'' ', ale#Env('name', 'xxx') + AssertEqual 'name=''foo bar'' ', ale#Env('name', 'foo bar') + endif diff --git a/test/test_errors_removed_after_filetype_changed.vader b/test/test_errors_removed_after_filetype_changed.vader index 92d248d0..651a74f2 100644 --- a/test/test_errors_removed_after_filetype_changed.vader +++ b/test/test_errors_removed_after_filetype_changed.vader @@ -1,8 +1,23 @@ Before: + Save &filetype + Save g:ale_buffer_info + Save g:ale_echo_cursor Save g:ale_run_synchronously + Save g:ale_run_synchronously + Save g:ale_set_highlights + Save g:ale_set_loclist + Save g:ale_set_quickfix + Save g:ale_set_signs + + " Enable only the one feature we need. + 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 - let b:old_filetype = &filetype let g:ale_run_synchronously = 1 + call setloclist(0, []) noautocmd let &filetype = 'foobar' @@ -10,6 +25,7 @@ Before: return [{'text': 'x', 'lnum': 1}] endfunction + call ale#linter#PreventLoading('foobar') call ale#linter#Define('foobar', { \ 'name': 'buffer_linter', \ 'callback': 'TestCallback', @@ -17,7 +33,7 @@ Before: \ 'command': 'true', \ 'read_buffer': 0, \}) - + call ale#linter#PreventLoading('foobar2') call ale#linter#Define('foobar2', { \ 'name': 'buffer_linter', \ 'callback': 'TestCallback', @@ -28,22 +44,16 @@ Before: After: Restore - - noautocmd let &filetype = b:old_filetype - unlet b:old_filetype delfunction TestCallback - if has_key(g:ale_buffer_info, bufnr('')) - call remove(g:ale_buffer_info, bufnr('')) - endif - - call ale#Queue(0) + call ale#linter#Reset() + call setloclist(0, []) Execute(Error should be removed when the filetype changes to something else we cannot check): call ale#Queue(0) sleep 1ms - AssertEqual 1, len(getloclist(0)) + AssertEqual 1, len(ale#test#GetLoclistWithoutModule()) noautocmd let &filetype = 'foobar2' @@ -51,11 +61,11 @@ Execute(Error should be removed when the filetype changes to something else we c sleep 1ms " We should get some items from the second filetype. - AssertEqual 1, len(getloclist(0)) + AssertEqual 1, len(ale#test#GetLoclistWithoutModule()) noautocmd let &filetype = 'xxx' call ale#Queue(0) sleep 1ms - AssertEqual 0, len(getloclist(0)) + AssertEqual 0, len(ale#test#GetLoclistWithoutModule()) diff --git a/test/test_filetype_linter_defaults.vader b/test/test_filetype_linter_defaults.vader index ea4a05fb..4f190226 100644 --- a/test/test_filetype_linter_defaults.vader +++ b/test/test_filetype_linter_defaults.vader @@ -22,7 +22,7 @@ Execute(The defaults for the csh filetype should be correct): AssertEqual [], GetLinterNames('csh') Execute(The defaults for the go filetype should be correct): - AssertEqual ['gofmt', 'golint', 'go vet'], GetLinterNames('go') + AssertEqual ['gofmt', 'golint', 'govet'], GetLinterNames('go') let g:ale_linters_explicit = 1 diff --git a/test/test_find_references.vader b/test/test_find_references.vader new file mode 100644 index 00000000..88b2d762 --- /dev/null +++ b/test/test_find_references.vader @@ -0,0 +1,279 @@ +Before: + call ale#test#SetDirectory('/testplugin/test') + call ale#test#SetFilename('dummy.txt') + + let g:old_filename = expand('%:p') + 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/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: + 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() + + 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 + 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 tsserver handler should be ignored): + call ale#references#HandleTSServerResponse(1, {'command': 'foo'}) + +Execute(Failed reference responses should be handled correctly): + call ale#references#SetMap({3: {}}) + call ale#references#HandleTSServerResponse( + \ 1, + \ {'command': 'references', 'request_seq': 3} + \) + AssertEqual {}, ale#references#GetMap() + +Given typescript(Some typescript file): + foo + somelongerline + bazxyzxyzxyz + +Execute(Results should be shown for tsserver responses): + call ale#references#SetMap({3: {}}) + call ale#references#HandleTSServerResponse(1, { + \ 'command': 'references', + \ 'request_seq': 3, + \ 'success': v:true, + \ 'body': { + \ 'symbolStartOffset': 9, + \ 'refs': [ + \ { + \ 'file': '/foo/bar/app.ts', + \ 'isWriteAccess': v:true, + \ 'lineText': 'import {doSomething} from ''./whatever''', + \ 'end': {'offset': 24, 'line': 9}, + \ 'start': {'offset': 9, 'line': 9}, + \ 'isDefinition': v:true, + \ }, + \ { + \ 'file': '/foo/bar/app.ts', + \ 'isWriteAccess': v:false, + \ 'lineText': ' doSomething()', + \ 'end': {'offset': 18, 'line': 804}, + \ 'start': {'offset': 3, 'line': 804}, + \ 'isDefinition': v:false, + \ }, + \ { + \ 'file': '/foo/bar/other/app.ts', + \ 'isWriteAccess': v:false, + \ 'lineText': ' doSomething()', + \ 'end': {'offset': 18, 'line': 51}, + \ 'start': {'offset': 3, 'line': 51}, + \ 'isDefinition': v:false, + \ }, + \ ], + \ 'symbolDisplayString': 'import doSomething', + \ 'symbolName': 'doSomething()', + \ }, + \}) + + AssertEqual + \ [ + \ {'filename': '/foo/bar/app.ts', 'column': 9, 'line': 9}, + \ {'filename': '/foo/bar/app.ts', 'column': 3, 'line': 804}, + \ {'filename': '/foo/bar/other/app.ts', 'column': 3, 'line': 51}, + \ ], + \ g:item_list + AssertEqual {}, ale#references#GetMap() + +Execute(The preview window should not be opened for empty tsserver responses): + call ale#references#SetMap({3: {}}) + call ale#references#HandleTSServerResponse(1, { + \ 'command': 'references', + \ 'request_seq': 3, + \ 'success': v:true, + \ 'body': { + \ 'symbolStartOffset': 9, + \ 'refs': [ + \ ], + \ 'symbolDisplayString': 'import doSomething', + \ 'symbolName': 'doSomething()', + \ }, + \}) + + Assert !g:preview_called + AssertEqual {}, ale#references#GetMap() + AssertEqual ['echom ''No references found.'''], g:expr_list + +Execute(tsserver reference requests should be sent): + runtime ale_linters/typescript/tsserver.vim + call setpos('.', [bufnr(''), 2, 5, 0]) + + ALEFindReferences + + " We shouldn't register the callback yet. + AssertEqual '''''', string(g:Callback) + + AssertEqual type(function('type')), type(g:WaitCallback) + AssertEqual 'references', g:capability_checked + call call(g:WaitCallback, [g:conn_id, '/foo/bar']) + + AssertEqual + \ 'function(''ale#references#HandleTSServerResponse'')', + \ string(g:Callback) + AssertEqual + \ [[0, 'ts@references', {'file': expand('%:p'), 'line': 2, 'offset': 5}]], + \ g:message_list + AssertEqual {'42': {}}, ale#references#GetMap() + +Given python(Some Python file): + foo + somelongerline + bazxyzxyzxyz + +Execute(LSP reference responses should be handled): + call ale#references#SetMap({3: {}}) + call ale#references#HandleLSPResponse( + \ 1, + \ { + \ 'id': 3, + \ 'result': [ + \ { + \ 'uri': ale#path#ToURI(ale#path#Simplify(g:dir . '/completion_dummy_file')), + \ 'range': { + \ 'start': {'line': 2, 'character': 7}, + \ }, + \ }, + \ { + \ '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, + \ }, + \ { + \ 'filename': ale#path#Simplify(g:dir . '/other_file'), + \ 'line': 8, + \ 'column': 16, + \ }, + \ ], + \ g:item_list + AssertEqual {}, ale#references#GetMap() + +Execute(Preview windows should not be opened for empty LSP reference responses): + call ale#references#SetMap({3: {}}) + call ale#references#HandleLSPResponse( + \ 1, + \ { + \ 'id': 3, + \ 'result': [ + \ ], + \ } + \) + + Assert !g:preview_called + AssertEqual {}, ale#references#GetMap() + AssertEqual ['echom ''No references found.'''], g:expr_list + +Execute(LSP reference requests should be sent): + runtime ale_linters/python/pyls.vim + let b:ale_linters = ['pyls'] + call setpos('.', [bufnr(''), 1, 5, 0]) + + ALEFindReferences + + " We shouldn't register the callback yet. + AssertEqual '''''', string(g:Callback) + + AssertEqual type(function('type')), type(g:WaitCallback) + AssertEqual 'references', g:capability_checked + call call(g:WaitCallback, [g:conn_id, '/foo/bar']) + + AssertEqual + \ 'function(''ale#references#HandleLSPResponse'')', + \ string(g:Callback) + + AssertEqual + \ [ + \ [1, 'textDocument/didChange', { + \ 'textDocument': { + \ 'uri': ale#path#ToURI(expand('%:p')), + \ 'version': g:ale_lsp_next_version_id - 1, + \ }, + \ 'contentChanges': [{'text': join(getline(1, '$'), "\n") . "\n"}] + \ }], + \ [0, 'textDocument/references', { + \ 'textDocument': {'uri': ale#path#ToURI(expand('%:p'))}, + \ 'position': {'line': 0, 'character': 3}, + \ 'context': {'includeDeclaration': v:false}, + \ }], + \ ], + \ g:message_list + + AssertEqual {'42': {}}, ale#references#GetMap() diff --git a/test/test_flow_command.vader b/test/test_flow_command.vader index 49546e94..c673ce0a 100644 --- a/test/test_flow_command.vader +++ b/test/test_flow_command.vader @@ -1,8 +1,11 @@ Before: runtime ale_linters/javascript/flow.vim + call ale#test#SetDirectory('/testplugin/test') After: + unlet! b:ale_javascript_flow_use_respect_pragma + call ale#test#RestoreDirectory() call ale#linter#Reset() call ale#semver#ResetVersionCache() @@ -15,6 +18,16 @@ Execute(flow should return a command to run if a .flowconfig file exists): \ . ' check-contents --respect-pragma --json --from ale %s', \ ale_linters#javascript#flow#GetCommand(bufnr('%'), []) +Execute(flow should not use the respect pragma argument if the option is off): + call ale#test#SetFilename('flow/a/sub/dummy') + + let b:ale_javascript_flow_use_respect_pragma = 0 + + AssertEqual + \ ale#Escape('flow') + \ . ' check-contents --json --from ale %s', + \ ale_linters#javascript#flow#GetCommand(bufnr('%'), []) + Execute(flow should should not use --respect-pragma for old versions): call ale#test#SetFilename('flow/a/sub/dummy') diff --git a/test/test_format_command.vader b/test/test_format_command.vader index f6143a5a..71285efa 100644 --- a/test/test_format_command.vader +++ b/test/test_format_command.vader @@ -15,10 +15,10 @@ After: delfunction CheckTempFile Execute(FormatCommand should do nothing to basic command strings): - AssertEqual ['', 'awesome-linter do something'], ale#command#FormatCommand(bufnr('%'), 'awesome-linter do something', 0) + AssertEqual ['', 'awesome-linter do something'], ale#command#FormatCommand(bufnr('%'), '', 'awesome-linter do something', 0) Execute(FormatCommand should handle %%, and ignore other percents): - AssertEqual ['', '% %%d %%f %x %'], ale#command#FormatCommand(bufnr('%'), '%% %%%d %%%f %x %', 0) + AssertEqual ['', '% %%d %%f %x %'], ale#command#FormatCommand(bufnr('%'), '', '%% %%%d %%%f %x %', 0) Execute(FormatCommand should convert %s to the current filename): AssertEqual @@ -26,10 +26,10 @@ Execute(FormatCommand should convert %s to the current filename): \ '', \ 'foo ' . ale#Escape(expand('%:p')) . ' bar ' . ale#Escape(expand('%:p')) \ ], - \ ale#command#FormatCommand(bufnr('%'), 'foo %s bar %s', 0) + \ ale#command#FormatCommand(bufnr('%'), '', 'foo %s bar %s', 0) Execute(FormatCommand should convert %t to a new temporary filename): - let g:result = ale#command#FormatCommand(bufnr('%'), 'foo %t bar %t', 0) + let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo %t bar %t', 0) call CheckTempFile(g:result[0]) @@ -43,7 +43,7 @@ Execute(FormatCommand should convert %t to a new temporary filename): AssertEqual g:match[1], g:match[2] Execute(FormatCommand should let you combine %s and %t): - let g:result = ale#command#FormatCommand(bufnr('%'), 'foo %t bar %s', 0) + let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo %t bar %s', 0) call CheckTempFile(g:result[0]) @@ -56,11 +56,34 @@ Execute(FormatCommand should let you combine %s and %t): " The second item should be equal to the original filename. AssertEqual ale#Escape(expand('%:p')), g:match[2] +Execute(FormatCommand should replace %e with the escaped executable): + if has('win32') + AssertEqual + \ ['', 'foo foo'], + \ ale#command#FormatCommand(bufnr('%'), 'foo', '%e %e', 0) + AssertEqual + \ ['', '"foo bar"'], + \ ale#command#FormatCommand(bufnr('%'), 'foo bar', '%e', 0) + AssertEqual + \ ['', '%e %e'], + \ ale#command#FormatCommand(bufnr('%'), '', '%e %e', 0) + else + AssertEqual + \ ['', '''foo'' ''foo'''], + \ ale#command#FormatCommand(bufnr('%'), 'foo', '%e %e', 0) + AssertEqual + \ ['', '''foo bar'''], + \ ale#command#FormatCommand(bufnr('%'), 'foo bar', '%e', 0) + AssertEqual + \ ['', '%e %e'], + \ ale#command#FormatCommand(bufnr('%'), '', '%e %e', 0) + endif + Execute(EscapeCommandPart should escape all percent signs): AssertEqual '%%s %%t %%%% %%s %%t %%%%', ale#engine#EscapeCommandPart('%s %t %% %s %t %%') Execute(EscapeCommandPart should pipe in temporary files appropriately): - let g:result = ale#command#FormatCommand(bufnr('%'), 'foo bar', 1) + let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo bar', 1) call CheckTempFile(g:result[0]) @@ -68,7 +91,7 @@ Execute(EscapeCommandPart should pipe in temporary files appropriately): Assert !empty(g:match), 'No match found! Result was: ' . g:result[1] AssertEqual ale#Escape(g:result[0]), g:match[1] - let g:result = ale#command#FormatCommand(bufnr('%'), 'foo bar %t', 1) + let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo bar %t', 1) call CheckTempFile(g:result[0]) diff --git a/test/test_format_temporary_file_creation.vader b/test/test_format_temporary_file_creation.vader index 1afaba30..385af908 100644 --- a/test/test_format_temporary_file_creation.vader +++ b/test/test_format_temporary_file_creation.vader @@ -1,12 +1,36 @@ Before: + Save g:ale_buffer_info + Save g:ale_echo_cursor + Save g:ale_enabled + Save g:ale_run_synchronously + Save g:ale_set_highlights + Save g:ale_set_loclist + Save g:ale_set_quickfix + Save g:ale_set_signs + + " Disable the features we don't need to check. + let g:ale_buffer_info = {} + let g:ale_echo_cursor = 0 + let g:ale_enabled = 1 + let g:ale_run_synchronously = 1 + let g:ale_set_highlights = 0 + let g:ale_set_loclist = 0 + let g:ale_set_quickfix = 0 + let g:ale_set_signs = 0 + let g:output = [] function! TestCallback(buffer, output) - let g:output = a:output + " Extract just letters from the output. + let g:output = filter( + \ map(a:output, 'matchstr(v:val, ''[a-zA-Z]\+'')'), + \ '!empty(v:val)' + \) return [] endfunction + call ale#linter#PreventLoading('foobar') call ale#linter#Define('foobar', { \ 'name': 'testlinter', \ 'callback': 'TestCallback', @@ -15,8 +39,12 @@ Before: \}) After: + Restore + unlet! g:output delfunction TestCallback + + call ale#engine#Cleanup(bufnr('')) call ale#linter#Reset() Given foobar (Some imaginary filetype): @@ -27,9 +55,6 @@ Given foobar (Some imaginary filetype): Execute(ALE should be able to read the %t file): AssertEqual 'foobar', &filetype - " Sleep a little so the test passes more. - sleep 100ms - call ale#Lint() - call ale#engine#WaitForJobs(2000) + ALELint AssertEqual ['foo', 'bar', 'baz'], g:output diff --git a/test/test_go_to_definition.vader b/test/test_go_to_definition.vader index b77a75ac..c64db514 100644 --- a/test/test_go_to_definition.vader +++ b/test/test_go_to_definition.vader @@ -3,46 +3,69 @@ Before: call ale#test#SetFilename('dummy.txt') let g:old_filename = expand('%:p') - let g:Callback = 0 + let g:Callback = '' 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/definition.vim runtime autoload/ale/linter.vim runtime autoload/ale/lsp.vim + runtime autoload/ale/util.vim - function! ale#linter#StartLSP(buffer, linter, callback) abort - let g:Callback = a:callback + 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 { - \ 'connection_id': 347, + \ 'buffer': a:buffer, + \ 'connection_id': g:conn_id, \ 'project_root': '/foo/bar', + \ 'language_id': 'python', \} endfunction - function! ale#lsp#Send(conn_id, message, root) abort + 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#definition#Execute(expr) abort + function! ale#util#Execute(expr) abort call add(g:expr_list, a:expr) endfunction After: + 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() + 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 unlet! b:ale_linters - runtime autoload/ale/definition.vim - runtime autoload/ale/linter.vim + runtime autoload/ale/lsp_linter.vim runtime autoload/ale/lsp.vim + runtime autoload/ale/util.vim Execute(Other messages for the tsserver handler should be ignored): call ale#definition#HandleTSServerResponse(1, {'command': 'foo'}) @@ -55,6 +78,19 @@ Execute(Failed definition responses should be handled correctly): \) AssertEqual {}, ale#definition#GetMap() +Execute(Failed definition responses with no files should be handled correctly): + call ale#definition#SetMap({3: {'open_in_tab': 0}}) + call ale#definition#HandleTSServerResponse( + \ 1, + \ { + \ 'command': 'definition', + \ 'request_seq': 3, + \ 'success': v:true, + \ 'body': [], + \ } + \) + AssertEqual {}, ale#definition#GetMap() + Given typescript(Some typescript file): foo somelongerline @@ -79,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] @@ -104,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] @@ -116,6 +152,13 @@ Execute(tsserver completion requests should be sent): ALEGoToDefinition + " We shouldn't register the callback yet. + AssertEqual '''''', string(g:Callback) + + AssertEqual type(function('type')), type(g:WaitCallback) + AssertEqual 'definition', g:capability_checked + call call(g:WaitCallback, [g:conn_id, '/foo/bar']) + AssertEqual \ 'function(''ale#definition#HandleTSServerResponse'')', \ string(g:Callback) @@ -130,6 +173,13 @@ Execute(tsserver tab completion requests should be sent): ALEGoToDefinitionInTab + " We shouldn't register the callback yet. + AssertEqual '''''', string(g:Callback) + + AssertEqual type(function('type')), type(g:WaitCallback) + AssertEqual 'definition', g:capability_checked + call call(g:WaitCallback, [g:conn_id, '/foo/bar']) + AssertEqual \ 'function(''ale#definition#HandleTSServerResponse'')', \ string(g:Callback) @@ -160,7 +210,29 @@ 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 {}, ale#definition#GetMap() + +Execute(Locations inside the same file should be jumped to without using :edit): + call ale#definition#SetMap({3: {'open_in_tab': 0}}) + call ale#definition#HandleLSPResponse( + \ 1, + \ { + \ 'id': 3, + \ 'result': { + \ 'uri': ale#path#ToURI(ale#path#Simplify(expand('%:p'))), + \ 'range': { + \ 'start': {'line': 2, 'character': 7}, + \ }, + \ }, + \ } + \) + + AssertEqual + \ [ \ ], \ g:expr_list AssertEqual [3, 7], getpos('.')[1:2] @@ -183,7 +255,7 @@ 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] @@ -214,7 +286,7 @@ 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] @@ -233,6 +305,13 @@ Execute(LSP completion requests should be sent): ALEGoToDefinition + " We shouldn't register the callback yet. + AssertEqual '''''', string(g:Callback) + + AssertEqual type(function('type')), type(g:WaitCallback) + AssertEqual 'definition', g:capability_checked + call call(g:WaitCallback, [g:conn_id, '/foo/bar']) + AssertEqual \ 'function(''ale#definition#HandleLSPResponse'')', \ string(g:Callback) @@ -262,6 +341,13 @@ Execute(LSP tab completion requests should be sent): ALEGoToDefinitionInTab + " We shouldn't register the callback yet. + AssertEqual '''''', string(g:Callback) + + AssertEqual type(function('type')), type(g:WaitCallback) + AssertEqual 'definition', g:capability_checked + call call(g:WaitCallback, [g:conn_id, '/foo/bar']) + AssertEqual \ 'function(''ale#definition#HandleLSPResponse'')', \ string(g:Callback) diff --git a/test/test_highlight_placement.vader b/test/test_highlight_placement.vader index 725faff4..53dcea06 100644 --- a/test/test_highlight_placement.vader +++ b/test/test_highlight_placement.vader @@ -1,7 +1,23 @@ Before: + Save g:ale_buffer_info + Save g:ale_echo_cursor Save g:ale_enabled + Save g:ale_run_synchronously + Save g:ale_set_highlights + Save g:ale_set_loclist + Save g:ale_set_quickfix Save g:ale_set_signs + let g:ale_run_synchronously = 1 + let g:ale_set_highlights = 1 + let g:ale_set_signs = 1 + let g:ale_buffer_info = {} + + " Disable features we don't need for these tests. + let g:ale_set_quickfix = 0 + let g:ale_set_loclist = 0 + let g:ale_echo_cursor = 0 + function! GenerateResults(buffer, output) return [ \ { @@ -53,8 +69,8 @@ After: delfunction GenerateResults call ale#linter#Reset() - let g:ale_buffer_info = {} call clearmatches() + sign unplace * highlight clear SomeOtherGroup Given testft(A Javscript file with warnings/errors): @@ -64,8 +80,7 @@ Given testft(A Javscript file with warnings/errors): line four Execute(Highlights should be set when a linter runs): - call ale#Lint() - call ale#engine#WaitForJobs(2000) + ALELint AssertEqual \ [ diff --git a/test/test_history_saving.vader b/test/test_history_saving.vader index 7dabcd9d..375e96a1 100644 --- a/test/test_history_saving.vader +++ b/test/test_history_saving.vader @@ -41,6 +41,7 @@ Before: After: Restore + unlet! g:expected_results unlet! b:ale_fixers unlet! b:ale_enabled " Clear the history we changed. @@ -52,9 +53,12 @@ After: let g:ale_history_enabled = 1 let g:ale_history_log_output = 0 unlet g:history + + call ale#engine#Cleanup(bufnr('')) + call ale#linter#Reset() + let g:ale_buffer_info = {} let g:ale_max_buffer_history_size = 20 - call ale#linter#Reset() delfunction TestFixer delfunction CollectResults @@ -64,16 +68,27 @@ Given foobar (Some imaginary filetype): Execute(History should be set when commands are run): AssertEqual 'foobar', &filetype - call ale#Lint() - call ale#engine#WaitForJobs(2000) + let g:expected_results = ['command', 'exit_code', 'job_id', 'status'] + + " 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#engine#WaitForJobs(2000) - let g:history = filter( - \ copy(ale#history#Get(bufnr(''))), - \ 'v:val.job_id isnot# ''executable''', - \) + let g:history = filter( + \ copy(ale#history#Get(bufnr(''))), + \ 'v:val.job_id isnot# ''executable''', + \) - AssertEqual 1, len(g:history) - AssertEqual sort(['status', 'exit_code', 'job_id', 'command']), sort(keys(g:history[0])) + AssertEqual 1, len(g:history) + + if sort(keys(g:history[0])) == g:expected_results + break + endif + endfor + + AssertEqual g:expected_results, sort(keys(g:history[0])) if has('win32') AssertEqual 'cmd /s/c "echo command history test"', g:history[0].command @@ -100,14 +115,24 @@ Execute(History should include command output if logging is enabled): AssertEqual 'foobar', &filetype let g:ale_history_log_output = 1 + let g:expected_results = ['command history test'] - call ale#Lint() - call ale#engine#WaitForJobs(2000) + " 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#engine#WaitForJobs(2000) + + let g:history = ale#history#Get(bufnr('')) + + AssertEqual 1, len(g:history) - let g:history = ale#history#Get(bufnr('')) + if get(g:history[0], 'output', []) == g:expected_results + break + endif + endfor - AssertEqual 1, len(g:history) - AssertEqual ['command history test'], g:history[0].output + AssertEqual g:expected_results, get(g:history[0], 'output', []) Execute(History items should be popped after going over the max): let b:ale_history = map(range(20), '{''status'': ''started'', ''job_id'': v:val, ''command'': ''foobar''}') diff --git a/test/test_hover.vader b/test/test_hover.vader new file mode 100644 index 00000000..a18fc651 --- /dev/null +++ b/test/test_hover.vader @@ -0,0 +1,151 @@ +Before: + call ale#test#SetDirectory('/testplugin/test') + call ale#test#SetFilename('dummy.txt') + + let g:Callback = 0 + let g:message_list = [] + let g:item_list = [] + let g:echo_list = [] + + runtime autoload/ale/linter.vim + runtime autoload/ale/lsp.vim + runtime autoload/ale/util.vim + + function! ale#lsp_linter#StartLSP(buffer, linter, callback) abort + let g:Callback = a:callback + + return { + \ 'connection_id': 347, + \ 'project_root': '/foo/bar', + \} + endfunction + + function! ale#lsp#Send(conn_id, message, root) abort + call add(g:message_list, a:message) + + return 42 + endfunction + + function! ale#util#ShowMessage(string) abort + call add(g:echo_list, a:string) + endfunction + + function! HandleValidLSPResult(result) abort + " The cursor is beyond the length of the line. + " We will clamp the cursor position with the line length. + call setpos('.', [bufnr(''), 1, 5, 0]) + + call ale#hover#SetMap({3: { + \ 'buffer': bufnr(''), + \ 'line': 1, + \ 'column': 5, + \}}) + call ale#hover#HandleLSPResponse( + \ 1, + \ { + \ 'id': 3, + \ 'result': a:result, + \ } + \) + endfunction + +After: + call ale#hover#SetMap({}) + call ale#test#RestoreDirectory() + call ale#linter#Reset() + + unlet! g:Callback + unlet! g:message_list + unlet! b:ale_linters + unlet! g:echo_list + + delfunction HandleValidLSPResult + + runtime autoload/ale/lsp_linter.vim + runtime autoload/ale/lsp.vim + runtime autoload/ale/util.vim + +Given python(Some Python file): + foo + somelongerline + bazxyzxyzxyz + +Execute(Other messages for the tsserver handler should be ignored): + call ale#hover#HandleTSServerResponse(1, {'command': 'foo'}) + +Execute(Failed hover responses should be handled correctly): + call ale#hover#SetMap({3: {}}) + call ale#hover#HandleTSServerResponse( + \ 1, + \ {'command': 'quickinfo', 'request_seq': 3} + \) + AssertEqual {}, ale#hover#GetMap() + +Given typescript(Some typescript file): + foo + somelongerline + bazxyzxyzxyz + +Execute(tsserver quickinfo responses will null missing bodies should be handled): + call ale#hover#SetMap({3: {}}) + call ale#hover#HandleTSServerResponse( + \ 1, + \ { + \ 'command': 'quickinfo', + \ 'request_seq': 3, + \ 'success': v:true, + \ } + \) + + AssertEqual {}, ale#hover#GetMap() + +Execute(tsserver quickinfo displayString values should be displayed): + call ale#hover#SetMap({3: {}}) + call ale#hover#HandleTSServerResponse( + \ 1, + \ { + \ 'command': 'quickinfo', + \ 'request_seq': 3, + \ 'success': v:true, + \ 'body': {'displayString': 'foo bar'}, + \ } + \) + + AssertEqual ['foo bar'], g:echo_list + AssertEqual {}, ale#hover#GetMap() + +Execute(LSP hover responses with just a string should be handled): + call HandleValidLSPResult({'contents': 'foobar'}) + + AssertEqual ['foobar'], g:echo_list + AssertEqual {}, ale#hover#GetMap() + +Execute(LSP hover null responses should be handled): + call HandleValidLSPResult(v:null) + + AssertEqual [], g:echo_list + AssertEqual {}, ale#hover#GetMap() + +Execute(LSP hover responses with markup content should be handled): + call HandleValidLSPResult({'contents': {'kind': 'something', 'value': 'markup'}}) + + AssertEqual ['markup'], g:echo_list + AssertEqual {}, ale#hover#GetMap() + +Execute(LSP hover response with lists of strings should be handled): + call HandleValidLSPResult({'contents': [ + \ "foo\n", + \ "bar\n", + \]}) + + AssertEqual ["foo\n\nbar\n"], g:echo_list + AssertEqual {}, ale#hover#GetMap() + +Execute(LSP hover response with lists of strings and marked strings should be handled): + call HandleValidLSPResult({'contents': [ + \ {'language': 'rust', 'value': 'foo'}, + \ "bar\n", + \]}) + + AssertEqual ["foo\nbar\n"], g:echo_list + AssertEqual {}, ale#hover#GetMap() diff --git a/test/test_ignoring_linters.vader b/test/test_ignoring_linters.vader new file mode 100644 index 00000000..1ddd30e8 --- /dev/null +++ b/test/test_ignoring_linters.vader @@ -0,0 +1,251 @@ +Execute(GetList should ignore some invalid values): + AssertEqual [], ale#engine#ignore#GetList('', 'foo') + AssertEqual [], ale#engine#ignore#GetList('', 0) + AssertEqual [], ale#engine#ignore#GetList('', v:null) + +Execute(GetList should handle Lists): + AssertEqual ['foo', 'bar'], ale#engine#ignore#GetList('', ['foo', 'bar']) + +Execute(GetList should handle Dictionaries): + AssertEqual + \ ['linter1', 'linter2'], + \ uniq(sort(ale#engine#ignore#GetList('x.y.z', { + \ 'x': ['linter1'], + \ 'abc': ['linter3'], + \ 'z': ['linter2'], + \ }))) + +Execute(Exclude should ignore some invalid values): + AssertEqual + \ [ + \ {'name': 'linter1', 'aliases': []}, + \ {'name': 'linter2', 'aliases': ['alias1']}, + \ {'name': 'linter3', 'aliases': []}, + \ ], + \ ale#engine#ignore#Exclude( + \ 'foo.bar', + \ [ + \ {'name': 'linter1', 'aliases': []}, + \ {'name': 'linter2', 'aliases': ['alias1']}, + \ {'name': 'linter3', 'aliases': []}, + \ ], + \ 'foo', + \ ) + AssertEqual + \ [ + \ {'name': 'linter1', 'aliases': []}, + \ {'name': 'linter2', 'aliases': ['alias1']}, + \ {'name': 'linter3', 'aliases': []}, + \ ], + \ ale#engine#ignore#Exclude( + \ 'foo.bar', + \ [ + \ {'name': 'linter1', 'aliases': []}, + \ {'name': 'linter2', 'aliases': ['alias1']}, + \ {'name': 'linter3', 'aliases': []}, + \ ], + \ 0, + \ ) + AssertEqual + \ [ + \ {'name': 'linter1', 'aliases': []}, + \ {'name': 'linter2', 'aliases': ['alias1']}, + \ {'name': 'linter3', 'aliases': []}, + \ ], + \ ale#engine#ignore#Exclude( + \ 'foo.bar', + \ [ + \ {'name': 'linter1', 'aliases': []}, + \ {'name': 'linter2', 'aliases': ['alias1']}, + \ {'name': 'linter3', 'aliases': []}, + \ ], + \ v:null, + \ ) + +Execute(Exclude should handle Lists): + AssertEqual + \ [ + \ {'name': 'linter3', 'aliases': []}, + \ ], + \ ale#engine#ignore#Exclude( + \ 'foo.bar', + \ [ + \ {'name': 'linter1', 'aliases': []}, + \ {'name': 'linter2', 'aliases': ['alias1']}, + \ {'name': 'linter3', 'aliases': []}, + \ ], + \ ['linter1', 'alias1'], + \ ) + +Execute(Exclude should handle Dictionaries): + AssertEqual + \ [ + \ {'name': 'linter3', 'aliases': []}, + \ ], + \ ale#engine#ignore#Exclude( + \ 'foo.bar', + \ [ + \ {'name': 'linter1', 'aliases': []}, + \ {'name': 'linter2', 'aliases': ['alias1']}, + \ {'name': 'linter3', 'aliases': []}, + \ ], + \ {'foo': ['linter1'], 'bar': ['alias1']}, + \ ) + +Before: + Save g:ale_linters_ignore + Save g:ale_buffer_info + + let g:linters = [] + let g:loclist = [] + let g:run_linters_called = 0 + + runtime autoload/ale/engine.vim + + " Mock the engine function so we can set it up. + function! ale#engine#RunLinters(buffer, linters, should_lint_file) abort + let g:linters = a:linters + let g:run_linters_called = 1 + endfunction + + function! ale#engine#HandleLoclist(linter_name, buffer, loclist) abort + let g:loclist = a:loclist + endfunction + + call ale#linter#Define('foobar', { + \ 'name': 'testlinter', + \ 'callback': 'TestCallback', + \ 'executable': has('win32') ? 'cmd' : 'true', + \ 'command': has('win32') ? 'echo' : 'true', + \}) + call ale#test#SetDirectory('/testplugin/test') + +After: + Restore + + unlet! b:ale_linted + unlet! b:ale_linters_ignore + unlet! b:ale_quitting + unlet! b:ale_save_event_fired + unlet! g:linters + unlet! g:loclist + unlet! g:lsp_message + + call ale#test#RestoreDirectory() + call ale#linter#Reset() + call ale#lsp_linter#ClearLSPData() + runtime autoload/ale/engine.vim + +Given foobar(An empty file): +Execute(Global ignore lists should be applied for linters): + ALELint + Assert g:run_linters_called, "The mock callback wasn't called" + AssertEqual ['testlinter'], map(g:linters, 'v:val.name') + + let g:ale_linters_ignore = ['testlinter'] + ALELint + AssertEqual [], g:linters + +Execute(buffer ignore lists should be applied for linters): + ALELint + Assert g:run_linters_called, "The mock callback wasn't called" + AssertEqual ['testlinter'], map(g:linters, 'v:val.name') + + let b:ale_linters_ignore = ['testlinter'] + ALELint + AssertEqual [], g:linters + +Execute(Buffer ignore lists should be applied for tsserver): + call ale#test#SetFilename('filename.ts') + call ale#engine#InitBufferInfo(bufnr('')) + + let g:lsp_message = { + \ 'seq': 0, + \ 'type': 'event', + \ 'event': 'syntaxDiag', + \ 'body': { + \ 'file': g:dir . '/filename.ts', + \ 'diagnostics':[ + \ { + \ 'start': { + \ 'line':2, + \ 'offset':14, + \ }, + \ 'end': { + \ 'line':2, + \ 'offset':15, + \ }, + \ 'text': ''','' expected.', + \ "code":1005 + \ }, + \ ], + \ }, + \} + + call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message) + + AssertEqual + \ [ + \ { + \ 'lnum': 2, + \ 'col': 14, + \ 'nr': 1005, + \ 'code': '1005', + \ 'type': 'E', + \ 'end_col': 15, + \ 'end_lnum': 2, + \ 'text': ''','' expected.', + \ }, + \ ], + \ g:loclist + + let g:loclist = [] + let b:ale_linters_ignore = ['tsserver'] + call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message) + + AssertEqual [], g:loclist + +Execute(Buffer ignore lists should be applied for LSP linters): + call ale#test#SetFilename('filename.py') + call ale#engine#InitBufferInfo(bufnr('')) + call ale#lsp_linter#SetLSPLinterMap({'347': 'lsplinter'}) + + let g:lsp_message = { + \ 'jsonrpc': '2.0', + \ 'method': 'textDocument/publishDiagnostics', + \ 'params': { + \ 'uri': ale#path#ToURI(expand('%:p')), + \ 'diagnostics': [ + \ { + \ 'severity': 1, + \ 'message': 'x', + \ 'range': { + \ 'start': {'line': 0, 'character': 9}, + \ 'end': {'line': 0, 'character': 9}, + \ }, + \ } + \ ], + \ }, + \} + + call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message) + + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'col': 10, + \ 'type': 'E', + \ 'end_col': 10, + \ 'end_lnum': 1, + \ 'text': 'x', + \ } + \ ], + \ g:loclist + + let b:ale_linters_ignore = ['lsplinter'] + let g:loclist = [] + + call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message) + + AssertEqual [], g:loclist diff --git a/test/test_kotlin_languageserver_path_detection.vader b/test/test_kotlin_languageserver_path_detection.vader new file mode 100644 index 00000000..36e6368e --- /dev/null +++ b/test/test_kotlin_languageserver_path_detection.vader @@ -0,0 +1,25 @@ +Before: + call ale#test#SetDirectory('/testplugin/test') + runtime ale_linters/kotlin/languageserver.vim + +After: + call ale#test#RestoreDirectory() + call ale#linter#Reset() + +Execute(Detect root of gradle project with build.gradle correctly): + call ale#test#SetFilename('gradle-test-files/build-gradle-project/src/main/kotlin/dummy.kt') + AssertEqual + \ ale#path#Simplify(g:dir . '/gradle-test-files/build-gradle-project'), + \ ale_linters#kotlin#languageserver#GetProjectRoot(bufnr('')) + +Execute(Detect root of maven project with pom.xml correctly): + call ale#test#SetFilename('maven-test-files/maven-kotlin-project/src/main/kotlin/dummy.kt') + AssertEqual + \ ale#path#Simplify(g:dir . '/maven-test-files/maven-kotlin-project'), + \ ale_linters#kotlin#languageserver#GetProjectRoot(bufnr('')) + +Execute(Detect no root in case of non maven/gradle project): + call ale#test#SetFilename('gradle-test-files/non-gradle-project/src/main/kotlin/dummy.kt') + AssertEqual + \ '', + \ ale_linters#kotlin#languageserver#GetProjectRoot(bufnr('')) diff --git a/test/test_line_join.vader b/test/test_line_join.vader index 25cefbcf..9356a2b7 100644 --- a/test/test_line_join.vader +++ b/test/test_line_join.vader @@ -18,67 +18,67 @@ After: delfunction RawCallback Execute (ALE should handle empty Lists for the lines): - let g:last_line = ale#job#JoinNeovimOutput(1, '', [], 'nl', function('LineCallback')) + let g:last_line = ale#util#JoinNeovimOutput(1, '', [], 'nl', function('LineCallback')) AssertEqual [], g:lines AssertEqual '', g:last_line Execute (ALE should pass on full lines for NeoVim): - let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x', 'y', ''], 'nl', function('LineCallback')) + let g:last_line = ale#util#JoinNeovimOutput(1, '', ['x', 'y', ''], 'nl', function('LineCallback')) AssertEqual ['x', 'y'], g:lines AssertEqual '', g:last_line Execute (ALE should pass on a single long line): - let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x'], 'nl', function('LineCallback')) + let g:last_line = ale#util#JoinNeovimOutput(1, '', ['x'], 'nl', function('LineCallback')) AssertEqual [], g:lines AssertEqual 'x', g:last_line Execute (ALE should handle just a single line of output): - let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x', ''], 'nl', function('LineCallback')) + let g:last_line = ale#util#JoinNeovimOutput(1, '', ['x', ''], 'nl', function('LineCallback')) AssertEqual ['x'], g:lines AssertEqual '', g:last_line Execute (ALE should join two incomplete pieces of large lines together): - let g:last_line = ale#job#JoinNeovimOutput(1, 'x', ['y'], 'nl', function('LineCallback')) + let g:last_line = ale#util#JoinNeovimOutput(1, 'x', ['y'], 'nl', function('LineCallback')) AssertEqual [], g:lines AssertEqual 'xy', g:last_line Execute (ALE join incomplete lines, and set new ones): - let g:last_line = ale#job#JoinNeovimOutput(1, 'x', ['y', 'z', 'a'], 'nl', function('LineCallback')) + let g:last_line = ale#util#JoinNeovimOutput(1, 'x', ['y', 'z', 'a'], 'nl', function('LineCallback')) AssertEqual ['xy', 'z'], g:lines AssertEqual 'a', g:last_line Execute (ALE join incomplete lines, and set new ones, with two elements): - let g:last_line = ale#job#JoinNeovimOutput(1, 'x', ['y', 'z'], 'nl', function('LineCallback')) + let g:last_line = ale#util#JoinNeovimOutput(1, 'x', ['y', 'z'], 'nl', function('LineCallback')) AssertEqual ['xy'], g:lines AssertEqual 'z', g:last_line Execute (ALE should pass on full lines for NeoVim for raw data): - let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x', 'y', ''], 'raw', function('RawCallback')) + let g:last_line = ale#util#JoinNeovimOutput(1, '', ['x', 'y', ''], 'raw', function('RawCallback')) AssertEqual "x\ny\n", g:data AssertEqual '', g:last_line Execute (ALE should pass on a single long line): - let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x'], 'raw', function('RawCallback')) + let g:last_line = ale#util#JoinNeovimOutput(1, '', ['x'], 'raw', function('RawCallback')) AssertEqual 'x', g:data AssertEqual '', g:last_line Execute (ALE should handle just a single line of output): - let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x', ''], 'raw', function('RawCallback')) + let g:last_line = ale#util#JoinNeovimOutput(1, '', ['x', ''], 'raw', function('RawCallback')) AssertEqual "x\n", g:data AssertEqual '', g:last_line Execute (ALE should pass on two lines and one incomplete one): - let g:last_line = ale#job#JoinNeovimOutput(1, '', ['y', 'z', 'a'], 'raw', function('RawCallback')) + let g:last_line = ale#util#JoinNeovimOutput(1, '', ['y', 'z', 'a'], 'raw', function('RawCallback')) AssertEqual "y\nz\na", g:data AssertEqual '', g:last_line diff --git a/test/test_lint_error_delay.vader b/test/test_lint_error_delay.vader deleted file mode 100644 index 7f081794..00000000 --- a/test/test_lint_error_delay.vader +++ /dev/null @@ -1,22 +0,0 @@ -Before: - Save g:ale_filetype_blacklist - - " Delete some variable which should be defined. - unlet! g:ale_filetype_blacklist - -After: - Restore - - call ale#ResetErrorDelays() - -Execute(ALE should stop queuing for a while after exceptions are thrown): - AssertThrows call ale#Queue(100) - call ale#Queue(100) - -Execute(ALE should stop linting for a while after exceptions are thrown): - AssertThrows call ale#Lint() - call ale#Lint() - -Execute(ALE should stop echoing messages for a while after exceptions are thrown): - AssertThrows call ale#cursor#EchoCursorWarning() - call ale#cursor#EchoCursorWarning() diff --git a/test/test_lint_file_linters.vader b/test/test_lint_file_linters.vader index 2e992e13..ca093aa8 100644 --- a/test/test_lint_file_linters.vader +++ b/test/test_lint_file_linters.vader @@ -51,7 +51,7 @@ Before: function! GetSimplerLoclist() let l:loclist = [] - for l:item in getloclist(0) + for l:item in ale#test#GetLoclistWithoutModule() call add(l:loclist, { \ 'lnum': l:item.lnum, \ 'col': l:item.col, @@ -85,7 +85,7 @@ Before: After: if !g:ale_run_synchronously - call ale#engine#WaitForJobs(2000) + call ale#engine#Cleanup(bufnr('')) endif Restore diff --git a/test/test_lint_on_enter_when_file_changed.vader b/test/test_lint_on_enter_when_file_changed.vader index d2b38e04..67f43c17 100644 --- a/test/test_lint_on_enter_when_file_changed.vader +++ b/test/test_lint_on_enter_when_file_changed.vader @@ -61,13 +61,13 @@ Execute(The file changed event function should lint the current buffer when it h \ 'nr': -1, \ 'pattern': '', \ 'valid': 1, - \ }], getloclist(0) + \ }], ale#test#GetLoclistWithoutModule() Execute(The buffer should be checked after entering it after the file has changed): let b:ale_file_changed = 1 set filetype=foobar - call ale#events#EnterEvent(bufnr('')) + call ale#events#ReadOrEnterEvent(bufnr('')) AssertEqual [{ \ 'bufnr': bufnr(''), @@ -79,4 +79,4 @@ Execute(The buffer should be checked after entering it after the file has change \ 'nr': -1, \ 'pattern': '', \ 'valid': 1, - \ }], getloclist(0) + \ }], ale#test#GetLoclistWithoutModule() diff --git a/test/test_lint_on_filetype_changed.vader b/test/test_lint_on_filetype_changed.vader index 591a5120..cfc99d58 100644 --- a/test/test_lint_on_filetype_changed.vader +++ b/test/test_lint_on_filetype_changed.vader @@ -1,10 +1,10 @@ Before: Save &filetype + Save g:ale_lint_on_filetype_changed + let g:ale_lint_on_filetype_changed = 1 let g:queue_calls = [] - unlet! b:ale_lint_on_enter - function! ale#Queue(...) call add(g:queue_calls, a:000) endfunction @@ -12,7 +12,6 @@ Before: After: Restore - unlet! b:ale_lint_on_enter unlet! g:queue_calls " Reload the ALE code to load the real function again. @@ -23,13 +22,13 @@ After: Execute(The original filetype should be set on BufEnter): let &filetype = 'foobar' - call ale#events#EnterEvent(bufnr('')) + call ale#events#ReadOrEnterEvent(bufnr('')) AssertEqual 'foobar', b:ale_original_filetype let &filetype = 'bazboz' - call ale#events#EnterEvent(bufnr('')) + call ale#events#ReadOrEnterEvent(bufnr('')) AssertEqual 'bazboz', b:ale_original_filetype @@ -48,27 +47,31 @@ Execute(Linting should be queued when the filetype changes): call ale#events#FileTypeEvent(bufnr(''), 'bazboz') AssertEqual [[300, 'lint_file', bufnr('')]], g:queue_calls + " The original filetype should be updated, so we don't trigger linting + " by setting a filetype equal to what it already is. + AssertEqual 'bazboz', b:ale_original_filetype -Execute(Linting shouldn't be done when the original filetype was blank and linting on enter is off): - let b:ale_lint_on_enter = 0 +Execute(Linting should be done when the original filetype was blank): let b:ale_original_filetype = '' call ale#events#FileTypeEvent(bufnr(''), 'bazboz') - AssertEqual [], g:queue_calls + AssertEqual [[300, 'lint_file', bufnr('')]], g:queue_calls + AssertEqual 'bazboz', b:ale_original_filetype -Execute(Linting should be done when the original filetype was blank and linting on enter is on): - let b:ale_lint_on_enter = 1 - let b:ale_original_filetype = '' +Execute(Linting should not be done when the setting is off): + let b:ale_original_filetype = 'foobar' + let g:ale_lint_on_filetype_changed = 0 call ale#events#FileTypeEvent(bufnr(''), 'bazboz') - AssertEqual [[300, 'lint_file', bufnr('')]], g:queue_calls + AssertEqual [], g:queue_calls + " We should still update the old filetype + AssertEqual 'bazboz', b:ale_original_filetype -Execute(The new filetype should become the "original" one if the original was blank and linting on enter is off): - let b:ale_lint_on_enter = 0 - let b:ale_original_filetype = '' +Execute(Linting should be done when the original filetype was not set): + unlet! b:ale_original_filetype call ale#events#FileTypeEvent(bufnr(''), 'bazboz') - AssertEqual 'bazboz', b:ale_original_filetype + AssertEqual [], g:queue_calls diff --git a/test/test_linter_defintion_processing.vader b/test/test_linter_defintion_processing.vader index d946a600..f0ec023a 100644 --- a/test/test_linter_defintion_processing.vader +++ b/test/test_linter_defintion_processing.vader @@ -5,11 +5,11 @@ After: unlet g:linter Execute (PreProcess should throw when the linter object is not a Dictionary): - AssertThrows call ale#linter#PreProcess('') + AssertThrows call ale#linter#PreProcess('testft', '') AssertEqual 'The linter object must be a Dictionary', g:vader_exception Execute (PreProcess should throw when there is no name): - AssertThrows call ale#linter#PreProcess({ + AssertThrows call ale#linter#PreProcess('testft', { \ 'callback': 'SomeFunction', \ 'executable': 'echo', \ 'command': 'echo', @@ -17,7 +17,7 @@ Execute (PreProcess should throw when there is no name): AssertEqual '`name` must be defined to name the linter', g:vader_exception Execute (PreProcess should throw when there is no callback): - AssertThrows call ale#linter#PreProcess({ + AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'executable': 'echo', \ 'command': 'echo', @@ -25,7 +25,7 @@ Execute (PreProcess should throw when there is no callback): AssertEqual '`callback` must be defined with a callback to accept output', g:vader_exception Execute (PreProcess should throw when then callback is not a function): - AssertThrows call ale#linter#PreProcess({ + AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'callback': 1, \ 'executable': 'echo', @@ -34,7 +34,7 @@ Execute (PreProcess should throw when then callback is not a function): AssertEqual '`callback` must be defined with a callback to accept output', g:vader_exception Execute (PreProcess should throw when there is no executable or executable_callback): - AssertThrows call ale#linter#PreProcess({ + AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'callback': 'SomeFunction', \ 'command': 'echo', @@ -42,7 +42,7 @@ Execute (PreProcess should throw when there is no executable or executable_callb AssertEqual 'Either `executable` or `executable_callback` must be defined', g:vader_exception Execute (PreProcess should throw when executable is not a string): - AssertThrows call ale#linter#PreProcess({ + AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'callback': 'SomeFunction', \ 'executable': 123, @@ -51,7 +51,7 @@ Execute (PreProcess should throw when executable is not a string): AssertEqual '`executable` must be a string if defined', g:vader_exception Execute (PreProcess should throw when executable_callback is not a callback): - AssertThrows call ale#linter#PreProcess({ + AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'callback': 'SomeFunction', \ 'executable_callback': 123, @@ -60,7 +60,7 @@ Execute (PreProcess should throw when executable_callback is not a callback): AssertEqual '`executable_callback` must be a callback if defined', g:vader_exception Execute (PreProcess should throw when there is no command): - AssertThrows call ale#linter#PreProcess({ + AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'callback': 'SomeFunction', \ 'executable': 'echo', @@ -68,7 +68,7 @@ Execute (PreProcess should throw when there is no command): AssertEqual 'Either `command`, `executable_callback`, `command_chain` must be defined', g:vader_exception Execute (PreProcess should throw when command is not a string): - AssertThrows call ale#linter#PreProcess({ + AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'callback': 'SomeFunction', \ 'executable': 'echo', @@ -77,7 +77,7 @@ Execute (PreProcess should throw when command is not a string): AssertEqual '`command` must be a string if defined', g:vader_exception Execute (PreProcess should throw when command_callback is not a callback): - AssertThrows call ale#linter#PreProcess({ + AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'callback': 'SomeFunction', \ 'executable': 'echo', @@ -86,7 +86,7 @@ Execute (PreProcess should throw when command_callback is not a callback): AssertEqual '`command_callback` must be a callback if defined', g:vader_exception Execute (PreProcess should when the output stream isn't a valid string): - AssertThrows call ale#linter#PreProcess({ + AssertThrows call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'callback': 'SomeFunction', \ 'executable': 'echo', @@ -96,7 +96,7 @@ Execute (PreProcess should when the output stream isn't a valid string): AssertEqual "`output_stream` must be 'stdout', 'stderr', or 'both'", g:vader_exception Execute (PreProcess should not throw when everything is correct): - call ale#linter#PreProcess({ + call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'callback': 'SomeFunction', \ 'executable': 'echo', @@ -104,7 +104,7 @@ Execute (PreProcess should not throw when everything is correct): \}) Execute (PreProcess should accept an stdout output_stream): - call ale#linter#PreProcess({ + call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'callback': 'SomeFunction', \ 'executable': 'echo', @@ -113,7 +113,7 @@ Execute (PreProcess should accept an stdout output_stream): \}) Execute (PreProcess should accept an stderr output_stream): - call ale#linter#PreProcess({ + call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'callback': 'SomeFunction', \ 'executable': 'echo', @@ -122,7 +122,7 @@ Execute (PreProcess should accept an stderr output_stream): \}) Execute (PreProcess should accept a 'both' output_stream): - call ale#linter#PreProcess({ + call ale#linter#PreProcess('testft', { \ 'name': 'foo', \ 'callback': 'SomeFunction', \ 'executable': 'echo', @@ -137,7 +137,7 @@ Execute(PreProcess should complain if the command_chain is not a List): \ 'executable': 'x', \ 'command_chain': 'x', \} - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual '`command_chain` must be a List', g:vader_exception Execute(PreProcess should complain if the command_chain is empty): @@ -147,7 +147,7 @@ Execute(PreProcess should complain if the command_chain is empty): \ 'executable': 'x', \ 'command_chain': [], \} - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual '`command_chain` must contain at least one item', g:vader_exception Execute(PreProcess should complain if the command_chain has no callback): @@ -157,7 +157,7 @@ Execute(PreProcess should complain if the command_chain has no callback): \ 'executable': 'x', \ 'command_chain': [{}], \} - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual 'The `command_chain` item 0 must define a `callback` function', g:vader_exception Execute(PreProcess should complain if the command_chain callback is not a function): @@ -167,7 +167,7 @@ Execute(PreProcess should complain if the command_chain callback is not a functi \ 'executable': 'x', \ 'command_chain': [{'callback': 2}], \} - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual 'The `command_chain` item 0 must define a `callback` function', g:vader_exception Execute(PreProcess should accept a chain with one callback): @@ -177,7 +177,7 @@ Execute(PreProcess should accept a chain with one callback): \ 'executable': 'x', \ 'command_chain': [{'callback': 'foo'}], \} - call ale#linter#PreProcess(g:linter) + call ale#linter#PreProcess('testft', g:linter) Execute(PreProcess should complain about invalid output_stream values in the chain): let g:linter = { @@ -186,7 +186,7 @@ Execute(PreProcess should complain about invalid output_stream values in the cha \ 'executable': 'x', \ 'command_chain': [{'callback': 'foo', 'output_stream': ''}], \} - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual "The `command_chain` item 0 `output_stream` flag must be 'stdout', 'stderr', or 'both'", g:vader_exception Execute(PreProcess should complain about valid output_stream values in the chain): @@ -196,11 +196,11 @@ Execute(PreProcess should complain about valid output_stream values in the chain \ 'executable': 'x', \ 'command_chain': [{'callback': 'foo', 'output_stream': 'stdout'}], \} - call ale#linter#PreProcess(g:linter) + call ale#linter#PreProcess('testft', g:linter) let g:linter.command_chain[0].output_stream = 'stderr' - call ale#linter#PreProcess(g:linter) + call ale#linter#PreProcess('testft', g:linter) let g:linter.command_chain[0].output_stream = 'both' - call ale#linter#PreProcess(g:linter) + call ale#linter#PreProcess('testft', g:linter) Execute(PreProcess should complain about invalid chain items at higher indices): let g:linter = { @@ -209,7 +209,7 @@ Execute(PreProcess should complain about invalid chain items at higher indices): \ 'executable': 'x', \ 'command_chain': [{'callback': 'foo'}, {'callback': 123}], \} - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual 'The `command_chain` item 1 must define a `callback` function', g:vader_exception Execute(PreProcess should complain when conflicting command options are used): @@ -220,19 +220,19 @@ Execute(PreProcess should complain when conflicting command options are used): \ 'command': 'foo', \ 'command_chain': [{'callback': 'foo'}], \} - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual 'Only one of `command`, `command_callback`, or `command_chain` should be set', g:vader_exception unlet g:linter.command let g:linter.command_callback = 'foo' - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual 'Only one of `command`, `command_callback`, or `command_chain` should be set', g:vader_exception let g:linter.command = 'foo' unlet g:linter.command_chain - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual 'Only one of `command`, `command_callback`, or `command_chain` should be set', g:vader_exception Execute(PreProcess should process the read_buffer option correctly): @@ -244,35 +244,35 @@ Execute(PreProcess should process the read_buffer option correctly): \ 'read_buffer': '0', \} - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual '`read_buffer` must be `0` or `1`', g:vader_exception let g:linter.read_buffer = 0 - call ale#linter#PreProcess(g:linter) + call ale#linter#PreProcess('testft', g:linter) let g:linter.read_buffer = 1 - call ale#linter#PreProcess(g:linter) + call ale#linter#PreProcess('testft', g:linter) unlet g:linter.read_buffer let g:linter.command_chain[0].read_buffer = '0' - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual 'The `command_chain` item 0 value for `read_buffer` must be `0` or `1`', g:vader_exception let g:linter.command_chain[0].read_buffer = 0 - call ale#linter#PreProcess(g:linter) + call ale#linter#PreProcess('testft', g:linter) let g:linter.command_chain[1].read_buffer = '0' - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual 'The `command_chain` item 1 value for `read_buffer` must be `0` or `1`', g:vader_exception let g:linter.command_chain[1].read_buffer = 1 - call ale#linter#PreProcess(g:linter) + call ale#linter#PreProcess('testft', g:linter) Execute(PreProcess should set a default value for read_buffer): let g:linter = { @@ -282,7 +282,7 @@ Execute(PreProcess should set a default value for read_buffer): \ 'command': 'x', \} - AssertEqual 1, ale#linter#PreProcess(g:linter).read_buffer + AssertEqual 1, ale#linter#PreProcess('testft', g:linter).read_buffer Execute(PreProcess should process the lint_file option correctly): let g:linter = { @@ -293,25 +293,25 @@ Execute(PreProcess should process the lint_file option correctly): \ 'lint_file': 'x', \} - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual '`lint_file` must be `0` or `1`', g:vader_exception let g:linter.lint_file = 0 - AssertEqual 0, ale#linter#PreProcess(g:linter).lint_file + AssertEqual 0, ale#linter#PreProcess('testft', g:linter).lint_file " The default for read_buffer should be 1 when lint_file is 0 - AssertEqual 1, ale#linter#PreProcess(g:linter).read_buffer + AssertEqual 1, ale#linter#PreProcess('testft', g:linter).read_buffer let g:linter.lint_file = 1 - AssertEqual 1, ale#linter#PreProcess(g:linter).lint_file + AssertEqual 1, ale#linter#PreProcess('testft', g:linter).lint_file " The default for read_buffer should change to 0 when lint_file is 1. - AssertEqual 0, ale#linter#PreProcess(g:linter).read_buffer + AssertEqual 0, ale#linter#PreProcess('testft', g:linter).read_buffer let g:linter.read_buffer = 1 " We shouldn't be able to set both options to 1 at the same time. - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual 'Only one of `lint_file` or `read_buffer` can be `1`', g:vader_exception Execute(PreProcess should set a default value for lint_file): @@ -322,7 +322,7 @@ Execute(PreProcess should set a default value for lint_file): \ 'command': 'x', \} - AssertEqual 0, ale#linter#PreProcess(g:linter).lint_file + AssertEqual 0, ale#linter#PreProcess('testft', g:linter).lint_file Execute(PreProcess should set a default value for aliases): let g:linter = { @@ -332,7 +332,7 @@ Execute(PreProcess should set a default value for aliases): \ 'command': 'x', \} - AssertEqual [], ale#linter#PreProcess(g:linter).aliases + AssertEqual [], ale#linter#PreProcess('testft', g:linter).aliases Execute(PreProcess should complain about invalid `aliases` values): let g:linter = { @@ -343,12 +343,12 @@ Execute(PreProcess should complain about invalid `aliases` values): \ 'aliases': 'foo', \} - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual '`aliases` must be a List of String values', g:vader_exception let g:linter.aliases = [1] - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual '`aliases` must be a List of String values', g:vader_exception Execute(PreProcess should accept `aliases` lists): @@ -360,11 +360,11 @@ Execute(PreProcess should accept `aliases` lists): \ 'aliases': [], \} - AssertEqual [], ale#linter#PreProcess(g:linter).aliases + AssertEqual [], ale#linter#PreProcess('testft', g:linter).aliases let g:linter.aliases = ['foo', 'bar'] - AssertEqual ['foo', 'bar'], ale#linter#PreProcess(g:linter).aliases + AssertEqual ['foo', 'bar'], ale#linter#PreProcess('testft', g:linter).aliases Execute(PreProcess should accept tsserver LSP configuration): let g:linter = { @@ -376,17 +376,17 @@ Execute(PreProcess should accept tsserver LSP configuration): \ 'project_root_callback': 'x', \} - AssertEqual 'tsserver', ale#linter#PreProcess(g:linter).lsp + AssertEqual 'tsserver', ale#linter#PreProcess('testft', g:linter).lsp call remove(g:linter, 'executable') let g:linter.executable_callback = 'X' - call ale#linter#PreProcess(g:linter) + call ale#linter#PreProcess('testft', g:linter) call remove(g:linter, 'command') let g:linter.command_callback = 'X' - call ale#linter#PreProcess(g:linter) + call ale#linter#PreProcess('testft', g:linter) Execute(PreProcess should accept stdio LSP configuration): let g:linter = { @@ -398,17 +398,17 @@ Execute(PreProcess should accept stdio LSP configuration): \ 'project_root_callback': 'x', \} - AssertEqual 'stdio', ale#linter#PreProcess(g:linter).lsp + AssertEqual 'stdio', ale#linter#PreProcess('testft', g:linter).lsp call remove(g:linter, 'executable') let g:linter.executable_callback = 'X' - call ale#linter#PreProcess(g:linter) + call ale#linter#PreProcess('testft', g:linter) call remove(g:linter, 'command') let g:linter.command_callback = 'X' - call ale#linter#PreProcess(g:linter) + call ale#linter#PreProcess('testft', g:linter) Execute(PreProcess should accept LSP server configurations): let g:linter = { @@ -419,7 +419,41 @@ Execute(PreProcess should accept LSP server configurations): \ 'project_root_callback': 'x', \} - AssertEqual 'socket', ale#linter#PreProcess(g:linter).lsp + AssertEqual 'socket', ale#linter#PreProcess('testft', g:linter).lsp + +Execute(PreProcess should accept let you specify the language as just a string): + let g:linter = { + \ 'name': 'x', + \ 'lsp': 'socket', + \ 'address_callback': 'X', + \ 'language': 'foobar', + \ 'project_root_callback': 'x', + \} + + AssertEqual 'foobar', ale#linter#PreProcess('testft', g:linter).language_callback(0) + +Execute(PreProcess should complain about using language and language_callback together): + let g:linter = { + \ 'name': 'x', + \ 'lsp': 'socket', + \ 'address_callback': 'X', + \ 'language': 'x', + \ 'language_callback': 'x', + \ 'project_root_callback': 'x', + \} + + AssertThrows call ale#linter#PreProcess('testft', g:linter) + AssertEqual 'Only one of `language` or `language_callback` should be set', g:vader_exception + +Execute(PreProcess should use the filetype as the language string by default): + let g:linter = { + \ 'name': 'x', + \ 'lsp': 'socket', + \ 'address_callback': 'X', + \ 'project_root_callback': 'x', + \} + + AssertEqual 'testft', ale#linter#PreProcess('testft', g:linter).language_callback(0) Execute(PreProcess should require an address_callback for LSP socket configurations): let g:linter = { @@ -427,7 +461,7 @@ Execute(PreProcess should require an address_callback for LSP socket configurati \ 'lsp': 'socket', \} - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual '`address_callback` must be defined for getting the LSP address', g:vader_exception Execute(PreProcess should complain about address_callback for non-LSP linters): @@ -439,5 +473,30 @@ Execute(PreProcess should complain about address_callback for non-LSP linters): \ 'address_callback': 'X', \} - AssertThrows call ale#linter#PreProcess(g:linter) + AssertThrows call ale#linter#PreProcess('testft', g:linter) AssertEqual '`address_callback` cannot be used when lsp != ''socket''', g:vader_exception + +Execute(PreProcess should complain about using initialization_options and initialization_options_callback together): + let g:linter = { + \ 'name': 'x', + \ 'lsp': 'socket', + \ 'address_callback': 'X', + \ 'language': 'x', + \ 'project_root_callback': 'x', + \ 'initialization_options': 'x', + \ 'initialization_options_callback': 'x', + \} + + AssertThrows call ale#linter#PreProcess('testft', g:linter) + AssertEqual 'Only one of `initialization_options` or `initialization_options_callback` should be set', g:vader_exception + +Execute (PreProcess should throw when initialization_options_callback is not a callback): + AssertThrows call ale#linter#PreProcess('testft', { + \ 'name': 'foo', + \ 'lsp': 'socket', + \ 'address_callback': 'X', + \ 'language': 'x', + \ 'project_root_callback': 'x', + \ 'initialization_options_callback': {}, + \}) + AssertEqual '`initialization_options_callback` must be a callback if defined', g:vader_exception diff --git a/test/test_linter_retrieval.vader b/test/test_linter_retrieval.vader index 5d1ee451..6c402d54 100644 --- a/test/test_linter_retrieval.vader +++ b/test/test_linter_retrieval.vader @@ -5,6 +5,9 @@ Before: let g:testlinter1 = {'name': 'testlinter1', 'executable': 'testlinter1', 'command': 'testlinter1', 'callback': 'testCB1', 'output_stream': 'stdout', 'read_buffer': 1, 'lint_file': 0, 'aliases': [], 'lsp': '', 'add_newline': 0} let g:testlinter2 = {'name': 'testlinter2', 'executable': 'testlinter2', 'command': 'testlinter2', 'callback': 'testCB2', 'output_stream': 'stdout', 'read_buffer': 0, 'lint_file': 1, 'aliases': [], 'lsp': '', 'add_newline': 0} call ale#linter#Reset() + call ale#linter#PreventLoading('testft') + call ale#linter#PreventLoading('javascript') + call ale#linter#PreventLoading('typescript') After: Restore @@ -145,6 +148,7 @@ Execute (Buffer-local overrides for aliases should be used): AssertEqual [g:testlinter1, g:testlinter2], ale#linter#Get('testft1') Execute (Linters should be loaded from disk appropriately): + call ale#linter#Reset() AssertEqual [{'name': 'testlinter', 'output_stream': 'stdout', 'executable': 'testlinter', 'command': 'testlinter', 'callback': 'testCB', 'read_buffer': 1, 'lint_file': 0, 'aliases': [], 'lsp': '', 'add_newline': 0}], ale#linter#Get('testft') diff --git a/test/test_linting_blacklist.vader b/test/test_linting_blacklist.vader index 9960264d..2d9ed585 100644 --- a/test/test_linting_blacklist.vader +++ b/test/test_linting_blacklist.vader @@ -2,6 +2,8 @@ Before: let g:ale_buffer_info = {} After: + call ale#engine#Cleanup(bufnr('')) + let g:ale_buffer_info = {} Given unite (A Unite.vim file): diff --git a/test/test_linting_updates_loclist.vader b/test/test_linting_updates_loclist.vader index 29ca05d4..921cdb08 100644 --- a/test/test_linting_updates_loclist.vader +++ b/test/test_linting_updates_loclist.vader @@ -1,31 +1,24 @@ Before: + Save g:ale_echo_cursor + Save g:ale_set_highlights + Save g:ale_set_loclist + Save g:ale_set_quickfix Save g:ale_set_signs + Save g:ale_run_synchronously + Save g:ale_set_lists_synchronously + Save g:ale_buffer_info + + " We want to check that sign IDs are set for this test. let g:ale_set_signs = 1 + let g:ale_set_loclist = 1 + " Disable features we don't need for these tests. + let g:ale_set_quickfix = 0 + let g:ale_set_highlights = 0 + let g:ale_echo_cursor = 0 - let g:expected_data = [ - \ { - \ 'lnum': 1, - \ 'bufnr': bufnr('%'), - \ 'vcol': 0, - \ 'linter_name': 'testlinter', - \ 'nr': -1, - \ 'type': 'W', - \ 'col': 10, - \ 'text': 'Infix operators must be spaced. [Warning/space-infix-ops]', - \ 'sign_id': 1000001, - \ }, - \ { - \ 'lnum': 2, - \ 'bufnr': bufnr('%'), - \ 'vcol': 0, - \ 'linter_name': 'testlinter', - \ 'nr': -1, - \ 'type': 'E', - \ 'col': 10, - \ 'text': 'Missing semicolon. [Error/semi]', - \ 'sign_id': 1000002, - \ } - \] + let g:ale_run_synchronously = 1 + let g:ale_set_lists_synchronously = 1 + let g:ale_buffer_info = {} function! TestCallback(buffer, output) return [ @@ -54,22 +47,47 @@ Before: sign unplace * + call ale#engine#Cleanup(bufnr('')) + After: Restore delfunction TestCallback - unlet! g:expected_data - let g:ale_buffer_info = {} call ale#linter#Reset() + sign unplace * + Given foobar (Some JavaScript with problems): var y = 3+3; var y = 3 Execute(The loclist should be updated after linting is done): - call ale#Lint() - call ale#engine#WaitForJobs(2000) + ALELint - AssertEqual ['' . bufnr('%')], keys(g:ale_buffer_info) - AssertEqual g:expected_data, g:ale_buffer_info[bufnr('%')].loclist + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'linter_name': 'testlinter', + \ 'nr': -1, + \ 'type': 'W', + \ 'col': 10, + \ 'text': 'Infix operators must be spaced. [Warning/space-infix-ops]', + \ 'sign_id': 1000001, + \ }, + \ { + \ 'lnum': 2, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'linter_name': 'testlinter', + \ 'nr': -1, + \ 'type': 'E', + \ 'col': 10, + \ 'text': 'Missing semicolon. [Error/semi]', + \ 'sign_id': 1000002, + \ } + \ ], + \ get(get(g:ale_buffer_info, bufnr('%'), {}), 'loclist', []) diff --git a/test/test_list_formatting.vader b/test/test_list_formatting.vader index 0c52f10f..dcefac53 100644 --- a/test/test_list_formatting.vader +++ b/test/test_list_formatting.vader @@ -53,7 +53,7 @@ Execute(Formatting with codes should work for the loclist): \ 'text': 'nocode', \ }, \ ], - \ getloclist(0) + \ ale#test#GetLoclistWithoutModule() call remove(g:loclist, 0) call AddItem({'text': 'withcode', 'code': 'E123'}) @@ -73,7 +73,7 @@ Execute(Formatting with codes should work for the loclist): \ 'text': 'E123: withcode', \ }, \ ], - \ getloclist(0) + \ ale#test#GetLoclistWithoutModule() Execute(Formatting with codes should work for the quickfix list): let g:ale_set_loclist = 0 @@ -96,7 +96,7 @@ Execute(Formatting with codes should work for the quickfix list): \ 'text': 'nocode', \ }, \ ], - \ getqflist() + \ ale#test#GetQflistWithoutModule() call remove(g:loclist, 0) call AddItem({'text': 'withcode', 'code': 'E123'}) @@ -116,7 +116,7 @@ Execute(Formatting with codes should work for the quickfix list): \ 'text': 'E123: withcode', \ }, \ ], - \ getqflist() + \ ale#test#GetQflistWithoutModule() Execute(Formatting with the linter name should work for the loclist): let g:ale_loclist_msg_format = '(%linter%) %s' @@ -138,7 +138,7 @@ Execute(Formatting with the linter name should work for the loclist): \ 'text': '(some_linter) whatever', \ }, \ ], - \ getloclist(0) + \ ale#test#GetLoclistWithoutModule() Execute(Formatting with the linter name should work for the quickfix list): let g:ale_loclist_msg_format = '(%linter%) %s' @@ -162,7 +162,7 @@ Execute(Formatting with the linter name should work for the quickfix list): \ 'text': '(some_linter) whatever', \ }, \ ], - \ getqflist() + \ ale#test#GetQflistWithoutModule() Execute(The buffer loclist format option should take precedence): let g:ale_loclist_msg_format = '(%linter%) %s' @@ -185,4 +185,4 @@ Execute(The buffer loclist format option should take precedence): \ 'text': 'FOO whatever', \ }, \ ], - \ getloclist(0) + \ ale#test#GetLoclistWithoutModule() diff --git a/test/test_list_opening.vader b/test/test_list_opening.vader index 63b30ef1..8f0b2fd5 100644 --- a/test/test_list_opening.vader +++ b/test/test_list_opening.vader @@ -5,6 +5,7 @@ Before: Save g:ale_open_list Save g:ale_keep_list_window_open Save g:ale_list_window_size + Save g:ale_list_vertical Save g:ale_buffer_info Save g:ale_set_lists_synchronously @@ -13,6 +14,7 @@ Before: let g:ale_open_list = 0 let g:ale_keep_list_window_open = 0 let g:ale_list_window_size = 10 + let g:ale_list_vertical = 0 let g:ale_set_lists_synchronously = 1 let g:loclist = [ @@ -33,16 +35,29 @@ Before: return 0 endfunction + " If the window is vertical, window size should match column size/width + function GetQuickfixIsVertical(cols) abort + for l:win in range(1, winnr('$')) + if getwinvar(l:win, '&buftype') is# 'quickfix' + return winwidth(l:win) == a:cols + endif + endfor + + return 0 + endfunction + After: Restore unlet! g:loclist + unlet! b:ale_list_vertical unlet! b:ale_list_window_size unlet! b:ale_open_list unlet! b:ale_keep_list_window_open unlet! b:ale_save_event_fired delfunction GetQuickfixHeight + delfunction GetQuickfixIsVertical " Close quickfix window after every execute block lcl @@ -98,6 +113,24 @@ Execute(The quickfix window height should be correct for the loclist with buffer AssertEqual 8, GetQuickfixHeight() +Execute(The quickfix window should be vertical for the loclist with appropriate variables): + let g:ale_open_list = 1 + let b:ale_list_window_size = 8 + let b:ale_list_vertical = 1 + + call ale#list#SetLists(bufnr('%'), g:loclist) + + AssertEqual 1, GetQuickfixIsVertical(8) + +Execute(The quickfix window should be horizontal for the loclist with appropriate variables): + let g:ale_open_list = 1 + let b:ale_list_window_size = 8 + let b:ale_list_vertical = 0 + + call ale#list#SetLists(bufnr('%'), g:loclist) + + AssertEqual 0, GetQuickfixIsVertical(8) + Execute(The quickfix window should stay open for just the loclist): let g:ale_open_list = 1 let g:ale_keep_list_window_open = 1 @@ -167,6 +200,24 @@ Execute(The quickfix window height should be correct for the quickfix list with AssertEqual 8, GetQuickfixHeight() +Execute(The quickfix window should be vertical for the quickfix with appropriate variables): + let g:ale_open_list = 1 + let b:ale_list_window_size = 8 + let b:ale_list_vertical = 1 + + call ale#list#SetLists(bufnr('%'), g:loclist) + + AssertEqual 1, GetQuickfixIsVertical(8) + +Execute(The quickfix window should be horizontal for the quickfix with appropriate variables): + let g:ale_open_list = 1 + let b:ale_list_window_size = 8 + let b:ale_list_vertical = 0 + + call ale#list#SetLists(bufnr('%'), g:loclist) + + AssertEqual 0, GetQuickfixIsVertical(8) + Execute(The buffer ale_open_list option should be respected): let b:ale_open_list = 1 diff --git a/test/test_list_titles.vader b/test/test_list_titles.vader index d521906f..1f0b2308 100644 --- a/test/test_list_titles.vader +++ b/test/test_list_titles.vader @@ -38,7 +38,7 @@ Execute(The loclist titles should be set appropriately): \ 'nr': 0, \ 'type': 'E', \ 'pattern': '', - \}], getloclist(0) + \}], ale#test#GetLoclistWithoutModule() if !has('nvim') AssertEqual @@ -68,7 +68,7 @@ Execute(The quickfix titles should be set appropriately): \ 'nr': 0, \ 'type': 'E', \ 'pattern': '', - \}], getqflist() + \}], ale#test#GetQflistWithoutModule() if !has('nvim') AssertEqual diff --git a/test/test_loclist_binary_search.vader b/test/test_loclist_binary_search.vader index 5558191c..219fb314 100644 --- a/test/test_loclist_binary_search.vader +++ b/test/test_loclist_binary_search.vader @@ -47,3 +47,20 @@ Execute(Searches should work with just one item): let g:loclist = [{'bufnr': 1, 'lnum': 3, 'col': 10}] AssertEqual 0, ale#util#BinarySearch(g:loclist, 1, 3, 2) + +Execute(Searches should return the last item on a single column): + let g:loclist = [ + \ {'bufnr': 1, 'lnum': 1, 'col': 10, 'type': 'W'}, + \ {'bufnr': 1, 'lnum': 1, 'col': 10, 'type': 'E'}, + \ {'bufnr': 1, 'lnum': 1, 'col': 11, 'type': 'W'}, + \ {'bufnr': 1, 'lnum': 1, 'col': 11, 'type': 'E'}, + \ {'bufnr': 1, 'lnum': 1, 'col': 20, 'type': 'W'}, + \ {'bufnr': 1, 'lnum': 1, 'col': 20, 'type': 'E'}, + \] + + " We should return the index for the last item at some column to the right. + AssertEqual 1, ale#util#BinarySearch(g:loclist, 1, 1, 1) + " We should return the index for the last item at the column we are on. + AssertEqual 3, ale#util#BinarySearch(g:loclist, 1, 1, 11) + " We should prefer items to the left of the cursor, over the right. + AssertEqual 3, ale#util#BinarySearch(g:loclist, 1, 1, 19) diff --git a/test/test_loclist_corrections.vader b/test/test_loclist_corrections.vader index 6224d608..48aa1f78 100644 --- a/test/test_loclist_corrections.vader +++ b/test/test_loclist_corrections.vader @@ -52,7 +52,7 @@ Execute(FixLocList should use the values we supply): \ 'lnum': 3, \ 'col': 4, \ 'bufnr': 10000, - \ 'vcol': 1, + \ 'vcol': 0, \ 'type': 'W', \ 'nr': 42, \ 'linter_name': 'foobar', @@ -324,7 +324,7 @@ Execute(FixLocList should interpret temporary filenames as being the current buf \ 'foobar', \ [ \ {'text': 'a', 'lnum': 2, 'filename': b:temp_name}, - \ {'text': 'a', 'lnum': 3, 'filename': b:temp_name}, + \ {'text': 'a', 'lnum': 3, 'filename': substitute(b:temp_name, '\\', '/', 'g')}, \ ], \ ) @@ -348,3 +348,33 @@ Execute(The error code should be passed on): \ 'foobar', \ [{'text': 'a', 'lnum': 11, 'code': 'some-code'}], \ ) + +Given(A file with Japanese multi-byte text): + はじめまして! + -私はワープです。 +Execute(character positions should be converted to byte positions): + AssertEqual + \ [ + \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 0, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'}, + \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 1, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'}, + \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 4, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'}, + \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 7, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'}, + \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 7, 'end_col': 13, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'}, + \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 7, 'end_col': 13, 'end_lnum': 1, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'}, + \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 7, 'end_col': 17, 'end_lnum': 2, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'}, + \ {'lnum': 2, 'bufnr': bufnr(''), 'col': 17, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'}, + \], + \ ale#engine#FixLocList( + \ bufnr('%'), + \ 'foobar', + \ [ + \ {'text': 'a', 'lnum': 1, 'col': 0, 'vcol': 1}, + \ {'text': 'a', 'lnum': 1, 'col': 1, 'vcol': 1}, + \ {'text': 'a', 'lnum': 1, 'col': 2, 'vcol': 1}, + \ {'text': 'a', 'lnum': 1, 'col': 3, 'vcol': 1}, + \ {'text': 'a', 'lnum': 1, 'col': 3, 'end_col': 5, 'vcol': 1}, + \ {'text': 'a', 'lnum': 1, 'col': 3, 'end_col': 5, 'end_lnum': 1, 'vcol': 1}, + \ {'text': 'a', 'lnum': 1, 'col': 3, 'end_col': 7, 'end_lnum': 2, 'vcol': 1}, + \ {'text': 'a', 'lnum': 2, 'col': 7, 'vcol': 1}, + \ ], + \ ) diff --git a/test/test_loclist_jumping.vader b/test/test_loclist_jumping.vader index 5e18499e..da9a1f57 100644 --- a/test/test_loclist_jumping.vader +++ b/test/test_loclist_jumping.vader @@ -2,15 +2,15 @@ Before: let g:ale_buffer_info = { \ bufnr(''): { \ 'loclist': [ - \ {'bufnr': bufnr('') - 1, 'lnum': 3, 'col': 2}, - \ {'bufnr': bufnr(''), 'lnum': 1, 'col': 2}, - \ {'bufnr': bufnr(''), 'lnum': 1, 'col': 3}, - \ {'bufnr': bufnr(''), 'lnum': 2, 'col': 1}, - \ {'bufnr': bufnr(''), 'lnum': 2, 'col': 2}, - \ {'bufnr': bufnr(''), 'lnum': 2, 'col': 3}, - \ {'bufnr': bufnr(''), 'lnum': 2, 'col': 6}, - \ {'bufnr': bufnr(''), 'lnum': 2, 'col': 700}, - \ {'bufnr': bufnr('') + 1, 'lnum': 3, 'col': 2}, + \ {'type': 'E', 'bufnr': bufnr('') - 1, 'lnum': 3, 'col': 2}, + \ {'type': 'E', 'bufnr': bufnr(''), 'lnum': 1, 'col': 2}, + \ {'type': 'E', 'bufnr': bufnr(''), 'lnum': 1, 'col': 3}, + \ {'type': 'E', 'bufnr': bufnr(''), 'lnum': 2, 'col': 1}, + \ {'type': 'E', 'bufnr': bufnr(''), 'lnum': 2, 'col': 2}, + \ {'type': 'E', 'bufnr': bufnr(''), 'lnum': 2, 'col': 3}, + \ {'type': 'E', 'bufnr': bufnr(''), 'lnum': 2, 'col': 6}, + \ {'type': 'E', 'bufnr': bufnr(''), 'lnum': 2, 'col': 700}, + \ {'type': 'E', 'bufnr': bufnr('') + 1, 'lnum': 3, 'col': 2}, \ ], \ }, \} @@ -81,7 +81,7 @@ Execute(We should be able to jump when the error line is blank): " Add a blank line at the end. call setline(1, getline('.', '$') + ['']) " Add a problem on the blank line. - call add(g:ale_buffer_info[bufnr('%')].loclist, {'bufnr': bufnr(''), 'lnum': 3, 'col': 1}) + call add(g:ale_buffer_info[bufnr('%')].loclist, {'type': 'E', 'bufnr': bufnr(''), 'lnum': 3, 'col': 1}) AssertEqual 0, len(getline(3)) AssertEqual [2, 8], TestJump('before', 0, [3, 1]) diff --git a/test/test_loclist_sorting.vader b/test/test_loclist_sorting.vader index 157b2a25..376e743a 100644 --- a/test/test_loclist_sorting.vader +++ b/test/test_loclist_sorting.vader @@ -25,3 +25,19 @@ Execute(loclist item should be sorted): \ {'bufnr': 2, 'lnum': 1, 'col': 2}, \ {'bufnr': -1, 'filename': 'c', 'lnum': 3, 'col': 2}, \], 'ale#util#LocItemCompare') + +Execute(Items should be sorted in by their problem priority when they lie on the same column): + AssertEqual [ + \ {'bufnr': 1, 'lnum': 1, 'col': 1, 'type': 'W', 'sub_type': 'style'}, + \ {'bufnr': 1, 'lnum': 1, 'col': 1, 'type': 'E', 'sub_type': 'style'}, + \ {'bufnr': 1, 'lnum': 1, 'col': 1, 'type': 'I'}, + \ {'bufnr': 1, 'lnum': 1, 'col': 1, 'type': 'W'}, + \ {'bufnr': 1, 'lnum': 1, 'col': 1, 'type': 'E'}, + \ ], + \ sort([ + \ {'bufnr': 1, 'lnum': 1, 'col': 1, 'type': 'E'}, + \ {'bufnr': 1, 'lnum': 1, 'col': 1, 'type': 'I'}, + \ {'bufnr': 1, 'lnum': 1, 'col': 1, 'type': 'W'}, + \ {'bufnr': 1, 'lnum': 1, 'col': 1, 'type': 'E', 'sub_type': 'style'}, + \ {'bufnr': 1, 'lnum': 1, 'col': 1, 'type': 'W', 'sub_type': 'style'}, + \], 'ale#util#LocItemCompare') diff --git a/test/test_no_linting_on_write_quit.vader b/test/test_no_linting_on_write_quit.vader index d3baeaa1..12ef38ed 100644 --- a/test/test_no_linting_on_write_quit.vader +++ b/test/test_no_linting_on_write_quit.vader @@ -3,9 +3,21 @@ Before: Save g:ale_fix_on_save Save g:ale_fixers Save g:ale_lint_on_save + Save g:ale_set_highlights + Save g:ale_set_lists_synchronously + Save g:ale_set_loclist + Save g:ale_set_quickfix + Save g:ale_set_signs - let g:ale_echo_cursor = 0 let g:ale_run_synchronously = 1 + let g:ale_set_lists_synchronously = 1 + " Disable the things we don't need, but leave enabled what we do. + let g:ale_echo_cursor = 0 + 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 [{'lnum': 1, 'col': 1, 'text': 'xxx'}] @@ -19,6 +31,7 @@ Before: \ 'testft': ['AddLine'], \} + call ale#linter#PreventLoading('testft') call ale#linter#Define('testft', { \ 'name': 'testlinter', \ 'callback': 'TestCallback', @@ -46,14 +59,14 @@ Execute(No linting should be done on :wq or :x): " First try just the SaveEvent, to be sure that we set errors in the test. call ale#events#SaveEvent(bufnr('')) - AssertEqual 1, len(getloclist(0)) + AssertEqual 1, len(ale#test#GetLoclistWithoutModule()) " Now try doing it again, but where we run the quit event first. call setloclist(0, []) call ale#events#QuitEvent(bufnr('')) call ale#events#SaveEvent(bufnr('')) - AssertEqual [], getloclist(0) + AssertEqual [], ale#test#GetLoclistWithoutModule() Execute(No linting should be for :w after :q fails): let g:ale_lint_on_save = 1 @@ -66,7 +79,7 @@ Execute(No linting should be for :w after :q fails): call ale#events#SaveEvent(bufnr('')) - AssertEqual 1, len(getloclist(0)) + AssertEqual 1, len(ale#test#GetLoclistWithoutModule()) Execute(No linting should be done on :wq or :x after fixing files): let g:ale_lint_on_save = 0 @@ -74,14 +87,14 @@ Execute(No linting should be done on :wq or :x after fixing files): call ale#events#SaveEvent(bufnr('')) - AssertEqual 1, len(getloclist(0)) + AssertEqual 1, len(ale#test#GetLoclistWithoutModule()) " Now try doing it again, but where we run the quit event first. call setloclist(0, []) call ale#events#QuitEvent(bufnr('')) call ale#events#SaveEvent(bufnr('')) - AssertEqual [], getloclist(0) + AssertEqual [], ale#test#GetLoclistWithoutModule() Execute(Linting should be done after :q fails and fixing files): let g:ale_lint_on_save = 0 @@ -94,4 +107,4 @@ Execute(Linting should be done after :q fails and fixing files): call ale#events#SaveEvent(bufnr('')) - AssertEqual 1, len(getloclist(0)) + AssertEqual 1, len(ale#test#GetLoclistWithoutModule()) 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_pattern_options.vader b/test/test_pattern_options.vader index 0e26eaaa..3b6500e5 100644 --- a/test/test_pattern_options.vader +++ b/test/test_pattern_options.vader @@ -1,8 +1,12 @@ Before: Save g:ale_pattern_options Save g:ale_pattern_options_enabled + Save b:ale_quitting + Save b:ale_original_filetype Save &filetype + unlet! b:ale_file_changed + let g:ale_pattern_options_enabled = 1 let g:ale_pattern_options = {} @@ -21,7 +25,7 @@ After: Execute(The pattern options function should work when there are no patterns): call ale#test#SetFilename('foobar.js') - call ale#pattern_options#SetOptions(bufnr('')) + call ale#events#ReadOrEnterEvent(bufnr('')) Execute(Buffer variables should be set when filename patterns match): let g:ale_pattern_options = { @@ -33,13 +37,13 @@ Execute(Buffer variables should be set when filename patterns match): \} call ale#test#SetFilename('foobar.js') - call ale#pattern_options#SetOptions(bufnr('')) + call ale#events#ReadOrEnterEvent(bufnr('')) AssertEqual 0, b:ale_enabled AssertEqual 0, b:some_option call ale#test#SetFilename('bazboz.js') - call ale#pattern_options#SetOptions(bufnr('')) + call ale#events#ReadOrEnterEvent(bufnr('')) AssertEqual 1, b:ale_enabled AssertEqual 347, b:some_option @@ -61,7 +65,7 @@ Execute(Multiple pattern matches should be applied): \} call ale#test#SetFilename('foobar.js') - call ale#pattern_options#SetOptions(bufnr('')) + call ale#events#ReadOrEnterEvent(bufnr('')) AssertEqual 1, b:ale_enabled AssertEqual 666, b:some_option @@ -71,7 +75,7 @@ Execute(Patterns should not be applied when the setting is disabled): let g:ale_pattern_options = {'foo': {'some_option': 666}} call ale#test#SetFilename('foobar.js') - call ale#pattern_options#SetOptions(bufnr('')) + call ale#events#ReadOrEnterEvent(bufnr('')) AssertEqual 0, b:some_option @@ -81,12 +85,23 @@ Execute(Patterns should be applied after the Dictionary changes): let g:ale_pattern_options = {} - call ale#pattern_options#SetOptions(bufnr('')) + call ale#events#ReadOrEnterEvent(bufnr('')) AssertEqual 0, b:some_option let g:ale_pattern_options['foo'] = {'some_option': 666} - call ale#pattern_options#SetOptions(bufnr('')) + call ale#events#ReadOrEnterEvent(bufnr('')) AssertEqual 666, b:some_option + +Execute(SetOptions should tolerate settings being unset): + " This might happen if ALE is loaded in a weird way, so tolerate it. + unlet! g:ale_pattern_options + unlet! g:ale_pattern_options_enabled + + call ale#events#ReadOrEnterEvent(bufnr('')) + + let g:ale_pattern_options_enabled = 1 + + call ale#events#ReadOrEnterEvent(bufnr('')) 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_prepare_command.vader b/test/test_prepare_command.vader index ed9272ab..75e4c0c6 100644 --- a/test/test_prepare_command.vader +++ b/test/test_prepare_command.vader @@ -22,6 +22,23 @@ Execute(sh should be used when the shell is fish): AssertEqual ['/bin/sh', '-c', 'foobar'], ale#job#PrepareCommand(bufnr(''), 'foobar') endif +Execute(sh should be used when the shell is powershell): + if !has('win32') + " Set something else, so we will replace that too. + let &shellcmdflag = '-f' + let &shell = 'pwsh' + + AssertEqual ['/bin/sh', '-c', 'foobar'], ale#job#PrepareCommand(bufnr(''), 'foobar') + + let &shell = '/usr/bin/pwsh' + + AssertEqual ['/bin/sh', '-c', 'foobar'], ale#job#PrepareCommand(bufnr(''), 'foobar') + + let &shell = '/usr/local/bin/pwsh' + + AssertEqual ['/bin/sh', '-c', 'foobar'], ale#job#PrepareCommand(bufnr(''), 'foobar') + endif + Execute(Other shells should be used when set): if !has('win32') let &shell = '/bin/bash' diff --git a/test/test_puppet_path_detection.vader b/test/test_puppet_path_detection.vader new file mode 100644 index 00000000..f8d3a0fa --- /dev/null +++ b/test/test_puppet_path_detection.vader @@ -0,0 +1,22 @@ +Before: + call ale#test#SetDirectory('/testplugin/test') + + runtime ale_linters/puppet/languageserver.vim + +After: + call ale#test#RestoreDirectory() + call ale#linter#Reset() + +Execute(old-style module should find its root correctly): + call ale#test#SetFilename('puppet-test-files/old-style-module/manifests/init.pp') + + AssertEqual + \ ale#path#Simplify(g:dir . '/puppet-test-files/old-style-module'), + \ ale_linters#puppet#languageserver#GetProjectRoot(bufnr('')) + +Execute(new-style module should find its root correctly): + call ale#test#SetFilename('puppet-test-files/new-style-module/lib/puppet/types/exampletype.rb') + + AssertEqual + \ ale#path#Simplify(g:dir . '/puppet-test-files/new-style-module'), + \ ale_linters#puppet#languageserver#GetProjectRoot(bufnr('')) diff --git a/test/test_quickfix_deduplication.vader b/test/test_quickfix_deduplication.vader index 0dff3f2e..9cb8b931 100644 --- a/test/test_quickfix_deduplication.vader +++ b/test/test_quickfix_deduplication.vader @@ -9,42 +9,42 @@ Execute: " Equal problems should be de-duplicated. let g:ale_buffer_info = { \ '1': {'loclist': [ - \ {'bufnr': 2, 'lnum': 1, 'col': 2, 'text': 'foo'}, - \ {'bufnr': 2, 'lnum': 1, 'col': 5, 'text': 'bar'}, - \ {'bufnr': -1, 'filename': 'c', 'lnum': 3, 'col': 2, 'text': 'x'}, - \ {'bufnr': 1, 'lnum': 5, 'col': 4, 'text': 'x'}, - \ {'bufnr': 2, 'lnum': 5, 'col': 5, 'text': 'foo'}, - \ {'bufnr': 1, 'lnum': 2, 'col': 10, 'text': 'x'}, - \ {'bufnr': 1, 'lnum': 3, 'col': 2, 'text': 'x'}, - \ {'bufnr': 1, 'lnum': 5, 'col': 5, 'text': 'x'}, - \ {'bufnr': -1, 'filename': 'b', 'lnum': 4, 'col': 2, 'text': 'x'}, - \ {'bufnr': -1, 'filename': 'b', 'lnum': 5, 'col': 2, 'text': 'x'}, - \ {'bufnr': 3, 'lnum': 1, 'col': 1, 'text': 'foo'}, + \ {'type': 'E', 'bufnr': 2, 'lnum': 1, 'col': 2, 'text': 'foo'}, + \ {'type': 'E', 'bufnr': 2, 'lnum': 1, 'col': 5, 'text': 'bar'}, + \ {'type': 'E', 'bufnr': -1, 'filename': 'c', 'lnum': 3, 'col': 2, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 1, 'lnum': 5, 'col': 4, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 2, 'lnum': 5, 'col': 5, 'text': 'foo'}, + \ {'type': 'E', 'bufnr': 1, 'lnum': 2, 'col': 10, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 1, 'lnum': 3, 'col': 2, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 1, 'lnum': 5, 'col': 5, 'text': 'x'}, + \ {'type': 'E', 'bufnr': -1, 'filename': 'b', 'lnum': 4, 'col': 2, 'text': 'x'}, + \ {'type': 'E', 'bufnr': -1, 'filename': 'b', 'lnum': 5, 'col': 2, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 3, 'lnum': 1, 'col': 1, 'text': 'foo'}, \ ]}, \ '2': {'loclist': [ - \ {'bufnr': 1, 'lnum': 2, 'col': 10, 'text': 'x'}, - \ {'bufnr': 1, 'lnum': 5, 'col': 5, 'text': 'x'}, - \ {'bufnr': 2, 'lnum': 1, 'col': 2, 'text': 'foo'}, - \ {'bufnr': 1, 'lnum': 3, 'col': 2, 'text': 'x'}, - \ {'bufnr': 1, 'lnum': 5, 'col': 4, 'text': 'x'}, - \ {'bufnr': 2, 'lnum': 1, 'col': 5, 'text': 'bar'}, - \ {'bufnr': 2, 'lnum': 5, 'col': 5, 'text': 'another error'}, + \ {'type': 'E', 'bufnr': 1, 'lnum': 2, 'col': 10, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 1, 'lnum': 5, 'col': 5, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 2, 'lnum': 1, 'col': 2, 'text': 'foo'}, + \ {'type': 'E', 'bufnr': 1, 'lnum': 3, 'col': 2, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 1, 'lnum': 5, 'col': 4, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 2, 'lnum': 1, 'col': 5, 'text': 'bar'}, + \ {'type': 'E', 'bufnr': 2, 'lnum': 5, 'col': 5, 'text': 'another error'}, \ ]}, \} AssertEqual \ [ - \ {'bufnr': -1, 'filename': 'b', 'lnum': 4, 'col': 2, 'text': 'x'}, - \ {'bufnr': -1, 'filename': 'b', 'lnum': 5, 'col': 2, 'text': 'x'}, - \ {'bufnr': -1, 'filename': 'c', 'lnum': 3, 'col': 2, 'text': 'x'}, - \ {'bufnr': 1, 'lnum': 2, 'col': 10, 'text': 'x'}, - \ {'bufnr': 1, 'lnum': 3, 'col': 2, 'text': 'x'}, - \ {'bufnr': 1, 'lnum': 5, 'col': 4, 'text': 'x'}, - \ {'bufnr': 1, 'lnum': 5, 'col': 5, 'text': 'x'}, - \ {'bufnr': 2, 'lnum': 1, 'col': 2, 'text': 'foo'}, - \ {'bufnr': 2, 'lnum': 1, 'col': 5, 'text': 'bar'}, - \ {'bufnr': 2, 'lnum': 5, 'col': 5, 'text': 'another error'}, - \ {'bufnr': 2, 'lnum': 5, 'col': 5, 'text': 'foo'}, - \ {'bufnr': 3, 'lnum': 1, 'col': 1, 'text': 'foo'}, + \ {'type': 'E', 'bufnr': -1, 'filename': 'b', 'lnum': 4, 'col': 2, 'text': 'x'}, + \ {'type': 'E', 'bufnr': -1, 'filename': 'b', 'lnum': 5, 'col': 2, 'text': 'x'}, + \ {'type': 'E', 'bufnr': -1, 'filename': 'c', 'lnum': 3, 'col': 2, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 1, 'lnum': 2, 'col': 10, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 1, 'lnum': 3, 'col': 2, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 1, 'lnum': 5, 'col': 4, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 1, 'lnum': 5, 'col': 5, 'text': 'x'}, + \ {'type': 'E', 'bufnr': 2, 'lnum': 1, 'col': 2, 'text': 'foo'}, + \ {'type': 'E', 'bufnr': 2, 'lnum': 1, 'col': 5, 'text': 'bar'}, + \ {'type': 'E', 'bufnr': 2, 'lnum': 5, 'col': 5, 'text': 'another error'}, + \ {'type': 'E', 'bufnr': 2, 'lnum': 5, 'col': 5, 'text': 'foo'}, + \ {'type': 'E', 'bufnr': 3, 'lnum': 1, 'col': 1, 'text': 'foo'}, \ ], \ ale#list#GetCombinedList() diff --git a/test/test_quitting_variable.vader b/test/test_quitting_variable.vader index bef344a8..32eb0c36 100644 --- a/test/test_quitting_variable.vader +++ b/test/test_quitting_variable.vader @@ -11,17 +11,17 @@ After: unlet! b:time_before Execute(QuitEvent should set b:ale_quitting some time from the clock): - let b:time_before = ale#util#ClockMilliseconds() + let b:time_before = ale#events#ClockMilliseconds() call ale#events#QuitEvent(bufnr('')) Assert b:ale_quitting >= b:time_before - Assert b:ale_quitting <= ale#util#ClockMilliseconds() + Assert b:ale_quitting <= ale#events#ClockMilliseconds() -Execute(EnterEvent should set b:ale_quitting to 0): +Execute(ReadOrEnterEvent should set b:ale_quitting to 0): let b:ale_quitting = 1 - call ale#events#EnterEvent(bufnr('')) + call ale#events#ReadOrEnterEvent(bufnr('')) AssertEqual 0, b:ale_quitting @@ -29,11 +29,11 @@ Execute(The QuitRecently function should work when the variable isn't set): AssertEqual 0, ale#events#QuitRecently(bufnr('')) Execute(The QuitRecently function should return 1 when ALE quit recently): - let b:ale_quitting = ale#util#ClockMilliseconds() + let b:ale_quitting = ale#events#ClockMilliseconds() AssertEqual 1, ale#events#QuitRecently(bufnr('')) Execute(The QuitRecently function should return 0 when a second has passed): - let b:ale_quitting = ale#util#ClockMilliseconds() - 1001 + let b:ale_quitting = ale#events#ClockMilliseconds() - 1001 AssertEqual 0, ale#events#QuitRecently(bufnr('')) diff --git a/test/test_results_not_cleared_when_opening_loclist.vader b/test/test_results_not_cleared_when_opening_loclist.vader index c983a89f..4a53d356 100644 --- a/test/test_results_not_cleared_when_opening_loclist.vader +++ b/test/test_results_not_cleared_when_opening_loclist.vader @@ -1,31 +1,11 @@ Before: - Save g:ale_run_synchronously + Save g:ale_buffer_info - let g:ale_run_synchronously = 1 - - function! TestCallback(buffer, output) - return [ - \ { - \ 'lnum': 1, - \ 'text': 'Something is wrong', - \ }, - \] - endfunction - - call ale#linter#Define('foobar', { - \ 'name': 'testlinter', - \ 'callback': 'TestCallback', - \ 'executable': has('win32') ? 'cmd' : 'true', - \ 'command': 'true', - \ 'read_buffer': 0, - \}) + call ale#linter#Reset() After: Restore - delfunction TestCallback - let g:ale_buffer_info = {} - call ale#linter#Reset() call setloclist(0, []) call clearmatches() sign unplace * @@ -34,10 +14,11 @@ Given foobar (Some file): abc Execute(The loclist shouldn't be cleared when opening the loclist): - call ale#Lint() - sleep 1ms - - AssertEqual 1, len(getloclist(0)), 'The loclist was never set' + call ale#engine#InitBufferInfo(bufnr('')) + let g:ale_buffer_info[bufnr('')].loclist = [ + \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2}, + \] + call setloclist(0, g:ale_buffer_info[bufnr('')].loclist) " The cleanup function is called when the loclist window is closed. " If some cleanup is done for this buffer, for which nothing is wrong, @@ -46,4 +27,4 @@ Execute(The loclist shouldn't be cleared when opening the loclist): :lopen :q - AssertEqual 1, len(getloclist(0)), 'The loclist was cleared' + AssertEqual 1, len(ale#test#GetLoclistWithoutModule()), 'The loclist was cleared' diff --git a/test/test_sandbox_execution.vader b/test/test_sandbox_execution.vader index 7f4941fd..4dbcb0db 100644 --- a/test/test_sandbox_execution.vader +++ b/test/test_sandbox_execution.vader @@ -24,10 +24,13 @@ Before: let g:ale_buffer_info = {} After: + unlet! b:in_sandbox + unlet! b:result + delfunction TestCallback call ale#linter#Reset() let g:ale_buffer_info = {} - unlet! b:in_sandbox + Given foobar (Some imaginary filetype): foo @@ -61,3 +64,41 @@ Execute(ALE shouldn't blow up if file cleanup happens in a sandbox): AssertEqual ['/tmp/foo'], g:ale_buffer_info[3].temporary_file_list AssertEqual ['/tmp/bar'], g:ale_buffer_info[3].temporary_directory_list + +Execute(You shouldn't be able to define linters from the sandbox): + call ale#linter#Reset() + call ale#linter#PreventLoading('testft') + + AssertThrows sandbox call ale#linter#Define('testft', { + \ 'name': 'testlinter', + \ 'output_stream': 'stdout', + \ 'executable': 'testlinter', + \ 'command': 'testlinter', + \ 'callback': 'testCB', + \}) + AssertEqual 'Vim(let):E48: Not allowed in sandbox', g:vader_exception + AssertEqual [], ale#linter#GetAll(['testft']) + +Execute(You shouldn't be able to register fixers from the sandbox): + call ale#fix#registry#Clear() + AssertThrows sandbox call ale#fix#registry#Add('prettier', '', ['javascript'], 'prettier') + AssertEqual 'Vim(let):E48: Not allowed in sandbox', g:vader_exception + AssertEqual [], ale#fix#registry#CompleteFixers('', 'ALEFix ', 7) + +Execute(You shouldn't be able to get linters from the sandbox, to prevent tampering): + AssertThrows sandbox call ale#linter#GetLintersLoaded() + AssertEqual 'Vim(let):E48: Not allowed in sandbox', g:vader_exception + + call ale#linter#Reset() + + sandbox let b:result = ale#linter#GetAll(['testft']) + + AssertEqual 0, len(b:result) + + let b:result = ale#linter#GetAll(['testft']) + + AssertEqual 1, len(b:result) + + sandbox let b:result = ale#linter#GetAll(['testft']) + + AssertEqual 0, len(b:result) diff --git a/test/test_set_list_timers.vader b/test/test_set_list_timers.vader index f8fcb6a0..e53b97a4 100644 --- a/test/test_set_list_timers.vader +++ b/test/test_set_list_timers.vader @@ -26,4 +26,4 @@ Execute(The SetLists function should work when run in a timer): \ 'nr': 0, \ 'type': 'E', \ 'pattern': '', - \}], getloclist(0) + \}], ale#test#GetLoclistWithoutModule() diff --git a/test/test_setting_loclist_from_another_buffer.vader b/test/test_setting_loclist_from_another_buffer.vader index 10a44cce..028ffb1e 100644 --- a/test/test_setting_loclist_from_another_buffer.vader +++ b/test/test_setting_loclist_from_another_buffer.vader @@ -21,6 +21,6 @@ Execute(Errors should be set in the loclist for the original buffer, not the new \ g:ale_buffer_info[(g:original_buffer)].loclist, \ ) - AssertEqual [], getloclist(0) + AssertEqual [], ale#test#GetLoclistWithoutModule() AssertEqual 1, len(getloclist(bufwinid(g:original_buffer))) AssertEqual 'foo', getloclist(bufwinid(g:original_buffer))[0].text diff --git a/test/test_setting_problems_found_in_previous_buffers.vader b/test/test_setting_problems_found_in_previous_buffers.vader index 45dfa662..4604005a 100644 --- a/test/test_setting_problems_found_in_previous_buffers.vader +++ b/test/test_setting_problems_found_in_previous_buffers.vader @@ -95,4 +95,4 @@ Execute(Problems found from previously opened buffers should be set when linting \ {'lnum': 2, 'bufnr': bufnr(''), 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'E', 'pattern': '', 'text': 'bar'}, \ {'lnum': 3, 'bufnr': bufnr(''), 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'E', 'pattern': '', 'text': 'baz'}, \ ], - \ getloclist(0) + \ ale#test#GetLoclistWithoutModule() diff --git a/test/test_should_do_nothing_conditions.vader b/test/test_should_do_nothing_conditions.vader index 23ebd92e..062ab875 100644 --- a/test/test_should_do_nothing_conditions.vader +++ b/test/test_should_do_nothing_conditions.vader @@ -1,4 +1,7 @@ Before: + Save g:ale_filetype_blacklist + Save g:ale_maximum_file_size + Save g:ale_enabled Save &l:statusline call ale#test#SetDirectory('/testplugin/test') @@ -12,6 +15,8 @@ Before: endif After: + Restore + call ale#test#RestoreDirectory() if b:funky_command_created @@ -21,8 +26,7 @@ After: unlet! b:funky_command_created - Restore - +Given foobar(An empty file): Execute(ALE shouldn't do much of anything for ctrlp-funky buffers): Assert !ale#ShouldDoNothing(bufnr('')), 'The preliminary check failed' @@ -39,3 +43,21 @@ Execute(ALE shouldn't try to check buffers with '.' as the filename): silent! noautocmd file . Assert ale#ShouldDoNothing(bufnr('')) + +Execute(DoNothing should return 0 when the filetype is empty): + AssertEqual + \ 0, + \ ale#ShouldDoNothing(bufnr('')), + \ 'ShouldDoNothing() was 1 for some other reason' + + set filetype= + + 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 + unlet! g:ale_enabled + + " This shouldn't throw exceptions. + call ale#ShouldDoNothing(bufnr('')) diff --git a/test/test_socket_connections.vader b/test/test_socket_connections.vader new file mode 100644 index 00000000..6837fe51 --- /dev/null +++ b/test/test_socket_connections.vader @@ -0,0 +1,92 @@ +Before: + let g:can_run_socket_tests = !has('win32') + \ && (exists('*ch_close') || exists('*chanclose')) + + if g:can_run_socket_tests + call ale#test#SetDirectory('/testplugin/test') + + let g:channel_id_received = 0 + let g:data_received = '' + + function! WaitForData(expected_data, timeout) abort + let l:ticks = 0 + + while l:ticks < a:timeout + " Sleep first, so we can switch to the callback. + let l:ticks += 10 + sleep 10ms + + if g:data_received is# a:expected_data + break + endif + endwhile + endfunction + + function! TestCallback(channel_id, data) abort + let g:channel_id_received = a:channel_id + let g:data_received .= a:data + endfunction + + let g:port = 10347 + let g:pid = str2nr(system( + \ 'python' + \ . ' ' . ale#Escape(g:dir . '/dumb_tcp_server.py') + \ . ' ' . g:port + \)) + endif + +After: + if g:can_run_socket_tests + call ale#test#RestoreDirectory() + + unlet! g:channel_id_received + unlet! g:data_received + unlet! g:channel_id + + delfunction WaitForData + delfunction TestCallback + + if has_key(g:, 'pid') + call system('kill ' . g:pid) + endif + + unlet! g:pid + unlet! g:port + endif + + unlet! g:can_run_socket_tests + +Execute(Sending and receiving connections to sockets should work): + if g:can_run_socket_tests + let g:channel_id = ale#socket#Open( + \ '127.0.0.1:' . g:port, + \ {'callback': function('TestCallback')} + \) + + Assert g:channel_id >= 0, 'The socket was not opened!' + + call ale#socket#Send(g:channel_id, 'hello') + call ale#socket#Send(g:channel_id, ' world') + + AssertEqual 1, ale#socket#IsOpen(g:channel_id) + + " Wait up to 1 second for the expected data to arrive. + call WaitForData('hello world', 1000) + + AssertEqual g:channel_id, g:channel_id_received + AssertEqual 'hello world', g:data_received + AssertEqual '127.0.0.1:' . g:port, ale#socket#GetAddress(g:channel_id) + + call ale#socket#Close(g:channel_id) + + AssertEqual 0, ale#socket#IsOpen(g:channel_id) + AssertEqual '', ale#socket#GetAddress(g:channel_id) + endif + + " NeoVim versions which can't connect to sockets should just fail. + if has('nvim') && !exists('*chanclose') + AssertEqual -1, ale#socket#Open( + \ '127.0.0.1:1111', + \ {'callback': function('function')} + \) + endif diff --git a/test/test_statusline.vader b/test/test_statusline.vader index 0ce1d36f..d928e7ee 100644 --- a/test/test_statusline.vader +++ b/test/test_statusline.vader @@ -91,43 +91,6 @@ Execute (Count should be match the loclist): Execute (Output should be empty for non-existent buffer): AssertEqual Counts({}), ale#statusline#Count(9001) -Execute (Status() should return just errors for the old format): - let g:ale_statusline_format = ['%sE', '%sW', 'OKIE'] - let g:ale_buffer_info = {bufnr(''): {}} - call ale#statusline#Update(bufnr(''), [ - \ {'bufnr': bufnr(''), 'type': 'E'}, - \ {'bufnr': bufnr(''), 'type': 'E', 'sub_type': 'style'}, - \]) - AssertEqual '2E', ale#statusline#Status() - -Execute (Status() should return just warnings for the old format): - let g:ale_statusline_format = ['%sE', '%sW', 'OKIE'] - let g:ale_buffer_info = {bufnr(''): {}} - call ale#statusline#Update(bufnr(''), [ - \ {'bufnr': bufnr(''), 'type': 'W'}, - \ {'bufnr': bufnr(''), 'type': 'W', 'sub_type': 'style'}, - \ {'bufnr': bufnr(''), 'type': 'I'}, - \]) - AssertEqual '3W', ale#statusline#Status() - -Execute (Status() should return errors and warnings for the old format): - let g:ale_statusline_format = ['%sE', '%sW', 'OKIE'] - let g:ale_buffer_info = {bufnr(''): {}} - call ale#statusline#Update(bufnr(''), [ - \ {'bufnr': bufnr(''), 'type': 'E'}, - \ {'bufnr': bufnr(''), 'type': 'E', 'sub_type': 'style'}, - \ {'bufnr': bufnr(''), 'type': 'W'}, - \ {'bufnr': bufnr(''), 'type': 'W', 'sub_type': 'style'}, - \ {'bufnr': bufnr(''), 'type': 'I'}, - \]) - AssertEqual '2E 3W', ale#statusline#Status() - -Execute (Status() should return the custom 'OK' string with the old format): - let g:ale_statusline_format = ['%sE', '%sW', 'OKIE'] - let g:ale_buffer_info = {bufnr(''): {}} - call ale#statusline#Update(bufnr(''), []) - AssertEqual 'OKIE', ale#statusline#Status() - Execute(ale#statusline#Update shouldn't blow up when globals are undefined): unlet! g:ale_statusline_format call ale#statusline#Update(1, []) @@ -135,7 +98,3 @@ Execute(ale#statusline#Update shouldn't blow up when globals are undefined): Execute(ale#statusline#Count should return 0 counts when globals are undefined): unlet! g:ale_statusline_format AssertEqual Counts({}), ale#statusline#Count(1) - -Execute(ale#statusline#Status should return 'OK' when globals are undefined): - unlet! g:ale_statusline_format - AssertEqual 'OK', ale#statusline#Status() diff --git a/test/test_temporary_file_management.vader b/test/test_temporary_file_management.vader index ae2bf251..e248331c 100644 --- a/test/test_temporary_file_management.vader +++ b/test/test_temporary_file_management.vader @@ -1,4 +1,7 @@ Before: + Save g:ale_buffer_info + + let g:ale_buffer_info = {} let g:ale_run_synchronously = 1 let g:command = 'echo test' @@ -41,6 +44,8 @@ Before: \}) After: + Restore + if !empty(g:preserved_directory) call delete(g:preserved_directory, 'rf') endif @@ -111,3 +116,17 @@ Execute(ALE should create and delete directories for ale#engine#CreateDirectory( Assert !isdirectory(b:dir), 'The directory was not deleted' Assert !isdirectory(b:dir2), 'The second directory was not deleted' + +Execute(ale#engine#ManageFile should add the file even if the buffer info hasn't be set yet): + let g:ale_buffer_info = {} + call ale#engine#ManageFile(bufnr(''), '/foo/bar') + AssertEqual + \ ['/foo/bar'], + \ g:ale_buffer_info[bufnr('')].temporary_file_list + +Execute(ale#engine#ManageDirectory should add the directory even if the buffer info hasn't be set yet): + let g:ale_buffer_info = {} + call ale#engine#ManageDirectory(bufnr(''), '/foo/bar') + AssertEqual + \ ['/foo/bar'], + \ g:ale_buffer_info[bufnr('')].temporary_directory_list 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_tmpdir_init.vader b/test/test_tmpdir_init.vader deleted file mode 100644 index 23326dcc..00000000 --- a/test/test_tmpdir_init.vader +++ /dev/null @@ -1,4 +0,0 @@ -Execute($TMPDIR should be set to a default value if unset): - if has('unix') - AssertEqual '/tmp', $TMPDIR - endif diff --git a/test/test_tmpdir_wrapper.vader b/test/test_tmpdir_wrapper.vader new file mode 100644 index 00000000..151b8943 --- /dev/null +++ b/test/test_tmpdir_wrapper.vader @@ -0,0 +1,32 @@ +Before: + let g:exists = exists('$TMPDIR') + let g:old_value = $TMPDIR + +After: + if g:exists + let $TMPDIR = g:old_value + else + silent! unlet! $TMPDIR + endif + + unlet! g:exists + unlet! g:old_value + +Execute(ale#util#Tempname shouldn't set $TMPDIR to an empty string if it isn't set): + " You can't run this test twice on old Vim versions. + if has('unix') + Assert ale#util#Tempname() =~# '^/tmp' + Assert !exists('$TMPDIR'), '$TMPDIR exists where it shouldn''t' + endif + +Execute(ale#util#Tempname shouldn't replace $TMPDIR and reset them to an empty string.): + if has('unix') + let $TMPDIR = '' + Assert ale#util#Tempname() =~# '^/tmp' + + if !has('nvim') + Assert exists('$TMPDIR'), '$TMPDIR doesn''t exist where it should' + endif + + AssertEqual '', $TMPDIR + endif diff --git a/test/test_verilog_verilator_options.vader b/test/test_verilog_verilator_options.vader index 561786ee..e53037b1 100644 --- a/test/test_verilog_verilator_options.vader +++ b/test/test_verilog_verilator_options.vader @@ -22,4 +22,3 @@ Execute(Set Verilog Verilator linter additional options to `-sv --default-langua \ g:matched , \ -1 , \ 'Additionnal arguments not found in the run command' - @@ -35,7 +35,3 @@ set ttimeoutlen=0 execute 'set encoding=utf-8' let g:mapleader=',' - -" Clear the TMPDIR value for tests. -" The plugin should set this to /tmp by default, which we will test. -let $TMPDIR = '' |