diff options
Diffstat (limited to 'test')
96 files changed, 3242 insertions, 437 deletions
diff --git a/test/command_callback/c_paths/dummy.c b/test/command_callback/c_paths/dummy.c new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/c_paths/dummy.c diff --git a/test/command_callback/php-langserver-project/vendor/bin/php-language-server.php b/test/command_callback/php-langserver-project/vendor/bin/php-language-server.php new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/php-langserver-project/vendor/bin/php-language-server.php diff --git a/test/command_callback/php_paths/project-with-phpcbf/foo/test.php b/test/command_callback/php_paths/project-with-phpcbf/foo/test.php new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/php_paths/project-with-phpcbf/foo/test.php diff --git a/test/command_callback/php_paths/project-with-phpcbf/vendor/bin/phpcbf b/test/command_callback/php_paths/project-with-phpcbf/vendor/bin/phpcbf new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/php_paths/project-with-phpcbf/vendor/bin/phpcbf diff --git a/test/command_callback/php_paths/project-without-phpcbf/foo/test.php b/test/command_callback/php_paths/project-without-phpcbf/foo/test.php new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/php_paths/project-without-phpcbf/foo/test.php diff --git a/test/command_callback/rust-rls-project/Cargo.toml b/test/command_callback/rust-rls-project/Cargo.toml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/rust-rls-project/Cargo.toml diff --git a/test/command_callback/standard-test-files/with-bin/node_modules/.bin/standard b/test/command_callback/standard-test-files/with-bin/node_modules/.bin/standard new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/standard-test-files/with-bin/node_modules/.bin/standard diff --git a/test/command_callback/standard-test-files/with-cmd/node_modules/standard/bin/cmd.js b/test/command_callback/standard-test-files/with-cmd/node_modules/standard/bin/cmd.js new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/standard-test-files/with-cmd/node_modules/standard/bin/cmd.js diff --git a/test/command_callback/swift_paths/dummy.swift b/test/command_callback/swift_paths/dummy.swift new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/swift_paths/dummy.swift diff --git a/test/command_callback/test_erlang_syntaxerl_command_callback.vader b/test/command_callback/test_erlang_syntaxerl_command_callback.vader new file mode 100644 index 00000000..1df2be39 --- /dev/null +++ b/test/command_callback/test_erlang_syntaxerl_command_callback.vader @@ -0,0 +1,58 @@ +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 + + +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('')) + + +Execute (The executable should be presented in the feature check command): + let g:ale_erlang_syntaxerl_executable = '/some/other/syntaxerl' + AssertEqual "'/some/other/syntaxerl' -h", ale_linters#erlang#syntaxerl#FeatureCheck(bufnr('')) + + let b:ale_erlang_syntaxerl_executable = '/yet/another/syntaxerl' + AssertEqual "'/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 "'/some/other/syntaxerl' %t", ale_linters#erlang#syntaxerl#GetCommand(bufnr(''), []) + + let b:ale_erlang_syntaxerl_executable = '/yet/another/syntaxerl' + AssertEqual "'/yet/another/syntaxerl' %t", ale_linters#erlang#syntaxerl#GetCommand(bufnr(''), []) + + +Execute (The -b option should be used when available): + AssertEqual "'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 "'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', + \ ]) diff --git a/test/command_callback/test_flake8_command_callback.vader b/test/command_callback/test_flake8_command_callback.vader index 70527ad3..c36fe4f5 100644 --- a/test/command_callback/test_flake8_command_callback.vader +++ b/test/command_callback/test_flake8_command_callback.vader @@ -19,23 +19,23 @@ Execute(The flake8 callbacks should return the correct default values): \ '''flake8'' --version', \ ale_linters#python#flake8#VersionCheck(bufnr('')) AssertEqual - \ '''flake8'' --stdin-display-name %s -', + \ '''flake8'' --format=default --stdin-display-name %s -', \ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.0']) " Try with older versions. call ale_linters#python#flake8#ClearVersionCache() AssertEqual - \ '''flake8'' -', + \ '''flake8'' --format=default -', \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9']) Execute(The flake8 command callback should let you set options): let g:ale_python_flake8_options = '--some-option' AssertEqual - \ '''flake8'' --some-option --stdin-display-name %s -', + \ '''flake8'' --some-option --format=default --stdin-display-name %s -', \ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.4']) call ale_linters#python#flake8#ClearVersionCache() AssertEqual - \ '''flake8'' --some-option -', + \ '''flake8'' --some-option --format=default -', \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9']) Execute(You should be able to set a custom executable and it should be escaped): @@ -48,7 +48,7 @@ Execute(You should be able to set a custom executable and it should be escaped): \ '''executable with spaces'' --version', \ ale_linters#python#flake8#VersionCheck(bufnr('')) AssertEqual - \ '''executable with spaces'' --stdin-display-name %s -', + \ '''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): @@ -62,7 +62,7 @@ Execute(The flake8 callbacks should detect virtualenv directories): \ ale_linters#python#flake8#VersionCheck(bufnr('')) AssertEqual \ '''' . g:dir . '/python_paths/with_virtualenv/env/bin/flake8''' - \ . ' --stdin-display-name %s -', + \ . ' --format=default --stdin-display-name %s -', \ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.0']) Execute(The FindProjectRoot should detect the project root directory for namespace package via Manifest.in): @@ -114,7 +114,7 @@ Execute(Using `python -m flake8` should be supported for running flake8): \ '''python'' -m flake8 --version', \ ale_linters#python#flake8#VersionCheck(bufnr('')) AssertEqual - \ '''python'' -m flake8 --some-option -', + \ '''python'' -m flake8 --some-option --format=default -', \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9']) call ale_linters#python#flake8#ClearVersionCache() @@ -129,5 +129,5 @@ Execute(Using `python -m flake8` should be supported for running flake8): \ '''python'' -m flake8 --version', \ ale_linters#python#flake8#VersionCheck(bufnr('')) AssertEqual - \ '''python'' -m flake8 --some-option -', + \ '''python'' -m flake8 --some-option --format=default -', \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9']) diff --git a/test/command_callback/test_haskell_hdevtools_command_callbacks.vader b/test/command_callback/test_haskell_hdevtools_command_callbacks.vader new file mode 100644 index 00000000..c5320c5c --- /dev/null +++ b/test/command_callback/test_haskell_hdevtools_command_callbacks.vader @@ -0,0 +1,37 @@ +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 + + 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('')) + + 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('')) + + let b:ale_haskell_hdevtools_executable = 'foobar' + + AssertEqual + \ ale#Escape('foobar') . b:command_tail, + \ ale_linters#haskell#hdevtools#GetCommand(bufnr('')) diff --git a/test/command_callback/test_idris_command_callbacks.vader b/test/command_callback/test_idris_command_callbacks.vader new file mode 100644 index 00000000..03a69f39 --- /dev/null +++ b/test/command_callback/test_idris_command_callbacks.vader @@ -0,0 +1,42 @@ +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 + +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('')) + +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('')) + + let b:ale_idris_idris_executable = 'foobar' + + AssertEqual + \ ale#Escape('foobar') . ' --total --warnpartial --warnreach --warnipkg --check %s', + \ ale_linters#idris#idris#GetCommand(bufnr('')) + +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('')) diff --git a/test/command_callback/test_nagelfar_command_callbacks.vader b/test/command_callback/test_nagelfar_command_callbacks.vader new file mode 100644 index 00000000..5c6be7f1 --- /dev/null +++ b/test/command_callback/test_nagelfar_command_callbacks.vader @@ -0,0 +1,42 @@ +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 + +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('')) + + 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('')) + + let b:ale_tcl_nagelfar_executable = 'foobar' + + AssertEqual + \ ale#Escape('foobar') . ' %s', + \ ale_linters#tcl#nagelfar#GetCommand(bufnr('')) + +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('')) diff --git a/test/command_callback/test_php_langserver_callbacks.vader b/test/command_callback/test_php_langserver_callbacks.vader new file mode 100644 index 00000000..38630f4b --- /dev/null +++ b/test/command_callback/test_php_langserver_callbacks.vader @@ -0,0 +1,52 @@ +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') + +After: + Restore + + if isdirectory(g:dir . '/.git') + call delete(g:dir . '/.git', 'd') + endif + + call ale#test#RestoreDirectory() + call ale#linter#Reset() + +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('')) + +Execute(Vendor executables should be detected): + call ale#test#SetFilename('php-langserver-project/test.php') + + AssertEqual + \ g:dir . '/php-langserver-project/vendor/bin/php-language-server.php', + \ ale_linters#php#langserver#GetExecutable(bufnr('')) + AssertEqual + \ 'php ' . ale#Escape( + \ 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('')) diff --git a/test/command_callback/test_phpstan_command_callbacks.vader b/test/command_callback/test_phpstan_command_callbacks.vader new file mode 100644 index 00000000..7366df8b --- /dev/null +++ b/test/command_callback/test_phpstan_command_callbacks.vader @@ -0,0 +1,29 @@ +Before: + Save g:ale_php_phpstan_executable + Save g:ale_php_phpstan_level + + unlet! g:ale_php_phpstan_executable + unlet! g:ale_php_phpstan_level + + runtime ale_linters/php/phpstan.vim + +After: + Restore + + call ale#linter#Reset() + +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('')) + +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('')) diff --git a/test/command_callback/test_pycodestyle_command_callback.vader b/test/command_callback/test_pycodestyle_command_callback.vader new file mode 100644 index 00000000..a5163461 --- /dev/null +++ b/test/command_callback/test_pycodestyle_command_callback.vader @@ -0,0 +1,23 @@ +Before: + runtime ale_linters/python/pycodestyle.vim + Save g:ale_python_pycodestyle_executable, + \ g:ale_python_pycodestyle_options, + \ g:ale_python_pycodestyle_use_global + +After: + call ale#linter#Reset() + Restore + +Execute(The pycodestyle command callback should return default string): + AssertEqual '''pycodestyle'' -', + \ ale_linters#python#pycodestyle#GetCommand(bufnr('')) + +Execute(The pycodestyle command callback should allow options): + let g:ale_python_pycodestyle_options = '--exclude=test*.py' + AssertEqual '''pycodestyle'' --exclude=test*.py -', + \ ale_linters#python#pycodestyle#GetCommand(bufnr('')) + +Execute(The pycodestyle executable should be configurable): + let g:ale_python_pycodestyle_executable = '~/.local/bin/pycodestyle' + AssertEqual '''~/.local/bin/pycodestyle'' -', + \ ale_linters#python#pycodestyle#GetCommand(bufnr('')) diff --git a/test/command_callback/test_rust_rls_callbacks.vader b/test/command_callback/test_rust_rls_callbacks.vader new file mode 100644 index 00000000..76e69927 --- /dev/null +++ b/test/command_callback/test_rust_rls_callbacks.vader @@ -0,0 +1,32 @@ +Before: + Save g:ale_rust_rls_executable + + unlet! g:ale_rust_rls_executable + + runtime ale_linters/rust/rls.vim + + call ale#test#SetDirectory('/testplugin/test/command_callback') + +After: + Restore + + call ale#test#RestoreDirectory() + call ale#linter#Reset() + +Execute(The default executable path should be correct): + AssertEqual 'rls', ale_linters#rust#rls#GetExecutable(bufnr('')) + AssertEqual + \ ale#Escape('rls') . ' +nightly', + \ ale_linters#rust#rls#GetCommand(bufnr('')) + +Execute(The language string should be correct): + AssertEqual 'rust', ale_linters#rust#rls#GetLanguage(bufnr('')) + +Execute(The project root should be detected correctly): + AssertEqual '', ale_linters#rust#rls#GetProjectRoot(bufnr('')) + + call ale#test#SetFilename('rust-rls-project/test.rs') + + AssertEqual + \ g:dir . '/rust-rls-project', + \ ale_linters#rust#rls#GetProjectRoot(bufnr('')) diff --git a/test/command_callback/test_shellcheck_command_callback.vader b/test/command_callback/test_shellcheck_command_callback.vader new file mode 100644 index 00000000..0d8fef66 --- /dev/null +++ b/test/command_callback/test_shellcheck_command_callback.vader @@ -0,0 +1,47 @@ +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 + +After: + Restore + + unlet! b:ale_sh_shellcheck_exclusions + unlet! b:ale_sh_shellcheck_executable + unlet! b:ale_sh_shellcheck_options + unlet! b:is_bash + + call ale#linter#Reset() + +Execute(The default shellcheck command should be correct): + AssertEqual + \ 'shellcheck -f gcc -', + \ ale_linters#sh#shellcheck#GetCommand(bufnr('')) + +Execute(The shellcheck command should accept options): + let b:ale_sh_shellcheck_options = '--foobar' + + AssertEqual + \ 'shellcheck --foobar -f gcc -', + \ ale_linters#sh#shellcheck#GetCommand(bufnr('')) + +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 + \ 'shellcheck --foobar -e foo,bar -f gcc -', + \ ale_linters#sh#shellcheck#GetCommand(bufnr('')) + +Execute(The shellcheck command should include the dialect): + let b:is_bash = 1 + + AssertEqual + \ 'shellcheck -s bash -f gcc -', + \ ale_linters#sh#shellcheck#GetCommand(bufnr('')) diff --git a/test/command_callback/test_standard_command_callback.vader b/test/command_callback/test_standard_command_callback.vader new file mode 100644 index 00000000..fa90175b --- /dev/null +++ b/test/command_callback/test_standard_command_callback.vader @@ -0,0 +1,98 @@ +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#test#SetFilename('testfile.js') + + runtime ale_linters/javascript/standard.vim + +After: + Restore + + unlet! b:executable + + let g:ale_has_override = {} + + call ale#test#SetFilename('test.txt') + + call ale#test#RestoreDirectory() + call ale#linter#Reset() + +Execute(bin/cmd.js paths should be preferred): + call ale#test#SetFilename('standard-test-files/with-cmd/testfile.js') + + let b:executable = g:dir + \ . '/standard-test-files/with-cmd/node_modules/standard/bin/cmd.js' + + AssertEqual + \ b:executable, + \ ale_linters#javascript#standard#GetExecutable(bufnr('')) + + AssertEqual + \ ale#Escape(b:executable) . ' --stdin %s', + \ ale_linters#javascript#standard#GetCommand(bufnr('')) + +Execute(.bin directories should be used too): + call ale#test#SetFilename('standard-test-files/with-bin/testfile.js') + + let b:executable = g:dir + \ . '/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('')) + +Execute(.js files should be executed with node on Windows): + let g:ale_has_override['win32'] = 1 + + call ale#test#SetFilename('standard-test-files/with-cmd/testfile.js') + + let b:executable = g:dir + \ . '/standard-test-files/with-cmd/node_modules/standard/bin/cmd.js' + + AssertEqual + \ b:executable, + \ ale_linters#javascript#standard#GetExecutable(bufnr('')) + + AssertEqual + \ 'node ' . ale#Escape(b:executable) . ' --stdin %s', + \ ale_linters#javascript#standard#GetCommand(bufnr('')) + +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('')) + +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('')) + +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('')) diff --git a/test/command_callback/test_thrift_command_callback.vader b/test/command_callback/test_thrift_command_callback.vader new file mode 100644 index 00000000..43487f42 --- /dev/null +++ b/test/command_callback/test_thrift_command_callback.vader @@ -0,0 +1,61 @@ +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 + + function! GetCommand(buffer) abort + call ale#engine#InitBufferInfo(a:buffer) + let l:result = ale_linters#thrift#thrift#GetCommand(a:buffer) + call ale#engine#Cleanup(a:buffer) + return l:result + endfunction + + runtime ale_linters/thrift/thrift.vim + +After: + Restore + 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() + +Execute(The executable should be configurable): + AssertEqual 'thrift', ale_linters#thrift#thrift#GetExecutable(bufnr('')) + + let b:ale_thrift_thrift_executable = 'foobar' + AssertEqual 'foobar', ale_linters#thrift#thrift#GetExecutable(bufnr('')) + +Execute(The executable should be used in the command): + Assert GetCommand(bufnr('%')) =~# "^'thrift'" + + let b:ale_thrift_thrift_executable = 'foobar' + Assert GetCommand(bufnr('%')) =~# "^'foobar'" + +Execute(The list of generators should be configurable): + Assert GetCommand(bufnr('%')) =~# '--gen cpp' + + let b:ale_thrift_thrift_generators = ['java', 'py:dynamic'] + Assert GetCommand(bufnr('%')) =~# '--gen java --gen py:dynamic' + + let b:ale_thrift_thrift_generators = [] + Assert GetCommand(bufnr('%')) =~# '--gen cpp' + +Execute(The list of include paths should be configurable): + Assert GetCommand(bufnr('%')) !~# '-I' + + let b:ale_thrift_thrift_includes = ['included/path'] + Assert GetCommand(bufnr('%')) =~# '-I included/path' + +Execute(The string of compiler options should be configurable): + Assert GetCommand(bufnr('%')) =~# '-strict' + + let b:ale_thrift_thrift_options = '-strict --allow-64bit-consts' + Assert GetCommand(bufnr('%')) =~# '-strict --allow-64bit-consts' diff --git a/test/command_callback/test_tslint_command_callback.vader b/test/command_callback/test_tslint_command_callback.vader new file mode 100644 index 00000000..694d36d6 --- /dev/null +++ b/test/command_callback/test_tslint_command_callback.vader @@ -0,0 +1,24 @@ +Before: + Save g:typescript_tslint_executable + Save g:typescript_tslint_config_path + Save g:typescript_tslint_use_global + + unlet! g:typescript_tslint_executable + unlet! g:typescript_tslint_config_path + unlet! g:typescript_tslint_use_global + + runtime ale_linters/typescript/tslint.vim + + call ale#test#SetDirectory('/testplugin/test/command_callback') + +After: + Restore + + call ale#test#RestoreDirectory() + call ale#linter#Reset() + +Execute(The default tslint command should be correct): + AssertEqual + \ 'cd ''' . expand('%:p:h') . ''' && ' + \ . 'tslint --format json %t', + \ ale_linters#typescript#tslint#GetCommand(bufnr('')) diff --git a/test/eslint-test-files/react-app/node_modules/standard/bin/cmd.js b/test/eslint-test-files/react-app/node_modules/standard/bin/cmd.js new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/eslint-test-files/react-app/node_modules/standard/bin/cmd.js diff --git a/test/eslint-test-files/react-app/node_modules/stylelint/bin/stylelint.js b/test/eslint-test-files/react-app/node_modules/stylelint/bin/stylelint.js new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/eslint-test-files/react-app/node_modules/stylelint/bin/stylelint.js diff --git a/test/eslint-test-files/react-app/subdir/testfile.css b/test/eslint-test-files/react-app/subdir/testfile.css new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/eslint-test-files/react-app/subdir/testfile.css diff --git a/test/fixers/long-line-project/setup.cfg b/test/fixers/long-line-project/setup.cfg new file mode 100644 index 00000000..43d7a3a1 --- /dev/null +++ b/test/fixers/long-line-project/setup.cfg @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 90 diff --git a/test/fixers/test_break_up_long_lines_python_fixer.vader b/test/fixers/test_break_up_long_lines_python_fixer.vader new file mode 100644 index 00000000..5fd991f0 --- /dev/null +++ b/test/fixers/test_break_up_long_lines_python_fixer.vader @@ -0,0 +1,39 @@ +Before: + call ale#test#SetDirectory('/testplugin/test/fixers') + +After: + call ale#test#RestoreDirectory() + +Execute(Long lines with basic function calls should be broken up correctly): + AssertEqual + \ [ + \ 'def foo():', + \ ' some_variable = this_is_a_longer_function(', + \ 'first_argument,', + \ ' second_argument,', + \ ' third_with_function_call(', + \ 'foo,', + \ ' bar,', + \ '))', + \ ], + \ ale#fixers#generic_python#BreakUpLongLines(bufnr(''), [ + \ 'def foo():', + \ ' some_variable = this_is_a_longer_function(first_argument, second_argument, third_with_function_call(foo, bar))', + \ ]) + +Execute(Longer lines should be permitted if a configuration file allows it): + call ale#test#SetFilename('long-line-project/foo/bar.py') + + AssertEqual + \ [ + \ 'x = this_line_is_between_79_and_90_characters(first, second, third, fourth, fifth)', + \ 'y = this_line_is_longer_than_90_characters(', + \ 'much_longer_word,', + \ ' another_longer_word,', + \ ' a_third_long_word,', + \ ')' + \ ], + \ ale#fixers#generic_python#BreakUpLongLines(bufnr(''), [ + \ 'x = this_line_is_between_79_and_90_characters(first, second, third, fourth, fifth)', + \ 'y = this_line_is_longer_than_90_characters(much_longer_word, another_longer_word, a_third_long_word)', + \ ]) diff --git a/test/fixers/test_clangformat_fixer_callback.vader b/test/fixers/test_clangformat_fixer_callback.vader new file mode 100644 index 00000000..a55576bf --- /dev/null +++ b/test/fixers/test_clangformat_fixer_callback.vader @@ -0,0 +1,36 @@ +Before: + Save g:ale_c_clangformat_executable + + " Use an invalid global executable, so we don't match it. + let g:ale_c_clangformat_executable = 'xxxinvalid' + + call ale#test#SetDirectory('/testplugin/test/fixers') + silent cd .. + silent cd command_callback + let g:dir = getcwd() + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The clang-format callback should return the correct default values): + call ale#test#SetFilename('c_paths/dummy.c') + + AssertEqual + \ { + \ 'command': ale#Escape(g:ale_c_clangformat_executable) + \ . ' ' + \ }, + \ ale#fixers#clangformat#Fix(bufnr('')) + +Execute(The clangformat callback should include any additional options): + call ale#test#SetFilename('c_paths/dummy.c') + let g:ale_c_clangformat_options = '--some-option' + + AssertEqual + \ { + \ 'command': ale#Escape(g:ale_c_clangformat_executable) + \ . ' --some-option', + \ }, + \ ale#fixers#clangformat#Fix(bufnr('')) diff --git a/test/fixers/test_phpcbf_fixer_callback.vader b/test/fixers/test_phpcbf_fixer_callback.vader new file mode 100644 index 00000000..c2fe3a66 --- /dev/null +++ b/test/fixers/test_phpcbf_fixer_callback.vader @@ -0,0 +1,56 @@ +Before: + Save g:ale_php_phpcbf_executable + Save g:ale_php_phpcbf_standard + Save g:ale_php_phpcbf_use_global + + let g:ale_php_phpcbf_executable = 'phpcbf_test' + let g:ale_php_phpcbf_standard = '' + let g:ale_php_phpcbf_use_global = 0 + + 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 phpcbf should use local by default): + call ale#test#SetFilename('php_paths/project-with-phpcbf/foo/test.php') + + AssertEqual + \ g:dir . '/php_paths/project-with-phpcbf/vendor/bin/phpcbf', + \ ale#fixers#phpcbf#GetExecutable(bufnr('')) + +Execute(use-global should override local detection): + let g:ale_php_phpcbf_use_global = 1 + call ale#test#SetFilename('php_paths/project-with-phpcbf/foo/test.php') + + AssertEqual + \ 'phpcbf_test', + \ ale#fixers#phpcbf#GetExecutable(bufnr('')) + +Execute(project without phpcbf should use global): + call ale#test#SetFilename('php_paths/project-without-phpcbf/foo/test.php') + + AssertEqual + \ 'phpcbf_test', + \ ale#fixers#phpcbf#GetExecutable(bufnr('')) + +Execute(The phpcbf callback should return the correct default values): + call ale#test#SetFilename('php_paths/project-with-phpcbf/foo/test.php') + + AssertEqual + \ {'command': ale#Escape(g:dir . '/php_paths/project-with-phpcbf/vendor/bin/phpcbf') . ' --stdin-path=%s ' }, + \ ale#fixers#phpcbf#Fix(bufnr('')) + +Execute(The phpcbf callback should include the phpcbf_standard option): + let g:ale_php_phpcbf_standard = 'phpcbf_ruleset.xml' + call ale#test#SetFilename('php_paths/project-with-phpcbf/foo/test.php') + + AssertEqual + \ {'command': ale#Escape(g:dir . '/php_paths/project-with-phpcbf/vendor/bin/phpcbf') . ' --stdin-path=%s ' . '--standard=phpcbf_ruleset.xml'}, + \ ale#fixers#phpcbf#Fix(bufnr('')) + diff --git a/test/fixers/test_prettier_fixer_callback.vader b/test/fixers/test_prettier_fixer_callback.vader new file mode 100644 index 00000000..1eb24dae --- /dev/null +++ b/test/fixers/test_prettier_fixer_callback.vader @@ -0,0 +1,58 @@ +Before: + call ale#test#SetDirectory('/testplugin/test/fixers') + Save g:ale_javascript_prettier_executable + Save g:ale_javascript_prettier_options + + " Use an invalid global executable, so we don't match it. + let g:ale_javascript_prettier_executable = 'xxxinvalid' + let g:ale_javascript_prettier_options = '' + + call ale#test#SetDirectory('/testplugin/test/fixers') + silent cd .. + silent cd command_callback + let g:dir = getcwd() + +After: + let g:ale_has_override = {} + call ale#test#RestoreDirectory() + +Execute(The prettier callback should return the correct default values): + call ale#test#SetFilename('../prettier-test-files/testfile.js') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape(g:ale_javascript_prettier_executable) + \ . ' %t' + \ . ' --write', + \ }, + \ ale#fixers#prettier#Fix(bufnr('')) + +Execute(The prettier callback should include configuration files when the option is set): + let g:ale_javascript_prettier_use_local_config = 1 + call ale#test#SetFilename('../prettier-test-files/with_config/testfile.js') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape(g:ale_javascript_prettier_executable) + \ . ' %t' + \ . ' --config ' . ale#Escape(simplify(g:dir . '/../prettier-test-files/with_config/.prettierrc')) + \ . ' --write', + \ }, + \ ale#fixers#prettier#Fix(bufnr('')) + +Execute(The prettier callback should include custom prettier options): + let g:ale_javascript_prettier_options = '--no-semi' + call ale#test#SetFilename('../prettier-test-files/with_config/testfile.js') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape(g:ale_javascript_prettier_executable) + \ . ' %t' + \ . ' --no-semi' + \ . ' --config ' . ale#Escape(simplify(g:dir . '/../prettier-test-files/with_config/.prettierrc')) + \ . ' --write', + \ }, + \ ale#fixers#prettier#Fix(bufnr('')) diff --git a/test/fixers/test_rubocop_fixer_callback.vader b/test/fixers/test_rubocop_fixer_callback.vader index e3383537..87d56d07 100644 --- a/test/fixers/test_rubocop_fixer_callback.vader +++ b/test/fixers/test_rubocop_fixer_callback.vader @@ -1,8 +1,10 @@ Before: Save g:ale_ruby_rubocop_executable + Save g:ale_ruby_rubocop_options " Use an invalid global executable, so we don't match it. let g:ale_ruby_rubocop_executable = 'xxxinvalid' + let g:ale_ruby_rubocop_options = '' call ale#test#SetDirectory('/testplugin/test/fixers') silent cd .. @@ -36,3 +38,17 @@ Execute(The rubocop callback should include configuration files): \ . ' --auto-correct %t', \ }, \ ale#fixers#rubocop#Fix(bufnr('')) + +Execute(The rubocop callback should include custom rubocop options): + let g:ale_ruby_rubocop_options = '--except Lint/Debugger' + call ale#test#SetFilename('ruby_paths/with_config/dummy.rb') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape(g:ale_ruby_rubocop_executable) + \ . ' --config ' . ale#Escape(g:dir . '/ruby_paths/with_config/.rubocop.yml') + \ . ' --except Lint/Debugger' + \ . ' --auto-correct %t', + \ }, + \ ale#fixers#rubocop#Fix(bufnr('')) diff --git a/test/fixers/test_standard_fixer_callback.vader b/test/fixers/test_standard_fixer_callback.vader new file mode 100644 index 00000000..934b07b8 --- /dev/null +++ b/test/fixers/test_standard_fixer_callback.vader @@ -0,0 +1,32 @@ +Before: + call ale#test#SetDirectory('/testplugin/test/fixers') + +After: + let g:ale_has_override = {} + call ale#test#RestoreDirectory() + +Execute(The path to standard.js should be run on Unix): + call ale#test#SetFilename('../eslint-test-files/react-app/subdir/testfile.js') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': + \ ale#Escape(simplify(g:dir . '/../eslint-test-files/react-app/node_modules/standard/bin/cmd.js')) + \ . ' --fix %t', + \ }, + \ ale#fixers#standard#Fix(bufnr('')) + +Execute(The standard fixer with standard.js should be run with node on Windows): + call ale#test#SetFilename('../eslint-test-files/react-app/subdir/testfile.js') + let g:ale_has_override['win32'] = 1 + + " We have to execute the file with node. + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': 'node ' + \ . ale#Escape(simplify(g:dir . '/../eslint-test-files/react-app/node_modules/standard/bin/cmd.js')) + \ . ' --fix %t', + \ }, + \ ale#fixers#standard#Fix(bufnr('')) diff --git a/test/fixers/test_stylelint_fixer_callback.vader b/test/fixers/test_stylelint_fixer_callback.vader new file mode 100644 index 00000000..6c991969 --- /dev/null +++ b/test/fixers/test_stylelint_fixer_callback.vader @@ -0,0 +1,32 @@ +Before: + call ale#test#SetDirectory('/testplugin/test/fixers') + +After: + let g:ale_has_override = {} + call ale#test#RestoreDirectory() + +Execute(The path to stylelint.js should be run on Unix): + call ale#test#SetFilename('../eslint-test-files/react-app/subdir/testfile.css') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': + \ ale#Escape(simplify(g:dir . '/../eslint-test-files/react-app/node_modules/stylelint/bin/stylelint.js')) + \ . ' --fix %t', + \ }, + \ ale#fixers#stylelint#Fix(bufnr('')) + +Execute(The stylelint fixer with stylelint.js should be run with node on Windows): + call ale#test#SetFilename('../eslint-test-files/react-app/subdir/testfile.css') + let g:ale_has_override['win32'] = 1 + + " We have to execute the file with node. + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': 'node ' + \ . ale#Escape(simplify(g:dir . '/../eslint-test-files/react-app/node_modules/stylelint/bin/stylelint.js')) + \ . ' --fix %t', + \ }, + \ ale#fixers#stylelint#Fix(bufnr('')) diff --git a/test/fixers/test_swiftformat_fixer_callback.vader b/test/fixers/test_swiftformat_fixer_callback.vader new file mode 100644 index 00000000..e3674ded --- /dev/null +++ b/test/fixers/test_swiftformat_fixer_callback.vader @@ -0,0 +1,38 @@ +Before: + Save g:ale_swift_swiftformat_executable + + " Use an invalid global executable, so we don't match it. + let g:ale_swift_swiftformat_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 swiftformat callback should return the correct default values): + call ale#test#SetFilename('swift_paths/dummy.swift') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape(g:ale_swift_swiftformat_executable) + \ . ' %t ', + \ }, + \ ale#fixers#swiftformat#Fix(bufnr('')) + +Execute(The swiftformat callback should include any additional options): + call ale#test#SetFilename('swift_paths/dummy.swift') + let g:ale_swift_swiftformat_options = '--some-option' + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape(g:ale_swift_swiftformat_executable) + \ . ' %t --some-option', + \ }, + \ ale#fixers#swiftformat#Fix(bufnr('')) diff --git a/test/handler/test_brakeman_handler.vader b/test/handler/test_brakeman_handler.vader index 240a0990..02d70234 100644 --- a/test/handler/test_brakeman_handler.vader +++ b/test/handler/test_brakeman_handler.vader @@ -1,20 +1,15 @@ Before: - " Switch to the test rails directory. - let b:path = getcwd() - silent! cd /testplugin/test/handler - cd ../ruby_fixtures/valid_rails_app/app/models + call ale#test#SetDirectory('/testplugin/test/handler') + cd .. - runtime ale_linters/ruby/brakeman.vim + runtime ale_linters/ruby/brakeman.vim After: - " Switch back to whatever directory it was that we started on. - silent! 'cd ' . fnameescape(b:path) - unlet! b:path - - call ale#linter#Reset() + call ale#test#RestoreDirectory() + call ale#linter#Reset() Execute(The brakeman handler should parse JSON correctly): - silent file! thing.rb + call ale#test#SetFilename('ruby_fixtures/valid_rails_app/app/models/thing.rb') AssertEqual \ [ @@ -78,3 +73,10 @@ Execute(The brakeman handler should parse JSON correctly when there is no output \ [], \ ale_linters#ruby#brakeman#Handle(347, [ \ ]) + \ +Execute(The brakeman handler should handle garbage output): + AssertEqual + \ [], + \ ale_linters#ruby#brakeman#Handle(347, [ + \ 'No such command in 2.4.1 of ruby', + \ ]) diff --git a/test/handler/test_crystal_handler.vader b/test/handler/test_crystal_handler.vader index bdc44644..984b976f 100644 --- a/test/handler/test_crystal_handler.vader +++ b/test/handler/test_crystal_handler.vader @@ -4,9 +4,7 @@ Execute(The crystal handler should parse lines correctly and add the column if i \ [ \ { \ 'lnum': 2, - \ 'bufnr': 255, \ 'col': 1, - \ 'type': 'E', \ 'text': 'unexpected token: EOF' \ } \ ], diff --git a/test/handler/test_embertemplatelint_handler.vader b/test/handler/test_embertemplatelint_handler.vader index cc3e8bb9..8e132d36 100644 --- a/test/handler/test_embertemplatelint_handler.vader +++ b/test/handler/test_embertemplatelint_handler.vader @@ -75,9 +75,11 @@ Execute(The ember-template-lint handler should handle template parsing error cor Execute(The ember-template-lint handler should handle no lint errors/warnings): AssertEqual - \ [ - \ ], + \ [], \ ale_linters#handlebars#embertemplatelint#Handle(347, []) + AssertEqual + \ [], + \ ale_linters#handlebars#embertemplatelint#Handle(347, ['{}']) After: call ale#linter#Reset() diff --git a/test/handler/test_eslint_handler.vader b/test/handler/test_eslint_handler.vader index 7ac26c72..943e177f 100644 --- a/test/handler/test_eslint_handler.vader +++ b/test/handler/test_eslint_handler.vader @@ -1,4 +1,11 @@ +Before: + Save g:ale_javascript_eslint_suppress_eslintignore + + let g:ale_javascript_eslint_suppress_eslintignore = 0 + After: + Restore + unlet! g:config_error_lines Execute(The eslint handler should parse lines correctly): @@ -206,3 +213,24 @@ Execute(The eslint hint about using typescript-eslint-parser): \ ale#handlers#eslint#Handle(bufnr(''), [ \ 'foo.ts:451:2: Parsing error: Unexpected token ) [Error]', \ ]) + +Execute(eslint should warn about ignored files by default): + AssertEqual + \ [{ + \ 'lnum': 0, + \ 'col': 0, + \ 'type': 'W', + \ 'text': 'File ignored because of a matching ignore pattern. Use "--no-ignore" to override. [Warning]' + \ }], + \ ale#handlers#eslint#Handle(347, [ + \ '/path/to/some/ignored.js:0:0: File ignored because of a matching ignore pattern. Use "--no-ignore" to override. [Warning]', + \ ]) + +Execute(eslint should not warn about ignored files when explicitly disabled): + let g:ale_javascript_eslint_suppress_eslintignore = 1 + + AssertEqual + \ [], + \ ale#handlers#eslint#Handle(347, [ + \ '/path/to/some/ignored.js:0:0: File ignored because of a matching ignore pattern. Use "--no-ignore" to override. [Warning]', + \ ]) diff --git a/test/handler/test_flow_handler.vader b/test/handler/test_flow_handler.vader index 46b52229..288610b0 100644 --- a/test/handler/test_flow_handler.vader +++ b/test/handler/test_flow_handler.vader @@ -7,6 +7,22 @@ After: unlet! g:actual call ale#linter#Reset() +Execute(The flow handler should throw away non-JSON lines): + AssertEqual + \ [], + \ ale_linters#javascript#flow#Handle(bufnr(''), [ + \ 'Already up-to-date.', + \ '{"flowVersion":"0.50.0","errors":[],"passed":true}', + \ ]) + AssertEqual + \ [], + \ ale_linters#javascript#flow#Handle(bufnr(''), [ + \ 'foo', + \ 'bar', + \ 'baz', + \ '{"flowVersion":"0.50.0","errors":[],"passed":true}', + \ ]) + Execute(The flow handler should process errors correctly.): silent! noautocmd file /home/w0rp/Downloads/graphql-js/src/language/parser.js diff --git a/test/handler/test_gcc_handler.vader b/test/handler/test_gcc_handler.vader index 72b7c541..2f60390c 100644 --- a/test/handler/test_gcc_handler.vader +++ b/test/handler/test_gcc_handler.vader @@ -94,3 +94,42 @@ Execute(The GCC handler shouldn't complain about #pragma once for headers): \ ale#handlers#gcc#HandleGCCFormat(347, [ \ '<stdin>:1:1: warning: #pragma once in main file [enabled by default]', \ ]) + +Execute(The GCC handler should handle syntax errors): + AssertEqual + \ [ + \ { + \ 'lnum': 6, + \ 'col': 12, + \ 'type': 'E', + \ 'text': 'invalid suffix "p" on integer constant' + \ }, + \ { + \ 'lnum': 17, + \ 'col': 5, + \ 'type': 'E', + \ 'text': 'invalid suffix "n" on integer constant' + \ }, + \ { + \ 'lnum': 4, + \ 'type': 'E', + \ 'text': 'variable or field ''foo'' declared void' + \ }, + \ { + \ 'lnum': 4, + \ 'type': 'E', + \ 'text': '''cat'' was not declared in this scope' + \ }, + \ { + \ 'lnum': 12, + \ 'type': 'E', + \ 'text': 'expected '';'' before ''o''' + \ }, + \ ], + \ ale#handlers#gcc#HandleGCCFormat(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', + \ '<stdin>:4: error: ''cat'' was not declared in this scope', + \ '<stdin>:12: error: expected `;'' before ''o''', + \ ]) diff --git a/test/handler/test_idris_handler.vader b/test/handler/test_idris_handler.vader new file mode 100644 index 00000000..1c20be7b --- /dev/null +++ b/test/handler/test_idris_handler.vader @@ -0,0 +1,52 @@ +Before: + runtime ale_linters/idris/idris.vim + +Execute(The idris handler should parse messages that reference a single column): + call ale#test#SetFilename('/tmp/foo.idr') + + AssertEqual + \ [ + \ { + \ 'lnum': 4, + \ 'col': 5, + \ 'type': 'E', + \ 'text': 'When checking right hand side of main with expected type IO () When checking an application of function Prelude.Monad.>>=: Type mismatch between IO () (Type of putStrLn _) and _ -> _ (Is putStrLn _ applied to too many arguments?) Specifically: Type mismatch between IO and \uv => _ -> uv' + \ } + \ ], + \ ale_linters#idris#idris#Handle(bufnr(''), [ + \ '/tmp/foo.idr:4:5:', + \ 'When checking right hand side of main with expected type', + \ ' IO ()', + \ '', + \ 'When checking an application of function Prelude.Monad.>>=:', + \ ' Type mismatch between', + \ ' IO () (Type of putStrLn _)', + \ ' and', + \ ' _ -> _ (Is putStrLn _ applied to too many arguments?)', + \ '', + \ ' Specifically:', + \ ' Type mismatch between', + \ ' IO', + \ ' and', + \ ' \uv => _ -> uv', + \ ]) + +Execute(The idris handler should parse messages that reference a column range): + call ale#test#SetFilename('/tmp/foo.idr') + + AssertEqual + \ [ + \ { + \ 'lnum': 11, + \ 'col': 11, + \ 'type': 'E', + \ 'text': 'When checking right hand side of Main.case block in main at /tmp/foo.idr:10:10 with expected type IO () Last statement in do block must be an expression' + \ } + \ ], + \ ale_linters#idris#idris#Handle(bufnr(''), [ + \ '/tmp/foo.idr:11:11-13:', + \ 'When checking right hand side of Main.case block in main at /tmp/foo.idr:10:10 with expected type', + \ ' IO ()', + \ '', + \ 'Last statement in do block must be an expression', + \ ]) diff --git a/test/handler/test_mypy_handler.vader b/test/handler/test_mypy_handler.vader index c949b1aa..d0cf91e2 100644 --- a/test/handler/test_mypy_handler.vader +++ b/test/handler/test_mypy_handler.vader @@ -11,16 +11,39 @@ Execute(The mypy handler should parse lines correctly): AssertEqual \ [ \ { + \ 'lnum': 768, + \ 'col': 38, + \ 'filename': 'foo/bar/foo/bar/baz.py', + \ 'type': 'E', + \ 'text': 'Cannot determine type of ''SOME_SYMBOL''', + \ }, + \ { + \ 'lnum': 821, + \ 'col': 38, + \ 'filename': 'foo/bar/foo/bar/baz.py', + \ 'type': 'E', + \ 'text': 'Cannot determine type of ''SOME_SYMBOL''', + \ }, + \ { + \ 'lnum': 38, + \ 'col': 44, + \ 'filename': 'foo/bar/foo/bar/other.py', + \ 'type': 'E', + \ 'text': 'Cannot determine type of ''ANOTHER_SYMBOL''', + \ }, + \ { \ 'lnum': 15, \ 'col': 3, - \ 'text': 'Argument 1 to "somefunc" has incompatible type "int"; expected "str"', + \ 'filename': 'foo/bar/foo/bar/__init__.py', \ 'type': 'E', + \ 'text': 'Argument 1 to "somefunc" has incompatible type "int"; expected "str"' \ }, \ { \ 'lnum': 72, \ 'col': 1, - \ 'text': 'Some warning', + \ 'filename': 'foo/bar/foo/bar/__init__.py', \ 'type': 'W', + \ 'text': 'Some warning', \ }, \ ], \ ale_linters#python#mypy#Handle(bufnr(''), [ @@ -47,8 +70,9 @@ Execute(The mypy handler should handle Windows names with spaces): \ { \ 'lnum': 4, \ 'col': 0, - \ 'text': "No library stub file for module 'django.db'", + \ 'filename': 'C:\something\with spaces.py', \ 'type': 'E', + \ 'text': 'No library stub file for module ''django.db''', \ }, \ ], \ ale_linters#python#mypy#Handle(bufnr(''), [ diff --git a/test/handler/test_nagelfar_handler.vader b/test/handler/test_nagelfar_handler.vader new file mode 100644 index 00000000..2a31f19e --- /dev/null +++ b/test/handler/test_nagelfar_handler.vader @@ -0,0 +1,171 @@ +Before: + runtime ale_linters/tcl/nagelfar.vim + +Execute(The nagelfar handler should parse lines correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 5, + \ 'type': 'W', + \ 'text': 'Found constant "bepa" which is also a variable.' + \ }, + \ { + \ 'lnum': 7, + \ 'type': 'E', + \ 'text': 'Unknown variable "cep"' + \ }, + \ { + \ 'lnum': 7, + \ 'type': 'W', + \ 'text': 'Unknown command "se"' + \ }, + \ { + \ 'lnum': 8, + \ 'type': 'E', + \ 'text': 'Unknown variable "epa"' + \ }, + \ { + \ 'lnum': 10, + \ 'type': 'E', + \ 'text': 'Unknown variable "depa"' + \ }, + \ { + \ 'lnum': 10, + \ 'type': 'W', + \ 'text': 'Suspicious variable name "$depa"' + \ }, + \ { + \ 'lnum': 11, + \ 'type': 'W', + \ 'text': 'Suspicious variable name "$cepa"' + \ }, + \ { + \ 'lnum': 13, + \ 'type': 'E', + \ 'text': 'Wrong number of arguments (3) to "set"' + \ }, + \ { + \ 'lnum': 13, + \ 'type': 'W', + \ 'text': 'Found constant "bepa" which is also a variable.' + \ }, + \ { + \ 'lnum': 13, + \ 'type': 'W', + \ 'text': 'Found constant "cepa" which is also a variable.' + \ }, + \ { + \ 'lnum': 18, + \ 'type': 'E', + \ 'text': 'Badly formed if statement' + \ }, + \ { + \ 'lnum': 24, + \ 'type': 'E', + \ 'text': 'Unknown subcommand "gurka" to "info"' + \ }, + \ { + \ 'lnum': 31, + \ 'type': 'W', + \ 'text': 'Switch pattern starting with #. This could be a bad comment.' + \ }, + \ { + \ 'lnum': 31, + \ 'type': 'W', + \ 'text': 'Unknown command "This"' + \ }, + \ { + \ 'lnum': 31, + \ 'type': 'W', + \ 'text': 'Unknown command "bad"' + \ }, + \ { + \ 'lnum': 34, + \ 'type': 'W', + \ 'text': 'Unknown command "miffo"' + \ }, + \ { + \ 'lnum': 55, + \ 'type': 'W', + \ 'text': 'Suspicious variable name "$bepa"' + \ }, + \ { + \ 'lnum': 56, + \ 'type': 'W', + \ 'text': 'Suspicious variable name "$apa"' + \ }, + \ { + \ 'lnum': 61, + \ 'type': 'E', + \ 'text': 'Could not complete statement.' + \ }, + \ { + \ 'lnum': 67, + \ 'type': 'E', + \ 'text': 'Could not complete statement.' + \ }, + \ { + \ 'lnum': 70, + \ 'type': 'E', + \ 'text': 'Wrong number of arguments (4) to "proc"' + \ }, + \ { + \ 'lnum': 72, + \ 'type': 'E', + \ 'text': 'Wrong number of arguments (1) to "if"' + \ }, + \ { + \ 'lnum': 75, + \ 'type': 'E', + \ 'text': 'Unbalanced close brace found' + \ }, + \ { + \ 'lnum': 82, + \ 'type': 'E', + \ 'text': 'Unbalanced close brace found' + \ }, + \ { + \ 'lnum': 88, + \ 'type': 'E', + \ 'text': 'Could not complete statement.' + \ }, + \ { + \ 'lnum': 90, + \ 'type': 'E', + \ 'text': 'Wrong number of arguments (1) to "if"' + \ }, + \ { + \ 'lnum': 93, + \ 'type': 'W', + \ 'text': 'Close brace not aligned with line 90 (4 0)' + \ }, + \ ], + \ ale_linters#tcl#nagelfar#Handle(bufnr(''), [ + \ 'Line 5: W Found constant "bepa" which is also a variable.', + \ 'Line 7: E Unknown variable "cep"', + \ 'Line 7: W Unknown command "se"', + \ 'Line 8: E Unknown variable "epa"', + \ 'Line 10: E Unknown variable "depa"', + \ 'Line 10: N Suspicious variable name "$depa"', + \ 'Line 11: N Suspicious variable name "$cepa"', + \ 'Line 13: E Wrong number of arguments (3) to "set"', + \ 'Line 13: W Found constant "bepa" which is also a variable.', + \ 'Line 13: W Found constant "cepa" which is also a variable.', + \ 'Line 18: E Badly formed if statement', + \ 'Line 24: E Unknown subcommand "gurka" to "info"', + \ 'Line 31: W Switch pattern starting with #. This could be a bad comment.', + \ 'Line 31: W Unknown command "This"', + \ 'Line 31: W Unknown command "bad"', + \ 'Line 34: W Unknown command "miffo"', + \ 'Line 55: N Suspicious variable name "$bepa"', + \ 'Line 56: N Suspicious variable name "$apa"', + \ 'Line 61: E Could not complete statement.', + \ 'Line 67: E Could not complete statement.', + \ 'Line 70: E Wrong number of arguments (4) to "proc"', + \ 'Line 72: E Wrong number of arguments (1) to "if"', + \ 'Line 75: E Unbalanced close brace found', + \ 'Line 82: E Unbalanced close brace found', + \ 'Line 88: E Could not complete statement.', + \ 'Line 90: E Wrong number of arguments (1) to "if"', + \ 'Line 93: N Close brace not aligned with line 90 (4 0)', + \ ]) diff --git a/test/test_phpstan_executable_detection.vader b/test/handler/test_phpstan_handler.vader index 24ba8cd8..207a7758 100644 --- a/test/test_phpstan_executable_detection.vader +++ b/test/handler/test_phpstan_handler.vader @@ -1,9 +1,4 @@ Before: - Save g:ale_php_phpstan_executable - Save g:ale_php_phpstan_level - - let g:ale_php_phpstan_executable = 'phpstan_test' - call ale#test#SetDirectory('/testplugin/test') runtime ale_linters/php/phpstan.vim @@ -14,45 +9,14 @@ After: call ale#test#RestoreDirectory() call ale#linter#Reset() -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 - \ 'phpstan_test analyze -l3 --errorFormat raw %s', - \ ale_linters#php#phpstan#GetCommand(bufnr('')) - -Execute(project with default level): - call ale#test#SetFilename('phpstan-test-files/foo/test.php') - - AssertEqual - \ 'phpstan_test analyze -l4 --errorFormat raw %s', - \ ale_linters#php#phpstan#GetCommand(bufnr('')) - -Execute(parse output without errors): +Execute(Output without errors should be parsed correctly): call ale#test#SetFilename('phpstan-test-files/foo/test.php') AssertEqual \ [], \ ale_linters#php#phpstan#Handle(bufnr(''), [" 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%"]) -Execute(parse output with one error): - call ale#test#SetFilename('phpstan-test-files/foo/test.php') - - AssertEqual - \ [ - \ { - \ 'lnum': 9, - \ 'text': 'Access to an undefined property Test::$var.', - \ 'type': 'W' - \ } - \ ], - \ ale_linters#php#phpstan#Handle(bufnr(''), [ - \ ' 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%', - \ 'phpstan-test-files/foo/test.php:9:Access to an undefined property Test::$var.', - \]) - -Execute(parse output with three errors): +Execute(Output with some errors should be parsed correctly): call ale#test#SetFilename('phpstan-test-files/foo/test.php') AssertEqual @@ -80,7 +44,7 @@ Execute(parse output with three errors): \ 'phpstan-test-files/foo/test.php:192:Invalid command testCommand.', \]) -Execute(parse output for windows filesystem): +Execute(Output should be parsed correctly with Windows paths): call ale#test#SetFilename('phpstan-test-files/foo/test.php') AssertEqual @@ -96,7 +60,7 @@ Execute(parse output for windows filesystem): \ 'D:\phpstan-test-files\foo\test.php:9:Access to an undefined property Test::$var.', \]) -Execute(parse output for not php file): +Execute(Output for .inc files should be parsed correctly): call ale#test#SetFilename('phpstan-test-files/test.inc') AssertEqual diff --git a/test/handler/test_pycodestyle_handler.vader b/test/handler/test_pycodestyle_handler.vader new file mode 100644 index 00000000..cc83fc83 --- /dev/null +++ b/test/handler/test_pycodestyle_handler.vader @@ -0,0 +1,48 @@ +Before: + runtime ale_linters/python/pycodestyle.vim + +After: + call ale#linter#Reset() + silent file something_else.py + +Execute(The pycodestyle handler should parse output): + AssertEqual + \ [ + \ { + \ 'lnum': 69, + \ 'col': 11, + \ 'text': 'E401 multiple imports on one line', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 77, + \ 'col': 1, + \ 'text': 'E302 expected 2 blank lines, found 1', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 88, + \ 'col': 5, + \ 'text': 'E301 expected 1 blank line, found 0', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 222, + \ 'col': 34, + \ 'text': 'W602 deprecated form of raising exception', + \ 'type': 'W', + \ }, + \ { + \ 'lnum': 544, + \ 'col': 21, + \ 'text': 'W601 .has_key() is deprecated, use ''in''', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#python#pycodestyle#Handle(bufnr(''), [ + \ 'stdin:69:11: E401 multiple imports on one line', + \ 'stdin:77:1: E302 expected 2 blank lines, found 1', + \ 'stdin:88:5: E301 expected 1 blank line, found 0', + \ 'stdin:222:34: W602 deprecated form of raising exception', + \ 'example.py:544:21: W601 .has_key() is deprecated, use ''in''', + \ ]) diff --git a/test/handler/test_rails_best_practices_handler.vader b/test/handler/test_rails_best_practices_handler.vader index 037d2527..11875cbd 100644 --- a/test/handler/test_rails_best_practices_handler.vader +++ b/test/handler/test_rails_best_practices_handler.vader @@ -1,20 +1,15 @@ Before: - " Switch to the test rails directory. - let b:path = getcwd() - silent! cd /testplugin/test/handler - cd ../ruby_fixtures/valid_rails_app/app/models + call ale#test#SetDirectory('/testplugin/test/handler') + cd .. - runtime ale_linters/ruby/rails_best_practices.vim + runtime ale_linters/ruby/rails_best_practices.vim After: - " Switch back to whatever directory it was that we started on. - silent! 'cd ' . fnameescape(b:path) - unlet! b:path - - call ale#linter#Reset() + call ale#test#RestoreDirectory() + call ale#linter#Reset() Execute(The rails_best_practices handler should parse JSON correctly): - silent file! thing.rb + call ale#test#SetFilename('ruby_fixtures/valid_rails_app/app/models/thing.rb') AssertEqual \ [ @@ -34,11 +29,11 @@ Execute(The rails_best_practices handler should parse JSON correctly): \ '{', \ '"message": "use local variable",', \ '"line_number": "5",', - \ '"filename": "/testplugin/test/ruby_fixtures/valid_rails_app/app/models/thing.rb"', + \ '"filename": "' . g:dir . '/ruby_fixtures/valid_rails_app/app/models/thing.rb"', \ '},{', \ '"message": "other advice",', \ '"line_number": "10",', - \ '"filename": "/testplugin/test/ruby_fixtures/valid_rails_app/app/models/thing.rb"', + \ '"filename": "' . g:dir . '/ruby_fixtures/valid_rails_app/app/models/thing.rb"', \ '}', \ ']' \ ]) @@ -48,3 +43,10 @@ Execute(The rails_best_practices handler should parse JSON correctly when there \ [], \ ale_linters#ruby#rails_best_practices#Handle(347, [ \ ]) + +Execute(The rails_best_practices handler should handle garbage output): + AssertEqual + \ [], + \ ale_linters#ruby#rails_best_practices#Handle(347, [ + \ 'No such command in 2.4.1 of ruby', + \ ]) diff --git a/test/handler/test_reek_handler.vader b/test/handler/test_reek_handler.vader index 67ba6f60..6861428c 100644 --- a/test/handler/test_reek_handler.vader +++ b/test/handler/test_reek_handler.vader @@ -2,68 +2,75 @@ Before: runtime ale_linters/ruby/reek.vim After: - call ale#linter#Reset() + call ale#linter#Reset() Execute(The reek handler should parse JSON correctly, with only context enabled): - let g:ale_ruby_reek_show_context = 1 - let g:ale_ruby_reek_show_wiki_link = 0 + let g:ale_ruby_reek_show_context = 1 + let g:ale_ruby_reek_show_wiki_link = 0 - AssertEqual - \ [ - \ { - \ 'lnum': 12, - \ 'text': 'Rule1: Context#method violates rule number one', - \ 'type': 'W', - \ }, - \ { - \ 'lnum': 34, - \ 'text': 'Rule2: Context#method violates rule number two', - \ 'type': 'W', - \ }, - \ { - \ 'lnum': 56, - \ 'text': 'Rule2: Context#method violates rule number two', - \ 'type': 'W', - \ }, - \ ], - \ ale_linters#ruby#reek#Handle(347, [ - \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"},{"context":"Context#method","lines":[34, 56],"message":"violates rule number two","smell_type":"Rule2","source":"/home/user/file.rb","name":"bad code","count":2,"wiki_link":"https://example.com/Rule1.md"}]' - \ ]) + AssertEqual + \ [ + \ { + \ 'lnum': 12, + \ 'text': 'Rule1: Context#method violates rule number one', + \ 'type': 'W', + \ }, + \ { + \ 'lnum': 34, + \ 'text': 'Rule2: Context#method violates rule number two', + \ 'type': 'W', + \ }, + \ { + \ 'lnum': 56, + \ 'text': 'Rule2: Context#method violates rule number two', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#ruby#reek#Handle(347, [ + \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"},{"context":"Context#method","lines":[34, 56],"message":"violates rule number two","smell_type":"Rule2","source":"/home/user/file.rb","name":"bad code","count":2,"wiki_link":"https://example.com/Rule1.md"}]' + \ ]) Execute(The reek handler should parse JSON correctly, with no context or wiki links): - let g:ale_ruby_reek_show_context = 0 - let g:ale_ruby_reek_show_wiki_link = 0 + let g:ale_ruby_reek_show_context = 0 + let g:ale_ruby_reek_show_wiki_link = 0 - AssertEqual - \ [ - \ { - \ 'lnum': 12, - \ 'text': 'Rule1: violates rule number one', - \ 'type': 'W', - \ }, - \ ], - \ ale_linters#ruby#reek#Handle(347, [ - \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"}]' - \ ]) + AssertEqual + \ [ + \ { + \ 'lnum': 12, + \ 'text': 'Rule1: violates rule number one', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#ruby#reek#Handle(347, [ + \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"}]' + \ ]) Execute(The reek handler should parse JSON correctly, with both context and wiki links): - let g:ale_ruby_reek_show_context = 1 - let g:ale_ruby_reek_show_wiki_link = 1 + let g:ale_ruby_reek_show_context = 1 + let g:ale_ruby_reek_show_wiki_link = 1 - AssertEqual - \ [ - \ { - \ 'lnum': 12, - \ 'text': 'Rule1: Context#method violates rule number one [https://example.com/Rule1.md]', - \ 'type': 'W', - \ }, - \ ], - \ ale_linters#ruby#reek#Handle(347, [ - \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"}]' - \ ]) + AssertEqual + \ [ + \ { + \ 'lnum': 12, + \ 'text': 'Rule1: Context#method violates rule number one [https://example.com/Rule1.md]', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#ruby#reek#Handle(347, [ + \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"}]' + \ ]) Execute(The reek handler should parse JSON correctly when there is no output from reek): - AssertEqual - \ [], - \ ale_linters#ruby#reek#Handle(347, [ - \ ]) + AssertEqual + \ [], + \ ale_linters#ruby#reek#Handle(347, [ + \ ]) + +Execute(The reek handler should handle garbage output): + AssertEqual + \ [], + \ ale_linters#ruby#reek#Handle(347, [ + \ 'No such command in 2.4.1 of ruby', + \ ]) diff --git a/test/handler/test_rubocop_handler.vader b/test/handler/test_rubocop_handler.vader index fffee7bb..4d3bbe29 100644 --- a/test/handler/test_rubocop_handler.vader +++ b/test/handler/test_rubocop_handler.vader @@ -12,28 +12,28 @@ Execute(The rubocop handler should parse lines correctly): \ 'lnum': 83, \ 'col': 29, \ 'end_col': 35, - \ 'text': 'Prefer single-quoted strings...', + \ 'text': 'Prefer single-quoted strings... [Style/SomeCop]', \ 'type': 'W', \ }, \ { \ 'lnum': 12, \ 'col': 2, \ 'end_col': 2, - \ 'text': 'Some error', + \ 'text': 'Some error [Style/SomeOtherCop]', \ 'type': 'E', \ }, \ { \ 'lnum': 10, \ 'col': 5, \ 'end_col': 12, - \ 'text': 'Regular warning', + \ 'text': 'Regular warning [Style/WarningCop]', \ 'type': 'W', \ }, \ { \ 'lnum': 11, \ 'col': 1, \ 'end_col': 1, - \ 'text': 'Another error', + \ 'text': 'Another error [Style/SpaceBeforeBlockBraces]', \ 'type': 'E', \ }, \ ], diff --git a/test/handler/test_scalac_handler.vader b/test/handler/test_scalac_handler.vader new file mode 100644 index 00000000..a4c7363a --- /dev/null +++ b/test/handler/test_scalac_handler.vader @@ -0,0 +1,18 @@ +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_syntaxerl_handler.vader b/test/handler/test_syntaxerl_handler.vader index 1308ec84..95f2bfef 100644 --- a/test/handler/test_syntaxerl_handler.vader +++ b/test/handler/test_syntaxerl_handler.vader @@ -4,7 +4,7 @@ Before: After: call ale#linter#Reset() -Execute: +Execute (Handle SyntaxErl output): AssertEqual \ [ \ { @@ -18,7 +18,7 @@ Execute: \ 'type': 'W', \ }, \ ], - \ ale_linters#erlang#syntaxerl#Handle(42, [ + \ ale_linters#erlang#syntaxerl#Handle(bufnr(''), [ \ "/tmp/v2wDixk/1/module.erl:42: syntax error before: ','", \ '/tmp/v2wDixk/2/module.erl:42: warning: function foo/0 is unused', \ ]) diff --git a/test/handler/test_thrift_handler.vader b/test/handler/test_thrift_handler.vader new file mode 100644 index 00000000..9bdb9378 --- /dev/null +++ b/test/handler/test_thrift_handler.vader @@ -0,0 +1,63 @@ +Before: + runtime ale_linters/thrift/thrift.vim + +After: + call ale#linter#Reset() + +Execute(The thrift handler should handle basic warnings and errors): + AssertEqual + \ [ + \ { + \ 'lnum': 17, + \ 'col': 0, + \ 'type': 'W', + \ 'text': 'The "byte" type is a compatibility alias for "i8". Use i8" to emphasize the signedness of this type.', + \ }, + \ { + \ 'lnum': 20, + \ 'col': 0, + \ 'type': 'W', + \ 'text': 'Could not find include file include.thrift', + \ }, + \ { + \ 'lnum': 83, + \ 'col': 0, + \ 'type': 'E', + \ 'text': 'Enum FOO is already defined!', + \ }, + \ ], + \ ale_linters#thrift#thrift#Handle(1, [ + \ '[WARNING:/path/filename.thrift:17] The "byte" type is a compatibility alias for "i8". Use i8" to emphasize the signedness of this type.', + \ '[WARNING:/path/filename.thrift:20] Could not find include file include.thrift', + \ '[FAILURE:/path/filename.thrift:83] Enum FOO is already defined!', + \ ]) + +Execute(The thrift handler should handle multiline errors): + AssertEqual + \ [ + \ { + \ 'lnum': 75, + \ 'col': 0, + \ 'type': 'E', + \ 'text': 'This integer is too big: "11111111114213213453243"', + \ }, + \ { + \ 'lnum': 76, + \ 'col': 0, + \ 'type': 'E', + \ 'text': 'Implicit field keys are deprecated and not allowed with -strict', + \ }, + \ { + \ 'lnum': 77, + \ 'col': 0, + \ 'type': 'E', + \ 'text': "Unknown error (last token was ';')", + \ }, + \ ], + \ ale_linters#thrift#thrift#Handle(1, [ + \ "[ERROR:/path/filename.thrift:75] (last token was '11111111114213213453243')", + \ 'This integer is too big: "11111111114213213453243"', + \ "[ERROR:/path/filename.thrift:76] (last token was ';')", + \ 'Implicit field keys are deprecated and not allowed with -strict', + \ "[ERROR:/path/filename.thrift:77] (last token was ';')", + \ ]) diff --git a/test/handler/test_tslint_handler.vader b/test/handler/test_tslint_handler.vader index 704123dd..5c8679a4 100644 --- a/test/handler/test_tslint_handler.vader +++ b/test/handler/test_tslint_handler.vader @@ -15,28 +15,40 @@ Execute(The tslint handler should parse lines correctly): \ { \ 'lnum': 1, \ 'col': 15, + \ 'filename': expand('%:p:h') . '/test.ts', \ 'end_lnum': 1, - \ 'end_col': 15, - \ 'text': 'Missing semicolon', \ 'type': 'E', + \ 'end_col': 15, + \ 'text': 'semicolon: Missing semicolon' \ }, \ { \ 'lnum': 2, \ 'col': 8, + \ 'filename': expand('%:p:h') . '/test.ts', \ 'end_lnum': 3, + \ 'type': 'W', \ 'end_col': 12, - \ 'text': 'Something else', + \ 'text': 'Something else' + \ }, + \ { + \ 'lnum': 2, + \ 'col': 8, + \ 'filename': expand('%:p:h') . '/something-else.ts', + \ 'end_lnum': 3, \ 'type': 'W', + \ 'end_col': 12, + \ 'text': 'something: Something else' \ }, \ { \ 'lnum': 31, \ 'col': 9, + \ 'filename': expand('%:p:h') . '/test.ts', \ 'end_lnum': 31, - \ 'end_col': 20, - \ 'text': 'Calls to console.log are not allowed.', \ 'type': 'E', + \ 'end_col': 20, + \ 'text': 'no-console: Calls to console.log are not allowed.' \ }, - \ ], + \ ] , \ ale_linters#typescript#tslint#Handle(bufnr(''), [json_encode([ \ { \ 'endPosition': { @@ -50,7 +62,7 @@ Execute(The tslint handler should parse lines correctly): \ 'innerStart': 14, \ 'innerText': ';' \ }, - \ 'name': 'app/test.ts', + \ 'name': 'test.ts', \ 'ruleName': 'semicolon', \ 'ruleSeverity': 'ERROR', \ 'startPosition': { @@ -71,8 +83,7 @@ Execute(The tslint handler should parse lines correctly): \ 'innerStart': 14, \ 'innerText': ';' \ }, - \ 'name': 'app/test.ts', - \ 'ruleName': 'something', + \ 'name': 'test.ts', \ 'ruleSeverity': 'WARNING', \ 'startPosition': { \ 'character': 7, @@ -92,7 +103,7 @@ Execute(The tslint handler should parse lines correctly): \ 'innerStart': 14, \ 'innerText': ';' \ }, - \ 'name': 'app/something-else.ts', + \ 'name': 'something-else.ts', \ 'ruleName': 'something', \ 'ruleSeverity': 'WARNING', \ 'startPosition': { @@ -108,7 +119,7 @@ Execute(The tslint handler should parse lines correctly): \ "position": 14590 \ }, \ "failure": "Calls to console.log are not allowed.", - \ 'name': 'app/test.ts', + \ 'name': 'test.ts', \ "ruleName": "no-console", \ "startPosition": { \ "character": 8, diff --git a/test/handler/test_vint_handler.vader b/test/handler/test_vint_handler.vader index c5af85c4..8747979c 100644 --- a/test/handler/test_vint_handler.vader +++ b/test/handler/test_vint_handler.vader @@ -1,6 +1,10 @@ -Execute(The vint handler should parse error messages correctly): - :file! gxc.vim +Before: + runtime ale_linters/vim/vint.vim + +After: + call ale#linter#Reset() +Execute(The vint handler should parse error messages correctly): AssertEqual \ [ \ { @@ -12,25 +16,44 @@ Execute(The vint handler should parse error messages correctly): \ { \ 'lnum': 3, \ 'col': 17, + \ 'end_col': 18, \ 'text': 'Use robust operators ''==#'' or ''==?'' instead of ''=='' (see Google VimScript Style Guide (Matching))', \ 'type': 'W', \ }, \ { \ 'lnum': 3, \ 'col': 8, + \ 'end_col': 15, \ 'text': 'Make the scope explicit like ''l:filename'' (see Anti-pattern of vimrc (Scope of identifier))', \ 'type': 'W', \ }, \ { \ 'lnum': 7, \ 'col': 8, + \ 'end_col': 15, \ 'text': 'Undefined variable: filename (see :help E738)', \ 'type': 'W', \ }, + \ { + \ 'lnum': 8, + \ 'col': 11, + \ 'end_col': 16, + \ 'text': 'E128: Function name must start with a capital or contain a colon: foobar (see ynkdir/vim-vimlparser)', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 9, + \ 'col': 12, + \ 'end_col': 13, + \ 'text': 'Use robust operators ''=~#'' or ''=~?'' instead of ''=~'' (see Google VimScript Style Guide (Matching))', + \ 'type': 'W', + \ }, \ ], - \ ale#handlers#gcc#HandleGCCFormat(347, [ + \ ale_linters#vim#vint#Handle(bufnr(''), [ \ 'gcc.vim:1:1: warning: Use scriptencoding when multibyte char exists (see :help :script encoding)', \ 'gcc.vim:3:17: warning: Use robust operators `==#` or `==?` instead of `==` (see Google VimScript Style Guide (Matching))', \ 'gcc.vim:3:8: style_problem: Make the scope explicit like `l:filename` (see Anti-pattern of vimrc (Scope of identifier))', \ 'gcc.vim:7:8: warning: Undefined variable: filename (see :help E738)', + \ 'gcc.vim:8:11: error: E128: Function name must start with a capital or contain a colon: foobar (see ynkdir/vim-vimlparser)', + \ 'gcc.vim:9:12: warning: Use robust operators `=~#` or `=~?` instead of `=~` (see Google VimScript Style Guide (Matching))', \ ]) diff --git a/test/lsp/test_lsp_client_messages.vader b/test/lsp/test_lsp_client_messages.vader index abf733ca..057abad4 100644 --- a/test/lsp/test_lsp_client_messages.vader +++ b/test/lsp/test_lsp_client_messages.vader @@ -1,10 +1,13 @@ Before: silent! cd /testplugin/test/lsp - let b:dir = getcwd() + let g:dir = getcwd() + let g:ale_lsp_next_version_id = 1 + + call ale#test#SetFilename('foo/bar.ts') After: - silent execute 'cd ' . fnameescape(b:dir) - unlet! b:dir + silent execute 'cd ' . fnameescape(g:dir) + unlet! g:dir Execute(ale#lsp#message#Initialize() should return correct messages): AssertEqual @@ -13,7 +16,7 @@ Execute(ale#lsp#message#Initialize() should return correct messages): \ 'initialize', \ { \ 'processId': getpid(), - \ 'rootUri': '/foo/bar', + \ 'rootPath': '/foo/bar', \ 'capabilities': {}, \ } \ ], @@ -28,36 +31,51 @@ Execute(ale#lsp#message#Shutdown() should return correct messages): Execute(ale#lsp#message#Exit() should return correct messages): AssertEqual [1, 'exit'], ale#lsp#message#Exit(), +Given typescript(A TypeScript file with 3 lines): + foo() + bar() + baz() + Execute(ale#lsp#message#DidOpen() should return correct messages): + let g:ale_lsp_next_version_id = 12 AssertEqual \ [ \ 1, \ 'textDocument/didOpen', \ { \ 'textDocument': { - \ 'uri': '/foo/bar', + \ 'uri': 'file://' . g:dir . '/foo/bar.ts', \ 'languageId': 'typescript', - \ 'version': 123, - \ 'text': 'foobar', + \ 'version': 12, + \ 'text': "foo()\nbar()\nbaz()", \ }, \ } \ ], - \ ale#lsp#message#DidOpen('/foo/bar', 'typescript', 123, 'foobar') + \ ale#lsp#message#DidOpen(bufnr(''), 'typescript') Execute(ale#lsp#message#DidChange() should return correct messages): + let g:ale_lsp_next_version_id = 34 + AssertEqual \ [ \ 1, \ 'textDocument/didChange', \ { \ 'textDocument': { - \ 'uri': '/foo/bar', - \ 'version': 123, + \ 'uri': 'file://' . g:dir . '/foo/bar.ts', + \ 'version': 34, \ }, - \ 'contentChanges': [{'text': 'foobar'}], + \ 'contentChanges': [{'text': "foo()\nbar()\nbaz()"}], \ } \ ], - \ ale#lsp#message#DidChange('/foo/bar', 123, 'foobar') + \ ale#lsp#message#DidChange(bufnr('')) + " The version numbers should increment. + AssertEqual + \ 35, + \ ale#lsp#message#DidChange(bufnr(''))[2].textDocument.version + AssertEqual + \ 36, + \ ale#lsp#message#DidChange(bufnr(''))[2].textDocument.version Execute(ale#lsp#message#DidSave() should return correct messages): AssertEqual @@ -66,11 +84,11 @@ Execute(ale#lsp#message#DidSave() should return correct messages): \ 'textDocument/didSave', \ { \ 'textDocument': { - \ 'uri': '/foo/bar', + \ 'uri': 'file://' . g:dir . '/foo/bar.ts', \ }, \ } \ ], - \ ale#lsp#message#DidSave('/foo/bar') + \ ale#lsp#message#DidSave(bufnr('')) Execute(ale#lsp#message#DidClose() should return correct messages): AssertEqual @@ -79,52 +97,41 @@ Execute(ale#lsp#message#DidClose() should return correct messages): \ 'textDocument/didClose', \ { \ 'textDocument': { - \ 'uri': '/foo/bar', + \ 'uri': 'file://' . g:dir . '/foo/bar.ts', \ }, \ } \ ], - \ ale#lsp#message#DidClose('/foo/bar') + \ ale#lsp#message#DidClose(bufnr('')) Execute(ale#lsp#tsserver_message#Open() should return correct messages): - silent! noautocmd file foo.ts - AssertEqual \ [ \ 1, \ 'ts@open', \ { - \ 'file': b:dir . '/foo.ts', + \ 'file': g:dir . '/foo/bar.ts', \ } \ ], \ ale#lsp#tsserver_message#Open(bufnr('')) Execute(ale#lsp#tsserver_message#Close() should return correct messages): - silent! noautocmd file foo.ts - AssertEqual \ [ \ 1, \ 'ts@close', \ { - \ 'file': b:dir . '/foo.ts', + \ 'file': g:dir . '/foo/bar.ts', \ } \ ], \ ale#lsp#tsserver_message#Close(bufnr('')) -Given typescript(A TypeScript file with 3 lines): - foo() - bar() - baz() - Execute(ale#lsp#tsserver_message#Change() should return correct messages): - silent! noautocmd file foo.ts - AssertEqual \ [ \ 1, \ 'ts@change', \ { - \ 'file': b:dir . '/foo.ts', + \ 'file': g:dir . '/foo/bar.ts', \ 'line': 1, \ 'offset': 1, \ 'endLine': 1073741824, @@ -135,27 +142,23 @@ Execute(ale#lsp#tsserver_message#Change() should return correct messages): \ ale#lsp#tsserver_message#Change(bufnr('')) Execute(ale#lsp#tsserver_message#Geterr() should return correct messages): - silent! noautocmd file foo.ts - AssertEqual \ [ \ 1, \ 'ts@geterr', \ { - \ 'files': [b:dir . '/foo.ts'], + \ 'files': [g:dir . '/foo/bar.ts'], \ } \ ], \ ale#lsp#tsserver_message#Geterr(bufnr('')) Execute(ale#lsp#tsserver_message#Completions() should return correct messages): - silent! noautocmd file foo.ts - AssertEqual \ [ \ 0, \ 'ts@completions', \ { - \ 'file': b:dir . '/foo.ts', + \ 'file': g:dir . '/foo/bar.ts', \ 'line': 347, \ 'offset': 12, \ 'prefix': 'abc', @@ -164,14 +167,12 @@ Execute(ale#lsp#tsserver_message#Completions() should return correct messages): \ ale#lsp#tsserver_message#Completions(bufnr(''), 347, 12, 'abc') Execute(ale#lsp#tsserver_message#CompletionEntryDetails() should return correct messages): - silent! noautocmd file foo.ts - AssertEqual \ [ \ 0, \ 'ts@completionEntryDetails', \ { - \ 'file': b:dir . '/foo.ts', + \ 'file': g:dir . '/foo/bar.ts', \ 'line': 347, \ 'offset': 12, \ 'entryNames': ['foo', 'bar'], diff --git a/test/lsp/test_other_initialize_message_handling.vader b/test/lsp/test_other_initialize_message_handling.vader new file mode 100644 index 00000000..3a7c7f62 --- /dev/null +++ b/test/lsp/test_other_initialize_message_handling.vader @@ -0,0 +1,66 @@ +Before: + let b:project = { + \ 'initialized': 0, + \ 'init_request_id': 3, + \ 'message_queue': [], + \} + + let b:conn = { + \ 'projects': { + \ '/foo/bar': b:project, + \ }, + \} + +After: + unlet! b:project + unlet! b:conn + +Execute(publishDiagnostics messages with files inside project directories should initialize projects): + " This is for some other file, ignore this one. + call ale#lsp#HandleOtherInitializeResponses(b:conn, { + \ 'method': 'textDocument/publishDiagnostics', + \ 'params': {'uri': 'file:///xyz/bar/baz.txt'}, + \}) + + AssertEqual + \ { + \ 'initialized': 0, + \ 'init_request_id': 3, + \ 'message_queue': [], + \ }, + \ b:project + + call ale#lsp#HandleOtherInitializeResponses(b:conn, { + \ 'method': 'textDocument/publishDiagnostics', + \ 'params': {'uri': 'file:///foo/bar/baz.txt'}, + \}) + + AssertEqual + \ { + \ 'initialized': 1, + \ 'init_request_id': 3, + \ 'message_queue': [], + \ }, + \ b:project + +Execute(Messages with no method and capabilities should initialize projects): + call ale#lsp#HandleOtherInitializeResponses(b:conn, { + \ 'result': {'capabilities': {}}, + \}) + + AssertEqual + \ { + \ 'initialized': 1, + \ 'init_request_id': 3, + \ 'message_queue': [], + \ }, + \ b:project + +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 diff --git a/test/lsp/test_read_lsp_diagnostics.vader b/test/lsp/test_read_lsp_diagnostics.vader index 63086a7f..3e637418 100644 --- a/test/lsp/test_read_lsp_diagnostics.vader +++ b/test/lsp/test_read_lsp_diagnostics.vader @@ -10,7 +10,7 @@ After: delfunction Range Execute(ale#lsp#response#ReadDiagnostics() should handle errors): - AssertEqual ['filename.ts', [ + AssertEqual [ \ { \ 'type': 'E', \ 'text': 'Something went wrong!', @@ -20,18 +20,18 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle errors): \ 'end_col': 16, \ 'nr': 'some-error', \ } - \ ]], - \ ale#lsp#response#ReadDiagnostics({'uri': 'filename.ts', 'diagnostics': [ + \ ], + \ ale#lsp#response#ReadDiagnostics({'params': {'uri': 'filename.ts', 'diagnostics': [ \ { \ 'severity': 1, \ 'range': Range(2, 10, 4, 15), \ 'code': 'some-error', \ 'message': 'Something went wrong!', \ }, - \ ]}) + \ ]}}) Execute(ale#lsp#response#ReadDiagnostics() should handle warnings): - AssertEqual ['filename.ts', [ + AssertEqual [ \ { \ 'type': 'W', \ 'text': 'Something went wrong!', @@ -41,18 +41,18 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle warnings): \ 'end_col': 4, \ 'nr': 'some-warning', \ } - \ ]], - \ ale#lsp#response#ReadDiagnostics({'uri': 'filename.ts', 'diagnostics': [ + \ ], + \ ale#lsp#response#ReadDiagnostics({'params': {'uri': 'filename.ts', 'diagnostics': [ \ { \ 'severity': 2, \ 'range': Range(1, 3, 1, 3), \ 'code': 'some-warning', \ 'message': 'Something went wrong!', \ }, - \ ]}) + \ ]}}) Execute(ale#lsp#response#ReadDiagnostics() should treat messages with missing severity as errors): - AssertEqual ['filename.ts', [ + AssertEqual [ \ { \ 'type': 'E', \ 'text': 'Something went wrong!', @@ -62,17 +62,17 @@ Execute(ale#lsp#response#ReadDiagnostics() should treat messages with missing se \ 'end_col': 16, \ 'nr': 'some-error', \ } - \ ]], - \ ale#lsp#response#ReadDiagnostics({'uri': 'filename.ts', 'diagnostics': [ + \ ], + \ ale#lsp#response#ReadDiagnostics({'params': {'uri': 'filename.ts', 'diagnostics': [ \ { \ 'range': Range(2, 10, 4, 15), \ 'code': 'some-error', \ 'message': 'Something went wrong!', \ }, - \ ]}) + \ ]}}) Execute(ale#lsp#response#ReadDiagnostics() should handle messages without codes): - AssertEqual ['filename.ts', [ + AssertEqual [ \ { \ 'type': 'E', \ 'text': 'Something went wrong!', @@ -81,16 +81,16 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle messages without codes) \ 'end_lnum': 5, \ 'end_col': 16, \ } - \ ]], - \ ale#lsp#response#ReadDiagnostics({'uri': 'filename.ts', 'diagnostics': [ + \ ], + \ ale#lsp#response#ReadDiagnostics({'params': {'uri': 'filename.ts', 'diagnostics': [ \ { \ 'range': Range(2, 10, 4, 15), \ 'message': 'Something went wrong!', \ }, - \ ]}) + \ ]}}) Execute(ale#lsp#response#ReadDiagnostics() should handle multiple messages): - AssertEqual ['filename.ts', [ + AssertEqual [ \ { \ 'type': 'E', \ 'text': 'Something went wrong!', @@ -107,8 +107,8 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle multiple messages): \ 'end_lnum': 2, \ 'end_col': 5, \ }, - \ ]], - \ ale#lsp#response#ReadDiagnostics({'uri': 'filename.ts', 'diagnostics': [ + \ ], + \ ale#lsp#response#ReadDiagnostics({'params': {'uri': 'filename.ts', 'diagnostics': [ \ { \ 'range': Range(0, 2, 0, 2), \ 'message': 'Something went wrong!', @@ -118,7 +118,7 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle multiple messages): \ 'range': Range(1, 4, 1, 4), \ 'message': 'A warning', \ }, - \ ]}) + \ ]}}) Execute(ale#lsp#response#ReadTSServerDiagnostics() should handle tsserver responses): AssertEqual [ diff --git a/test/prettier-test-files/testfile.js b/test/prettier-test-files/testfile.js new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/prettier-test-files/testfile.js diff --git a/test/prettier-test-files/with_config/.prettierrc b/test/prettier-test-files/with_config/.prettierrc new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/prettier-test-files/with_config/.prettierrc diff --git a/test/prettier-test-files/with_config/testfile.js b/test/prettier-test-files/with_config/testfile.js new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/prettier-test-files/with_config/testfile.js diff --git a/test/sign/test_sign_parsing.vader b/test/sign/test_sign_parsing.vader index ee112a1b..07848afb 100644 --- a/test/sign/test_sign_parsing.vader +++ b/test/sign/test_sign_parsing.vader @@ -1,6 +1,6 @@ Execute (Parsing English signs should work): AssertEqual - \ [[9, 1000001, 'ALEWarningSign']], + \ [0, [[9, 1000001, 'ALEWarningSign']]], \ ale#sign#ParseSigns([ \ 'Signs for app.js:', \ ' line=9 id=1000001 name=ALEWarningSign', @@ -8,20 +8,28 @@ Execute (Parsing English signs should work): Execute (Parsing Russian signs should work): AssertEqual - \ [[1, 1000001, 'ALEErrorSign']], + \ [0, [[1, 1000001, 'ALEErrorSign']]], \ ale#sign#ParseSigns([' строка=1 id=1000001 имя=ALEErrorSign']) Execute (Parsing Japanese signs should work): AssertEqual - \ [[1, 1000001, 'ALEWarningSign']], + \ [0, [[1, 1000001, 'ALEWarningSign']]], \ ale#sign#ParseSigns([' 行=1 識別子=1000001 名前=ALEWarningSign']) Execute (Parsing Spanish signs should work): AssertEqual - \ [[12, 1000001, 'ALEWarningSign']], + \ [0, [[12, 1000001, 'ALEWarningSign']]], \ ale#sign#ParseSigns([' línea=12 id=1000001 nombre=ALEWarningSign']) Execute (Parsing Italian signs should work): AssertEqual - \ [[1, 1000001, 'ALEWarningSign']], + \ [0, [[1, 1000001, 'ALEWarningSign']]], \ ale#sign#ParseSigns([' riga=1 id=1000001, nome=ALEWarningSign']) + \ +Execute (The sign parser should indicate if the dummy sign is set): + AssertEqual + \ [1, [[1, 1000001, 'ALEErrorSign']]], + \ ale#sign#ParseSigns([ + \ ' строка=1 id=1000001 имя=ALEErrorSign', + \ ' line=1 id=1000000 name=ALEDummySign', + \ ]) diff --git a/test/sign/test_sign_placement.vader b/test/sign/test_sign_placement.vader index 77f9bb6d..abae765b 100644 --- a/test/sign/test_sign_placement.vader +++ b/test/sign/test_sign_placement.vader @@ -1,4 +1,8 @@ Before: + Save g:ale_set_signs + + let g:ale_set_signs = 1 + function! GenerateResults(buffer, output) return [ \ { @@ -65,41 +69,43 @@ Before: \}) After: + Restore + unlet! g:loclist delfunction GenerateResults delfunction ParseSigns call ale#linter#Reset() sign unplace * -Execute(ale#sign#GetSignType should return the right sign types): - AssertEqual 'ALEErrorSign', ale#sign#GetSignType([{'type': 'E'}]) - AssertEqual 'ALEStyleErrorSign', ale#sign#GetSignType([{'type': 'E', 'sub_type': 'style'}]) - AssertEqual 'ALEWarningSign', ale#sign#GetSignType([{'type': 'W'}]) - AssertEqual 'ALEStyleWarningSign', ale#sign#GetSignType([{'type': 'W', 'sub_type': 'style'}]) - AssertEqual 'ALEInfoSign', ale#sign#GetSignType([{'type': 'I'}]) - AssertEqual 'ALEErrorSign', ale#sign#GetSignType([ +Execute(ale#sign#GetSignName should return the right sign names): + AssertEqual 'ALEErrorSign', ale#sign#GetSignName([{'type': 'E'}]) + AssertEqual 'ALEStyleErrorSign', ale#sign#GetSignName([{'type': 'E', 'sub_type': 'style'}]) + AssertEqual 'ALEWarningSign', ale#sign#GetSignName([{'type': 'W'}]) + AssertEqual 'ALEStyleWarningSign', ale#sign#GetSignName([{'type': 'W', 'sub_type': 'style'}]) + AssertEqual 'ALEInfoSign', ale#sign#GetSignName([{'type': 'I'}]) + AssertEqual 'ALEErrorSign', ale#sign#GetSignName([ \ {'type': 'E'}, \ {'type': 'W'}, \ {'type': 'I'}, \ {'type': 'E', 'sub_type': 'style'}, \ {'type': 'W', 'sub_type': 'style'}, \]) - AssertEqual 'ALEWarningSign', ale#sign#GetSignType([ + AssertEqual 'ALEWarningSign', ale#sign#GetSignName([ \ {'type': 'W'}, \ {'type': 'I'}, \ {'type': 'E', 'sub_type': 'style'}, \ {'type': 'W', 'sub_type': 'style'}, \]) - AssertEqual 'ALEInfoSign', ale#sign#GetSignType([ + AssertEqual 'ALEInfoSign', ale#sign#GetSignName([ \ {'type': 'I'}, \ {'type': 'E', 'sub_type': 'style'}, \ {'type': 'W', 'sub_type': 'style'}, \]) - AssertEqual 'ALEStyleErrorSign', ale#sign#GetSignType([ + AssertEqual 'ALEStyleErrorSign', ale#sign#GetSignName([ \ {'type': 'E', 'sub_type': 'style'}, \ {'type': 'W', 'sub_type': 'style'}, \]) - AssertEqual 'ALEStyleWarningSign', ale#sign#GetSignType([ + AssertEqual 'ALEStyleWarningSign', ale#sign#GetSignName([ \ {'type': 'W', 'sub_type': 'style'}, \]) @@ -124,34 +130,32 @@ Execute(The current signs should be set for running a job): \ ], \ ParseSigns() - Execute(Loclist items with sign_id values should be kept): - exec 'sign place 1000347 line=3 name=ALEErrorSign buffer=' . bufnr('%') - exec 'sign place 1000348 line=15 name=ALEErrorSign buffer=' . bufnr('%') - exec 'sign place 1000349 line=16 name=ALEWarningSign buffer=' . bufnr('%') + exec 'sign place 1000347 line=3 name=ALEErrorSign buffer=' . bufnr('') + exec 'sign place 1000348 line=15 name=ALEErrorSign buffer=' . bufnr('') + exec 'sign place 1000349 line=16 name=ALEWarningSign buffer=' . bufnr('') let g:loclist = [ - \ {'lnum': 1, 'col': 1, 'type': 'E', 'text': 'a', 'sign_id': 1000348}, - \ {'lnum': 2, 'col': 1, 'type': 'W', 'text': 'b', 'sign_id': 1000349}, - \ {'lnum': 3, 'col': 1, 'type': 'E', 'text': 'c', 'sign_id': 1000347}, - \ {'lnum': 4, 'col': 1, 'type': 'W', 'text': 'd'}, - \ {'lnum': 15, 'col': 2, 'type': 'W', 'text': 'e'}, - \ {'lnum': 16, 'col': 2, 'type': 'E', 'text': 'f'}, + \ {'bufnr': bufnr(''), 'lnum': 1, 'col': 1, 'type': 'E', 'text': 'a', 'sign_id': 1000348}, + \ {'bufnr': bufnr(''), 'lnum': 2, 'col': 1, 'type': 'W', 'text': 'b', 'sign_id': 1000349}, + \ {'bufnr': bufnr(''), 'lnum': 3, 'col': 1, 'type': 'E', 'text': 'c', 'sign_id': 1000347}, + \ {'bufnr': bufnr(''), 'lnum': 4, 'col': 1, 'type': 'W', 'text': 'd'}, + \ {'bufnr': bufnr(''), 'lnum': 15, 'col': 2, 'type': 'W', 'text': 'e'}, + \ {'bufnr': bufnr(''), 'lnum': 16, 'col': 2, 'type': 'E', 'text': 'f'}, \] - call ale#sign#SetSigns(bufnr('%'), g:loclist) - call ale#sign#RemoveDummySignIfNeeded(bufnr('%')) + call ale#sign#SetSigns(bufnr(''), g:loclist) " Sign IDs from before should be kept, and new signs should use " IDs that haven't been used yet. AssertEqual \ [ - \ {'lnum': 3, 'col': 1, 'type': 'E', 'text': 'c', 'sign_id': 1000347}, - \ {'lnum': 4, 'col': 1, 'type': 'W', 'text': 'd', 'sign_id': 1000350}, - \ {'lnum': 15, 'col': 1, 'type': 'E', 'text': 'a', 'sign_id': 1000351}, - \ {'lnum': 15, 'col': 2, 'type': 'W', 'text': 'e', 'sign_id': 1000351}, - \ {'lnum': 16, 'col': 1, 'type': 'W', 'text': 'b', 'sign_id': 1000352}, - \ {'lnum': 16, 'col': 2, 'type': 'E', 'text': 'f', 'sign_id': 1000352}, + \ {'bufnr': bufnr(''), 'lnum': 3, 'col': 1, 'type': 'E', 'text': 'c', 'sign_id': 1000347}, + \ {'bufnr': bufnr(''), 'lnum': 4, 'col': 1, 'type': 'W', 'text': 'd', 'sign_id': 1000350}, + \ {'bufnr': bufnr(''), 'lnum': 15, 'col': 1, 'type': 'E', 'text': 'a', 'sign_id': 1000348}, + \ {'bufnr': bufnr(''), 'lnum': 15, 'col': 2, 'type': 'W', 'text': 'e', 'sign_id': 1000348}, + \ {'bufnr': bufnr(''), 'lnum': 16, 'col': 1, 'type': 'W', 'text': 'b', 'sign_id': 1000351}, + \ {'bufnr': bufnr(''), 'lnum': 16, 'col': 2, 'type': 'E', 'text': 'f', 'sign_id': 1000351}, \ ], \ g:loclist @@ -161,13 +165,104 @@ Execute(Loclist items with sign_id values should be kept): AssertEqual \ [ \ ['15', '1000348', 'ALEErrorSign'], - \ ['15', '1000351', 'ALEErrorSign'], - \ ['16', '1000349', 'ALEWarningSign'], - \ ['16', '1000352', 'ALEErrorSign'], + \ ['16', '1000351', 'ALEErrorSign'], \ ['3', '1000347', 'ALEErrorSign'], \ ['4', '1000350', 'ALEWarningSign'], \ ], \ sort(ParseSigns()) -Execute(No excpetions should be thrown when setting signs for invalid buffers): +Execute(Items for other buffers should be ignored): + let g:loclist = [ + \ {'bufnr': bufnr('') - 1, 'lnum': 1, 'col': 1, 'type': 'E', 'text': 'a'}, + \ {'bufnr': bufnr('') - 1, 'lnum': 2, 'col': 1, 'type': 'E', 'text': 'a', 'sign_id': 1000347}, + \ {'bufnr': bufnr(''), 'lnum': 1, 'col': 1, 'type': 'E', 'text': 'a'}, + \ {'bufnr': bufnr(''), 'lnum': 2, 'col': 1, 'type': 'W', 'text': 'b'}, + \ {'bufnr': bufnr(''), 'lnum': 3, 'col': 1, 'type': 'E', 'text': 'c'}, + \ {'bufnr': bufnr(''), 'lnum': 4, 'col': 1, 'type': 'W', 'text': 'd'}, + \ {'bufnr': bufnr(''), 'lnum': 15, 'col': 2, 'type': 'W', 'text': 'e'}, + \ {'bufnr': bufnr(''), 'lnum': 16, 'col': 2, 'type': 'E', 'text': 'f'}, + \ {'bufnr': bufnr('') + 1, 'lnum': 1, 'col': 1, 'type': 'E', 'text': 'a'}, + \] + + call ale#sign#SetSigns(bufnr(''), g:loclist) + + AssertEqual + \ [ + \ ['1', '1000001', 'ALEErrorSign'], + \ ['15', '1000005', 'ALEWarningSign'], + \ ['16', '1000006', 'ALEErrorSign'], + \ ['2', '1000002', 'ALEWarningSign'], + \ ['3', '1000003', 'ALEErrorSign'], + \ ['4', '1000004', 'ALEWarningSign'], + \ ], + \ sort(ParseSigns()) + +Execute(Signs should be downgraded correctly): + call ale#sign#SetSigns(bufnr(''), [ + \ {'bufnr': bufnr(''), 'lnum': 1, 'col': 1, 'type': 'E', 'text': 'x'}, + \ {'bufnr': bufnr(''), 'lnum': 2, 'col': 1, 'type': 'W', 'text': 'x'}, + \]) + + AssertEqual + \ [ + \ ['1', '1000001', 'ALEErrorSign'], + \ ['2', '1000002', 'ALEWarningSign'], + \ ], + \ sort(ParseSigns()) + + call ale#sign#SetSigns(bufnr(''), [ + \ {'bufnr': bufnr(''), 'lnum': 1, 'col': 1, 'type': 'W', 'text': 'x'}, + \ {'bufnr': bufnr(''), 'lnum': 2, 'col': 1, 'type': 'I', 'text': 'x'}, + \]) + + AssertEqual + \ [ + \ ['1', '1000003', 'ALEWarningSign'], + \ ['2', '1000004', 'ALEInfoSign'], + \ ], + \ sort(ParseSigns()) + +Execute(Signs should be upgraded correctly): + call ale#sign#SetSigns(bufnr(''), [ + \ {'bufnr': bufnr(''), 'lnum': 1, 'col': 1, 'type': 'W', 'text': 'x'}, + \ {'bufnr': bufnr(''), 'lnum': 2, 'col': 1, 'type': 'I', 'text': 'x'}, + \]) + + AssertEqual + \ [ + \ ['1', '1000001', 'ALEWarningSign'], + \ ['2', '1000002', 'ALEInfoSign'], + \ ], + \ sort(ParseSigns()) + + call ale#sign#SetSigns(bufnr(''), [ + \ {'bufnr': bufnr(''), 'lnum': 1, 'col': 1, 'type': 'E', 'text': 'x'}, + \ {'bufnr': bufnr(''), 'lnum': 2, 'col': 1, 'type': 'W', 'text': 'x'}, + \]) + + AssertEqual + \ [ + \ ['1', '1000003', 'ALEErrorSign'], + \ ['2', '1000004', 'ALEWarningSign'], + \ ], + \ sort(ParseSigns()) + +Execute(It should be possible to clear signs with empty lists): + let g:loclist = [ + \ {'bufnr': bufnr(''), 'lnum': 16, 'col': 2, 'type': 'E', 'text': 'f'}, + \] + + call ale#sign#SetSigns(bufnr(''), g:loclist) + + AssertEqual + \ [ + \ ['16', '1000001', 'ALEErrorSign'], + \ ], + \ sort(ParseSigns()) + + call ale#sign#SetSigns(bufnr(''), []) + + AssertEqual [], ParseSigns() + +Execute(No exceptions should be thrown when setting signs for invalid buffers): call ale#sign#SetSigns(123456789, [{'lnum': 15, 'col': 2, 'type': 'W', 'text': 'e'}]) diff --git a/test/test_ale_fix.vader b/test/test_ale_fix.vader index d7c3fb35..b5c16724 100644 --- a/test/test_ale_fix.vader +++ b/test/test_ale_fix.vader @@ -82,6 +82,8 @@ After: call ale#fix#registry#ResetToDefaults() call ale#linter#Reset() + setlocal buftype=nofile + if filereadable('fix_test_file') call delete('fix_test_file') endif @@ -245,8 +247,11 @@ Execute(ALEFix should save files on the save event): let g:ale_fixers.testft = ['AddDollars'] + " We have to set the buftype to empty so the file will be written. + setlocal buftype= + call SetUpLinters() - call ale#events#SaveEvent() + call ale#events#SaveEvent(bufnr('')) " We should save the file. AssertEqual ['$a', '$b', '$c'], readfile('fix_test_file') @@ -285,7 +290,7 @@ Execute(ALEFix should still lint with no linters to be applied): let g:ale_fixers.testft = [] call SetUpLinters() - call ale#events#SaveEvent() + call ale#events#SaveEvent(bufnr('')) Assert !filereadable('fix_test_file'), 'The file should not have been saved' @@ -317,7 +322,7 @@ Execute(ALEFix should still lint when nothing was fixed on save): let g:ale_fixers.testft = ['DoNothing'] call SetUpLinters() - call ale#events#SaveEvent() + call ale#events#SaveEvent(bufnr('')) Assert !filereadable('fix_test_file'), 'The file should not have been saved' diff --git a/test/test_ale_info.vader b/test/test_ale_info.vader index a8913df4..8ab5ad54 100644 --- a/test/test_ale_info.vader +++ b/test/test_ale_info.vader @@ -1,14 +1,19 @@ Before: Save g:ale_warn_about_trailing_whitespace Save g:ale_linters + Save g:ale_fixers + + unlet! b:ale_history let g:ale_warn_about_trailing_whitespace = 1 let g:testlinter1 = {'name': 'testlinter1', 'executable': 'testlinter1', 'command': 'testlinter1', 'callback': 'testCB1', 'output_stream': 'stdout'} let g:testlinter2 = {'name': 'testlinter2', 'executable': 'testlinter2', 'command': 'testlinter2', 'callback': 'testCB2', 'output_stream': 'stdout'} + call ale#engine#ResetExecutableCache() call ale#linter#Reset() let g:ale_linters = {} + let g:ale_fixers = {} let g:ale_linter_aliases = {} let g:ale_buffer_info = {} let g:globals_lines = [ @@ -59,9 +64,10 @@ After: let g:ale_buffer_info = {} - unlet! g:testlinter1 - unlet! g:testlinter2 + unlet! g:testlinter1 + unlet! g:testlinter2 + unlet! b:ale_history unlet! b:ale_linters unlet! g:output unlet! g:globals_string @@ -247,12 +253,10 @@ Execute (ALEInfo should output linter aliases): Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo should return command history): - let g:ale_buffer_info[bufnr('%')] = { - \ 'history': [ - \ {'status': 'started', 'job_id': 347, 'command': 'first command'}, - \ {'status': 'started', 'job_id': 347, 'command': ['/bin/bash', '\c', 'last command']}, - \ ], - \} + let b:ale_history = [ + \ {'status': 'started', 'job_id': 347, 'command': 'first command'}, + \ {'status': 'started', 'job_id': 347, 'command': ['/bin/bash', '\c', 'last command']}, + \] call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) @@ -271,12 +275,10 @@ Execute (ALEInfo should return command history): Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo command history should print exit codes correctly): - let g:ale_buffer_info[bufnr('%')] = { - \ 'history': [ - \ {'status': 'finished', 'exit_code': 0, 'job_id': 347, 'command': 'first command'}, - \ {'status': 'finished', 'exit_code': 1, 'job_id': 347, 'command': ['/bin/bash', '\c', 'last command']}, - \ ], - \} + let b:ale_history = [ + \ {'status': 'finished', 'exit_code': 0, 'job_id': 347, 'command': 'first command'}, + \ {'status': 'finished', 'exit_code': 1, 'job_id': 347, 'command': ['/bin/bash', '\c', 'last command']}, + \] call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) @@ -297,31 +299,29 @@ Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo command history should print command output if logging is on): let g:ale_history_log_output = 1 - let g:ale_buffer_info[bufnr('%')] = { - \ 'history': [ - \ { - \ 'status': 'finished', - \ 'exit_code': 0, - \ 'job_id': 347, - \ 'command': 'first command', - \ 'output': ['some', 'first command output'], - \ }, - \ { - \ 'status': 'finished', - \ 'exit_code': 1, - \ 'job_id': 347, - \ 'command': ['/bin/bash', '\c', 'last command'], - \ 'output': ['different second command output'], - \ }, - \ { - \ 'status': 'finished', - \ 'exit_code': 0, - \ 'job_id': 347, - \ 'command': 'command with no output', - \ 'output': [], - \ }, - \ ], - \} + let b:ale_history = [ + \ { + \ 'status': 'finished', + \ 'exit_code': 0, + \ 'job_id': 347, + \ 'command': 'first command', + \ 'output': ['some', 'first command output'], + \ }, + \ { + \ 'status': 'finished', + \ 'exit_code': 1, + \ 'job_id': 347, + \ 'command': ['/bin/bash', '\c', 'last command'], + \ 'output': ['different second command output'], + \ }, + \ { + \ 'status': 'finished', + \ 'exit_code': 0, + \ 'job_id': 347, + \ 'command': 'command with no output', + \ 'output': [], + \ }, + \] call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) @@ -351,3 +351,20 @@ Execute (ALEInfo command history should print command output if logging is on): \ '', \ '<<<NO OUTPUT RETURNED>>>', \]) + +Execute (ALEInfo should include executable checks in the history): + call ale#linter#Define('testft', g:testlinter1) + call ale#engine#IsExecutable(bufnr(''), 'echo') + call ale#engine#IsExecutable(bufnr(''), 'TheresNoWayThisIsExecutable') + + call CheckInfo([ + \ ' Current Filetype: testft.testft2', + \ 'Available Linters: [''testlinter1'']', + \ ' Enabled Linters: [''testlinter1'']', + \ ' Linter Variables:', + \ '', + \] + g:globals_lines + g:command_header + [ + \ '', + \ '(executable check - success) echo', + \ '(executable check - failure) TheresNoWayThisIsExecutable', + \]) diff --git a/test/test_ale_init_au_groups.vader b/test/test_ale_init_au_groups.vader index c20f4f97..2685f50b 100644 --- a/test/test_ale_init_au_groups.vader +++ b/test/test_ale_init_au_groups.vader @@ -21,8 +21,14 @@ Before: let l:header = split(l:line)[1] let l:header = get(l:event_name_corrections, l:header, l:header) elseif !empty(l:header) - call add(l:matches, join(split(l:header . l:line))) - let l:header = '' + " There's an extra line for buffer events, and we should only look + " for the one matching the current buffer. + if l:line =~# '<buffer=' . bufnr('') . '>' + let l:header .= ' <buffer>' + else + call add(l:matches, join(split(l:header . l:line))) + let l:header = '' + endif endif endfor @@ -40,11 +46,18 @@ Before: Save g:ale_lint_on_save Save g:ale_echo_cursor Save g:ale_fix_on_save + Save g:ale_completion_enabled After: delfunction CheckAutocmd Restore + if g:ale_completion_enabled + call ale#completion#Enable() + else + call ale#completion#Disable() + endif + call ALEInitAuGroups() Execute (g:ale_lint_on_text_changed = 0 should bind no events): @@ -107,18 +120,20 @@ Execute (g:ale_pattern_options_enabled = 1 should bind BufReadPost and BufEnter) \ 'BufReadPost * call ale#pattern_options#SetOptions()', \], CheckAutocmd('ALEPatternOptionsGroup') -Execute (g:ale_lint_on_enter = 0 should bind no events): +Execute (g:ale_lint_on_enter = 0 should bind only the BufEnter event): let g:ale_lint_on_enter = 0 - AssertEqual [], CheckAutocmd('ALERunOnEnterGroup') + 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()', - \ 'BufReadPost * call ale#Queue(300, ''lint_file'')', - \ 'BufWinEnter * call ale#Queue(300, ''lint_file'')', + \ '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') @@ -127,18 +142,17 @@ Execute (g:ale_lint_on_filetype_changed = 0 should bind no events): AssertEqual [], CheckAutocmd('ALERunOnFiletypeChangeGroup') -Execute (g:ale_lint_on_filetype_changed = 1 should bind FileType, and required buffer events): +Execute (g:ale_lint_on_filetype_changed = 1 should bind the FileType event): let g:ale_lint_on_filetype_changed = 1 - AssertEqual [ - \ 'BufEnter * let b:ale_original_filetype = &filetype', - \ 'BufReadPost * let b:ale_original_filetype = &filetype', - \ 'FileType * ' - \ . 'if has_key(b:, ''ale_original_filetype'') ' - \ . '&& b:ale_original_filetype !=# expand(''<amatch>'')' - \ . '| call ale#Queue(300, ''lint_file'')' - \ . '| endif', - \], CheckAutocmd('ALERunOnFiletypeChangeGroup') + AssertEqual + \ [ + \ 'FileType * call ale#events#FileTypeEvent( ' + \ . 'str2nr(expand(''<abuf>'')), ' + \ . 'expand(''<amatch>'')' + \ . ')', + \ ], + \ CheckAutocmd('ALERunOnFiletypeChangeGroup') Execute (g:ale_lint_on_save = 0 should bind no events): let g:ale_lint_on_save = 0 @@ -151,7 +165,7 @@ Execute (g:ale_lint_on_save = 1 should bind no events): let g:ale_fix_on_save = 0 AssertEqual [ - \ 'BufWritePost * call ale#events#SaveEvent()', + \ 'BufWritePost * call ale#events#SaveEvent(str2nr(expand(''<abuf>'')))', \], CheckAutocmd('ALERunOnSaveGroup') Execute (g:ale_lint_on_save = 0 and g:ale_fix_on_save = 1 should bind events): @@ -159,7 +173,7 @@ Execute (g:ale_lint_on_save = 0 and g:ale_fix_on_save = 1 should bind events): let g:ale_fix_on_save = 1 AssertEqual [ - \ 'BufWritePost * call ale#events#SaveEvent()', + \ 'BufWritePost * call ale#events#SaveEvent(str2nr(expand(''<abuf>'')))', \], CheckAutocmd('ALERunOnSaveGroup') Execute (g:ale_fix_on_save = 1 should bind events even when ALE is disabled): @@ -168,7 +182,7 @@ Execute (g:ale_fix_on_save = 1 should bind events even when ALE is disabled): let g:ale_fix_on_save = 1 AssertEqual [ - \ 'BufWritePost * call ale#events#SaveEvent()', + \ 'BufWritePost * call ale#events#SaveEvent(str2nr(expand(''<abuf>'')))', \], CheckAutocmd('ALERunOnSaveGroup') Execute (g:ale_echo_cursor = 0 should bind no events): @@ -184,3 +198,21 @@ Execute (g:ale_echo_cursor = 1 should bind cursor events): \ 'CursorMoved * call ale#cursor#EchoCursorWarningWithDelay()', \ 'InsertLeave * call ale#cursor#EchoCursorWarning()', \], CheckAutocmd('ALECursorGroup') + +Execute(Enabling completion should set up autocmd events correctly): + let g:ale_completion_enabled = 0 + call ale#completion#Enable() + + AssertEqual [ + \ 'CompleteDone * call ale#completion#Done()', + \ 'TextChangedI * call ale#completion#Queue()', + \], CheckAutocmd('ALECompletionGroup') + AssertEqual 1, g:ale_completion_enabled + +Execute(Disabling completion should remove autocmd events correctly): + let g:ale_completion_enabled = 1 + call ale#completion#Enable() + call ale#completion#Disable() + + AssertEqual [], CheckAutocmd('ALECompletionGroup') + AssertEqual 0, g:ale_completion_enabled diff --git a/test/test_ale_lint_command.vader b/test/test_ale_lint_command.vader index 9e70017c..42554ec1 100644 --- a/test/test_ale_lint_command.vader +++ b/test/test_ale_lint_command.vader @@ -1,4 +1,8 @@ Before: + Save g:ale_buffer_info + + let g:ale_buffer_info = {} + let g:expected_loclist = [{ \ 'bufnr': bufnr('%'), \ 'lnum': 2, @@ -38,6 +42,8 @@ Before: \}) After: + Restore + unlet! g:expected_loclist unlet! g:expected_groups diff --git a/test/test_ale_toggle.vader b/test/test_ale_toggle.vader index 202d8a35..f5d8599f 100644 --- a/test/test_ale_toggle.vader +++ b/test/test_ale_toggle.vader @@ -1,4 +1,12 @@ Before: + Save g:ale_buffer_info + Save g:ale_set_signs + Save g:ale_set_lists_synchronously + + let g:ale_set_signs = 1 + let g:ale_set_lists_synchronously = 1 + + let g:ale_buffer_info = {} let g:expected_loclist = [{ \ 'bufnr': bufnr('%'), \ 'lnum': 2, @@ -42,10 +50,11 @@ Before: for l:line in split(l:output, "\n") let l:match = matchlist(l:line, '^ALE[a-zA-Z]\+Group') - " We don't care about checking for the completion or fixing groups here. + " We don't care about some groups here. if !empty(l:match) \&& l:match[0] !=# 'ALECompletionGroup' \&& l:match[0] !=# 'ALEBufferFixGroup' + \&& l:match[0] !=# 'ALEPatternOptionsGroup' call add(l:results, l:match[0]) endif endfor @@ -63,11 +72,14 @@ Before: \ 'read_buffer': 0, \}) + sign unplace * + After: + Restore + unlet! g:expected_loclist unlet! g:expected_groups - let g:ale_buffer_info = {} call ale#linter#Reset() " Toggle ALE back on if we fail when it's disabled. @@ -91,7 +103,7 @@ Execute(ALEToggle should reset everything and then run again): " First check that everything is there... AssertEqual g:expected_loclist, getloclist(0) - AssertEqual [[2, 1000001, 'ALEErrorSign']], ale#sign#FindCurrentSigns(bufnr('%')) + AssertEqual [0, [[2, 1000001, 'ALEErrorSign']]], ale#sign#FindCurrentSigns(bufnr('%')) AssertEqual \ [{'group': 'ALEError', 'pos1': [2, 3, 1]}], \ map(getmatches(), '{''group'': v:val.group, ''pos1'': v:val.pos1}') @@ -104,7 +116,7 @@ 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#sign#FindCurrentSigns(bufnr('%')), 'The signs were not cleared' + AssertEqual [0, []], ale#sign#FindCurrentSigns(bufnr('%')), 'The signs were not cleared' AssertEqual [], getmatches(), 'The highlights were not cleared' AssertEqual ['ALECleanupGroup', 'ALEHighlightBufferGroup'], ParseAuGroups() @@ -113,9 +125,53 @@ Execute(ALEToggle should reset everything and then run again): call ale#engine#WaitForJobs(2000) AssertEqual g:expected_loclist, getloclist(0) - AssertEqual [[2, 1000001, 'ALEErrorSign']], ale#sign#FindCurrentSigns(bufnr('%')) + AssertEqual [0, [[2, 1000001, 'ALEErrorSign']]], ale#sign#FindCurrentSigns(bufnr('%')) AssertEqual \ [{'group': 'ALEError', 'pos1': [2, 3, 1]}], \ map(getmatches(), '{''group'': v:val.group, ''pos1'': v:val.pos1}') AssertEqual g:expected_groups, ParseAuGroups() 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): + AssertEqual 'foobar', &filetype + + let g:ale_buffer_info['/foo/bar/baz.txt'] = { + \ 'job_list': [], + \ 'active_linter_list': [], + \ 'loclist': [], + \ 'temporary_file_list': [], + \ 'temporary_directory_list': [], + \ 'history': [], + \} + + call ale#Lint() + call ale#engine#WaitForJobs(2000) + + " Now Toggle ALE off. + ALEToggle + + AssertEqual + \ { + \ 'job_list': [], + \ 'active_linter_list': [], + \ 'loclist': [], + \ 'temporary_file_list': [], + \ 'temporary_directory_list': [], + \ 'history': [], + \ }, + \ get(g:ale_buffer_info, '/foo/bar/baz.txt', {}) + + " Toggle ALE on again. + ALEToggle + call ale#engine#WaitForJobs(2000) + + AssertEqual + \ { + \ 'job_list': [], + \ 'active_linter_list': [], + \ 'loclist': [], + \ 'temporary_file_list': [], + \ 'temporary_directory_list': [], + \ 'history': [], + \ }, + \ get(g:ale_buffer_info, '/foo/bar/baz.txt', {}) diff --git a/test/test_balloon_messages.vader b/test/test_balloon_messages.vader index 50dc6af4..ec09fe29 100644 --- a/test/test_balloon_messages.vader +++ b/test/test_balloon_messages.vader @@ -3,16 +3,19 @@ Before: let g:ale_buffer_info[347] = {'loclist': [ \ { + \ 'bufnr': 347, \ 'lnum': 1, \ 'col': 10, \ 'text': 'Missing semicolon. (semi)', \ }, \ { + \ 'bufnr': 347, \ 'lnum': 2, \ 'col': 10, \ 'text': 'Infix operators must be spaced. (space-infix-ops)' \ }, \ { + \ 'bufnr': 347, \ 'lnum': 2, \ 'col': 15, \ 'text': 'Missing radix parameter (radix)' diff --git a/test/test_completion.vader b/test/test_completion.vader index ce7a8ef3..811a2645 100644 --- a/test/test_completion.vader +++ b/test/test_completion.vader @@ -1,3 +1,37 @@ +Before: + Save g:ale_completion_enabled + Save g:ale_completion_delay + Save g:ale_completion_max_suggestions + Save &l:omnifunc + Save &l:completeopt + + let g:test_vars = { + \ 'feedkeys_calls': [], + \} + + function! ale#util#FeedKeys(string, mode) abort + call add(g:test_vars.feedkeys_calls, [a:string, a:mode]) + endfunction + +After: + Restore + + unlet! g:test_vars + unlet! b:ale_old_omnifunc + unlet! b:ale_old_completopt + unlet! b:ale_completion_info + unlet! b:ale_completion_response + unlet! b:ale_completion_parser + + runtime autoload/ale/completion.vim + runtime autoload/ale/lsp.vim + + if g:ale_completion_enabled + call ale#completion#Enable() + else + call ale#completion#Disable() + endif + Execute(TypeScript completions responses should be parsed correctly): AssertEqual [], \ ale#completion#ParseTSServerCompletions({ @@ -19,13 +53,15 @@ Execute(TypeScript completion details responses should be parsed correctly): \ 'word': 'abc', \ 'menu': '(property) Foo.abc: number', \ 'info': '', - \ 'kind': 'f' + \ 'kind': 'f', + \ 'icase': 1, \ }, \ { \ 'word': 'def', \ 'menu': '(property) Foo.def: number', \ 'info': 'foo bar baz', - \ 'kind': 'f' + \ 'kind': 'f', + \ 'icase': 1, \ }, \ ], \ ale#completion#ParseTSServerCompletionEntryDetails({ @@ -72,6 +108,89 @@ Execute(TypeScript completion details responses should be parsed correctly): \ ], \}) +Execute(Prefix filtering should work for Lists of strings): + AssertEqual + \ ['FooBar', 'foo'], + \ ale#completion#Filter(['FooBar', 'FongBar', 'baz', 'foo'], 'foo') + AssertEqual + \ ['FooBar', 'FongBar', 'baz', 'foo'], + \ ale#completion#Filter(['FooBar', 'FongBar', 'baz', 'foo'], '.') + +Execute(Prefix filtering should work for completion items): + AssertEqual + \ [{'word': 'FooBar'}, {'word': 'foo'}], + \ ale#completion#Filter( + \ [ + \ {'word': 'FooBar'}, + \ {'word': 'FongBar'}, + \ {'word': 'baz'}, + \ {'word': 'foo'}, + \ ], + \ 'foo' + \ ) + AssertEqual + \ [ + \ {'word': 'FooBar'}, + \ {'word': 'FongBar'}, + \ {'word': 'baz'}, + \ {'word': 'foo'}, + \ ], + \ ale#completion#Filter( + \ [ + \ {'word': 'FooBar'}, + \ {'word': 'FongBar'}, + \ {'word': 'baz'}, + \ {'word': 'foo'}, + \ ], + \ '.' + \ ) + +Execute(The right message sent to the tsserver LSP when the first completion message is received): + " The cursor position needs to match what was saved before. + call setpos('.', [bufnr(''), 1, 1, 0]) + let b:ale_completion_info = { + \ 'conn_id': 123, + \ 'prefix': 'f', + \ 'request_id': 4, + \ 'line': 1, + \ 'column': 1, + \} + " We should only show up to this many suggestions. + let g:ale_completion_max_suggestions = 3 + + " Replace the Send function for LSP, so we can monitor calls to it. + function! ale#lsp#Send(conn_id, message) abort + let g:test_vars.message = a:message + endfunction + + " Handle the response for completions. + call ale#completion#HandleTSServerLSPResponse(123, { + \ 'request_seq': 4, + \ 'command': 'completions', + \ 'body': [ + \ {'name': 'Baz'}, + \ {'name': 'dingDong'}, + \ {'name': 'Foo'}, + \ {'name': 'FooBar'}, + \ {'name': 'frazzle'}, + \ {'name': 'FFS'}, + \ ], + \}) + + " The entry details messages should have been sent. + AssertEqual + \ [ + \ 0, + \ 'ts@completionEntryDetails', + \ { + \ 'file': expand('%:p'), + \ 'entryNames': ['Foo', 'FooBar', 'frazzle'], + \ 'offset': 1, + \ 'line': 1, + \ }, + \ ], + \ g:test_vars.message + Given typescript(): let abc = y. let foo = ab @@ -88,3 +207,122 @@ 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(ale#completion#Show() should remember the omnifunc setting and replace it): + let &l:omnifunc = 'FooBar' + + call ale#completion#Show('Response', 'Parser') + + AssertEqual 'FooBar', b:ale_old_omnifunc + AssertEqual 'ale#completion#OmniFunc', &l:omnifunc + +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,preview,noselect,noinsert', &l:completeopt + +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,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:test_vars.feedkeys_calls + +Execute(ale#completion#Show() should set up the response and parser): + call ale#completion#Show('Response', 'Parser') + + AssertEqual 'Response', b:ale_completion_response + AssertEqual 'Parser', b:ale_completion_parser + +Execute(ale#completion#Done() should restore old omnifunc values): + let b:ale_old_omnifunc = 'FooBar' + + call ale#completion#Done() + + " We reset the old omnifunc setting and remove the buffer variable. + AssertEqual 'FooBar', &l:omnifunc + Assert !has_key(b:, 'ale_old_omnifunc') + +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() + + AssertEqual 'menu', &l:completeopt + Assert !has_key(b:, 'ale_old_completopt') + +Execute(ale#completion#Done() should leave settings alone when none were remembered): + let &l:omnifunc = 'BazBoz' + let &l:completeopt = 'menu' + + call ale#completion#Done() + + AssertEqual 'BazBoz', &l:omnifunc + AssertEqual 'menu', &l:completeopt + +Execute(The completion request_id should be reset when queuing again): + let b:ale_completion_info = {'request_id': 123} + + let g:ale_completion_delay = 0 + call ale#completion#Queue() + sleep 1m + + AssertEqual 0, b:ale_completion_info.request_id + +Execute(b:ale_completion_info should be set up correctly when requesting completions): + call setpos('.', [bufnr(''), 3, 14, 0]) + call ale#completion#GetCompletions() + + AssertEqual + \ { + \ 'request_id': 0, + \ 'conn_id': 0, + \ 'column': 14, + \ 'line': 3, + \ 'prefix': 'ab', + \ }, + \ b:ale_completion_info + +Execute(ale#completion#GetCompletions should be called when the cursor position stays the same): + let g:test_vars.get_completions_called = 0 + + " We just want to check if the function is called. + function! ale#completion#GetCompletions() + let g:test_vars.get_completions_called = 1 + endfunction + + let g:ale_completion_delay = 0 + call ale#completion#Queue() + sleep 1m + + Assert g:test_vars.get_completions_called + +Execute(ale#completion#GetCompletions should not be called when the cursor position changes): + call setpos('.', [bufnr(''), 1, 2, 0]) + + let g:test_vars.get_completions_called = 0 + + " We just want to check if the function is called. + function! ale#completion#GetCompletions() + let g:test_vars.get_completions_called = 1 + endfunction + + let g:ale_completion_delay = 0 + call ale#completion#Queue() + + " Change the cursor position before the callback is triggered. + call setpos('.', [bufnr(''), 2, 2, 0]) + + sleep 1m + + Assert !g:test_vars.get_completions_called diff --git a/test/test_engine_lsp_response_handling.vader b/test/test_engine_lsp_response_handling.vader new file mode 100644 index 00000000..b3a45b14 --- /dev/null +++ b/test/test_engine_lsp_response_handling.vader @@ -0,0 +1,155 @@ +Before: + Save g:ale_buffer_info + call ale#test#SetDirectory('/testplugin/test') + +After: + Restore + + call ale#test#RestoreDirectory() + call ale#linter#Reset() + +Execute(tsserver syntax error responses should be handled correctly): + runtime ale_linters/typescript/tsserver.vim + call ale#test#SetFilename('filename.ts') + call ale#engine#InitBufferInfo(bufnr('')) + + " When we get syntax errors and no semantic errors, we should keep the + " syntax errors. + call ale#engine#HandleLSPResponse(1, { + \ '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#engine#HandleLSPResponse(1, { + \ 'seq': 0, + \ 'type': 'event', + \ 'event': 'semanticDiag', + \ 'body': { + \ 'file': g:dir . '/filename.ts', + \ 'diagnostics':[ + \ ], + \ }, + \}) + + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'bufnr': bufnr(''), + \ 'col': 14, + \ 'vcol': 0, + \ 'nr': 1005, + \ 'type': 'E', + \ 'text': ''','' expected.', + \ 'valid': 1, + \ 'pattern': '', + \ }, + \ ], + \ getloclist(0) + + " After we get empty syntax errors, we should clear them. + call ale#engine#HandleLSPResponse(1, { + \ 'seq': 0, + \ 'type': 'event', + \ 'event': 'syntaxDiag', + \ 'body': { + \ 'file': g:dir . '/filename.ts', + \ 'diagnostics':[ + \ ], + \ }, + \}) + + AssertEqual + \ [ + \ ], + \ getloclist(0) + +Execute(tsserver semantic error responses should be handled correctly): + runtime ale_linters/typescript/tsserver.vim + call ale#test#SetFilename('filename.ts') + call ale#engine#InitBufferInfo(bufnr('')) + + " When we get syntax errors and no semantic errors, we should keep the + " syntax errors. + call ale#engine#HandleLSPResponse(1, { + \ 'seq': 0, + \ 'type': 'event', + \ 'event': 'syntaxDiag', + \ 'body': { + \ 'file': g:dir . '/filename.ts', + \ 'diagnostics':[ + \ ], + \ }, + \}) + call ale#engine#HandleLSPResponse(1, { + \ 'seq': 0, + \ 'type': 'event', + \ 'event': 'semanticDiag', + \ 'body': { + \ 'file': g:dir . '/filename.ts', + \ 'diagnostics':[ + \ { + \ 'start': { + \ 'line':2, + \ 'offset':14, + \ }, + \ 'end': { + \ 'line':2, + \ 'offset':15, + \ }, + \ 'text': 'Some semantic error', + \ "code":1005 + \ }, + \ ], + \ }, + \}) + + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'bufnr': bufnr(''), + \ 'col': 14, + \ 'vcol': 0, + \ 'nr': 1005, + \ 'type': 'E', + \ 'text': 'Some semantic error', + \ 'valid': 1, + \ 'pattern': '', + \ }, + \ ], + \ getloclist(0) + + " After we get empty syntax errors, we should clear them. + call ale#engine#HandleLSPResponse(1, { + \ 'seq': 0, + \ 'type': 'event', + \ 'event': 'semanticDiag', + \ 'body': { + \ 'file': g:dir . '/filename.ts', + \ 'diagnostics':[ + \ ], + \ }, + \}) + + AssertEqual + \ [ + \ ], + \ getloclist(0) diff --git a/test/test_fuzzy_json_decode.vader b/test/test_fuzzy_json_decode.vader new file mode 100644 index 00000000..4ac0ca1b --- /dev/null +++ b/test/test_fuzzy_json_decode.vader @@ -0,0 +1,21 @@ +Execute(FuzzyJSONDecode should return the default for empty Lists): + AssertEqual [], ale#util#FuzzyJSONDecode([], []) + AssertEqual {}, ale#util#FuzzyJSONDecode([], {}) + +Execute(FuzzyJSONDecode should return the default for empty Strings): + AssertEqual [], ale#util#FuzzyJSONDecode('', []) + AssertEqual {}, ale#util#FuzzyJSONDecode('', {}) + +Execute(FuzzyJSONDecode should return the default for Lists with invalid JSON): + AssertEqual [], ale#util#FuzzyJSONDecode(['x'], []) + AssertEqual {}, ale#util#FuzzyJSONDecode(['x'], {}) + +Execute(FuzzyJSONDecode should return the default for Strings with invalid JSON): + AssertEqual [], ale#util#FuzzyJSONDecode('x', []) + AssertEqual {}, ale#util#FuzzyJSONDecode('x', {}) + +Execute(FuzzyJSONDecode should return the JSON from the JSON string): + AssertEqual {'x': 3}, ale#util#FuzzyJSONDecode('{"x": 3}', []) + AssertEqual {'x': 3}, ale#util#FuzzyJSONDecode('{"x": 3}', {}) + AssertEqual {'x': 3}, ale#util#FuzzyJSONDecode(['{"x"', ': 3}'], []) + AssertEqual {'x': 3}, ale#util#FuzzyJSONDecode(['{"x"', ': 3}'], {}) diff --git a/test/test_get_abspath.vader b/test/test_get_abspath.vader new file mode 100644 index 00000000..2def3773 --- /dev/null +++ b/test/test_get_abspath.vader @@ -0,0 +1,15 @@ +Execute(Relative paths should be resolved correctly): + AssertEqual + \ '/foo/bar/baz/whatever.txt', + \ ale#path#GetAbsPath('/foo/bar/xyz', '../baz/whatever.txt') + AssertEqual + \ '/foo/bar/xyz/whatever.txt', + \ ale#path#GetAbsPath('/foo/bar/xyz', './whatever.txt') + AssertEqual + \ '/foo/bar/xyz/whatever.txt', + \ ale#path#GetAbsPath('/foo/bar/xyz', 'whatever.txt') + +Execute(Absolute paths should be resolved correctly): + AssertEqual + \ '/ding/dong', + \ ale#path#GetAbsPath('/foo/bar/xyz', '/ding/dong') diff --git a/test/test_highlight_placement.vader b/test/test_highlight_placement.vader index 02f570b9..c1909c4f 100644 --- a/test/test_highlight_placement.vader +++ b/test/test_highlight_placement.vader @@ -162,6 +162,7 @@ Execute(Higlight end columns should set an appropriate size): Execute(Higlight end columns should set an appropriate size): call ale#highlight#SetHighlights(bufnr('%'), [ + \ {'bufnr': bufnr('%') - 1, 'type': 'E', 'lnum': 1, 'col': 1}, \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 1, 'col': 1}, \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 2, 'col': 1}, \ {'bufnr': bufnr('%'), 'type': 'E', 'sub_type': 'style', 'lnum': 3, 'col': 1}, @@ -169,6 +170,7 @@ Execute(Higlight end columns should set an appropriate size): \ {'bufnr': bufnr('%'), 'type': 'W', 'lnum': 5, 'col': 1}, \ {'bufnr': bufnr('%'), 'type': 'W', 'sub_type': 'style', 'lnum': 6, 'col': 1}, \ {'bufnr': bufnr('%'), 'type': 'I', 'lnum': 7, 'col': 1}, + \ {'bufnr': bufnr('%') + 1, 'type': 'E', 'lnum': 1, 'col': 1}, \]) AssertEqual diff --git a/test/test_history_saving.vader b/test/test_history_saving.vader index 8207d153..3b8fb2aa 100644 --- a/test/test_history_saving.vader +++ b/test/test_history_saving.vader @@ -2,6 +2,8 @@ Before: Save g:ale_max_buffer_history_size Save g:ale_history_log_output + unlet! b:ale_history + " Temporarily set the shell to /bin/sh, if it isn't already set that way. " This will make it so the test works when running it directly. let g:current_shell = &shell @@ -26,6 +28,9 @@ Before: After: Restore + " Clear the history we changed. + unlet! b:ale_history + " Reset the shell back to what it was before. let &shell = g:current_shell unlet g:current_shell @@ -46,7 +51,7 @@ Execute(History should be set when commands are run): call ale#Lint() call ale#engine#WaitForJobs(2000) - let g:history = g:ale_buffer_info[bufnr('%')].history + let g:history = ale#history#Get(bufnr('')) AssertEqual 1, len(g:history) AssertEqual sort(['status', 'exit_code', 'job_id', 'command']), sort(keys(g:history[0])) @@ -64,7 +69,7 @@ Execute(History should be not set when disabled): call ale#Lint() call ale#engine#WaitForJobs(2000) - AssertEqual 0, len(g:ale_buffer_info[bufnr('%')].history) + AssertEqual [], ale#history#Get(bufnr('')) Execute(History should include command output if logging is enabled): AssertEqual 'foobar', &filetype @@ -74,35 +79,32 @@ Execute(History should include command output if logging is enabled): call ale#Lint() call ale#engine#WaitForJobs(2000) - let g:history = g:ale_buffer_info[bufnr('%')].history + let g:history = ale#history#Get(bufnr('')) AssertEqual 1, len(g:history) AssertEqual ['command history test'], g:history[0].output Execute(History items should be popped after going over the max): - let g:ale_buffer_info[1] = { - \ 'history': map(range(20), '{''status'': ''started'', ''job_id'': v:val, ''command'': ''foobar''}'), - \} + let b:ale_history = map(range(20), '{''status'': ''started'', ''job_id'': v:val, ''command'': ''foobar''}') - call ale#history#Add(1, 'started', 347, 'last command') + call ale#history#Add(bufnr(''), 'started', 347, 'last command') AssertEqual \ ( \ map(range(1, 19), '{''status'': ''started'', ''job_id'': v:val, ''command'': ''foobar''}') \ + [{'status': 'started', 'job_id': 347, 'command': 'last command'}] \ ), - \ g:ale_buffer_info[1].history + \ ale#history#Get(bufnr('')) Execute(Nothing should be added to history if the size is too low): let g:ale_max_buffer_history_size = 0 - let g:ale_buffer_info[1] = {'history': []} - call ale#history#Add(1, 'started', 347, 'last command') + call ale#history#Add(bufnr(''), 'started', 347, 'last command') - AssertEqual [], g:ale_buffer_info[1].history + AssertEqual [], ale#history#Get(bufnr('')) let g:ale_max_buffer_history_size = -2 call ale#history#Add(1, 'started', 347, 'last command') - AssertEqual [], g:ale_buffer_info[1].history + AssertEqual [], ale#history#Get(bufnr('')) diff --git a/test/test_lint_error_delay.vader b/test/test_lint_error_delay.vader new file mode 100644 index 00000000..4c7f0947 --- /dev/null +++ b/test/test_lint_error_delay.vader @@ -0,0 +1,26 @@ +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 queuing echo messages for a while after exceptions are thrown): + AssertThrows call ale#cursor#EchoCursorWarningWithDelay() + call ale#cursor#EchoCursorWarningWithDelay() + +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 b0dc1eb3..cb859790 100644 --- a/test/test_lint_file_linters.vader +++ b/test/test_lint_file_linters.vader @@ -1,6 +1,11 @@ Before: Save g:ale_run_synchronously + Save g:ale_buffer_info + Save g:ale_linters + + let g:ale_buffer_info = {} let g:ale_run_synchronously = 1 + call ale#ResetLintFileMarkers() let g:buffer_result = [ \ { @@ -74,8 +79,14 @@ Before: call ale#test#SetFilename(g:filename) After: + if !g:ale_run_synchronously + call ale#engine#WaitForJobs(2000) + endif + Restore + unlet! b:ale_save_event_fired + unlet! b:ale_enabled unlet g:buffer_result let g:ale_buffer_info = {} call ale#linter#Reset() @@ -95,8 +106,6 @@ Given foobar (Some imaginary filetype): baz Execute(Running linters without 'lint_file' should run only buffer linters): - call ale#ResetLintFileMarkers() - let g:ale_buffer_info = {} call ale#Queue(0) AssertEqual [ @@ -115,9 +124,6 @@ Execute(Running linters without 'lint_file' should run only buffer linters): \], GetSimplerLoclist() Execute(Running linters with 'lint_file' should run all linters): - call ale#ResetLintFileMarkers() - let g:ale_buffer_info = {} - Assert filereadable(expand('%:p')), 'The file was not readable' call ale#Queue(0, 'lint_file') @@ -150,9 +156,6 @@ Execute(Running linters with 'lint_file' should run all linters): \], GetSimplerLoclist() Execute(Linter errors from files should be kept): - call ale#ResetLintFileMarkers() - let g:ale_buffer_info = {} - Assert filereadable(expand('%:p')), 'The file was not readable' call ale#Queue(0, 'lint_file') @@ -189,3 +192,98 @@ Execute(Linter errors from files should be kept): \ 'type': 'E', \ }, \], GetSimplerLoclist() + +Execute(Linter errors from files should be kept when no other linters are run): + let g:ale_linters = {'foobar': ['lint_file_linter']} + Assert filereadable(expand('%:p')), 'The file was not readable' + + call ale#Queue(0, 'lint_file') + + AssertEqual [ + \ { + \ 'lnum': 1, + \ 'col': 3, + \ 'text': 'file warning', + \ 'type': 'W', + \ }, + \ { + \ 'lnum': 2, + \ 'col': 3, + \ 'text': 'file error', + \ 'type': 'E', + \ }, + \], GetSimplerLoclist() + + call ale#Queue(0) + + AssertEqual [ + \ { + \ 'lnum': 1, + \ 'col': 3, + \ 'text': 'file warning', + \ 'type': 'W', + \ }, + \ { + \ 'lnum': 2, + \ 'col': 3, + \ 'text': 'file error', + \ 'type': 'E', + \ }, + \], GetSimplerLoclist() + +Execute(The Save event should respect the buffer number): + let g:ale_linters = {'foobar': ['lint_file_linter']} + Assert filereadable(expand('%:p')), 'The file was not readable' + + call ale#events#SaveEvent(bufnr('') + 1) + + " We shouldn't get any prblems yet. + AssertEqual [], GetSimplerLoclist() + + call ale#events#SaveEvent(bufnr('')) + + " We should get them now we used the right buffer number. + AssertEqual [ + \ { + \ 'lnum': 1, + \ 'col': 3, + \ 'text': 'file warning', + \ 'type': 'W', + \ }, + \ { + \ 'lnum': 2, + \ 'col': 3, + \ 'text': 'file error', + \ 'type': 'E', + \ }, + \], GetSimplerLoclist() + +Execute(The Save event should set b:ale_save_event_fired to 1): + let b:ale_enabled = 0 + call ale#events#SaveEvent(bufnr('')) + + " This flag needs to be set so windows can be opened, etc. + AssertEqual 1, b:ale_save_event_fired + +Execute(b:ale_save_event_fired should be set to 0 when results are set): + let b:ale_save_event_fired = 1 + + call ale#engine#SetResults(bufnr(''), []) + + AssertEqual 0, b:ale_save_event_fired + +Execute(lint_file linters should stay running after checking without them): + let g:ale_run_synchronously = 0 + + " Run all linters, then just the buffer linters. + call ale#Queue(0, 'lint_file') + call ale#Queue(0) + + " The lint_file linter should still be running. + AssertEqual + \ ['lint_file_linter', 'buffer_linter'], + \ g:ale_buffer_info[bufnr('')].active_linter_list + " We should have 1 job for each linter. + AssertEqual 2, len(g:ale_buffer_info[bufnr('')].job_list) + + call ale#engine#WaitForJobs(2000) diff --git a/test/test_lint_on_enter_when_file_changed.vader b/test/test_lint_on_enter_when_file_changed.vader index cfa53878..4d4f19cc 100644 --- a/test/test_lint_on_enter_when_file_changed.vader +++ b/test/test_lint_on_enter_when_file_changed.vader @@ -64,7 +64,7 @@ Execute(The buffer should be checked after entering it after the file has change let b:ale_file_changed = 1 set filetype=foobar - call ale#events#EnterEvent() + call ale#events#EnterEvent(bufnr('')) AssertEqual [{ \ 'bufnr': bufnr(''), diff --git a/test/test_lint_on_filetype_changed.vader b/test/test_lint_on_filetype_changed.vader new file mode 100644 index 00000000..44446ef0 --- /dev/null +++ b/test/test_lint_on_filetype_changed.vader @@ -0,0 +1,47 @@ +Before: + Save &filetype + + let g:queue_calls = [] + + function! ale#Queue(...) + call add(g:queue_calls, a:000) + endfunction + +After: + Restore + + unlet! g:queue_calls + + " Reload the ALE code to load the real function again. + runtime autoload/ale.vim + + unlet! b:ale_original_filetype + +Execute(The original filetype should be set on BufEnter): + let &filetype = 'foobar' + + call ale#events#EnterEvent(bufnr('')) + + AssertEqual 'foobar', b:ale_original_filetype + + let &filetype = 'bazboz' + + call ale#events#EnterEvent(bufnr('')) + + AssertEqual 'bazboz', b:ale_original_filetype + +Execute(Linting should not be queued when the filetype is the same): + let b:ale_original_filetype = 'foobar' + let g:queue_calls = [] + + call ale#events#FileTypeEvent(bufnr(''), 'foobar') + + AssertEqual [], g:queue_calls + +Execute(Linting should be queued when the filetype changes): + let b:ale_original_filetype = 'foobar' + let g:queue_calls = [] + + call ale#events#FileTypeEvent(bufnr(''), 'bazboz') + + AssertEqual [[300, 'lint_file', bufnr('')]], g:queue_calls diff --git a/test/test_linter_defintion_processing.vader b/test/test_linter_defintion_processing.vader index 572591db..d946a600 100644 --- a/test/test_linter_defintion_processing.vader +++ b/test/test_linter_defintion_processing.vader @@ -372,6 +372,8 @@ Execute(PreProcess should accept tsserver LSP configuration): \ 'executable': 'x', \ 'command': 'x', \ 'lsp': 'tsserver', + \ 'language_callback': 'x', + \ 'project_root_callback': 'x', \} AssertEqual 'tsserver', ale#linter#PreProcess(g:linter).lsp @@ -392,6 +394,8 @@ Execute(PreProcess should accept stdio LSP configuration): \ 'executable': 'x', \ 'command': 'x', \ 'lsp': 'stdio', + \ 'language_callback': 'x', + \ 'project_root_callback': 'x', \} AssertEqual 'stdio', ale#linter#PreProcess(g:linter).lsp @@ -411,6 +415,8 @@ Execute(PreProcess should accept LSP server configurations): \ 'name': 'x', \ 'lsp': 'socket', \ 'address_callback': 'X', + \ 'language_callback': 'x', + \ 'project_root_callback': 'x', \} AssertEqual 'socket', ale#linter#PreProcess(g:linter).lsp diff --git a/test/test_linting_updates_loclist.vader b/test/test_linting_updates_loclist.vader index 19adfa1f..a1daf28d 100644 --- a/test/test_linting_updates_loclist.vader +++ b/test/test_linting_updates_loclist.vader @@ -1,4 +1,7 @@ Before: + Save g:ale_set_signs + let g:ale_set_signs = 1 + let g:expected_data = [ \ { \ 'lnum': 1, @@ -49,7 +52,11 @@ Before: \ 'read_buffer': 0, \}) + sign unplace * + After: + Restore + delfunction TestCallback unlet! g:expected_data diff --git a/test/test_list_opening.vader b/test/test_list_opening.vader index a46f28e5..7d386d80 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_buffer_info let g:ale_set_loclist = 1 let g:ale_set_quickfix = 0 @@ -13,11 +14,12 @@ Before: let g:ale_list_window_size = 10 let g:loclist = [ - \ {'lnum': 5, 'col': 5}, - \ {'lnum': 5, 'col': 4}, - \ {'lnum': 2, 'col': 10}, - \ {'lnum': 3, 'col': 2}, + \ {'bufnr': bufnr(''), 'lnum': 5, 'col': 5, 'text': 'x'}, + \ {'bufnr': bufnr(''), 'lnum': 5, 'col': 4, 'text': 'x'}, + \ {'bufnr': bufnr(''), 'lnum': 2, 'col': 10, 'text': 'x'}, + \ {'bufnr': bufnr(''), 'lnum': 3, 'col': 2, 'text': 'x'}, \] + let g:ale_buffer_info = {bufnr(''): {'loclist': g:loclist}} function GetQuickfixHeight() abort for l:win in range(1, winnr('$')) @@ -34,6 +36,10 @@ After: unlet! g:loclist 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 " Close quickfix window after every execute block @@ -117,6 +123,10 @@ Execute(The quickfix window should open for the quickfix list): let g:ale_set_quickfix = 1 let g:ale_open_list = 1 + let g:ale_buffer_info[bufnr('') + 1] = { + \ 'loclist': [{'bufnr': -1, 'filename': '/foo/bar', 'lnum': 5, 'col': 5, 'text': 'x'}], + \} + " It should not open for an empty list. call ale#list#SetLists(bufnr('%'), []) call ale#list#CloseWindowIfNeeded(bufnr('')) @@ -127,10 +137,17 @@ Execute(The quickfix window should open for the quickfix list): call ale#list#CloseWindowIfNeeded(bufnr('')) Assert ale#list#IsQuickfixOpen(), 'The quickfix window was closed when the list was not empty' - " Clear the list and it should close again. + " Clear this List. The window should stay open, as there are other items. + let g:ale_buffer_info[bufnr('')].loclist = [] + call ale#list#SetLists(bufnr('%'), []) + call ale#list#CloseWindowIfNeeded(bufnr('')) + Assert ale#list#IsQuickfixOpen(), 'The quickfix window closed even though there are items in another buffer' + + " Clear the other List now. Now the window should close. + call remove(g:ale_buffer_info, bufnr('') + 1) call ale#list#SetLists(bufnr('%'), []) call ale#list#CloseWindowIfNeeded(bufnr('')) - Assert !ale#list#IsQuickfixOpen(), 'The quickfix window was not closed when the list was empty' + Assert !ale#list#IsQuickfixOpen(), 'The quickfix window was not closed' Execute(The quickfix window should stay open for the quickfix list): let g:ale_set_quickfix = 1 @@ -163,3 +180,41 @@ Execute(The quickfix window height should be correct for the quickfix list with call ale#list#CloseWindowIfNeeded(bufnr('')) AssertEqual 8, GetQuickfixHeight() + +Execute(The buffer ale_open_list option should be respected): + let b:ale_open_list = 1 + + call ale#list#SetLists(bufnr('%'), g:loclist) + Assert ale#list#IsQuickfixOpen() + +Execute(The buffer ale_keep_list_window_open option should be respected): + let b:ale_open_list = 1 + let b:ale_keep_list_window_open = 1 + + call ale#list#SetLists(bufnr('%'), g:loclist) + call ale#list#CloseWindowIfNeeded(bufnr('')) + call ale#list#SetLists(bufnr('%'), []) + call ale#list#CloseWindowIfNeeded(bufnr('')) + + Assert ale#list#IsQuickfixOpen() + +Execute(The ale_open_list='on_save' option should work): + let b:ale_open_list = 'on_save' + + call ale#list#SetLists(bufnr('%'), g:loclist) + " The list shouldn't open yet, the event wasn't fired. + Assert !ale#list#IsQuickfixOpen() + + let b:ale_save_event_fired = 1 + + call ale#list#SetLists(bufnr('%'), g:loclist) + " Now the list should have opened. + Assert ale#list#IsQuickfixOpen() + +Execute(The window shouldn't open on save when ale_open_list=0): + let b:ale_open_list = 0 + let b:ale_save_event_fired = 1 + + call ale#list#SetLists(bufnr('%'), g:loclist) + " Now the list should have opened. + Assert !ale#list#IsQuickfixOpen() diff --git a/test/test_list_titles.vader b/test/test_list_titles.vader index fe28629d..74cb4bcc 100644 --- a/test/test_list_titles.vader +++ b/test/test_list_titles.vader @@ -1,7 +1,9 @@ Before: Save g:ale_set_loclist Save g:ale_set_quickfix + Save g:ale_buffer_info + let g:ale_buffer_info = {} let g:ale_set_loclist = 0 let g:ale_set_quickfix = 0 @@ -43,6 +45,10 @@ Execute(The quickfix titles should be set appropriately): let g:ale_set_quickfix = 1 + let g:ale_buffer_info[bufnr('')] = { + \ 'loclist': [{'bufnr': bufnr(''), 'lnum': 5, 'col': 5, 'text': 'x', 'type': 'E'}], + \} + call ale#list#SetLists(bufnr(''), [ \ {'bufnr': bufnr(''), 'lnum': 5, 'col': 5, 'text': 'x', 'type': 'E'}, \]) diff --git a/test/test_loclist_binary_search.vader b/test/test_loclist_binary_search.vader index e0b2c651..5558191c 100644 --- a/test/test_loclist_binary_search.vader +++ b/test/test_loclist_binary_search.vader @@ -1,26 +1,49 @@ Before: let g:loclist = [ - \ {'lnum': 2, 'col': 10}, - \ {'lnum': 3, 'col': 2}, - \ {'lnum': 3, 'col': 10}, - \ {'lnum': 3, 'col': 12}, - \ {'lnum': 3, 'col': 25}, - \ {'lnum': 5, 'col': 4}, - \ {'lnum': 5, 'col': 5}, + \ {'bufnr': 1, 'lnum': 2, 'col': 10}, + \ {'bufnr': 1, 'lnum': 3, 'col': 2}, + \ {'bufnr': 1, 'lnum': 3, 'col': 10}, + \ {'bufnr': 1, 'lnum': 3, 'col': 12}, + \ {'bufnr': 1, 'lnum': 3, 'col': 25}, + \ {'bufnr': 1, 'lnum': 5, 'col': 4}, + \ {'bufnr': 1, 'lnum': 5, 'col': 5}, + \ {'bufnr': 1, 'lnum': 9, 'col': 5}, + \ {'bufnr': 1, 'lnum': 10, 'col': 1}, + \ {'bufnr': 2, 'lnum': 7, 'col': 10}, + \ {'bufnr': 2, 'lnum': 9, 'col': 2}, + \ {'bufnr': 2, 'lnum': 10, 'col': 2}, + \ {'bufnr': 2, 'lnum': 11, 'col': 2}, \] -Execute (Exact column matches should be correct): - AssertEqual 1, ale#util#BinarySearch(g:loclist, 3, 2) +After: + unlet g:loclist -Execute (Off lines, there should be no match): - AssertEqual -1, ale#util#BinarySearch(g:loclist, 4, 2) +Execute(Exact column matches should be correct): + AssertEqual 1, ale#util#BinarySearch(g:loclist, 1, 3, 2) -Execute (Near column matches should be taken): - AssertEqual 2, ale#util#BinarySearch(g:loclist, 3, 11) - AssertEqual 4, ale#util#BinarySearch(g:loclist, 3, 13) +Execute(Off lines, there should be no match): + AssertEqual -1, ale#util#BinarySearch(g:loclist, 1, 4, 2) -Execute (Columns before should be taken when the cursor is far ahead): - AssertEqual 4, ale#util#BinarySearch(g:loclist, 3, 300) +Execute(Near column matches should be taken): + AssertEqual 2, ale#util#BinarySearch(g:loclist, 1, 3, 11) + AssertEqual 3, ale#util#BinarySearch(g:loclist, 1, 3, 13) -After: - unlet g:loclist +Execute(Columns before should be taken when the cursor is far ahead): + AssertEqual 4, ale#util#BinarySearch(g:loclist, 1, 3, 300) + +Execute(The only problems on lines in later columns should be matched): + AssertEqual 7, ale#util#BinarySearch(g:loclist, 1, 9, 1) + +Execute(The only problems on lines in earlier columns should be matched): + AssertEqual 8, ale#util#BinarySearch(g:loclist, 1, 10, 30) + +Execute(Lines for other buffers should not be matched): + AssertEqual -1, ale#util#BinarySearch(g:loclist, 1, 7, 10) + +Execute(Searches for buffers later in the list should work): + AssertEqual 10, ale#util#BinarySearch(g:loclist, 2, 9, 10) + +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) diff --git a/test/test_loclist_corrections.vader b/test/test_loclist_corrections.vader index e23109ed..e6844d8e 100644 --- a/test/test_loclist_corrections.vader +++ b/test/test_loclist_corrections.vader @@ -1,3 +1,7 @@ +After: + unlet! b:temp_name + unlet! b:other_bufnr + Given foo (Some file with lines to count): foo12345678 bar12345678 @@ -202,7 +206,6 @@ Execute(FixLocList should pass on end_lnum values): \ ], \ ) - Execute(FixLocList should allow subtypes to be set): AssertEqual \ [ @@ -223,3 +226,104 @@ Execute(FixLocList should allow subtypes to be set): \ 'foobar', \ [{'text': 'a', 'lnum': 11, 'sub_type': 'style'}], \ ) + +Execute(FixLocList should accept filenames): + let b:other_bufnr = bufnr('/foo/bar/baz', 1) + + " Make sure we actually get another buffer number, or the test is invalid. + AssertNotEqual -1, b:other_bufnr + + call ale#test#SetFilename('test.txt') + + AssertEqual + \ [ + \ { + \ 'text': 'a', + \ 'lnum': 2, + \ 'col': 0, + \ 'bufnr': bufnr('%'), + \ 'filename': expand('%:p'), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'foobar', + \ }, + \ { + \ 'text': 'a', + \ 'lnum': 3, + \ 'col': 0, + \ 'bufnr': bufnr('%'), + \ 'filename': expand('%:p'), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'foobar', + \ }, + \ { + \ 'text': 'a', + \ 'lnum': 4, + \ 'col': 0, + \ 'bufnr': b:other_bufnr, + \ 'filename': '/foo/bar/baz', + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'foobar', + \ }, + \ { + \ 'text': 'a', + \ 'lnum': 5, + \ 'col': 0, + \ 'bufnr': b:other_bufnr, + \ 'filename': '/foo/bar/baz', + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'foobar', + \ }, + \], + \ ale#engine#FixLocList( + \ bufnr('%'), + \ 'foobar', + \ [ + \ {'text': 'a', 'lnum': 2, 'filename': expand('%:p')}, + \ {'text': 'a', 'lnum': 3, 'filename': expand('%:p')}, + \ {'text': 'a', 'lnum': 4, 'filename': '/foo/bar/baz'}, + \ {'text': 'a', 'lnum': 5, 'filename': '/foo/bar/baz'}, + \ ], + \ ) + +Execute(FixLocList should interpret temporary filenames as being the current buffer): + let b:temp_name = tempname() + + AssertEqual + \ [ + \ { + \ 'text': 'a', + \ 'lnum': 2, + \ 'col': 0, + \ 'bufnr': bufnr(''), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'foobar', + \ }, + \ { + \ 'text': 'a', + \ 'lnum': 3, + \ 'col': 0, + \ 'bufnr': bufnr(''), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'foobar', + \ }, + \], + \ ale#engine#FixLocList( + \ bufnr(''), + \ 'foobar', + \ [ + \ {'text': 'a', 'lnum': 2, 'filename': b:temp_name}, + \ {'text': 'a', 'lnum': 3, 'filename': b:temp_name}, + \ ], + \ ) diff --git a/test/test_loclist_jumping.vader b/test/test_loclist_jumping.vader index 13eac5ce..5e18499e 100644 --- a/test/test_loclist_jumping.vader +++ b/test/test_loclist_jumping.vader @@ -1,14 +1,16 @@ Before: let g:ale_buffer_info = { - \ bufnr('%'): { + \ bufnr(''): { \ 'loclist': [ - \ {'lnum': 1, 'col': 2}, - \ {'lnum': 1, 'col': 3}, - \ {'lnum': 2, 'col': 1}, - \ {'lnum': 2, 'col': 2}, - \ {'lnum': 2, 'col': 3}, - \ {'lnum': 2, 'col': 6}, - \ {'lnum': 2, 'col': 700}, + \ {'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}, \ ], \ }, \} @@ -74,3 +76,15 @@ Execute(We shouldn't move when jumping to the first item where there are none): let g:ale_buffer_info[bufnr('%')].loclist = [] AssertEqual [1, 6], TestJump(0, 0, [1, 6]) + +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}) + + AssertEqual 0, len(getline(3)) + AssertEqual [2, 8], TestJump('before', 0, [3, 1]) + AssertEqual [2, 8], TestJump('before', 1, [3, 1]) + AssertEqual [3, 1], TestJump('after', 0, [3, 1]) + AssertEqual [1, 2], TestJump('after', 1, [3, 1]) diff --git a/test/test_loclist_sorting.vader b/test/test_loclist_sorting.vader index 6e52be6f..157b2a25 100644 --- a/test/test_loclist_sorting.vader +++ b/test/test_loclist_sorting.vader @@ -1,21 +1,27 @@ -Before: - let g:loclist = [ - \ {'lnum': 5, 'col': 5}, - \ {'lnum': 5, 'col': 4}, - \ {'lnum': 2, 'col': 10}, - \ {'lnum': 3, 'col': 2}, - \] - -Execute (Sort loclist with comparison function): - call sort(g:loclist, 'ale#util#LocItemCompare') - -Then (loclist item should be sorted): +Execute(loclist item should be sorted): AssertEqual [ - \ {'lnum': 2, 'col': 10}, - \ {'lnum': 3, 'col': 2}, - \ {'lnum': 5, 'col': 4}, - \ {'lnum': 5, 'col': 5}, - \], g:loclist - -After: - unlet g:loclist + \ {'bufnr': -1, 'filename': 'b', 'lnum': 4, 'col': 2}, + \ {'bufnr': -1, 'filename': 'b', 'lnum': 5, 'col': 2}, + \ {'bufnr': -1, 'filename': 'c', 'lnum': 3, 'col': 2}, + \ {'bufnr': 1, 'lnum': 2, 'col': 10}, + \ {'bufnr': 1, 'lnum': 3, 'col': 2}, + \ {'bufnr': 1, 'lnum': 5, 'col': 4}, + \ {'bufnr': 1, 'lnum': 5, 'col': 5}, + \ {'bufnr': 2, 'lnum': 1, 'col': 2}, + \ {'bufnr': 2, 'lnum': 1, 'col': 5}, + \ {'bufnr': 2, 'lnum': 5, 'col': 5}, + \ {'bufnr': 3, 'lnum': 1, 'col': 1}, + \ ], + \ sort([ + \ {'bufnr': 3, 'lnum': 1, 'col': 1}, + \ {'bufnr': -1, 'filename': 'b', 'lnum': 5, 'col': 2}, + \ {'bufnr': 1, 'lnum': 5, 'col': 5}, + \ {'bufnr': 2, 'lnum': 5, 'col': 5}, + \ {'bufnr': -1, 'filename': 'b', 'lnum': 4, 'col': 2}, + \ {'bufnr': 1, 'lnum': 5, 'col': 4}, + \ {'bufnr': 1, 'lnum': 2, 'col': 10}, + \ {'bufnr': 2, 'lnum': 1, 'col': 5}, + \ {'bufnr': 1, 'lnum': 3, 'col': 2}, + \ {'bufnr': 2, 'lnum': 1, 'col': 2}, + \ {'bufnr': -1, 'filename': 'c', 'lnum': 3, 'col': 2}, + \], 'ale#util#LocItemCompare') diff --git a/test/test_path_uri.vader b/test/test_path_uri.vader new file mode 100644 index 00000000..dbceac3a --- /dev/null +++ b/test/test_path_uri.vader @@ -0,0 +1,16 @@ +Execute(ale#path#ToURI should work for Windows paths): + AssertEqual 'file:///C:/foo/bar/baz.tst', ale#path#ToURI('C:\foo\bar\baz.tst') + AssertEqual 'foo/bar/baz.tst', ale#path#ToURI('foo\bar\baz.tst') + +Execute(ale#path#ToURI should work for Unix paths): + AssertEqual 'file:///foo/bar/baz.tst', ale#path#ToURI('/foo/bar/baz.tst') + AssertEqual 'foo/bar/baz.tst', ale#path#ToURI('foo/bar/baz.tst') + +Execute(ale#path#ToURI should keep safe characters): + AssertEqual '//a-zA-Z0-9$-_.!*''(),', ale#path#ToURI('\/a-zA-Z0-9$-_.!*''(),') + +Execute(ale#path#ToURI should percent encode unsafe characters): + AssertEqual '%20%2b%3a%3f%26%3d', ale#path#ToURI(' +:?&=') + +Execute(ale#path#FromURI should decode percent encodings): + AssertEqual ' +:?&=', ale#path#FromURI('%20%2b%3a%3f%26%3d') diff --git a/test/test_quickfix_deduplication.vader b/test/test_quickfix_deduplication.vader new file mode 100644 index 00000000..0dff3f2e --- /dev/null +++ b/test/test_quickfix_deduplication.vader @@ -0,0 +1,50 @@ +Before: + Save g:ale_buffer_info + +After: + Restore + +Execute: + " Results from multiple buffers should be gathered together. + " 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'}, + \ ]}, + \ '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'}, + \ ]}, + \} + + 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'}, + \ ], + \ ale#list#GetCombinedList() diff --git a/test/test_results_not_cleared_when_opening_loclist.vader b/test/test_results_not_cleared_when_opening_loclist.vader index 07d3d303..0c053b85 100644 --- a/test/test_results_not_cleared_when_opening_loclist.vader +++ b/test/test_results_not_cleared_when_opening_loclist.vader @@ -26,6 +26,9 @@ After: delfunction TestCallback let g:ale_buffer_info = {} call ale#linter#Reset() + call setloclist(0, []) + call clearmatches() + sign unplace * Given foobar (Some file): abc diff --git a/test/test_set_list_timers.vader b/test/test_set_list_timers.vader new file mode 100644 index 00000000..90aacb55 --- /dev/null +++ b/test/test_set_list_timers.vader @@ -0,0 +1,38 @@ +Before: + Save g:ale_set_lists_synchronously + Save g:ale_open_list + + let g:ale_set_lists_synchronously = 0 + +After: + Restore + + sleep 1ms + call setloclist(0, []) + lclose + +Execute(The SetLists function should work when run in a timer): + call ale#list#SetLists(bufnr(''), [ + \ {'bufnr': bufnr(''), 'lnum': 5, 'col': 5, 'text': 'x', 'type': 'E'}, + \]) + sleep 1ms + AssertEqual [{ + \ 'lnum': 5, + \ 'bufnr': bufnr(''), + \ 'col': 5, + \ 'text': 'x', + \ 'valid': 1, + \ 'vcol': 0, + \ 'nr': 0, + \ 'type': 'E', + \ 'pattern': '', + \}], getloclist(0) + +Execute(The CloseWindowIfNeeded function should work when run in a timer): + let g:ale_open_list = 1 + lopen + + call ale#list#CloseWindowIfNeeded(bufnr('')) + sleep 1ms + + Assert !ale#list#IsQuickfixOpen(), 'The window was not closed!' diff --git a/test/test_setting_loclist_from_another_buffer.vader b/test/test_setting_loclist_from_another_buffer.vader index 4b757c61..10a44cce 100644 --- a/test/test_setting_loclist_from_another_buffer.vader +++ b/test/test_setting_loclist_from_another_buffer.vader @@ -1,12 +1,25 @@ Before: + Save g:ale_buffer_info + + let g:ale_buffer_info = { + \ bufnr(''): { + \ 'loclist': [{'bufnr': bufnr(''), 'lnum': 4, 'col': 1, 'text': 'foo'}] + \ }, + \} + let g:original_buffer = bufnr('%') - new + noautocmd new After: + Restore + unlet! g:original_buffer Execute(Errors should be set in the loclist for the original buffer, not the new one): - call ale#list#SetLists(g:original_buffer, [{'lnum': 4, 'text': 'foo'}]) + call ale#list#SetLists( + \ g:original_buffer, + \ g:ale_buffer_info[(g:original_buffer)].loclist, + \ ) AssertEqual [], getloclist(0) AssertEqual 1, len(getloclist(bufwinid(g:original_buffer))) diff --git a/test/test_setting_problems_found_in_previous_buffers.vader b/test/test_setting_problems_found_in_previous_buffers.vader new file mode 100644 index 00000000..45dfa662 --- /dev/null +++ b/test/test_setting_problems_found_in_previous_buffers.vader @@ -0,0 +1,98 @@ +Before: + Save g:ale_buffer_info + Save &filetype + Save g:ale_set_lists_synchronously + + let g:ale_set_lists_synchronously = 1 + + " Set up items in other buffers which should set in this one. + let g:ale_buffer_info = {} + call ale#engine#InitBufferInfo(bufnr('') + 1) + let g:ale_buffer_info[bufnr('') + 1].loclist = + \ ale#engine#FixLocList(bufnr('') + 1, 'linter_one', [ + \ {'lnum': 1, 'filename': expand('%:p'), 'text': 'foo'}, + \ {'lnum': 2, 'filename': expand('%:p'), 'text': 'bar'}, + \ {'lnum': 2, 'text': 'ignore this one'}, + \ ]) + call ale#engine#InitBufferInfo(bufnr('') + 2) + let g:ale_buffer_info[bufnr('') + 2].loclist = + \ ale#engine#FixLocList(bufnr('') + 2, 'linter_one', [ + \ {'lnum': 1, 'filename': expand('%:p'), 'text': 'foo'}, + \ {'lnum': 3, 'filename': expand('%:p'), 'text': 'baz'}, + \ {'lnum': 5, 'text': 'ignore this one'}, + \ ]) + + call ale#linter#Define('foobar', { + \ 'name': 'linter_one', + \ 'callback': 'WhoCares', + \ 'executable': 'echo', + \ 'command': 'sleep 1000', + \ 'lint_file': 1, + \}) + +After: + call ale#engine#Cleanup(bufnr('')) + Restore + call ale#linter#Reset() + + " Items and markers, etc. + call setloclist(0, []) + call clearmatches() + sign unplace * + +Given foobar(A file with some lines): + foo + bar + baz + +Execute(Problems found from previously opened buffers should be set when linting for the first time): + call ale#engine#RunLinters(bufnr(''), ale#linter#Get(&filetype), 0) + + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'bufnr': bufnr(''), + \ 'col': 0, + \ 'filename': expand('%:p'), + \ 'linter_name': 'linter_one', + \ 'nr': -1, + \ 'type': 'E', + \ 'vcol': 0, + \ 'text': 'foo', + \ 'sign_id': 1000001, + \ }, + \ { + \ 'lnum': 2, + \ 'bufnr': bufnr(''), + \ 'col': 0, + \ 'filename': expand('%:p'), + \ 'linter_name': 'linter_one', + \ 'nr': -1, + \ 'type': 'E', + \ 'vcol': 0, + \ 'text': 'bar', + \ 'sign_id': 1000002, + \ }, + \ { + \ 'lnum': 3, + \ 'bufnr': bufnr(''), + \ 'col': 0, + \ 'filename': expand('%:p'), + \ 'linter_name': 'linter_one', + \ 'nr': -1, + \ 'type': 'E', + \ 'vcol': 0, + \ 'text': 'baz', + \ 'sign_id': 1000003, + \ }, + \ ], + \ g:ale_buffer_info[bufnr('')].loclist + + AssertEqual + \ [ + \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'E', 'pattern': '', 'text': 'foo'}, + \ {'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) diff --git a/test/test_shell_detection.vader b/test/test_shell_detection.vader new file mode 100644 index 00000000..37cf43ce --- /dev/null +++ b/test/test_shell_detection.vader @@ -0,0 +1,83 @@ +Before: + runtime ale_linters/sh/shell.vim + runtime ale_linters/sh/shellcheck.vim + +After: + call ale#linter#Reset() + + unlet! b:is_bash + unlet! b:is_sh + unlet! b:is_kornshell + +Given(A file with a Bash hashbang): + #!/bin/bash + +Execute(/bin/bash should be detected appropriately): + AssertEqual 'bash', ale#handlers#sh#GetShellType(bufnr('')) + AssertEqual 'bash', ale_linters#sh#shell#GetExecutable(bufnr('')) + AssertEqual 'bash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with /bin/sh): + #!/usr/bin/env sh -eu --foobar + +Execute(/bin/sh should be detected appropriately): + AssertEqual 'sh', ale#handlers#sh#GetShellType(bufnr('')) + AssertEqual 'sh', ale_linters#sh#shell#GetExecutable(bufnr('')) + AssertEqual 'sh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with bash as an argument to env): + #!/usr/bin/env bash + +Execute(/usr/bin/env bash should be detected appropriately): + AssertEqual 'bash', ale#handlers#sh#GetShellType(bufnr('')) + AssertEqual 'bash', ale_linters#sh#shell#GetExecutable(bufnr('')) + AssertEqual 'bash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with a tcsh hash bang and arguments): + #!/usr/bin/env tcsh -eu --foobar + +Execute(tcsh should be detected appropriately): + AssertEqual 'tcsh', ale#handlers#sh#GetShellType(bufnr('')) + AssertEqual 'tcsh', ale_linters#sh#shell#GetExecutable(bufnr('')) + AssertEqual 'tcsh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with a zsh hash bang and arguments): + #!/usr/bin/env zsh -eu --foobar + +Execute(zsh should be detected appropriately): + AssertEqual 'zsh', ale#handlers#sh#GetShellType(bufnr('')) + AssertEqual 'zsh', ale_linters#sh#shell#GetExecutable(bufnr('')) + AssertEqual 'zsh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with a csh hash bang and arguments): + #!/usr/bin/env csh -eu --foobar + +Execute(zsh should be detected appropriately): + AssertEqual 'csh', ale#handlers#sh#GetShellType(bufnr('')) + AssertEqual 'csh', ale_linters#sh#shell#GetExecutable(bufnr('')) + AssertEqual 'csh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with a sh hash bang and arguments): + #!/usr/bin/env sh -eu --foobar + +Execute(sh should be detected appropriately): + AssertEqual 'sh', ale#handlers#sh#GetShellType(bufnr('')) + AssertEqual 'sh', ale_linters#sh#shell#GetExecutable(bufnr('')) + AssertEqual 'sh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file without a hashbang): + +Execute(The bash dialect should be used for shellcheck if b:is_bash is 1): + let b:is_bash = 1 + + AssertEqual 'bash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + +Execute(The sh dialect should be used for shellcheck if b:is_sh is 1): + let b:is_sh = 1 + + AssertEqual 'sh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + +Execute(The ksh dialect should be used for shellcheck if b:is_kornshell is 1): + let b:is_kornshell = 1 + + AssertEqual 'ksh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) diff --git a/test/test_statusline.vader b/test/test_statusline.vader index bd0fd5dc..7978a509 100644 --- a/test/test_statusline.vader +++ b/test/test_statusline.vader @@ -1,9 +1,11 @@ Before: - Save g:ale_statusline_format, g:ale_buffer_info + Save g:ale_statusline_format + Save g:ale_buffer_info + let g:ale_buffer_info = {} " A function for conveniently creating expected count objects. - function Counts(data) abort + function! Counts(data) abort let l:res = { \ '0': 0, \ '1': 0, @@ -28,10 +30,11 @@ Before: After: Restore + delfunction Counts Execute (Count should be 0 when data is empty): - AssertEqual Counts({}), ale#statusline#Count(bufnr('%')) + AssertEqual Counts({}), ale#statusline#Count(bufnr('')) Execute (Count should read data from the cache): let g:ale_buffer_info = {'44': {'count': Counts({'error': 1, 'warning': 2})}} @@ -44,23 +47,33 @@ Execute (The count should be correct after an update): Execute (Count should be match the loclist): let g:ale_buffer_info = { - \ bufnr('%'): { + \ bufnr(''): { \ 'loclist': [ - \ {'type': 'E'}, - \ {'type': 'E', 'sub_type': 'style'}, - \ {'type': 'E', 'sub_type': 'style'}, - \ {'type': 'W'}, - \ {'type': 'W'}, - \ {'type': 'W'}, - \ {'type': 'W', 'sub_type': 'style'}, - \ {'type': 'W', 'sub_type': 'style'}, - \ {'type': 'W', 'sub_type': 'style'}, - \ {'type': 'W', 'sub_type': 'style'}, - \ {'type': 'I'}, - \ {'type': 'I'}, - \ {'type': 'I'}, - \ {'type': 'I'}, - \ {'type': 'I'}, + \ {'bufnr': bufnr('') - 1, 'type': 'E'}, + \ {'bufnr': bufnr('') - 1, 'type': 'E', 'sub_type': 'style'}, + \ {'bufnr': bufnr('') - 1, 'type': 'W'}, + \ {'bufnr': bufnr('') - 1, 'type': 'W', 'sub_type': 'style'}, + \ {'bufnr': bufnr('') - 1, 'type': 'I'}, + \ {'bufnr': bufnr(''), 'type': 'E'}, + \ {'bufnr': bufnr(''), 'type': 'E', 'sub_type': 'style'}, + \ {'bufnr': bufnr(''), 'type': 'E', 'sub_type': 'style'}, + \ {'bufnr': bufnr(''), 'type': 'W'}, + \ {'bufnr': bufnr(''), 'type': 'W'}, + \ {'bufnr': bufnr(''), 'type': 'W'}, + \ {'bufnr': bufnr(''), 'type': 'W', 'sub_type': 'style'}, + \ {'bufnr': bufnr(''), 'type': 'W', 'sub_type': 'style'}, + \ {'bufnr': bufnr(''), 'type': 'W', 'sub_type': 'style'}, + \ {'bufnr': bufnr(''), 'type': 'W', 'sub_type': 'style'}, + \ {'bufnr': bufnr(''), 'type': 'I'}, + \ {'bufnr': bufnr(''), 'type': 'I'}, + \ {'bufnr': bufnr(''), 'type': 'I'}, + \ {'bufnr': bufnr(''), 'type': 'I'}, + \ {'bufnr': bufnr(''), 'type': 'I'}, + \ {'bufnr': bufnr('') + 1, 'type': 'E'}, + \ {'bufnr': bufnr('') + 1, 'type': 'E', 'sub_type': 'style'}, + \ {'bufnr': bufnr('') + 1, 'type': 'W'}, + \ {'bufnr': bufnr('') + 1, 'type': 'W', 'sub_type': 'style'}, + \ {'bufnr': bufnr('') + 1, 'type': 'I'}, \ ], \ }, \} @@ -73,59 +86,56 @@ Execute (Count should be match the loclist): \ '0': 3, \ '1': 12, \ 'total': 15, - \}, ale#statusline#Count(bufnr('%')) + \}, ale#statusline#Count(bufnr('')) Execute (Output should be empty for non-existant 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('%'), [ - \ {'type': 'E'}, - \ {'type': 'E', 'sub_type': 'style'}, + 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('%'), [ - \ {'type': 'W'}, - \ {'type': 'W', 'sub_type': 'style'}, - \ {'type': 'I'}, + 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('%'), [ - \ {'type': 'E'}, - \ {'type': 'E', 'sub_type': 'style'}, - \ {'type': 'W'}, - \ {'type': 'W', 'sub_type': 'style'}, - \ {'type': 'I'}, + 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('%'), []) + 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_buffer_info unlet! g:ale_statusline_format call ale#statusline#Update(1, []) Execute(ale#statusline#Count should return 0 counts when globals are undefined): - unlet! g:ale_buffer_info 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_buffer_info unlet! g:ale_statusline_format AssertEqual 'OK', ale#statusline#Status() diff --git a/test/test_writefile_function.vader b/test/test_writefile_function.vader new file mode 100644 index 00000000..4e4aab53 --- /dev/null +++ b/test/test_writefile_function.vader @@ -0,0 +1,48 @@ +Before: + call ale#test#SetDirectory('/testplugin/test') + +After: + noautocmd :e! ++ff=unix + setlocal buftype=nofile + + if filereadable('.newline-test') + call delete('.newline-test') + endif + + call ale#test#RestoreDirectory() + +Given(A file with Windows line ending characters): + first
+ second
+ third
+ +Execute(Carriage returns should be included for ale#util#Writefile): + call ale#test#SetFilename('.newline-test') + + setlocal buftype= + noautocmd :w + noautocmd :e! ++ff=dos + + call ale#util#Writefile(bufnr(''), getline(1, '$'), '.newline-test') + + AssertEqual + \ ["first\r", "second\r", "third\r", ''], + \ readfile('.newline-test', 'b') + \ +Given(A file with Unix line ending characters): + first + second + third + +Execute(Unix file lines should be written as normal): + call ale#test#SetFilename('.newline-test') + + setlocal buftype= + noautocmd :w + noautocmd :e! ++ff=unix + + call ale#util#Writefile(bufnr(''), getline(1, '$'), '.newline-test') + + AssertEqual + \ ['first', 'second', 'third', ''], + \ readfile('.newline-test', 'b') diff --git a/test/util/test_cd_string_commands.vader b/test/util/test_cd_string_commands.vader index b0b6c157..f8a97cb8 100644 --- a/test/util/test_cd_string_commands.vader +++ b/test/util/test_cd_string_commands.vader @@ -1,8 +1,15 @@ Before: silent! cd /testplugin/test/util + let g:dir = getcwd() + +After: + silent execute 'cd ' . fnameescape(g:dir) + unlet! g:dir Execute(CdString should output the correct command string): AssertEqual 'cd ''/foo bar/baz'' && ', ale#path#CdString('/foo bar/baz') Execute(BufferCdString should output the correct command string): - AssertEqual 'cd ' . shellescape(getcwd()) . ' && ', ale#path#BufferCdString(bufnr('')) + call ale#test#SetFilename('foo.txt') + + AssertEqual 'cd ' . shellescape(g:dir) . ' && ', ale#path#BufferCdString(bufnr('')) @@ -1,5 +1,8 @@ " vint: -ProhibitSetNoCompatible +" Make most tests just set lists synchronously when run in Docker. +let g:ale_set_lists_synchronously = 1 + " Load builtin plugins " We need this because run_vim.sh sets -i NONE set runtimepath=/home/vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,/testplugin,/vader |