diff options
Diffstat (limited to 'test')
81 files changed, 1631 insertions, 182 deletions
diff --git a/test/command_callback/ccls_paths/with_build_dir/unusual_build_dir_name/compile_commands.json b/test/command_callback/ccls_paths/with_build_dir/unusual_build_dir_name/compile_commands.json new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/ccls_paths/with_build_dir/unusual_build_dir_name/compile_commands.json diff --git a/test/command_callback/hdl_server/foo.vhd b/test/command_callback/hdl_server/foo.vhd new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/hdl_server/foo.vhd diff --git a/test/command_callback/hdl_server/with_config_file/.hdl_checker.config b/test/command_callback/hdl_server/with_config_file/.hdl_checker.config new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/hdl_server/with_config_file/.hdl_checker.config diff --git a/test/command_callback/hdl_server/with_config_file/_hdl_checker.config b/test/command_callback/hdl_server/with_config_file/_hdl_checker.config new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/hdl_server/with_config_file/_hdl_checker.config diff --git a/test/command_callback/hdl_server/with_config_file/foo.vhd b/test/command_callback/hdl_server/with_config_file/foo.vhd new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/hdl_server/with_config_file/foo.vhd diff --git a/test/command_callback/hdl_server/with_git/files/foo.vhd b/test/command_callback/hdl_server/with_git/files/foo.vhd new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/test/command_callback/hdl_server/with_git/files/foo.vhd @@ -0,0 +1 @@ + diff --git a/test/command_callback/java_paths/build/gen/main/java/com/something/dummy b/test/command_callback/java_paths/build/gen/main/java/com/something/dummy new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/java_paths/build/gen/main/java/com/something/dummy diff --git a/test/command_callback/java_paths/build/gen2/main/java/com/something/dummy b/test/command_callback/java_paths/build/gen2/main/java/com/something/dummy new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/java_paths/build/gen2/main/java/com/something/dummy diff --git a/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/mypy.ini b/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/mypy.ini new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/mypy.ini diff --git a/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/tests/pytest.ini b/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/tests/pytest.ini new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/tests/pytest.ini diff --git a/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/tests/testsubfolder/my_tests.py b/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/tests/testsubfolder/my_tests.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/tests/testsubfolder/my_tests.py diff --git a/test/command_callback/test_bashate_command_callback.vader b/test/command_callback/test_bashate_command_callback.vader new file mode 100644 index 00000000..714cf690 --- /dev/null +++ b/test/command_callback/test_bashate_command_callback.vader @@ -0,0 +1,15 @@ +Before: + call ale#assert#SetUpLinterTest('sh', 'bashate') + call ale#test#SetFilename('test.sh') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default bashate command should be correct): + AssertLinter 'bashate', ale#Escape('bashate') . ' %t' + +Execute(The bashate command should accept options): + let b:ale_sh_bashate_options = '-i E310 --max-line-length 100' + + AssertLinter 'bashate', + \ ale#Escape('bashate') . ' -i E310 --max-line-length 100 %t' diff --git a/test/command_callback/test_c_ccls_command_callbacks.vader b/test/command_callback/test_c_ccls_command_callbacks.vader index 43fdb366..04643d02 100644 --- a/test/command_callback/test_c_ccls_command_callbacks.vader +++ b/test/command_callback/test_c_ccls_command_callbacks.vader @@ -4,6 +4,10 @@ Before: call ale#assert#SetUpLinterTest('c', 'ccls') + Save b:ale_c_build_dir_names + Save b:ale_c_ccls_executable + Save b:ale_c_ccls_init_options + After: call ale#assert#TearDownLinterTest() @@ -47,3 +51,19 @@ Execute(The initialization options should be configurable): let b:ale_c_ccls_init_options = { 'cacheDirectory': '/tmp/ccls' } AssertLSPOptions { 'cacheDirectory': '/tmp/ccls' } + +Execute(The compile command database should be detected correctly): + call ale#test#SetFilename('ccls_paths/with_ccls/dummy.c') + + AssertLSPOptions {} + + call ale#test#SetFilename('ccls_paths/with_compile_commands_json/dummy.c') + + AssertLSPOptions { 'compilationDatabaseDirectory': + \ ale#path#Simplify(g:dir . '/ccls_paths/with_compile_commands_json') } + + call ale#test#SetFilename('ccls_paths/with_build_dir/dummy.c') + let b:ale_c_build_dir_names = ['unusual_build_dir_name'] + + AssertLSPOptions { 'compilationDatabaseDirectory': + \ ale#path#Simplify(g:dir . '/ccls_paths/with_build_dir/unusual_build_dir_name') } diff --git a/test/command_callback/test_c_cppcheck_command_callbacks.vader b/test/command_callback/test_c_cppcheck_command_callbacks.vader index 3d487a31..b6ea3179 100644 --- a/test/command_callback/test_c_cppcheck_command_callbacks.vader +++ b/test/command_callback/test_c_cppcheck_command_callbacks.vader @@ -1,7 +1,6 @@ Before: call ale#assert#SetUpLinterTest('c', 'cppcheck') - - let b:command_tail = ' -q --language=c --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t' + let b:command_tail = ' -q --language=c --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'' --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t' After: " Remove a test file we might open for some tests. @@ -10,9 +9,8 @@ After: set buftype=nofile endif - call ale#assert#TearDownLinterTest() - unlet! b:command_tail + call ale#assert#TearDownLinterTest() Execute(The executable should be configurable): AssertLinter 'cppcheck', ale#Escape('cppcheck') . b:command_tail @@ -28,6 +26,7 @@ Execute(cppcheck for C should detect compile_commands.json files): \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ . ale#Escape('cppcheck') \ . ' -q --language=c' + \ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}''' \ . ' --project=' . ale#Escape('compile_commands.json') \ . ' --enable=style %t' @@ -38,6 +37,7 @@ Execute(cppcheck for C should detect compile_commands.json files in build direct \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/with_build_dir')) \ . ale#Escape('cppcheck') \ . ' -q --language=c' + \ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}''' \ . ' --project=' . ale#Escape(ale#path#Simplify('build/compile_commands.json')) \ . ' --enable=style %t' @@ -47,6 +47,7 @@ Execute(cppcheck for C should include file dir if compile_commands.json file is AssertLinter 'cppcheck', \ ale#Escape('cppcheck') \ . ' -q --language=c' + \ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}''' \ . ' --enable=style' \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths')) \ . ' %t' @@ -61,6 +62,7 @@ Execute(cppcheck for C should ignore compile_commands.json file if buffer is mod \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ . ale#Escape('cppcheck') \ . ' -q --language=c' + \ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}''' \ . ' --enable=style' \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ . ' %t' diff --git a/test/command_callback/test_checkstyle_command_callback.vader b/test/command_callback/test_checkstyle_command_callback.vader index 7a9f26b3..5824df87 100644 --- a/test/command_callback/test_checkstyle_command_callback.vader +++ b/test/command_callback/test_checkstyle_command_callback.vader @@ -20,11 +20,11 @@ Execute(The checkstyle executable should be configurable): \ . ' %s' Execute(Custom options should be supported): - let b:ale_java_checkstyle_options = '--foobar' + let b:ale_java_checkstyle_options = '--foobar -cp -classpath /path/to/checkstyle-8.7-all.jar' AssertLinter 'checkstyle', \ ale#Escape('checkstyle') - \ . ' --foobar' + \ . ' --foobar -cp -classpath /path/to/checkstyle-8.7-all.jar' \ . ' -c ' . ale#Escape('/google_checks.xml') \ . ' %s' diff --git a/test/command_callback/test_cpp_ccls_command_callbacks.vader b/test/command_callback/test_cpp_ccls_command_callbacks.vader index eece42bc..f603ac07 100644 --- a/test/command_callback/test_cpp_ccls_command_callbacks.vader +++ b/test/command_callback/test_cpp_ccls_command_callbacks.vader @@ -4,6 +4,10 @@ Before: call ale#assert#SetUpLinterTest('cpp', 'ccls') + Save b:ale_c_build_dir_names + Save b:ale_cpp_ccls_executable + Save b:ale_cpp_ccls_init_options + After: call ale#assert#TearDownLinterTest() @@ -47,3 +51,19 @@ Execute(The initialization options should be configurable): let b:ale_cpp_ccls_init_options = { 'cacheDirectory': '/tmp/ccls' } AssertLSPOptions { 'cacheDirectory': '/tmp/ccls' } + +Execute(The compile command database should be detected correctly): + call ale#test#SetFilename('ccls_paths/with_ccls/dummy.c') + + AssertLSPOptions {} + + call ale#test#SetFilename('ccls_paths/with_compile_commands_json/dummy.c') + + AssertLSPOptions { 'compilationDatabaseDirectory': + \ ale#path#Simplify(g:dir . '/ccls_paths/with_compile_commands_json') } + + call ale#test#SetFilename('ccls_paths/with_build_dir/dummy.c') + let b:ale_c_build_dir_names = ['unusual_build_dir_name'] + + AssertLSPOptions { 'compilationDatabaseDirectory': + \ ale#path#Simplify(g:dir . '/ccls_paths/with_build_dir/unusual_build_dir_name') } diff --git a/test/command_callback/test_cpp_cppcheck_command_callbacks.vader b/test/command_callback/test_cpp_cppcheck_command_callbacks.vader index 02bdf748..b19c09b1 100644 --- a/test/command_callback/test_cpp_cppcheck_command_callbacks.vader +++ b/test/command_callback/test_cpp_cppcheck_command_callbacks.vader @@ -1,6 +1,6 @@ Before: call ale#assert#SetUpLinterTest('cpp', 'cppcheck') - let b:command_tail = ' -q --language=c++ --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t' + let b:command_tail = ' -q --language=c++ --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'' --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t' After: " Remove a test file we might open for some tests. @@ -26,6 +26,7 @@ Execute(cppcheck for C++ should detect compile_commands.json files): \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ . ale#Escape('cppcheck') \ . ' -q --language=c++' + \ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}''' \ . ' --project=' . ale#Escape('compile_commands.json') \ . ' --enable=style %t' @@ -36,6 +37,7 @@ Execute(cppcheck for C++ should detect compile_commands.json files in build dire \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/with_build_dir')) \ . ale#Escape('cppcheck') \ . ' -q --language=c++' + \ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}''' \ . ' --project=' . ale#Escape(ale#path#Simplify('build/compile_commands.json')) \ . ' --enable=style %t' @@ -45,6 +47,7 @@ Execute(cppcheck for C++ should include file dir if compile_commands.json file i AssertLinter 'cppcheck', \ ale#Escape('cppcheck') \ . ' -q --language=c++' + \ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}''' \ . ' --enable=style' \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths')) \ . ' %t' @@ -59,6 +62,7 @@ Execute(cppcheck for C++ should ignore compile_commands.json file if buffer is m \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ . ale#Escape('cppcheck') \ . ' -q --language=c++' + \ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}''' \ . ' --enable=style' \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ . ' %t' diff --git a/test/command_callback/test_eclipselsp_command_callback.vader b/test/command_callback/test_eclipselsp_command_callback.vader index f25ed5fc..6bbc4053 100644 --- a/test/command_callback/test_eclipselsp_command_callback.vader +++ b/test/command_callback/test_eclipselsp_command_callback.vader @@ -54,6 +54,7 @@ Execute(VersionCheck should return correct version): Execute(The eclipselsp callback should return the correct default value): let cmd = [ ale#Escape('java'), + \ '', \ '-Declipse.application=org.eclipse.jdt.ls.core.id1', \ '-Dosgi.bundles.defaultStartLevel=4', \ '-Declipse.product=org.eclipse.jdt.ls.core.product', @@ -72,6 +73,7 @@ Execute(The eclipselsp callback should return the correct default value): Execute(The eclipselsp callback should allow custom executable): let b:ale_java_eclipselsp_executable='/bin/foobar' let cmd = [ ale#Escape('/bin/foobar'), + \ '', \ '-Declipse.application=org.eclipse.jdt.ls.core.id1', \ '-Dosgi.bundles.defaultStartLevel=4', \ '-Declipse.product=org.eclipse.jdt.ls.core.product', @@ -87,9 +89,12 @@ Execute(The eclipselsp callback should allow custom executable): \] AssertLinter '/bin/foobar', join(cmd, ' ') -Execute(The eclipselsp callback should allow custom configuration path): +Execute(The eclipselsp callback should allow custom configuration path and javaagent): let b:ale_java_eclipselsp_config_path = '/home/config' + let b:ale_java_eclipselsp_javaagent = '/home/lombok.jar /home/lombok2.jar' let cmd = [ ale#Escape('java'), + \ ale#Escape('-javaagent:/home/lombok.jar'), + \ ale#Escape('-javaagent:/home/lombok2.jar'), \ '-Declipse.application=org.eclipse.jdt.ls.core.id1', \ '-Dosgi.bundles.defaultStartLevel=4', \ '-Declipse.product=org.eclipse.jdt.ls.core.product', diff --git a/test/command_callback/test_gopls_command_callback.vader b/test/command_callback/test_gopls_command_callback.vader index 92b20b18..73fcbf03 100644 --- a/test/command_callback/test_gopls_command_callback.vader +++ b/test/command_callback/test_gopls_command_callback.vader @@ -49,7 +49,10 @@ Execute(Should return directory for 'go.mod' if found in parent directory): Execute(Should return nearest directory with '.git' if found in parent directory): call ale#test#SetFilename('test.go') - call mkdir(g:dir . '/.git') + + if !isdirectory(g:dir . '/.git') + call mkdir(g:dir . '/.git') + endif AssertLSPProject g:dir diff --git a/test/command_callback/test_javac_command_callback.vader b/test/command_callback/test_javac_command_callback.vader index 42c64e54..d2eebf7a 100644 --- a/test/command_callback/test_javac_command_callback.vader +++ b/test/command_callback/test_javac_command_callback.vader @@ -31,7 +31,7 @@ After: Execute(The javac callback should return the correct default value): AssertLinter 'javac', g:prefix . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' -Execute(The javac callback should use g:ale_java_javac_classpath correctly): +Execute(The javac callback should use string type g:ale_java_javac_classpath correctly): let g:ale_java_javac_classpath = 'foo.jar' AssertLinter 'javac', @@ -39,6 +39,14 @@ Execute(The javac callback should use g:ale_java_javac_classpath correctly): \ . ' -cp ' . ale#Escape('foo.jar') \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' +Execute(The javac callback should use list type g:ale_java_javac_classpath correctly): + let g:ale_java_javac_classpath = ['foo.jar'] + + AssertLinter 'javac', + \ g:prefix + \ . ' -cp ' . ale#Escape('foo.jar') + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' + Execute(The executable should be configurable): let g:ale_java_javac_executable = 'foobar' @@ -108,6 +116,137 @@ Execute(The javac callback should combine discovered classpaths and manual ones) \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + let g:ale_java_javac_classpath = ['configured.jar'] + let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [ + \ '[DEBUG] Ignore this.', + \ '[INFO] Something we should ignore.', + \ '/foo/bar.jar', + \ '/xyz/abc.jar', + \], {}) + + AssertEqual + \ g:prefix + \ . ' -cp ' + \ . ale#Escape(join( + \ [ + \ '/foo/bar.jar', + \ '/xyz/abc.jar', + \ 'configured.jar', + \ ], + \ g:cp_sep + \ )) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', + \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + + let g:ale_java_javac_classpath = ['configured.jar', 'configured2.jar'] + let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [ + \ '[DEBUG] Ignore this.', + \ '[INFO] Something we should ignore.', + \ '/foo/bar.jar', + \ '/xyz/abc.jar', + \], {}) + + AssertEqual + \ g:prefix + \ . ' -cp ' + \ . ale#Escape(join( + \ [ + \ '/foo/bar.jar', + \ '/xyz/abc.jar', + \ 'configured.jar', + \ 'configured2.jar', + \ ], + \ g:cp_sep + \ )) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', + \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + +Execute(The javac callback should use string type g:ale_java_javac_sourcepath correctly): + let g:ale_java_javac_sourcepath = 'java_paths/build/gen/main' + + AssertLinter 'javac', + \ g:prefix + \ . ' -sourcepath ' . ale#Escape( + \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/') + \ ) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' + +Execute(The javac callback should use list type g:ale_java_javac_sourcepath correctly): + let g:ale_java_javac_sourcepath = ['java_paths/build/gen/main'] + + AssertLinter 'javac', + \ g:prefix + \ . ' -sourcepath ' . ale#Escape( + \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/') + \ ) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' + +Execute(The javac callback shouldn't add -sourcepath when g:ale_java_javac_sourcepath variable path doesn't exist): + let g:ale_java_javac_sourcepath = 'java_paths/build/gen3/main' + + AssertLinter 'javac', + \ g:prefix + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' + +Execute(The javac callback should combine discovered sourcepath and manual ones): + call ale#engine#Cleanup(bufnr('')) + call ale#test#SetFilename('java_paths/src/main/java/com/something/dummy.java') + call ale#engine#InitBufferInfo(bufnr('')) + + let g:ale_java_javac_sourcepath = 'java_paths/build/gen/main' + let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {}) + + AssertEqual + \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ . ' -sourcepath ' . ale#Escape(join([ + \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'), + \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/'), + \ ], g:cp_sep)) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', + \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + + let g:ale_java_javac_sourcepath = 'java_paths/build/gen/main' + \ . g:cp_sep . 'java_paths/build/gen2/main' + let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {}) + + AssertEqual + \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ . ' -sourcepath ' . ale#Escape(join([ + \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'), + \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/'), + \ ale#path#Simplify(g:dir . '/java_paths/build/gen2/main/') + \ ], g:cp_sep)) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', + \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + + let g:ale_java_javac_sourcepath = ['java_paths/build/gen/main'] + let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {}) + + AssertEqual + \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ . ' -sourcepath ' . ale#Escape(join([ + \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'), + \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/') + \ ], g:cp_sep)) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', + \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + + let g:ale_java_javac_sourcepath = [ + \ 'java_paths/build/gen/main', + \ 'java_paths/build/gen2/main' + \ ] + let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {}) + + AssertEqual + \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ . ' -sourcepath ' . ale#Escape(join([ + \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'), + \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/'), + \ ale#path#Simplify(g:dir . '/java_paths/build/gen2/main/') + \ ], g:cp_sep)) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', + \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + Execute(The javac callback should detect source directories): call ale#engine#Cleanup(bufnr('')) noautocmd e! java_paths/src/main/java/com/something/dummy diff --git a/test/command_callback/test_mypy_command_callback.vader b/test/command_callback/test_mypy_command_callback.vader index 8ca35207..afa9f9af 100644 --- a/test/command_callback/test_mypy_command_callback.vader +++ b/test/command_callback/test_mypy_command_callback.vader @@ -52,6 +52,15 @@ Execute(The mypy callbacks should detect virtualenv directories and switch to th \ . ' --show-column-numbers ' \ . '--shadow-file %s %t %s' +Execute(The mypy callbacks should cd to directory containing mypy.ini if found): + silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_mypy_ini_and_pytest_ini/tests/testsubfolder/my_tests.py') + + AssertLinter 'mypy', + \ ale#path#CdString(ale#path#Simplify(g:dir . '/python_paths/with_mypy_ini_and_pytest_ini')) + \ . ale#Escape('mypy') + \ . ' --show-column-numbers ' + \ . '--shadow-file %s %t %s' + Execute(You should able able to use the global mypy instead): silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') let g:ale_python_mypy_use_global = 1 diff --git a/test/command_callback/test_objc_ccls_command_callbacks.vader b/test/command_callback/test_objc_ccls_command_callbacks.vader index 5aa69d6a..34b8539e 100644 --- a/test/command_callback/test_objc_ccls_command_callbacks.vader +++ b/test/command_callback/test_objc_ccls_command_callbacks.vader @@ -1,6 +1,10 @@ Before: call ale#assert#SetUpLinterTest('objc', 'ccls') + Save b:ale_c_build_dir_names + Save b:ale_objc_ccls_executable + Save b:ale_objc_ccls_init_options + After: call ale#assert#TearDownLinterTest() @@ -44,3 +48,19 @@ Execute(The initialization options should be configurable): let b:ale_objc_ccls_init_options = { 'cacheDirectory': '/tmp/ccls' } AssertLSPOptions { 'cacheDirectory': '/tmp/ccls' } + +Execute(The compile command database should be detected correctly): + call ale#test#SetFilename('ccls_paths/with_ccls/dummy.c') + + AssertLSPOptions {} + + call ale#test#SetFilename('ccls_paths/with_compile_commands_json/dummy.c') + + AssertLSPOptions { 'compilationDatabaseDirectory': + \ ale#path#Simplify(g:dir . '/ccls_paths/with_compile_commands_json') } + + call ale#test#SetFilename('ccls_paths/with_build_dir/dummy.c') + let b:ale_c_build_dir_names = ['unusual_build_dir_name'] + + AssertLSPOptions { 'compilationDatabaseDirectory': + \ ale#path#Simplify(g:dir . '/ccls_paths/with_build_dir/unusual_build_dir_name') } diff --git a/test/command_callback/test_pyright_command_callback.vader b/test/command_callback/test_pyright_command_callback.vader new file mode 100644 index 00000000..3e421bd9 --- /dev/null +++ b/test/command_callback/test_pyright_command_callback.vader @@ -0,0 +1,116 @@ +Before: + call ale#assert#SetUpLinterTest('python', 'pyright') + + let b:bin_dir = has('win32') ? 'Scripts' : 'bin' + +After: + unlet! b:bin_dir + unlet! b:executable + + call ale#assert#TearDownLinterTest() + +Execute(The command callback should return the correct default string): + AssertLinter + \ 'pyright-langserver', + \ ale#Escape('pyright-langserver') . ' --stdio' + +Execute(The executable should be configurable): + let g:ale_python_pyright_executable = '/bin/foo-bar' + + AssertLinter + \ '/bin/foo-bar', + \ ale#Escape('/bin/foo-bar') . ' --stdio' + +Execute(The default configuration should be mostly empty): + " The default configuration needs to have at least one key in it, + " or the server won't start up properly. + AssertLSPConfig {'python': {}} + + let b:ale_python_pyright_config = {} + + AssertLSPConfig {'python': {}} + +Execute(virtualenv paths should be set in configuration by default): + call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py') + + AssertLSPConfig { + \ 'python': { + \ 'pythonPath': ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/python'), + \ 'venvPath': ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env'), + \ }, + \} + +Execute(The pythonPath should be set based on whatever the ovveride for the venvPath is set to): + call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py') + + " This overrides the default detection of the path. + let b:ale_python_pyright_config = { + \ 'python': { + \ 'venvPath': '/foo/bar', + \ }, + \} + + AssertLSPConfig { + \ 'python': { + \ 'pythonPath': ale#path#Simplify('/foo/bar/' . b:bin_dir . '/python'), + \ 'venvPath': '/foo/bar', + \ }, + \} + +Execute(You should be able to override pythonPath when venvPath is detected): + call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py') + + " This overrides the default detection of the path. + let b:ale_python_pyright_config = { + \ 'python': { + \ 'pythonPath': '/bin/python', + \ }, + \} + + AssertLSPConfig { + \ 'python': { + \ 'pythonPath': '/bin/python', + \ 'venvPath': ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env'), + \ }, + \} + +Execute(You should be able to override both pythonPath and venvPath): + call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py') + + " This overrides the default detection of the path. + let b:ale_python_pyright_config = { + \ 'python': { + \ 'pythonPath': '/bin/python', + \ 'venvPath': '/other/dir', + \ }, + \} + + AssertLSPConfig { + \ 'python': { + \ 'pythonPath': '/bin/python', + \ 'venvPath': '/other/dir', + \ }, + \} + +Execute(You should be able to define other settings): + call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py') + + let b:ale_python_pyright_config = { + \ 'python': { + \ 'analysis': {'logLevel': 'warning'}, + \ }, + \ 'pyright': { + \ 'disableLanguageServices': v:true, + \ }, + \} + + AssertLSPConfig { + \ 'python': { + \ 'analysis': {'logLevel': 'warning'}, + \ 'pythonPath': ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/python'), + \ 'venvPath': ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env'), + \ }, + \ 'pyright': { + \ 'disableLanguageServices': v:true, + \ }, + \} diff --git a/test/command_callback/test_revive_command_callbacks.vader b/test/command_callback/test_revive_command_callbacks.vader new file mode 100644 index 00000000..172294f3 --- /dev/null +++ b/test/command_callback/test_revive_command_callbacks.vader @@ -0,0 +1,30 @@ +Before: + Save g:ale_go_go111module + + call ale#assert#SetUpLinterTest('go', 'revive') + +After: + Restore + + unlet! b:ale_go_go111module + + call ale#assert#TearDownLinterTest() + +Execute(The default revive command should be correct): + AssertLinter 'revive', ale#Escape('revive') . ' %t' + +Execute(The revive executable should be configurable): + let b:ale_go_revive_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') . ' %t' + +Execute(The revive options should be configurable): + let b:ale_go_revive_options = '--foo' + + AssertLinter 'revive', ale#Escape('revive') . ' --foo %t' + +Execute(The revive command should support Go environment variables): + let b:ale_go_go111module = 'on' + + AssertLinter 'revive', + \ ale#Env('GO111MODULE', 'on') . ale#Escape('revive') . ' %t' diff --git a/test/command_callback/test_rust_analyzer_callbacks.vader b/test/command_callback/test_rust_analyzer_callbacks.vader new file mode 100644 index 00000000..95866076 --- /dev/null +++ b/test/command_callback/test_rust_analyzer_callbacks.vader @@ -0,0 +1,20 @@ +Before: + call ale#assert#SetUpLinterTest('rust', 'analyzer') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default executable path should be correct): + AssertLinter 'rust-analyzer', ale#Escape('rust-analyzer') + +Execute(The project root should be detected correctly): + AssertLSPProject '' + + call ale#test#SetFilename('rust-rls-project/test.rs') + + AssertLSPProject ale#path#Simplify(g:dir . '/rust-rls-project') + +Execute(Should accept configuration settings): + AssertLSPConfig {} + let b:ale_rust_analyzer_config = {'rust': {'clippy_preference': 'on'}} + AssertLSPConfig {'rust': {'clippy_preference': 'on'}} diff --git a/test/command_callback/test_standardts_command_callback.vader b/test/command_callback/test_standardts_command_callback.vader new file mode 100644 index 00000000..d769e712 --- /dev/null +++ b/test/command_callback/test_standardts_command_callback.vader @@ -0,0 +1,43 @@ +Before: + call ale#assert#SetUpLinterTest('typescript', 'standard') + call ale#test#SetFilename('testfile.js') + unlet! b:executable + +After: + call ale#assert#TearDownLinterTest() + +Execute(bin/cmd.js paths should be preferred): + call ale#test#SetFilename('standard-test-files/with-cmd/testfile.js') + + let b:executable = ale#path#Simplify( + \ g:dir + \ . '/standard-test-files/with-cmd/node_modules/standard/bin/cmd.js' + \) + + AssertLinter b:executable, + \ (has('win32') ? 'node.exe ' : '') + \ . ale#Escape(b:executable) + \ . ' --stdin %s' + +Execute(.bin directories should be used too): + call ale#test#SetFilename('standard-test-files/with-bin/testfile.js') + + let b:executable = ale#path#Simplify( + \ g:dir + \ . '/standard-test-files/with-bin/node_modules/.bin/standard' + \) + + AssertLinter b:executable, ale#Escape(b:executable) . ' --stdin %s' + +Execute(The global executable should be used otherwise): + AssertLinter 'standard', ale#Escape('standard') . ' --stdin %s' + +Execute(The global executable should be configurable): + let b:ale_typescript_standard_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') . ' --stdin %s' + +Execute(The options should be configurable): + let b:ale_typescript_standard_options = '--wat' + + AssertLinter 'standard', ale#Escape('standard') . ' --wat --stdin %s' diff --git a/test/command_callback/test_terraform_lsp_command_callback.vader b/test/command_callback/test_terraform_lsp_command_callback.vader new file mode 100644 index 00000000..7a491d54 --- /dev/null +++ b/test/command_callback/test_terraform_lsp_command_callback.vader @@ -0,0 +1,48 @@ +Before: + call ale#assert#SetUpLinterTest('terraform', 'terraform_lsp') + +After: + if isdirectory(g:dir . '/.terraform') + call delete(g:dir . '/.terraform', 'd') + endif + + unlet! b:ale_terraform_langserver_executable + unlet! b:ale_terraform_langserver_options + + call ale#assert#TearDownLinterTest() + +Execute(Should send correct LSP language): + AssertLSPLanguage 'terraform' + +Execute(Should load default executable): + AssertLinter 'terraform-lsp', ale#Escape('terraform-lsp') + +Execute(Should configure custom executable): + let b:ale_terraform_langserver_executable = 'foo' + AssertLinter 'foo', ale#Escape('foo') + +Execute(Should set custom options): + let b:ale_terraform_langserver_options = '--bar' + + AssertLinter 'terraform-lsp', + \ ale#Escape('terraform-lsp') . ' --bar' + +Execute(Should return current directory if it contains .terraform directory): + call mkdir(g:dir . '/.terraform') + AssertLSPProject g:dir + +Execute(Should return nearest directory with .terraform if found in parent directory): + call ale#test#SetFilename('../terraform_files/main.tf') + + let b:parent_dir = ale#path#Simplify(g:dir . '/..') + let b:tf_dir = b:parent_dir . '/.terraform' + + if !isdirectory(b:tf_dir) + call mkdir(b:tf_dir) + endif + + AssertLSPProject b:parent_dir + + call delete(b:tf_dir, 'd') + unlet!b:parent_dir + unlet!b:tf_dir diff --git a/test/command_callback/test_vim_vimls.vader b/test/command_callback/test_vim_vimls.vader new file mode 100644 index 00000000..ab12b637 --- /dev/null +++ b/test/command_callback/test_vim_vimls.vader @@ -0,0 +1,76 @@ +" Author: Jeffrey Lau https://github.com/zoonfafer +" Description: Tests for the Vim vimls linter + +Before: + call ale#assert#SetUpLinterTest('vim', 'vimls') + +After: + if isdirectory(g:dir . '/.git') + call delete(g:dir . '/.git', 'd') + endif + + call ale#assert#TearDownLinterTest() + +Execute(should set correct defaults): + AssertLinter 'vim-language-server', ale#Escape('vim-language-server') . ' --stdio' + +Execute(should set correct LSP values): + call ale#test#SetFilename('vim_fixtures/path_with_autoload/test.vim') + AssertLSPLanguage 'vim' + AssertLSPOptions {} + AssertLSPConfig {} + AssertLSPProject ale#path#Simplify(g:dir . '/vim_fixtures/path_with_autoload') + +Execute(should set correct project for .git/): + let b:parent_dir = ale#path#Simplify(g:dir . '/..') + let b:git_dir = b:parent_dir . '/.git' + + call ale#test#SetFilename('vim_fixtures/test.vim') + + if !isdirectory(b:git_dir) + call mkdir(b:git_dir) + endif + + AssertLSPProject ale#path#Simplify(b:parent_dir) + + call delete(b:git_dir, 'd') + unlet! b:git_dir + +Execute(should set correct project for plugin/): + call ale#test#SetFilename('vim_fixtures/path_with_plugin/test.vim') + + AssertLSPProject ale#path#Simplify(g:dir . '/vim_fixtures/path_with_plugin') + +Execute(should accept configuration settings): + AssertLSPConfig {} + + let b:ale_vim_vimls_config = {'vim': {'foobar': v:true}} + AssertLSPConfig {'vim': {'foobar': v:true}} + +Execute(should set correct project for .vimrc): + call ale#test#SetFilename('vim_fixtures/path_with_vimrc/.vimrc') + + AssertLSPProject ale#path#Simplify(g:dir . '/vim_fixtures/path_with_vimrc') + +Execute(should set correct project for init.vim): + call ale#test#SetFilename('vim_fixtures/path_with_initvim/init.vim') + + AssertLSPProject ale#path#Simplify(g:dir . '/vim_fixtures/path_with_initvim') + +Execute(should use the local executable when available): + call ale#test#SetFilename('vim_fixtures/file.vim') + + AssertLinter ale#path#Simplify(g:dir . '/vim_fixtures/node_modules/.bin/vim-language-server'), + \ ale#Escape(ale#path#Simplify(g:dir . '/vim_fixtures/node_modules/.bin/vim-language-server')) . ' --stdio' + +Execute(should let the global executable to be used): + let g:ale_vim_vimls_use_global = 1 + call ale#test#SetFilename('vim_fixtures/file.vim') + + AssertLinter 'vim-language-server', + \ ale#Escape('vim-language-server') . ' --stdio' + +Execute(should let the executable to be configured): + let g:ale_vim_vimls_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') . ' --stdio' diff --git a/test/command_callback/test_zig_zls_callbacks.vader b/test/command_callback/test_zig_zls_callbacks.vader new file mode 100644 index 00000000..6e42cc4b --- /dev/null +++ b/test/command_callback/test_zig_zls_callbacks.vader @@ -0,0 +1,15 @@ +Before: + call ale#assert#SetUpLinterTest('zig', 'zls') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default executable path should be correct): + AssertLinter 'zls', ale#Escape('zls') + +Execute(The project root should be detected correctly): + AssertLSPProject '' + + call ale#test#SetFilename('zig-zls-project/main.zig') + + AssertLSPProject ale#path#Simplify(g:dir . '/zig-zls-project') diff --git a/test/command_callback/vim_fixtures/invalid_vim_project/test.vim b/test/command_callback/vim_fixtures/invalid_vim_project/test.vim new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/vim_fixtures/invalid_vim_project/test.vim diff --git a/test/command_callback/vim_fixtures/node_modules/.bin/vim-language-server b/test/command_callback/vim_fixtures/node_modules/.bin/vim-language-server new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/vim_fixtures/node_modules/.bin/vim-language-server diff --git a/test/command_callback/vim_fixtures/path_with_autoload/autoload/test.vim b/test/command_callback/vim_fixtures/path_with_autoload/autoload/test.vim new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/vim_fixtures/path_with_autoload/autoload/test.vim diff --git a/test/command_callback/vim_fixtures/path_with_autoload/test.vim b/test/command_callback/vim_fixtures/path_with_autoload/test.vim new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/vim_fixtures/path_with_autoload/test.vim diff --git a/test/command_callback/vim_fixtures/path_with_initvim/init.vim b/test/command_callback/vim_fixtures/path_with_initvim/init.vim new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/vim_fixtures/path_with_initvim/init.vim diff --git a/test/command_callback/vim_fixtures/path_with_plugin/plugin/test.vim b/test/command_callback/vim_fixtures/path_with_plugin/plugin/test.vim new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/vim_fixtures/path_with_plugin/plugin/test.vim diff --git a/test/command_callback/vim_fixtures/path_with_plugin/test.vim b/test/command_callback/vim_fixtures/path_with_plugin/test.vim new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/vim_fixtures/path_with_plugin/test.vim diff --git a/test/command_callback/vim_fixtures/path_with_vimrc/.vimrc b/test/command_callback/vim_fixtures/path_with_vimrc/.vimrc new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/vim_fixtures/path_with_vimrc/.vimrc diff --git a/test/command_callback/zig-zls-project/build.zig b/test/command_callback/zig-zls-project/build.zig new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/zig-zls-project/build.zig diff --git a/test/completion/test_completion_events.vader b/test/completion/test_completion_events.vader index d70fefeb..3a7a31d0 100644 --- a/test/completion/test_completion_events.vader +++ b/test/completion/test_completion_events.vader @@ -50,7 +50,8 @@ Before: let g:handle_code_action_called = 0 function! MockHandleCodeAction() abort " delfunction! ale#code_action#HandleCodeAction - function! ale#code_action#HandleCodeAction(action) abort + function! ale#code_action#HandleCodeAction(action, should_save) abort + AssertEqual v:false, a:should_save let g:handle_code_action_called += 1 endfunction endfunction @@ -233,7 +234,7 @@ Execute(ale#completion#Show() should make the correct feedkeys() call for manual AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls Execute(ale#completion#Show() should not call feedkeys() for other sources): - let b:ale_completion_info = {'source': 'deoplete'} + let b:ale_completion_info = {'source': 'other-source'} call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}]) sleep 1ms @@ -334,7 +335,7 @@ Execute(b:ale_completion_info should be set up correctly when requesting complet Execute(b:ale_completion_info should be set up correctly for other sources): let b:ale_completion_result = [] call setpos('.', [bufnr(''), 3, 14, 0]) - call ale#completion#GetCompletions('deoplete') + call ale#completion#GetCompletions('ale-callback') AssertEqual \ { @@ -344,7 +345,7 @@ Execute(b:ale_completion_info should be set up correctly for other sources): \ 'line_length': 14, \ 'line': 3, \ 'prefix': 'ab', - \ 'source': 'deoplete', + \ 'source': 'ale-callback', \ }, \ b:ale_completion_info Assert !exists('b:ale_completion_result') diff --git a/test/completion/test_lsp_completion_parsing.vader b/test/completion/test_lsp_completion_parsing.vader index ef954564..e233c955 100644 --- a/test/completion/test_lsp_completion_parsing.vader +++ b/test/completion/test_lsp_completion_parsing.vader @@ -17,17 +17,17 @@ Execute(Should handle Rust completion results correctly): \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = &''a str>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = Cow<''a, str>>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Searcher', 'menu': 'type Searcher = <&''b str as Pattern<''a>>::Searcher;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Searcher', 'menu': 'type Searcher = <&''b str as Pattern<''a>>::Searcher;', 'info': '', 'kind': 't', 'icase': 1}, \ {'word': 'default', 'menu': 'fn default() -> String', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = String;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Target', 'menu': 'type Target = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Err', 'menu': 'type Err = ParseError;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = String;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Target', 'menu': 'type Target = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Err', 'menu': 'type Err = ParseError;', 'info': '', 'kind': 't', 'icase': 1}, \ {'word': 'from_str', 'menu': 'fn from_str(s: &str) -> Result<String, ParseError>', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from', 'menu': 'fn from(s: &''a str) -> String', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from', 'menu': 'fn from(s: Box<str>) -> String', 'info': '', 'kind': 'f', 'icase': 1}, @@ -526,3 +526,73 @@ Execute(Should handle completion messages with the deprecated insertText attribu \ ], \ }, \ }) + +Execute(Should handle completion messages with additionalTextEdits): + AssertEqual + \ [ + \ { + \ 'word': 'next_callback', + \ 'menu': 'PlayTimeCallback', + \ 'info': '', + \ 'kind': 'v', + \ 'icase': 1, + \ 'user_data': json_encode({ + \ 'codeActions': [ + \ { + \ 'description': 'completion', + \ 'changes': [ + \ { + \ 'fileName': expand('#' . bufnr('') . ':p'), + \ 'textChanges': [ + \ { + \ 'start': { + \ 'line': 11, + \ 'offset': 2, + \ }, + \ 'end': { + \ 'line': 13, + \ 'offset': 4, + \ }, + \ 'newText': 'from "module" import next_callback', + \ }, + \ ], + \ }, + \ ], + \ }, + \ ], + \ }), + \ }, + \ ], + \ ale#completion#ParseLSPCompletions({ + \ 'id': 226, + \ 'jsonrpc': '2.0', + \ 'result': { + \ 'isIncomplete': v:false, + \ 'items': [ + \ { + \ 'detail': 'PlayTimeCallback', + \ 'filterText': 'next_callback', + \ 'insertText': 'next_callback', + \ 'insertTextFormat': 1, + \ 'kind': 6, + \ 'label': ' next_callback', + \ 'sortText': '3ee19999next_callback', + \ 'additionalTextEdits': [ + \ { + \ 'range': { + \ 'start': { + \ 'line': 10, + \ 'character': 1, + \ }, + \ 'end': { + \ 'line': 12, + \ 'character': 3, + \ }, + \ }, + \ 'newText': 'from "module" import next_callback', + \ }, + \ ], + \ }, + \ ], + \ }, + \ }) diff --git a/test/completion/test_public_completion_api.vader b/test/completion/test_public_completion_api.vader index c3cd42b8..f26fdc12 100644 --- a/test/completion/test_public_completion_api.vader +++ b/test/completion/test_public_completion_api.vader @@ -37,6 +37,7 @@ Execute(ale#completion#GetCompletionPositionForDeoplete() should return the posi AssertEqual 4, ale#completion#GetCompletionPositionForDeoplete('foo bar') Execute(ale#completion#CanProvideCompletions should return 0 when no completion sources are available): + let b:ale_linters = ['flake8'] AssertEqual 0, ale#completion#CanProvideCompletions() Execute(ale#completion#CanProvideCompletions should return 1 when at least one completion source is available): diff --git a/test/completion/test_tsserver_completion_parsing.vader b/test/completion/test_tsserver_completion_parsing.vader index 5dfef531..58b56ce6 100644 --- a/test/completion/test_tsserver_completion_parsing.vader +++ b/test/completion/test_tsserver_completion_parsing.vader @@ -81,7 +81,7 @@ Execute(TypeScript completion details responses should be parsed correctly): \ 'word': 'abc', \ 'menu': '(property) Foo.abc: number', \ 'info': '', - \ 'kind': 'f', + \ 'kind': 'v', \ 'icase': 1, \ 'dup': g:ale_completion_tsserver_autoimport, \ }, @@ -89,7 +89,7 @@ Execute(TypeScript completion details responses should be parsed correctly): \ 'word': 'def', \ 'menu': '(property) Foo.def: number', \ 'info': 'foo bar baz', - \ 'kind': 'f', + \ 'kind': 'v', \ 'icase': 1, \ 'dup': g:ale_completion_tsserver_autoimport, \ }, @@ -97,7 +97,7 @@ Execute(TypeScript completion details responses should be parsed correctly): \ 'word': 'ghi', \ 'menu': '(class) Foo', \ 'info': '', - \ 'kind': 'f', + \ 'kind': 'v', \ 'icase': 1, \ 'dup': g:ale_completion_tsserver_autoimport, \ }, @@ -169,7 +169,7 @@ Execute(Entries without details should be included in the responses): \ 'word': 'abc', \ 'menu': 'import { def } from "./Foo"; (property) Foo.abc: number', \ 'info': '', - \ 'kind': 'f', + \ 'kind': 'v', \ 'icase': 1, \ 'user_data': json_encode({ \ 'codeActions': [{ @@ -183,7 +183,7 @@ Execute(Entries without details should be included in the responses): \ 'word': 'def', \ 'menu': '(property) Foo.def: number', \ 'info': 'foo bar baz', - \ 'kind': 'f', + \ 'kind': 'v', \ 'icase': 1, \ 'dup': g:ale_completion_tsserver_autoimport, \ }, diff --git a/test/eslint-test-files/react-app/subdir-with-package-json/node_modules/.gitkeep b/test/eslint-test-files/react-app/subdir-with-package-json/node_modules/.gitkeep new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/eslint-test-files/react-app/subdir-with-package-json/node_modules/.gitkeep diff --git a/test/fixers/test_astyle_fixer_callback.vader b/test/fixers/test_astyle_fixer_callback.vader new file mode 100644 index 00000000..ac756870 --- /dev/null +++ b/test/fixers/test_astyle_fixer_callback.vader @@ -0,0 +1,96 @@ +Before: + Save g:ale_c_astyle_executable + Save g:ale_c_astyle_project_options + Save g:ale_cpp_astyle_project_options + + " Use an invalid global executable, so we don't match it. + let g:ale_c_astyle_executable = 'xxxinvalid' + let g:ale_cpp_astyle_executable = 'invalidpp' + let g:ale_c_astyle_project_options = '' + let g:ale_cpp_astyle_project_options = '' + + call ale#test#SetDirectory('/testplugin/test/fixers') + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The astyle callback should return the correct default values): + " Because this file doesn't exist, no astylrc config + " exists near it. Therefore, project_options is empty. + call ale#test#SetFilename('../c_files/testfile.c') + let targetfile = bufname(bufnr('%')) + + AssertEqual + \ { + \ 'command': ale#Escape(g:ale_c_astyle_executable) + \ . ' --stdin=' . ale#Escape(targetfile) + \ }, + \ ale#fixers#astyle#Fix(bufnr('')) + +Execute(The astyle callback should support cpp files): + " Because this file doesn't exist, no astylrc config + " exists near it. Therefore, project_options is empty. + call ale#test#SetFilename('../cpp_files/dummy.cpp') + set filetype=cpp " The test fails without this + let targetfile = bufname(bufnr('%')) + + AssertEqual + \ { + \ 'command': ale#Escape(g:ale_cpp_astyle_executable) + \ . ' --stdin=' . ale#Escape(targetfile) + \ }, + \ ale#fixers#astyle#Fix(bufnr('')) + +Execute(The astyle callback should support cpp files with option file set): + call ale#test#SetFilename('../cpp_files/dummy.cpp') + let g:ale_cpp_astyle_project_options = '.astylerc_cpp' + let targetfile = bufname(bufnr('%')) + set filetype=cpp " The test fails without this + + AssertEqual + \ { + \ 'command': ale#Escape('invalidpp') + \ . ' --project=' . g:ale_cpp_astyle_project_options + \ . ' --stdin=' . ale#Escape(targetfile) + \ }, + \ ale#fixers#astyle#Fix(bufnr('')) + +Execute(The astyle callback should return the correct default values with a specified option file): + call ale#test#SetFilename('../c_files/testfile.c') + let g:ale_c_astyle_project_options = '.astylerc_c' + let targetfile = bufname(bufnr('%')) + + AssertEqual + \ { + \ 'command': ale#Escape('xxxinvalid') + \ . ' --project=' . g:ale_c_astyle_project_options + \ . ' --stdin=' . ale#Escape(targetfile) + \ }, + \ ale#fixers#astyle#Fix(bufnr('')) + +Execute(The astyle callback should find nearest default option file _astylrc): + call ale#test#SetFilename('../test_c_projects/makefile_project/subdir/file.c') + let targetfile = bufname(bufnr('%')) + + AssertEqual + \ { + \ 'command': ale#Escape('xxxinvalid') + \ . ' --project=_astylerc' + \ . ' --stdin=' . ale#Escape(targetfile) + \ }, + \ ale#fixers#astyle#Fix(bufnr('')) + +Execute(The astyle callback should find .astylrc in the same directory as src): + call ale#test#SetFilename('../test_cpp_project/dummy.cpp') + set filetype=cpp " The test fails without this + let targetfile = bufname(bufnr('%')) + + AssertEqual + \ { + \ 'command': ale#Escape('invalidpp') + \ . ' --project=.astylerc' + \ . ' --stdin=' . ale#Escape(targetfile) + \ }, + \ ale#fixers#astyle#Fix(bufnr('')) diff --git a/test/fixers/test_eslint_fixer_callback.vader b/test/fixers/test_eslint_fixer_callback.vader index ad80bdd5..400267ac 100644 --- a/test/fixers/test_eslint_fixer_callback.vader +++ b/test/fixers/test_eslint_fixer_callback.vader @@ -13,7 +13,9 @@ Execute(The executable path should be correct): AssertFixer \ { \ 'read_temporary_file': 1, - \ 'command': (has('win32') ? 'node.exe ' : '') + \ 'command': + \ ale#path#CdString(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app')) + \ . (has('win32') ? 'node.exe ' : '') \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/.eslintrc.js')) \ . ' --fix %t', @@ -150,7 +152,9 @@ Execute(The lower priority configuration file in a nested directory should be pr AssertFixer \ { \ 'read_temporary_file': 1, - \ 'command': (has('win32') ? 'node.exe ' : '') + \ 'command': + \ ale#path#CdString(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app')) + \ . (has('win32') ? 'node.exe ' : '') \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/subdir-with-config/.eslintrc')) \ . ' --fix %t', @@ -164,7 +168,9 @@ Execute(--config in options should override configuration file detection for old AssertFixer \ { \ 'read_temporary_file': 1, - \ 'command': (has('win32') ? 'node.exe ' : '') + \ 'command': + \ ale#path#CdString(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app')) + \ . (has('win32') ? 'node.exe ' : '') \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ' --config /foo.cfg' \ . ' --fix %t', @@ -175,7 +181,9 @@ Execute(--config in options should override configuration file detection for old AssertFixer \ { \ 'read_temporary_file': 1, - \ 'command': (has('win32') ? 'node.exe ' : '') + \ 'command': + \ ale#path#CdString(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app')) + \ . (has('win32') ? 'node.exe ' : '') \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ' -c /foo.cfg' \ . ' --fix %t', @@ -187,7 +195,9 @@ Execute(package.json should be used as a last resort): AssertFixer \ { \ 'read_temporary_file': 1, - \ 'command': (has('win32') ? 'node.exe ' : '') + \ 'command': + \ ale#path#CdString(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app')) + \ . (has('win32') ? 'node.exe ' : '') \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/.eslintrc.js')) \ . ' --fix %t', @@ -199,7 +209,8 @@ Execute(package.json should be used as a last resort): \ { \ 'read_temporary_file': 1, \ 'command': - \ ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/node_modules/.bin/eslint')) + \ ale#path#CdString(ale#path#Simplify(g:dir . '/../eslint-test-files')) + \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/node_modules/.bin/eslint')) \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/package.json')) \ . ' --fix %t', \ } @@ -214,7 +225,9 @@ Execute(The version check should be correct): \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ' --version', \ { - \ 'command': (has('win32') ? 'node.exe ' : '') + \ 'command': + \ ale#path#CdString(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app')) + \ . (has('win32') ? 'node.exe ' : '') \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ' --stdin-filename %s --stdin --fix-dry-run --format=json', \ 'process_with': 'ale#fixers#eslint#ProcessFixDryRunOutput', @@ -223,7 +236,9 @@ Execute(The version check should be correct): AssertFixer [ \ { - \ 'command': (has('win32') ? 'node.exe ' : '') + \ 'command': + \ ale#path#CdString(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app')) + \ . (has('win32') ? 'node.exe ' : '') \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ' --stdin-filename %s --stdin --fix-dry-run --format=json', \ 'process_with': 'ale#fixers#eslint#ProcessFixDryRunOutput', @@ -236,7 +251,9 @@ Execute(--fix-dry-run should be used for 4.9.0 and up): GivenCommandOutput ['4.9.0'] AssertFixer \ { - \ 'command': (has('win32') ? 'node.exe ' : '') + \ 'command': + \ ale#path#CdString(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app')) + \ . (has('win32') ? 'node.exe ' : '') \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ' --stdin-filename %s --stdin --fix-dry-run --format=json', \ 'process_with': 'ale#fixers#eslint#ProcessFixDryRunOutput', @@ -249,7 +266,8 @@ Execute(--fix-to-stdout should be used for eslint_d): \ { \ 'read_temporary_file': 1, \ 'command': - \ ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/app-with-eslint-d/node_modules/.bin/eslint_d')) + \ ale#path#CdString(ale#path#Simplify(g:dir . '/../eslint-test-files/app-with-eslint-d')) + \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/app-with-eslint-d/node_modules/.bin/eslint_d')) \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/package.json')) \ . ' --fix %t', \ } @@ -260,7 +278,8 @@ Execute(--fix-to-stdout should be used for eslint_d): AssertFixer \ { \ 'command': - \ ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/app-with-eslint-d/node_modules/.bin/eslint_d')) + \ ale#path#CdString(ale#path#Simplify(g:dir . '/../eslint-test-files/app-with-eslint-d')) + \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/app-with-eslint-d/node_modules/.bin/eslint_d')) \ . ' --stdin-filename %s --stdin --fix-to-stdout', \ 'process_with': 'ale#fixers#eslint#ProcessEslintDOutput', \ } @@ -270,7 +289,8 @@ Execute(--fix-to-stdout should be used for eslint_d): AssertFixer \ { \ 'command': - \ ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/app-with-eslint-d/node_modules/.bin/eslint_d')) + \ ale#path#CdString(ale#path#Simplify(g:dir . '/../eslint-test-files/app-with-eslint-d')) + \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/app-with-eslint-d/node_modules/.bin/eslint_d')) \ . ' --stdin-filename %s --stdin --fix-to-stdout', \ 'process_with': 'ale#fixers#eslint#ProcessEslintDOutput', \ } diff --git a/test/fixers/test_ktlint_fixer_callback.vader b/test/fixers/test_ktlint_fixer_callback.vader index 47b37788..ba01a409 100644 --- a/test/fixers/test_ktlint_fixer_callback.vader +++ b/test/fixers/test_ktlint_fixer_callback.vader @@ -21,9 +21,8 @@ Execute(The ktlint callback should return the correct default values): AssertEqual \ { \ 'command': ale#Escape('xxxinvalid') - \ . ' %t' + \ . ' --stdin' \ . ' --format', - \ 'read_temporary_file': 1, \ }, \ ale#fixers#ktlint#Fix(bufnr('')) @@ -37,8 +36,7 @@ Execute(The ktlint callback should include custom ktlint options): \ 'command': ale#Escape('xxxinvalid') \ . ' ' . g:ale_kotlin_ktlint_options \ . ' --ruleset /path/to/custom/ruleset.jar' - \ . ' %t' + \ . ' --stdin' \ . ' --format', - \ 'read_temporary_file': 1, \ }, \ ale#fixers#ktlint#Fix(bufnr('')) diff --git a/test/fixers/test_nimpretty_fixer_callback.vader b/test/fixers/test_nimpretty_fixer_callback.vader new file mode 100644 index 00000000..a26f649a --- /dev/null +++ b/test/fixers/test_nimpretty_fixer_callback.vader @@ -0,0 +1,23 @@ +Before: + call ale#assert#SetUpFixerTest('nim', 'nimpretty') + +After: + call ale#assert#TearDownFixerTest() + +Execute(The nimpretty callback should return the correct default values): + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('nimpretty') . ' %t --maxLineLen:80' + \ }, + \ ale#fixers#nimpretty#Fix(bufnr('')) + +Execute(The nimpretty callback should include any additional options): + let g:ale_nim_nimpretty_options = '--some-option' + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('nimpretty') . ' %t --some-option' + \ }, + \ ale#fixers#nimpretty#Fix(bufnr('')) diff --git a/test/fixers/test_tslint_fixer_callback.vader b/test/fixers/test_tslint_fixer_callback.vader index aa9c0322..a88992fa 100644 --- a/test/fixers/test_tslint_fixer_callback.vader +++ b/test/fixers/test_tslint_fixer_callback.vader @@ -27,7 +27,7 @@ Execute(The tslint callback should return the correct default values): \ 'read_temporary_file': 1, \ 'command': ale#Escape('tslint') \ . ' -c ' . ale#Escape('tslint.json') - \ . ' --fix %t', + \ . ' --outputAbsolutePaths --fix %t', \ }, \ ale#fixers#tslint#Fix(bufnr('')) @@ -40,6 +40,6 @@ Execute(The tslint callback should include custom tslint config option): \ 'read_temporary_file': 1, \ 'command': ale#Escape('tslint') \ . ' -c ' . ale#Escape('.tslintrc') - \ . ' --fix %t', + \ . ' --outputAbsolutePaths --fix %t', \ }, \ ale#fixers#tslint#Fix(bufnr('')) diff --git a/test/handler/test_bashate_handler.vader b/test/handler/test_bashate_handler.vader new file mode 100644 index 00000000..b61bb956 --- /dev/null +++ b/test/handler/test_bashate_handler.vader @@ -0,0 +1,36 @@ +Before: + runtime ale_linters/sh/bashate.vim + +After: + call ale#linter#Reset() + +Execute(The bashate handler should handle basic errors): + AssertEqual + \ [ + \ { + \ 'lnum': 777, + \ 'col': 1, + \ 'text': 'E003 Indent not multiple of 4', + \ }, + \ { + \ 'lnum': 783, + \ 'col': 1, + \ 'text': 'E020 Function declaration not in format ^function name {$', + \ }, + \ { + \ 'lnum': 786, + \ 'col': 1, + \ 'text': 'E010 The "do" should be on same line as for', + \ }, + \ { + \ 'lnum': 791, + \ 'col': 1, + \ 'text': 'E006 Line too long', + \ }, + \ ], + \ ale_linters#sh#bashate#Handle(bufnr(''), [ + \ 'run:777:1: E003 Indent not multiple of 4', + \ 'run:783:1: E020 Function declaration not in format ^function name {$', + \ 'run:786:1: E010 The "do" should be on same line as for', + \ 'run:791:1: E006 Line too long', + \ ]) diff --git a/test/handler/test_cppcheck_handler.vader b/test/handler/test_cppcheck_handler.vader index f153b9b5..55a5d29b 100644 --- a/test/handler/test_cppcheck_handler.vader +++ b/test/handler/test_cppcheck_handler.vader @@ -10,19 +10,29 @@ Execute(Basic errors should be handled by cppcheck): AssertEqual \ [ \ { - \ 'lnum': 5, + \ 'lnum': 974, + \ 'col' : 6, \ 'type': 'E', - \ 'text': 'Array ''a[10]'' accessed at index 10, which is out of bounds', + \ 'sub_type': '', + \ 'text': 'Array ''n[3]'' accessed at index 3, which is out of bounds.', + \ 'code': 'arrayIndexOutOfBounds' \ }, \ { - \ 'lnum': 7, + \ 'lnum': 1185, + \ 'col' : 10, \ 'type': 'W', - \ 'text': 'Some other problem', + \ 'sub_type': 'style', + \ 'text': 'The scope of the variable ''indxStr'' can be reduced.', + \ 'code': 'variableScope' \ }, \ ], \ ale#handlers#cppcheck#HandleCppCheckFormat(bufnr(''), [ - \ '[test.cpp:5]: (error) Array ''a[10]'' accessed at index 10, which is out of bounds', - \ '[test.cpp:7]: (warning) Some other problem', + \ 'test.cpp:974:6: error: Array ''n[3]'' accessed at index 3, which is out of bounds. [arrayIndexOutOfBounds]\', + \ ' n[3]=3;', + \ ' ^', + \ 'test.cpp:1185:10: style: The scope of the variable ''indxStr'' can be reduced. [variableScope]\', + \ ' char indxStr[16];', + \ ' ^', \ ]) Execute(Problems from other files should be ignored by cppcheck): @@ -32,5 +42,7 @@ Execute(Problems from other files should be ignored by cppcheck): \ [ \ ], \ ale#handlers#cppcheck#HandleCppCheckFormat(bufnr(''), [ - \ '[bar.cpp:5]: (error) Array ''a[10]'' accessed at index 10, which is out of bounds', + \ 'bar.cpp:974:6: error: Array ''n[3]'' accessed at index 3, which is out of bounds. [arrayIndexOutOfBounds]\', + \ ' n[3]=3;', + \ ' ^', \ ]) diff --git a/test/handler/test_dockerfile_lint_handler.vader b/test/handler/test_dockerfile_lint_handler.vader index 619b7bde..a73db8cd 100644 --- a/test/handler/test_dockerfile_lint_handler.vader +++ b/test/handler/test_dockerfile_lint_handler.vader @@ -26,21 +26,25 @@ Execute(The dockerfile_lint handler should handle a normal example): \ 'lnum': -1, \ 'type': 'E', \ 'text': "Required LABEL name/key 'Name' is not defined", + \ 'detail': "Required LABEL name/key 'Name' is not defined\n\nhttp://docs.projectatomic.io/container-best-practices/#_recommended_labels_for_your_project", \ }, \ { \ 'lnum': -1, \ 'type': 'E', \ 'text': "Required LABEL name/key 'Version' is not defined", + \ 'detail': "Required LABEL name/key 'Version' is not defined\n\nhttp://docs.projectatomic.io/container-best-practices/#_recommended_labels_for_your_project", \ }, \ { \ 'lnum': 3, \ 'type': 'I', - \ 'text': "the MAINTAINER command is deprecated. MAINTAINER is deprecated in favor of using LABEL since Docker v1.13.0", + \ 'text': "the MAINTAINER command is deprecated", + \ 'detail': "the MAINTAINER command is deprecated\n\nMAINTAINER is deprecated in favor of using LABEL since Docker v1.13.0\n\nhttps://github.com/docker/cli/blob/master/docs/deprecated.md#maintainer-in-dockerfile", \ }, \ { \ 'lnum': -1, \ 'type': 'I', \ 'text': "There is no 'CMD' instruction", + \ 'detail': "There is no 'CMD' instruction\n\nhttps://docs.docker.com/engine/reference/builder/#cmd", \ }, \ ], \ ale_linters#dockerfile#dockerfile_lint#Handle(bufnr(''), [ diff --git a/test/handler/test_eslint_json_handler.vader b/test/handler/test_eslint_json_handler.vader index 8e07bd80..6235794a 100644 --- a/test/handler/test_eslint_json_handler.vader +++ b/test/handler/test_eslint_json_handler.vader @@ -21,6 +21,7 @@ After: unlet! g:config_error_lines Execute(The eslint handler should parse json correctly): + call ale#test#SetFilename('foo.js') AssertEqual \ [ \ { @@ -53,6 +54,21 @@ Execute(The eslint handler should parse json correctly): \ '[{"filePath":"foo.js","messages":[{"ruleId":"no-unused-vars","severity":1,"message":"''variable'' is assigned a value but never used.","line":1,"column":7,"nodeType":"Identifier","endLine":1,"endColumn":15},{"ruleId":"semi","severity":1,"message":"Missing semicolon.","line":5,"column":15,"nodeType":"ExpressionStatement","fix":{"range":[46,46],"text":";"}},{"ruleId":"no-redeclare","severity":2,"message":"''variable'' is already defined.","line":7,"column":7,"nodeType":"Identifier","endLine":7,"endColumn":15}],"errorCount":1,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":1,"source":"const variable = {\n a: 3\n};\n\nconsole.log(1)\n\nclass variable {\n}\n"}]' \ ]) +Execute(The eslint handler should suppress deprecation warnings): + call ale#test#SetFilename('foo.js') + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'col': 9, + \ 'text': 'Parsing error: Unexpected token Controller', + \ 'type': 'E', + \ } + \ ], + \ ale#handlers#eslint#HandleJSON(bufnr(''), [ + \ '[{"filePath":"foo.js","messages":[{"ruleId":null,"fatal":true,"severity":2 ,"message":"Parsing error: Unexpected token Controller","line":1,"column":9}],"errorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount": 0,"source":"i:mport Controller from \"@ember/controller\";\nimport listViewControllerMixin from \"elearning/mixins/list-view-controller\";\nimport { inject as service } from \"@ember/service\";\n\nexport default Controller.extend(listViewControllerMixin(), {\n modelName: \"notification\",\n intl: service(),\n\n flatpickrLocale: computed(\"intl.locale\", function() {\n return this.intl.locale.firstObject.split(\"-\")[0];\n })\n});\n"}]', '(node:616989) [ESLINT_LEGACY_OBJECT_REST_SPREAD] DeprecationWarning: The ''parserOptions.ecmaFeatures.experimentalObjectRestSpread'' option is deprecated. Use ''parser Options.ecmaVersion'' instead. (found in "node_modules/eslint-plugin-ember/lib/config/base.js")]' + \ ]) + Execute(The eslint handler should print a message about a missing configuration file): let g:config_error_lines = [ \ '', @@ -262,7 +278,7 @@ Execute(Suppressing missing configs shouldn't suppress module import errors): \ ale#handlers#eslint#HandleJSON(bufnr(''), g:config_error_lines[:]) Execute(The eslint handler should hint about using typescript-eslint-parser): - silent! noautocmd file foo.ts + call ale#test#SetFilename('foo.ts') AssertEqual \ [ @@ -326,7 +342,7 @@ Execute(Failing to connect to eslint_d should be handled correctly): \ ]) Execute(Disabling warnings about trailing spaces should work): - silent! noautocmd file foo.ts + call ale#test#SetFilename('foo.js') AssertEqual \ [ diff --git a/test/handler/test_go_generic_handler.vader b/test/handler/test_go_generic_handler.vader index 624e56c1..2b17fdcb 100644 --- a/test/handler/test_go_generic_handler.vader +++ b/test/handler/test_go_generic_handler.vader @@ -15,8 +15,24 @@ Execute(The golang handler should return the correct filenames): \ 'type': 'E', \ 'filename': ale#path#Simplify(expand('%:p:h') . '/other.go'), \ }, + \ { + \ 'lnum': 18, + \ 'col': 0, + \ 'text': 'random error', + \ 'type': 'E', + \ 'filename': ale#path#Simplify(expand('%:p:h') . '/go1.14.go'), + \ }, + \ { + \ 'lnum': 36, + \ 'col': 2, + \ 'text': 'another random error', + \ 'type': 'E', + \ 'filename': ale#path#Simplify(expand('%:p:h') . '/anothergo1.14.go'), + \ }, \ ], \ ale#handlers#go#Handler(bufnr(''), [ \ 'test.go:27: some error', \ 'other.go:27:5: some error with a column', + \ 'vet: go1.14.go:18:0: random error', + \ 'vet: anothergo1.14.go:36:2: another random error', \ ]) diff --git a/test/handler/test_markdownlint_handler.vader b/test/handler/test_markdownlint_handler.vader index db6acc66..f2e6e328 100644 --- a/test/handler/test_markdownlint_handler.vader +++ b/test/handler/test_markdownlint_handler.vader @@ -4,21 +4,88 @@ Before: After: call ale#linter#Reset() -Execute(The Markdownlint handler should parse output correctly): +Execute(The Markdownlint handler should parse pre v0.19.0 output with single digit line correctly): AssertEqual \ [ \ { \ 'lnum': 1, - \ 'text': '(MD002/first-header-h1) First header should be a top level header [Expected: h1; Actual: h2]', + \ 'code': 'MD013/line-length', + \ 'text': 'Line length [Expected: 80; Actual: 114]', \ 'type': 'W' - \ }, + \ } + \ ], + \ ale#handlers#markdownlint#Handle(0, [ + \ 'README.md: 1: MD013/line-length Line length [Expected: 80; Actual: 114]' + \ ]) + +Execute(The Markdownlint handler should parse pre v0.19.0 output with multi digit line correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 100, + \ 'code': 'MD013/line-length', + \ 'text': 'Line length [Expected: 80; Actual: 114]', + \ 'type': 'W' + \ } + \ ], + \ ale#handlers#markdownlint#Handle(0, [ + \ 'README.md: 100: MD013/line-length Line length [Expected: 80; Actual: 114]' + \ ]) + +Execute(The Markdownlint handler should parse post v0.19.0 output with single digit line correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'code': 'MD013/line-length', + \ 'text': 'Line length [Expected: 80; Actual: 114]', + \ 'type': 'W' + \ } + \ ], + \ ale#handlers#markdownlint#Handle(0, [ + \ 'README.md:1 MD013/line-length Line length [Expected: 80; Actual: 114]' + \ ]) + +Execute(The Markdownlint handler should parse post v0.19.0 output with multi digit line correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 100, + \ 'code': 'MD013/line-length', + \ 'text': 'Line length [Expected: 80; Actual: 114]', + \ 'type': 'W' + \ } + \ ], + \ ale#handlers#markdownlint#Handle(0, [ + \ 'README.md:100 MD013/line-length Line length [Expected: 80; Actual: 114]' + \ ]) + + +Execute(The Markdownlint handler should parse post v0.22.0 output with column correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 10, + \ 'col': 20, + \ 'code': 'MD013/line-length', + \ 'text': 'Line length [Expected: 80; Actual: 114]', + \ 'type': 'W' + \ } + \ ], + \ ale#handlers#markdownlint#Handle(0, [ + \ 'README.md:10:20 MD013/line-length Line length [Expected: 80; Actual: 114]' + \ ]) + +Execute(The Markdownlint handler should parse output with multiple slashes in rule name correctly): + AssertEqual + \ [ \ { - \ 'lnum': 298, - \ 'text': '(MD033/no-inline-html) Inline HTML [Element: p]', + \ 'lnum': 10, + \ 'code': 'MD022/blanks-around-headings/blanks-around-headers', + \ 'text': 'Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Above] [Context: "### something"]', \ 'type': 'W' \ } \ ], \ ale#handlers#markdownlint#Handle(0, [ - \ 'README.md: 1: MD002/first-header-h1 First header should be a top level header [Expected: h1; Actual: h2]', - \ 'README.md: 298: MD033/no-inline-html Inline HTML [Element: p]' + \ 'README.md:10 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Above] [Context: "### something"]' \ ]) diff --git a/test/handler/test_mypy_handler.vader b/test/handler/test_mypy_handler.vader index 6e96f3f3..039155a2 100644 --- a/test/handler/test_mypy_handler.vader +++ b/test/handler/test_mypy_handler.vader @@ -1,6 +1,8 @@ Before: Save g:ale_python_mypy_ignore_invalid_syntax + Save g:ale_python_mypy_show_notes + unlet! g:ale_python_mypy_show_notes unlet! g:ale_python_mypy_ignore_invalid_syntax runtime ale_linters/python/mypy.vim @@ -16,6 +18,8 @@ After: Execute(The mypy handler should parse lines correctly): call ale#test#SetFilename('__init__.py') + let g:ale_python_mypy_show_notes = 0 + AssertEqual \ [ \ { @@ -69,6 +73,31 @@ Execute(The mypy handler should parse lines correctly): \ '__init__.py:72:1: warning: Some warning', \ ]) +Execute(The mypy handler should show notes if enabled): + call ale#test#SetFilename('__init__.py') + + AssertEqual + \ [ + \ { + \ 'lnum': 72, + \ 'col': 1, + \ 'filename': ale#path#Simplify(g:dir . '/__init__.py'), + \ 'type': 'I', + \ 'text': 'A note', + \ }, + \ ], + \ ale_linters#python#mypy#Handle(bufnr(''), [ + \ '__init__.py:72:1: note: A note', + \ ]) + + let g:ale_python_mypy_show_notes = 0 + + AssertEqual + \ [], + \ ale_linters#python#mypy#Handle(bufnr(''), [ + \ '__init__.py:72:1: note: A note', + \ ]) + Execute(The mypy handler should handle Windows names with spaces): " This test works on Unix, where this is seen as a single filename silent file C:\\something\\with\ spaces.py diff --git a/test/handler/test_puppet_handler.vader b/test/handler/test_puppet_handler.vader index e73c9dc7..03adc9f0 100644 --- a/test/handler/test_puppet_handler.vader +++ b/test/handler/test_puppet_handler.vader @@ -49,3 +49,29 @@ Execute(The puppet handler should parse lines and column correctly): \ "Error: Could not parse for environment production: Syntax error at ':' at C:/puppet/modules/nginx/manifests/init.pp:54:9", \ "Error: Could not parse for environment production: Syntax error at 'parameter1' (file: /tmp/modules/mariadb/manifests/slave.pp, line: 45, column: 12)", \ ]) + +Execute(The puppet handler should correctly parse errors that are reported before even trying to parse for an environment): + " Line Error + AssertEqual + \ [ + \ { + \ 'lnum': 5, + \ 'col': 11, + \ 'text': "Illegal attempt to assign to 'a Name'. Not an assignable reference" + \ }, + \ ], + \ ale_linters#puppet#puppet#Handle(255, [ + \ "Error: Illegal attempt to assign to 'a Name'. Not an assignable reference (file: /tmp/modules/waffles/manifests/syrup.pp, line: 5, column: 11)", + \ ]) +Execute(The puppet handler should parse lines when end of input is the location): + AssertEqual + \ [ + \ { + \ 'lnum': 0, + \ 'col': 0, + \ 'text': "Syntax error at end of input" + \ }, + \ ], + \ ale_linters#puppet#puppet#Handle(255, [ + \ "Error: Could not parse for environment production: Syntax error at end of input (file: /tmp//modules/test/manifests/init.pp)", + \ ]) diff --git a/test/handler/test_shellcheck_handler.vader b/test/handler/test_shellcheck_handler.vader index bfb73ffa..33f12989 100644 --- a/test/handler/test_shellcheck_handler.vader +++ b/test/handler/test_shellcheck_handler.vader @@ -22,7 +22,7 @@ Execute(The shellcheck handler should handle basic errors or warnings): \ 'code': 'SC1068', \ }, \ ], - \ ale_linters#sh#shellcheck#Handle(bufnr(''), [ + \ ale#handlers#shellcheck#Handle(bufnr(''), [ \ '-:2:1: warning: In POSIX sh, ''let'' is not supported. [SC2039]', \ '-:2:3: error: Don''t put spaces around the = in assignments. [SC1068]', \ ]) @@ -38,6 +38,6 @@ Execute(The shellcheck handler should handle notes): \ 'code': 'SC2086', \ }, \ ], - \ ale_linters#sh#shellcheck#Handle(bufnr(''), [ + \ ale#handlers#shellcheck#Handle(bufnr(''), [ \ '-:3:3: note: Double quote to prevent globbing and word splitting. [SC2086]', \ ]) diff --git a/test/handler/test_verilator_handler.vader b/test/handler/test_verilator_handler.vader new file mode 100644 index 00000000..5e51b5c9 --- /dev/null +++ b/test/handler/test_verilator_handler.vader @@ -0,0 +1,48 @@ +Before: + runtime ale_linters/verilog/verilator.vim + +After: + call ale#linter#Reset() + + +Execute (The verilator handler should parse legacy messages with only line numbers): + AssertEqual + \ [ + \ { + \ 'lnum': 3, + \ 'type': 'E', + \ 'text': 'syntax error, unexpected IDENTIFIER' + \ }, + \ { + \ 'lnum': 10, + \ 'type': 'W', + \ 'text': 'Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=).' + \ }, + \ ], + \ ale_linters#verilog#verilator#Handle(bufnr(''), [ + \ '%Error: foo_verilator_linted.v:3: syntax error, unexpected IDENTIFIER', + \ '%Warning-BLKSEQ: bar_verilator_linted.v:10: Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=).', + \ ]) + + +Execute (The verilator handler should parse new format messages with line and column numbers): + AssertEqual + \ [ + \ { + \ 'lnum': 3, + \ 'col' : 1, + \ 'type': 'E', + \ 'text': 'syntax error, unexpected endmodule, expecting ;' + \ }, + \ { + \ 'lnum': 4, + \ 'col' : 6, + \ 'type': 'W', + \ 'text': 'Signal is not used: r' + \ }, + \ ], + \ ale_linters#verilog#verilator#Handle(bufnr(''), [ + \ '%Error: bar_verilator_linted.v:3:1: syntax error, unexpected endmodule, expecting ;', + \ '%Warning-UNUSED: foo_verilator_linted.v:4:6: Signal is not used: r', + \ ]) + diff --git a/test/lsp/test_other_initialize_message_handling.vader b/test/lsp/test_other_initialize_message_handling.vader index 6473e283..b6ef852a 100644 --- a/test/lsp/test_other_initialize_message_handling.vader +++ b/test/lsp/test_other_initialize_message_handling.vader @@ -131,7 +131,7 @@ Execute(Disabled capabilities should be recognised correctly): \ }, \ 'definitionProvider': v:false, \ 'experimental': {}, - \ 'documentHighlightProvider': v:true + \ 'documentHighlightProvider': v:true, \ }, \ }, \}) @@ -150,6 +150,57 @@ Execute(Disabled capabilities should be recognised correctly): \ b:conn.capabilities AssertEqual [[1, 'initialized', {}]], g:message_list +Execute(Capabilities should be enabled when send as Dictionaries): + call ale#lsp#HandleInitResponse(b:conn, { + \ 'jsonrpc': '2.0', + \ 'id': 1, + \ 'result': { + \ 'capabilities': { + \ 'renameProvider': {}, + \ 'executeCommandProvider': { + \ 'commands': [], + \ }, + \ 'hoverProvider': {}, + \ 'documentSymbolProvider': v:true, + \ 'documentRangeFormattingProvider': v:true, + \ 'codeLensProvider': { + \ 'resolveProvider': v:false + \ }, + \ 'completionProvider': { + \ 'triggerCharacters': ['.'], + \ 'resolveProvider': v:false + \ }, + \ 'referencesProvider': {}, + \ 'textDocumentSync': 2, + \ 'documentFormattingProvider': v:true, + \ 'codeActionProvider': v:true, + \ 'signatureHelpProvider': { + \ 'triggerCharacters': ['(', ','], + \ }, + \ 'definitionProvider': {}, + \ 'typeDefinitionProvider': {}, + \ 'experimental': {}, + \ 'documentHighlightProvider': v:true, + \ 'workspaceSymbolProvider': {} + \ }, + \ }, + \}) + + AssertEqual 1, b:conn.initialized + AssertEqual + \ { + \ 'completion_trigger_characters': ['.'], + \ 'completion': 1, + \ 'references': 1, + \ 'hover': 1, + \ 'definition': 1, + \ 'typeDefinition': 1, + \ 'symbol_search': 1, + \ 'rename': 1, + \ }, + \ b:conn.capabilities + AssertEqual [[1, 'initialized', {}]], g:message_list + Execute(Results that are not dictionaries should be handled correctly): call ale#lsp#HandleInitResponse(b:conn, { \ 'jsonrpc': '2.0', diff --git a/test/python/test_deoplete_source.py b/test/python/test_deoplete_source.py index 9e56a10d..8304fa25 100644 --- a/test/python/test_deoplete_source.py +++ b/test/python/test_deoplete_source.py @@ -8,15 +8,20 @@ ale_module = imp.load_source( class VimMock(object): - def __init__(self, call_list, call_results): + def __init__(self, call_list, call_results, commands): self.__call_list = call_list self.__call_results = call_results + self.__commands = commands + def call(self, function, *args): self.__call_list.append((function, args)) return self.__call_results.get(function, 0) + def command(self, command): + self.__commands.append(command) + class DeopleteSourceTest(unittest.TestCase): def setUp(self): @@ -24,8 +29,10 @@ class DeopleteSourceTest(unittest.TestCase): self.call_list = [] self.call_results = {'ale#completion#CanProvideCompletions': 1} + self.commands = [] self.source = ale_module.Source('vim') - self.source.vim = VimMock(self.call_list, self.call_results) + self.source.vim = VimMock( + self.call_list, self.call_results, self.commands) def test_attributes(self): """ @@ -48,6 +55,7 @@ class DeopleteSourceTest(unittest.TestCase): 'cpp': r'(\.|::|->)\w*$', }, 'is_bytepos': True, + 'is_volatile': True, 'mark': '[L]', 'min_pattern_length': 1, 'name': 'ale', @@ -64,70 +72,28 @@ class DeopleteSourceTest(unittest.TestCase): ]) def test_request_completion_results(self): - context = {'is_async': False} + context = {'event': 'TextChangedI', 'is_refresh': True} self.assertEqual(self.source.gather_candidates(context), []) - self.assertEqual(context, {'is_async': True}) self.assertEqual(self.call_list, [ ('ale#completion#CanProvideCompletions', ()), - ('ale#completion#GetCompletions', ('deoplete',)), + ]) + self.assertEqual(self.commands, [ + "call ale#completion#GetCompletions('ale-callback', " + \ + "{'callback': {completions -> deoplete#auto_complete() }})" ]) def test_request_completion_results_from_buffer_without_providers(self): self.call_results['ale#completion#CanProvideCompletions'] = 0 - context = {'is_async': False} + context = {'event': 'TextChangedI', 'is_refresh': True} self.assertIsNone(self.source.gather_candidates(context), []) - self.assertEqual(context, {'is_async': False}) - self.assertEqual(self.call_list, [ - ('ale#completion#CanProvideCompletions', ()), - ]) - - def test_refresh_completion_results(self): - context = {'is_async': False} - - self.assertEqual(self.source.gather_candidates(context), []) - self.assertEqual(context, {'is_async': True}) - self.assertEqual(self.call_list, [ - ('ale#completion#CanProvideCompletions', ()), - ('ale#completion#GetCompletions', ('deoplete',)), - ]) - - context = {'is_async': True, 'is_refresh': True} - - self.assertEqual(self.source.gather_candidates(context), []) - self.assertEqual(context, {'is_async': True, 'is_refresh': True}) self.assertEqual(self.call_list, [ ('ale#completion#CanProvideCompletions', ()), - ('ale#completion#GetCompletions', ('deoplete',)), - ('ale#completion#CanProvideCompletions', ()), - ('ale#completion#GetCompletions', ('deoplete',)), ]) - def test_poll_no_result(self): - context = {'is_async': True} - self.call_results['ale#completion#GetCompletionResult'] = None - - self.assertEqual(self.source.gather_candidates(context), []) - self.assertEqual(context, {'is_async': True}) - self.assertEqual(self.call_list, [ - ('ale#completion#CanProvideCompletions', ()), - ('ale#completion#GetCompletionResult', ()), - ]) - - def test_poll_empty_result_ready(self): - context = {'is_async': True} - self.call_results['ale#completion#GetCompletionResult'] = [] - - self.assertEqual(self.source.gather_candidates(context), []) - self.assertEqual(context, {'is_async': False}) - self.assertEqual(self.call_list, [ - ('ale#completion#CanProvideCompletions', ()), - ('ale#completion#GetCompletionResult', ()), - ]) - - def test_poll_non_empty_result_ready(self): - context = {'is_async': True} + def test_async_event(self): + context = {'event': 'Async', 'is_refresh': True} self.call_results['ale#completion#GetCompletionResult'] = [ { 'word': 'foobar', @@ -147,7 +113,7 @@ class DeopleteSourceTest(unittest.TestCase): 'info': '', }, ]) - self.assertEqual(context, {'is_async': False}) + self.assertEqual(self.call_list, [ ('ale#completion#CanProvideCompletions', ()), ('ale#completion#GetCompletionResult', ()), diff --git a/test/sign/test_linting_sets_signs.vader b/test/sign/test_linting_sets_signs.vader index 60ae0a83..1d1f9802 100644 --- a/test/sign/test_linting_sets_signs.vader +++ b/test/sign/test_linting_sets_signs.vader @@ -32,7 +32,7 @@ Before: function! CollectSigns() redir => l:output - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') silent exec 'sign place group=ale' else silent exec 'sign place' diff --git a/test/sign/test_sign_parsing.vader b/test/sign/test_sign_parsing.vader index 157ff2f4..c0967f43 100644 --- a/test/sign/test_sign_parsing.vader +++ b/test/sign/test_sign_parsing.vader @@ -1,5 +1,5 @@ Execute (Parsing English signs should work): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [0, [[9, 1000001, 'ALEWarningSign']]], \ ale#sign#ParseSigns([ @@ -16,7 +16,7 @@ Execute (Parsing English signs should work): endif Execute (Parsing Russian signs should work): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [0, [[1, 1000001, 'ALEErrorSign']]], \ ale#sign#ParseSigns([' строка=1 id=1000001 группа=ale имя=ALEErrorSign']) @@ -27,7 +27,7 @@ Execute (Parsing Russian signs should work): endif Execute (Parsing Japanese signs should work): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [0, [[1, 1000001, 'ALEWarningSign']]], \ ale#sign#ParseSigns([' 行=1 識別子=1000001 グループ=ale 名前=ALEWarningSign']) @@ -38,7 +38,7 @@ Execute (Parsing Japanese signs should work): endif Execute (Parsing Spanish signs should work): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [0, [[12, 1000001, 'ALEWarningSign']]], \ ale#sign#ParseSigns([' línea=12 id=1000001 grupo=ale nombre=ALEWarningSign']) @@ -49,7 +49,7 @@ Execute (Parsing Spanish signs should work): endif Execute (Parsing Italian signs should work): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [0, [[1, 1000001, 'ALEWarningSign']]], \ ale#sign#ParseSigns([' riga=1 id=1000001, gruppo=ale nome=ALEWarningSign']) @@ -60,7 +60,7 @@ Execute (Parsing Italian signs should work): endif Execute (Parsing German signs should work): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [0, [[235, 1000001, 'ALEErrorSign']]], \ ale#sign#ParseSigns([' Zeile=235 id=1000001 Gruppe=ale Name=ALEErrorSign']) @@ -71,7 +71,7 @@ Execute (Parsing German signs should work): endif Execute (The sign parser should indicate if the dummy sign is set): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [1, [[1, 1000001, 'ALEErrorSign']]], \ ale#sign#ParseSigns([ diff --git a/test/sign/test_sign_placement.vader b/test/sign/test_sign_placement.vader index 80153b22..d8d05b28 100644 --- a/test/sign/test_sign_placement.vader +++ b/test/sign/test_sign_placement.vader @@ -68,7 +68,7 @@ Before: function! ParseSigns() redir => l:output - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') silent sign place group=ale else silent sign place @@ -152,7 +152,7 @@ Execute(The current signs should be set for running a job): \ ParseSigns() Execute(Loclist items with sign_id values should be kept): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') exec 'sign place 1000347 group=ale line=3 name=ALEErrorSign buffer=' . bufnr('') exec 'sign place 1000348 group=ale line=15 name=ALEErrorSign buffer=' . bufnr('') exec 'sign place 1000349 group=ale line=16 name=ALEWarningSign buffer=' . bufnr('') @@ -297,7 +297,7 @@ Execute(No exceptions should be thrown when setting signs for invalid buffers): Execute(Signs should be removed when lines have multiple sign IDs on them): " We can fail to remove signs if there are multiple signs on one line, " say after deleting lines in Vim, etc. - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') exec 'sign place 1000347 group=ale line=3 name=ALEErrorSign buffer=' . bufnr('') exec 'sign place 1000348 group=ale line=3 name=ALEWarningSign buffer=' . bufnr('') exec 'sign place 1000349 group=ale line=10 name=ALEErrorSign buffer=' . bufnr('') diff --git a/test/terraform_files/main.tf b/test/terraform_files/main.tf new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/terraform_files/main.tf diff --git a/test/test_ale_has.vader b/test/test_ale_has.vader index b8a99103..633c7186 100644 --- a/test/test_ale_has.vader +++ b/test/test_ale_has.vader @@ -1,4 +1,5 @@ Execute(Checks for versions below the current version should succeed): + AssertEqual 1, ale#Has('ale-2.7.0') AssertEqual 1, ale#Has('ale-2.6.0') AssertEqual 1, ale#Has('ale-2.5.0') AssertEqual 1, ale#Has('ale-2.4.0') diff --git a/test/test_autocmd_commands.vader b/test/test_autocmd_commands.vader index 355b4c77..a69333d4 100644 --- a/test/test_autocmd_commands.vader +++ b/test/test_autocmd_commands.vader @@ -49,6 +49,7 @@ Before: Save g:ale_lint_on_save Save g:ale_lint_on_text_changed Save g:ale_pattern_options_enabled + Save g:ale_hover_cursor " Turn everything on by defaul for these tests. let g:ale_completion_enabled = 1 @@ -61,6 +62,7 @@ Before: let g:ale_lint_on_save = 1 let g:ale_lint_on_text_changed = 1 let g:ale_pattern_options_enabled = 1 + let g:ale_hover_cursor = 1 After: delfunction CheckAutocmd @@ -84,6 +86,7 @@ Execute (All events should be set up when everything is on): \ 'BufWinEnter * call ale#events#LintOnEnter(str2nr(expand(''<abuf>'')))', \ 'BufWritePost * call ale#events#SaveEvent(str2nr(expand(''<abuf>'')))', \ 'CursorHold * if exists(''*ale#engine#Cleanup'') | call ale#cursor#EchoCursorWarningWithDelay() | endif', + \ 'CursorHold if exists(''*ale#lsp#Send'') | call ale#hover#ShowTruncatedMessageAtCursor() | endif', \ 'CursorMoved * if exists(''*ale#engine#Cleanup'') | call ale#cursor#EchoCursorWarningWithDelay() | endif', \ 'FileChangedShellPost * call ale#events#FileChangedEvent(str2nr(expand(''<abuf>'')))', \ 'FileType * call ale#events#FileTypeEvent( str2nr(expand(''<abuf>'')), expand(''<amatch>''))', @@ -95,9 +98,30 @@ Execute (All events should be set up when everything is on): \ CheckAutocmd('ALEEvents') Execute (Only the required events should be bound even if various settings are off): + let g:ale_enabled = 1 + let g:ale_completion_enabled = 0 + let g:ale_echo_cursor = 0 + let g:ale_fix_on_save = 0 + let g:ale_lint_on_enter = 0 + let g:ale_lint_on_filetype_changed = 0 + let g:ale_lint_on_insert_leave = 0 + let g:ale_lint_on_save = 0 + let g:ale_lint_on_text_changed = 0 + let g:ale_pattern_options_enabled = 0 + let g:ale_hover_cursor = 0 + + AssertEqual + \ [ + \ 'BufEnter * call ale#events#ReadOrEnterEvent(str2nr(expand(''<abuf>'')))', + \ 'BufReadPost * call ale#events#ReadOrEnterEvent(str2nr(expand(''<abuf>'')))', + \ 'BufWritePost * call ale#events#SaveEvent(str2nr(expand(''<abuf>'')))', + \ ], + \ CheckAutocmd('ALEEvents') + +Execute (The cursor hoever event should be enabled with g:ale_hover_cursor = 1): + let g:ale_enabled = 1 let g:ale_completion_enabled = 0 let g:ale_echo_cursor = 0 - let g:ale_enabled = 0 let g:ale_fix_on_save = 0 let g:ale_lint_on_enter = 0 let g:ale_lint_on_filetype_changed = 0 @@ -105,12 +129,14 @@ Execute (Only the required events should be bound even if various settings are o let g:ale_lint_on_save = 0 let g:ale_lint_on_text_changed = 0 let g:ale_pattern_options_enabled = 0 + let g:ale_hover_cursor = 1 AssertEqual \ [ \ 'BufEnter * call ale#events#ReadOrEnterEvent(str2nr(expand(''<abuf>'')))', \ 'BufReadPost * call ale#events#ReadOrEnterEvent(str2nr(expand(''<abuf>'')))', \ 'BufWritePost * call ale#events#SaveEvent(str2nr(expand(''<abuf>'')))', + \ 'CursorHold * if exists(''*ale#lsp#Send'') | call ale#hover#ShowTruncatedMessageAtCursor() | endif', \ ], \ CheckAutocmd('ALEEvents') diff --git a/test/test_c_projects/makefile_project/_astylerc b/test/test_c_projects/makefile_project/_astylerc new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/test_c_projects/makefile_project/_astylerc diff --git a/test/test_code_action.vader b/test/test_code_action.vader index ffaca630..b47f24ff 100644 --- a/test/test_code_action.vader +++ b/test/test_code_action.vader @@ -37,10 +37,10 @@ Before: After: " Close the extra buffers if we opened it. if bufnr(g:file1) != -1 - execute ':bp | :bd ' . bufnr(g:file1) + execute ':bp! | :bd! ' . bufnr(g:file1) endif if bufnr(g:file2) != -1 - execute ':bp | :bd ' . bufnr(g:file2) + execute ':bp! | :bd! ' . bufnr(g:file2) endif if filereadable(g:file1) @@ -116,7 +116,7 @@ Execute(It should modify and save multiple files): \ 'newText': "import {A, B} from 'module'\n\n", \ }] \ }], - \}) + \}, v:true) AssertEqual [ \ 'class Value {', @@ -161,7 +161,7 @@ Execute(Beginning of file can be modified): \ 'newText': "type A: string\ntype B: number\n", \ }], \ }] - \}) + \}, v:true) AssertEqual [ \ 'type A: string', @@ -192,7 +192,7 @@ Execute(End of file can be modified): \ 'newText': "type A: string\ntype B: number\n", \ }], \ }] - \}) + \}, v:true) AssertEqual g:test.text + [ \ 'type A: string', @@ -227,7 +227,7 @@ Execute(Current buffer contents will be reloaded): \ 'newText': "type A: string\ntype B: number\n", \ }], \ }] - \}) + \}, v:true) AssertEqual [ \ 'type A: string', @@ -249,11 +249,11 @@ Execute(Cursor will not move when it is before text change): let g:test.changes = g:test.create_change(2, 3, 2, 8, 'value2') call setpos('.', [0, 1, 1, 0]) - call ale#code_action#HandleCodeAction(g:test.changes) + call ale#code_action#HandleCodeAction(g:test.changes, v:true) AssertEqual [1, 1], getpos('.')[1:2] call setpos('.', [0, 2, 2, 0]) - call ale#code_action#HandleCodeAction(g:test.changes) + call ale#code_action#HandleCodeAction(g:test.changes, v:true) AssertEqual [2, 2], getpos('.')[1:2] # ====C==== @@ -264,7 +264,7 @@ Execute(Cursor column will move to the change end when cursor between start/end) call WriteFileAndEdit() call setpos('.', [0, 2, r, 0]) AssertEqual ' value: string', getline('.') - call ale#code_action#HandleCodeAction(g:test.changes) + call ale#code_action#HandleCodeAction(g:test.changes, v:true) AssertEqual ' value2: string', getline('.') AssertEqual [2, 9], getpos('.')[1:2] endfor @@ -275,7 +275,8 @@ Execute(Cursor column will move back when new text is shorter): call WriteFileAndEdit() call setpos('.', [0, 2, 8, 0]) AssertEqual ' value: string', getline('.') - call ale#code_action#HandleCodeAction(g:test.create_change(2, 3, 2, 8, 'val')) + call ale#code_action#HandleCodeAction( + \ g:test.create_change(2, 3, 2, 8, 'val'), v:true) AssertEqual ' val: string', getline('.') AssertEqual [2, 6], getpos('.')[1:2] @@ -286,7 +287,8 @@ Execute(Cursor column will move forward when new text is longer): call setpos('.', [0, 2, 8, 0]) AssertEqual ' value: string', getline('.') - call ale#code_action#HandleCodeAction(g:test.create_change(2, 3, 2, 8, 'longValue')) + call ale#code_action#HandleCodeAction( + \ g:test.create_change(2, 3, 2, 8, 'longValue'), v:true) AssertEqual ' longValue: string', getline('.') AssertEqual [2, 12], getpos('.')[1:2] @@ -297,7 +299,8 @@ Execute(Cursor line will move when updates are happening on lines above): call WriteFileAndEdit() call setpos('.', [0, 3, 1, 0]) AssertEqual '}', getline('.') - call ale#code_action#HandleCodeAction(g:test.create_change(1, 1, 2, 1, "test\ntest\n")) + call ale#code_action#HandleCodeAction( + \ g:test.create_change(1, 1, 2, 1, "test\ntest\n"), v:true) AssertEqual '}', getline('.') AssertEqual [4, 1], getpos('.')[1:2] @@ -308,7 +311,8 @@ Execute(Cursor line and column will move when change on lines above and just bef call WriteFileAndEdit() call setpos('.', [0, 2, 2, 0]) AssertEqual ' value: string', getline('.') - call ale#code_action#HandleCodeAction(g:test.create_change(1, 1, 2, 1, "test\ntest\n123")) + call ale#code_action#HandleCodeAction( + \ g:test.create_change(1, 1, 2, 1, "test\ntest\n123"), v:true) AssertEqual '123 value: string', getline('.') AssertEqual [3, 5], getpos('.')[1:2] @@ -319,7 +323,8 @@ Execute(Cursor line and column will move at the end of changes): call WriteFileAndEdit() call setpos('.', [0, 2, 10, 0]) AssertEqual ' value: string', getline('.') - call ale#code_action#HandleCodeAction(g:test.create_change(1, 1, 3, 1, "test\n")) + call ale#code_action#HandleCodeAction( + \ g:test.create_change(1, 1, 3, 1, "test\n"), v:true) AssertEqual '}', getline('.') AssertEqual [2, 1], getpos('.')[1:2] @@ -329,6 +334,19 @@ Execute(Cursor will not move when changes happening on lines >= cursor, but afte call WriteFileAndEdit() call setpos('.', [0, 2, 3, 0]) AssertEqual ' value: string', getline('.') - call ale#code_action#HandleCodeAction(g:test.create_change(2, 10, 3, 1, "number\n")) + call ale#code_action#HandleCodeAction( + \ g:test.create_change(2, 10, 3, 1, "number\n"), v:true) AssertEqual ' value: number', getline('.') AssertEqual [2, 3], getpos('.')[1:2] + +Execute(It should just modify file when should_save is set to v:false): + call WriteFileAndEdit() + let g:test.change = g:test.create_change(1, 1, 1, 1, "import { writeFile } from 'fs';\n") + call ale#code_action#HandleCodeAction(g:test.change, v:false) + AssertEqual 1, getbufvar(bufnr(''), '&modified') + AssertEqual [ + \ 'import { writeFile } from ''fs'';', + \ 'class Name {', + \ ' value: string', + \ '}', + \], getline(1, '$') diff --git a/test/test_cpp_project/.astylerc b/test/test_cpp_project/.astylerc new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/test_cpp_project/.astylerc diff --git a/test/test_cpp_project/dummy.cpp b/test/test_cpp_project/dummy.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/test_cpp_project/dummy.cpp diff --git a/test/test_cursor_warnings.vader b/test/test_cursor_warnings.vader index 2a6156f0..339cd71e 100644 --- a/test/test_cursor_warnings.vader +++ b/test/test_cursor_warnings.vader @@ -15,7 +15,7 @@ Before: \ 'col': 10, \ 'bufnr': bufnr('%'), \ 'vcol': 0, - \ 'linter_name': 'eslint', + \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'W', \ 'code': 'semi', @@ -26,7 +26,7 @@ Before: \ 'col': 10, \ 'bufnr': bufnr('%'), \ 'vcol': 0, - \ 'linter_name': 'eslint', + \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'E', \ 'code': 'semi', @@ -38,7 +38,7 @@ Before: \ 'col': 14, \ 'bufnr': bufnr('%'), \ 'vcol': 0, - \ 'linter_name': 'eslint', + \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'I', \ 'text': 'Some information', @@ -48,7 +48,7 @@ Before: \ 'col': 10, \ 'bufnr': bufnr('%'), \ 'vcol': 0, - \ 'linter_name': 'eslint', + \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'W', \ 'code': 'space-infix-ops', @@ -59,7 +59,7 @@ Before: \ 'col': 15, \ 'bufnr': bufnr('%'), \ 'vcol': 0, - \ 'linter_name': 'eslint', + \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'E', \ 'code': 'radix', @@ -70,7 +70,7 @@ Before: \ 'col': 1, \ 'bufnr': bufnr('%'), \ 'vcol': 0, - \ 'linter_name': 'eslint', + \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'E', \ 'text': 'lowercase error', @@ -196,7 +196,7 @@ Execute(The linter name should be formatted into the message correctly): call ale#cursor#EchoCursorWarning() AssertEqual - \ 'eslint: Infix operators must be spaced.', + \ 'bettercode: Infix operators must be spaced.', \ GetLastMessage() Execute(The severity should be formatted into the message correctly): diff --git a/test/test_eslint_executable_detection.vader b/test/test_eslint_executable_detection.vader index 64383dcb..3fed63da 100644 --- a/test/test_eslint_executable_detection.vader +++ b/test/test_eslint_executable_detection.vader @@ -57,13 +57,44 @@ Execute(eslint.js executables should be run with node on Windows): " We have to execute the file with node. if has('win32') AssertEqual - \ ale#Escape('node.exe') . ' ' + \ ale#path#CdString(ale#path#Simplify(g:dir . '/eslint-test-files/react-app')) + \ . ale#Escape('node.exe') . ' ' \ . ale#Escape(ale#path#Simplify(g:dir . '/eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ' -f json --stdin --stdin-filename %s', \ ale#handlers#eslint#GetCommand(bufnr('')) else AssertEqual - \ ale#Escape(ale#path#Simplify(g:dir . '/eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) + \ ale#path#CdString(ale#path#Simplify(g:dir . '/eslint-test-files/react-app')) + \ . ale#Escape(ale#path#Simplify(g:dir . '/eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) + \ . ' -f json --stdin --stdin-filename %s', + \ ale#handlers#eslint#GetCommand(bufnr('')) + endif + +Execute(eslint.js should be run from containing project with eslint): + call ale#test#SetFilename('eslint-test-files/react-app/subdir-with-package-json/testfile.js') + + " We have to execute the file with node. + if has('win32') + AssertEqual + \ ale#path#CdString(ale#path#Simplify(g:dir . '/eslint-test-files/react-app')) + \ . ale#Escape('node.exe') . ' ' + \ . ale#Escape(ale#path#Simplify(g:dir . '/eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) + \ . ' -f json --stdin --stdin-filename %s', + \ ale#handlers#eslint#GetCommand(bufnr('')) + else + AssertEqual + \ ale#path#CdString(ale#path#Simplify(g:dir . '/eslint-test-files/react-app')) + \ . ale#Escape(ale#path#Simplify(g:dir . '/eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ' -f json --stdin --stdin-filename %s', \ ale#handlers#eslint#GetCommand(bufnr('')) endif + +Execute(eslint.js executables can be run outside project dir): + " Set filename above eslint-test-files (which contains node_modules) + call ale#test#SetFilename('testfile.js') + + " cd "..." not present, since project root not found (from node_modules) + AssertEqual + \ ale#Escape(ale#handlers#eslint#GetExecutable(bufnr(''))) + \ . ' -f json --stdin --stdin-filename %s', + \ ale#handlers#eslint#GetCommand(bufnr('')) diff --git a/test/test_filetype_linter_defaults.vader b/test/test_filetype_linter_defaults.vader index 9c40cb23..842cc394 100644 --- a/test/test_filetype_linter_defaults.vader +++ b/test/test_filetype_linter_defaults.vader @@ -32,7 +32,7 @@ Execute(The defaults for the help filetype should be correct): AssertEqual [], GetLinterNames('help') Execute(The defaults for the python filetype should be correct): - AssertEqual ['flake8', 'mypy', 'pylint'], GetLinterNames('python') + AssertEqual ['flake8', 'mypy', 'pylint', 'pyright'], GetLinterNames('python') let g:ale_linters_explicit = 1 @@ -61,7 +61,7 @@ Execute(The defaults for the zsh filetype should be correct): Execute(The defaults for the verilog filetype should be correct): " This filetype isn't configured with default, so we can test loading all " available linters with this. - AssertEqual ['iverilog', 'verilator', 'vlog', 'xvlog'], GetLinterNames('verilog') + AssertEqual ['hdl-checker', 'iverilog', 'verilator', 'vlog', 'xvlog'], GetLinterNames('verilog') let g:ale_linters_explicit = 1 diff --git a/test/test_find_references.vader b/test/test_find_references.vader index 1a147849..9949362a 100644 --- a/test/test_find_references.vader +++ b/test/test_find_references.vader @@ -2,6 +2,8 @@ Before: call ale#test#SetDirectory('/testplugin/test') call ale#test#SetFilename('dummy.txt') + Save g:ale_default_navigation + let g:old_filename = expand('%:p') let g:Callback = '' let g:expr_list = [] @@ -12,6 +14,7 @@ Before: let g:capability_checked = '' let g:conn_id = v:null let g:InitCallback = v:null + let g:ale_default_navigation = 'buffer' runtime autoload/ale/lsp_linter.vim runtime autoload/ale/lsp.vim @@ -63,6 +66,8 @@ Before: endfunction After: + Restore + if g:conn_id isnot v:null call ale#lsp#RemoveConnectionWithID(g:conn_id) endif @@ -152,6 +157,20 @@ Execute(Results should be shown for tsserver responses): \ g:item_list AssertEqual {}, ale#references#GetMap() + " We should be able to repeat selections with ALERepeatSelection + let g:ale_item_list = [] + + ALERepeatSelection + + AssertEqual + \ [ + \ {'filename': '/foo/bar/app.ts', 'column': 9, 'line': 9, 'match': 'import {doSomething} from ''./whatever'''}, + \ {'filename': '/foo/bar/app.ts', 'column': 3, 'line': 804, 'match': 'doSomething()'}, + \ {'filename': '/foo/bar/other/app.ts', 'column': 3, 'line': 51, 'match': 'doSomething()'}, + \ ], + \ g:item_list + AssertEqual {}, ale#references#GetMap() + Execute(The preview window should not be opened for empty tsserver responses): call ale#references#SetMap({3: {}}) call ale#references#HandleTSServerResponse(1, { @@ -195,7 +214,7 @@ Execute(tsserver reference requests should be sent): \ [0, 'ts@references', {'file': expand('%:p'), 'line': 2, 'offset': 5}] \ ], \ g:message_list - AssertEqual {'42': {'use_relative_paths': 0}}, ale#references#GetMap() + AssertEqual {'42': {'open_in': 'current-buffer', 'use_relative_paths': 0}}, ale#references#GetMap() Execute('-relative' argument should enable 'use_relative_paths' in HandleTSServerResponse): runtime ale_linters/typescript/tsserver.vim @@ -205,7 +224,48 @@ Execute('-relative' argument should enable 'use_relative_paths' in HandleTSServe call g:InitCallback() - AssertEqual {'42': {'use_relative_paths': 1}}, ale#references#GetMap() + AssertEqual {'42': {'open_in': 'current-buffer', 'use_relative_paths': 1}}, ale#references#GetMap() + +Execute(`-tab` should display results in tabs): + runtime ale_linters/typescript/tsserver.vim + call setpos('.', [bufnr(''), 2, 5, 0]) + + ALEFindReferences -tab + + call g:InitCallback() + + AssertEqual {'42': {'open_in': 'tab', 'use_relative_paths': 0}}, ale#references#GetMap() + +Execute(The default navigation type should be used): + runtime ale_linters/typescript/tsserver.vim + call setpos('.', [bufnr(''), 2, 5, 0]) + + let g:ale_default_navigation = 'tab' + ALEFindReferences + + call g:InitCallback() + + AssertEqual {'42': {'open_in': 'tab', 'use_relative_paths': 0}}, ale#references#GetMap() + +Execute(`-split` should display results in splits): + runtime ale_linters/typescript/tsserver.vim + call setpos('.', [bufnr(''), 2, 5, 0]) + + ALEFindReferences -split + + call g:InitCallback() + + AssertEqual {'42': {'open_in': 'split', 'use_relative_paths': 0}}, ale#references#GetMap() + +Execute(`-vsplit` should display results in vsplits): + runtime ale_linters/typescript/tsserver.vim + call setpos('.', [bufnr(''), 2, 5, 0]) + + ALEFindReferences -vsplit + + call g:InitCallback() + + AssertEqual {'42': {'open_in': 'vsplit', 'use_relative_paths': 0}}, ale#references#GetMap() Given python(Some Python file): foo @@ -302,7 +362,7 @@ Execute(LSP reference requests should be sent): \ ], \ g:message_list - AssertEqual {'42': {'use_relative_paths': 0}}, ale#references#GetMap() + AssertEqual {'42': {'open_in': 'current-buffer', 'use_relative_paths': 0}}, ale#references#GetMap() Execute('-relative' argument should enable 'use_relative_paths' in HandleLSPResponse): runtime ale_linters/python/pyls.vim @@ -313,4 +373,4 @@ Execute('-relative' argument should enable 'use_relative_paths' in HandleLSPResp call g:InitCallback() - AssertEqual {'42': {'use_relative_paths': 1}}, ale#references#GetMap() + AssertEqual {'42': {'open_in': 'current-buffer', 'use_relative_paths': 1}}, ale#references#GetMap() diff --git a/test/test_go_to_definition.vader b/test/test_go_to_definition.vader index 3479d7b5..a517bd54 100644 --- a/test/test_go_to_definition.vader +++ b/test/test_go_to_definition.vader @@ -2,6 +2,8 @@ Before: call ale#test#SetDirectory('/testplugin/test') call ale#test#SetFilename('dummy.txt') + Save g:ale_default_navigation + let g:old_filename = expand('%:p') let g:Callback = '' let g:message_list = [] @@ -9,6 +11,7 @@ Before: let g:capability_checked = '' let g:conn_id = v:null let g:InitCallback = v:null + let g:ale_default_navigation = 'buffer' runtime autoload/ale/linter.vim runtime autoload/ale/lsp_linter.vim @@ -54,6 +57,8 @@ Before: endfunction After: + Restore + if g:conn_id isnot v:null call ale#lsp#RemoveConnectionWithID(g:conn_id) endif @@ -164,7 +169,7 @@ Execute(Other files should be jumped to for definition responses in tabs too): AssertEqual {}, ale#definition#GetMap() Execute(Other files should be jumped to for definition responses in splits too): - call ale#definition#SetMap({3: {'open_in': 'horizontal-split'}}) + call ale#definition#SetMap({3: {'open_in': 'split'}}) call ale#definition#HandleTSServerResponse( \ 1, \ { @@ -189,7 +194,7 @@ Execute(Other files should be jumped to for definition responses in splits too): AssertEqual {}, ale#definition#GetMap() Execute(Other files should be jumped to for definition responses in vsplits too): - call ale#definition#SetMap({3: {'open_in': 'vertical-split'}}) + call ale#definition#SetMap({3: {'open_in': 'vsplit'}}) call ale#definition#HandleTSServerResponse( \ 1, \ { @@ -241,7 +246,32 @@ Execute(tsserver tab definition requests should be sent): runtime ale_linters/typescript/tsserver.vim call setpos('.', [bufnr(''), 2, 5, 0]) - ALEGoToDefinitionInTab + ALEGoToDefinition -tab + + " We shouldn't register the callback yet. + AssertEqual '''''', string(g:Callback) + + AssertEqual type(function('type')), type(g:InitCallback) + call g:InitCallback() + + AssertEqual 'definition', g:capability_checked + AssertEqual + \ 'function(''ale#definition#HandleTSServerResponse'')', + \ string(g:Callback) + AssertEqual + \ [ + \ ale#lsp#tsserver_message#Change(bufnr('')), + \ [0, 'ts@definition', {'file': expand('%:p'), 'line': 2, 'offset': 5}] + \ ], + \ g:message_list + AssertEqual {'42': {'open_in': 'tab'}}, ale#definition#GetMap() + +Execute(The default navigation type should be used): + runtime ale_linters/typescript/tsserver.vim + call setpos('.', [bufnr(''), 2, 5, 0]) + + let g:ale_default_navigation = 'tab' + ALEGoToDefinition " We shouldn't register the callback yet. AssertEqual '''''', string(g:Callback) @@ -448,7 +478,7 @@ Execute(LSP tab definition requests should be sent): let b:ale_linters = ['pyls'] call setpos('.', [bufnr(''), 1, 5, 0]) - ALEGoToDefinitionInTab + ALEGoToDefinition -tab " We shouldn't register the callback yet. AssertEqual '''''', string(g:Callback) diff --git a/test/test_hdl_checker_options.vader b/test/test_hdl_checker_options.vader new file mode 100644 index 00000000..4bee0f55 --- /dev/null +++ b/test/test_hdl_checker_options.vader @@ -0,0 +1,78 @@ +Before: + call ale#assert#SetUpLinterTest('vhdl', 'hdl_checker') + + Save g:ale_hdl_checker_config_file + Save g:ale_hdl_checker_options + + let g:default_config_file = has('unix') ? '.hdl_checker.config' : '_hdl_checker.config' + +After: + Restore + call ale#assert#TearDownLinterTest() + unlet! g:default_config_file + +Execute(Get default initialization dict): + AssertEqual + \ {'project_file': g:default_config_file}, + \ ale#handlers#hdl_checker#GetInitOptions(bufnr('')) + +Execute(Get custom initialization dict): + let g:ale_hdl_checker_config_file = 'some_file_name' + + AssertEqual + \ {'project_file': 'some_file_name'}, + \ ale#handlers#hdl_checker#GetInitOptions(bufnr('')) + +Execute(Get the checker command without extra user parameters): + AssertEqual + \ ale#Escape('hdl_checker') . ' --lsp', + \ ale#handlers#hdl_checker#GetCommand(bufnr('')) + +Execute(Get the checker command with user configured parameters): + let g:ale_hdl_checker_options = '--log-level DEBUG' + + AssertEqual + \ ale#Escape('hdl_checker') . ' --lsp --log-level DEBUG', + \ ale#handlers#hdl_checker#GetCommand(bufnr('')) + +Execute(Customize executable): + let g:ale_hdl_checker_executable = '/some/other/path' + AssertEqual + \ ale#Escape('/some/other/path') . ' --lsp', + \ ale#handlers#hdl_checker#GetCommand(bufnr('')) + +Execute(Get project root based on .git): + call ale#test#SetFilename('hdl_server/with_git/files/foo.vhd') + " Create .git file + silent! call mkdir(g:dir . '/hdl_server/with_git/.git') + AssertNotEqual '', glob(g:dir . '/hdl_server/with_git/.git') + + AssertEqual + \ ale#path#Simplify(g:dir . '/hdl_server/with_git'), + \ ale#handlers#hdl_checker#GetProjectRoot(bufnr('')) + +Execute(Get project root based on config file): + call ale#test#SetFilename('hdl_server/with_config_file/foo.vhd') + + AssertEqual + \ ale#path#Simplify(g:dir . '/hdl_server/with_config_file'), + \ ale#handlers#hdl_checker#GetProjectRoot(bufnr('')) + +Execute(Return no project root if neither .git or config file are found): + let g:call_count = 0 + + " Mock this command to avoid the test to find ale's own .git folder + function! ale#handlers#hdl_checker#IsDotGit(path) abort + let g:call_count += 1 + return 0 + endfunction + + call ale#test#SetFilename('hdl_server/foo.vhd') + + AssertEqual + \ '', + \ ale#handlers#hdl_checker#GetProjectRoot(bufnr('')) + + AssertEqual g:call_count, 1 + + unlet! g:call_count diff --git a/test/test_highlight_placement.vader b/test/test_highlight_placement.vader index 3b259655..dab73073 100644 --- a/test/test_highlight_placement.vader +++ b/test/test_highlight_placement.vader @@ -7,6 +7,8 @@ Before: Save g:ale_set_loclist Save g:ale_set_quickfix Save g:ale_set_signs + Save g:ale_exclude_highlights + Save b:ale_exclude_highlights runtime autoload/ale/highlight.vim @@ -20,6 +22,8 @@ Before: let g:ale_set_quickfix = 0 let g:ale_set_loclist = 0 let g:ale_echo_cursor = 0 + let g:ale_exclude_highlights = [] + let b:ale_exclude_highlights = [] function! GenerateResults(buffer, output) return [ @@ -363,6 +367,23 @@ Execute(Highlights should always be cleared when the buffer highlight list is em \ GetMatchesWithoutIDs() endif +Execute(Highlights should be hidden when excluded): + let b:ale_exclude_highlights = ['ig.*ore', 'nope'] + + call ale#highlight#SetHighlights(bufnr('%'), [ + \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 1, 'col': 1, 'text': 'hello'}, + \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 2, 'col': 1, 'text': 'ignore'}, + \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 1, 'text': 'nope'}, + \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 4, 'col': 1, 'text': 'world'}, + \]) + + AssertEqual + \ [ + \ {'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1]}, + \ {'group': 'ALEError', 'priority': 10, 'pos1': [4, 1, 1]}, + \ ], + \ GetMatchesWithoutIDs() + Execute(Highlights should be cleared when ALE is disabled): let g:ale_enabled = 1 call ale#highlight#SetHighlights(bufnr(''), [ diff --git a/test/test_hover.vader b/test/test_hover.vader index 917694a2..8b4cf7bd 100644 --- a/test/test_hover.vader +++ b/test/test_hover.vader @@ -133,6 +133,12 @@ Execute(LSP hover responses with markup content should be handled): AssertEqual ['markup'], g:echo_list AssertEqual {}, ale#hover#GetMap() +Execute(LSP hover responses with markup content missing values should be handled): + call HandleValidLSPResult({'contents': {'kind': 'something'}}) + + AssertEqual [], g:echo_list + AssertEqual {}, ale#hover#GetMap() + Execute(LSP hover response with lists of strings should be handled): call HandleValidLSPResult({'contents': [ \ "foo\n", @@ -145,6 +151,7 @@ Execute(LSP hover response with lists of strings should be handled): Execute(LSP hover response with lists of strings and marked strings should be handled): call HandleValidLSPResult({'contents': [ \ {'language': 'rust', 'value': 'foo'}, + \ {'language': 'foobar'}, \ "bar\n", \]}) diff --git a/test/test_organize_imports.vader b/test/test_organize_imports.vader index 137326a9..c51ff1c0 100644 --- a/test/test_organize_imports.vader +++ b/test/test_organize_imports.vader @@ -57,8 +57,9 @@ Before: call add(g:expr_list, a:expr) endfunction - function! ale#code_action#HandleCodeAction(code_action) abort + function! ale#code_action#HandleCodeAction(code_action, should_save) abort let g:handle_code_action_called = 1 + AssertEqual v:false, a:should_save call add(g:code_actions, a:code_action) endfunction diff --git a/test/test_rename.vader b/test/test_rename.vader index 98e3ef30..34d9e32e 100644 --- a/test/test_rename.vader +++ b/test/test_rename.vader @@ -57,8 +57,9 @@ Before: call add(g:expr_list, a:expr) endfunction - function! ale#code_action#HandleCodeAction(code_action) abort + function! ale#code_action#HandleCodeAction(code_action, should_save) abort let g:handle_code_action_called = 1 + AssertEqual v:true, a:should_save call add(g:code_actions, a:code_action) endfunction @@ -326,6 +327,115 @@ Execute(Code actions from LSP should be handled): \ ], \ g:code_actions +Execute(DocumentChanges from LSP should be handled): + call ale#rename#HandleLSPResponse(1, { + \ 'id': 3, + \ 'result': { + \ 'documentChanges': [ + \ { + \ 'textDocument': { + \ 'version': 1.0, + \ 'uri': 'file:///foo/bar/file1.ts', + \ }, + \ 'edits': [ + \ { + \ 'range': { + \ 'start': { + \ 'line': 1, + \ 'character': 2, + \ }, + \ 'end': { + \ 'line': 3, + \ 'character': 4, + \ }, + \ }, + \ 'newText': 'bla123', + \ }, + \ ], + \ }, + \ ], + \ }, + \}) + + AssertEqual + \ [ + \ { + \ 'description': 'rename', + \ 'changes': [ + \ { + \ 'fileName': '/foo/bar/file1.ts', + \ 'textChanges': [ + \ { + \ 'start': { + \ 'line': 2, + \ 'offset': 3, + \ }, + \ 'end': { + \ 'line': 4, + \ 'offset': 5, + \ }, + \ 'newText': 'bla123', + \ }, + \ ], + \ }, + \ ], + \ } + \ ], + \ g:code_actions + +Execute(Single DocumentChange from LSP should be handled): + call ale#rename#HandleLSPResponse(1, { + \ 'id': 3, + \ 'result': { + \ 'documentChanges': { + \ 'textDocument': { + \ 'version': 1.0, + \ 'uri': 'file:///foo/bar/file1.ts', + \ }, + \ 'edits': [ + \ { + \ 'range': { + \ 'start': { + \ 'line': 1, + \ 'character': 2, + \ }, + \ 'end': { + \ 'line': 3, + \ 'character': 4, + \ }, + \ }, + \ 'newText': 'bla123', + \ }, + \ ], + \ }, + \ }, + \}) + + AssertEqual + \ [ + \ { + \ 'description': 'rename', + \ 'changes': [ + \ { + \ 'fileName': '/foo/bar/file1.ts', + \ 'textChanges': [ + \ { + \ 'start': { + \ 'line': 2, + \ 'offset': 3, + \ }, + \ 'end': { + \ 'line': 4, + \ 'offset': 5, + \ }, + \ 'newText': 'bla123', + \ }, + \ ], + \ }, + \ ], + \ } + \ ], + \ g:code_actions Execute(LSP should perform no action when no result): call ale#rename#HandleLSPResponse(1, { \ 'id': 3, diff --git a/test/test_shell_detection.vader b/test/test_shell_detection.vader index 88ee462d..6452287f 100644 --- a/test/test_shell_detection.vader +++ b/test/test_shell_detection.vader @@ -15,7 +15,7 @@ Given(A file with a Bash hashbang): 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('')) + AssertEqual 'bash', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with /bin/sh): #!/usr/bin/env sh -eu --foobar @@ -23,7 +23,7 @@ Given(A file with /bin/sh): 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('')) + AssertEqual 'sh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with bash as an argument to env): #!/usr/bin/env bash @@ -31,7 +31,7 @@ Given(A file with bash as an argument to env): 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('')) + AssertEqual 'bash', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with a tcsh hash bang and arguments): #!/usr/bin/env tcsh -eu --foobar @@ -39,7 +39,7 @@ Given(A file with a tcsh hash bang and arguments): 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('')) + AssertEqual 'tcsh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with a zsh hash bang and arguments): #!/usr/bin/env zsh -eu --foobar @@ -47,7 +47,7 @@ Given(A file with a zsh hash bang and arguments): 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('')) + AssertEqual 'zsh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with a csh hash bang and arguments): #!/usr/bin/env csh -eu --foobar @@ -55,7 +55,7 @@ Given(A file with a csh hash bang and arguments): Execute(csh 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('')) + AssertEqual 'csh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with a ksh hashbang): #!/bin/ksh @@ -63,7 +63,7 @@ Given(A file with a ksh hashbang): Execute(/bin/ksh should be detected appropriately): AssertEqual 'ksh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'ksh', ale_linters#sh#shell#GetExecutable(bufnr('')) - AssertEqual 'ksh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'ksh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with a ksh as an argument to env): #!/usr/bin/env ksh @@ -71,7 +71,7 @@ Given(A file with a ksh as an argument to env): Execute(ksh should be detected appropriately): AssertEqual 'ksh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'ksh', ale_linters#sh#shell#GetExecutable(bufnr('')) - AssertEqual 'ksh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'ksh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with a sh hash bang and arguments): #!/usr/bin/env sh -eu --foobar @@ -79,24 +79,24 @@ Given(A file with a sh hash bang and arguments): 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('')) + AssertEqual 'sh', ale#handlers#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('')) + AssertEqual 'bash', ale#handlers#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('')) + AssertEqual 'sh', ale#handlers#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('')) + AssertEqual 'ksh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with /bin/ash): #!/bin/ash @@ -106,7 +106,7 @@ Execute(The ash dialect should be used for the shell and the base function): AssertEqual 'ash', ale_linters#sh#shell#GetExecutable(bufnr('')) Execute(dash should be used for shellcheck, which has no ash dialect): - AssertEqual 'dash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'dash', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with /bin/dash): #!/bin/dash @@ -116,4 +116,4 @@ Execute(The dash dialect should be used for the shell and the base function): AssertEqual 'dash', ale_linters#sh#shell#GetExecutable(bufnr('')) Execute(dash should be used for shellcheck): - AssertEqual 'dash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'dash', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) |