summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authortoastal <toastal@protonmail.com>2020-12-21 10:26:09 +0700
committertoastal <toastal@protonmail.com>2020-12-21 10:26:09 +0700
commit9c7e1fe4ddb6729d2518b4102ae203ac00f8bc05 (patch)
tree53cc5b0b1e8036269a13535f6a65542ae40aa72e /test
parent42e4b148616981234425b31d2858c62f30e4153d (diff)
parentf996ede5999c99b1b3e3cecc02dbd06cb286d3ff (diff)
downloadale-9c7e1fe4ddb6729d2518b4102ae203ac00f8bc05.zip
merging master
Diffstat (limited to 'test')
-rw-r--r--test/command_callback/php-intelephense-project/with-composer/composer.json0
-rwxr-xr-xtest/command_callback/python_paths/with_virtualenv/env/Scripts/autoimport.exe0
-rw-r--r--test/command_callback/python_paths/with_virtualenv/env/Scripts/yamlfix.exe0
-rwxr-xr-xtest/command_callback/python_paths/with_virtualenv/env/bin/autoimport0
-rwxr-xr-xtest/command_callback/python_paths/with_virtualenv/env/bin/yamlfix0
-rw-r--r--test/command_callback/r_paths/.Rprofile0
-rw-r--r--test/command_callback/test_erlang_elvis_command_callback.vader16
-rw-r--r--test/command_callback/test_php_intelephense_command_callback.vader26
-rw-r--r--test/command_callback/test_r_languageserver_callbacks.vader22
-rw-r--r--test/command_callback/test_sorbet_command_callback.vader7
-rw-r--r--test/completion/test_lsp_completion_parsing.vader6
-rw-r--r--test/fixers/test_autoimport_fixer_callback.vader50
-rw-r--r--test/fixers/test_gofmt_fixer_callback.vader14
-rw-r--r--test/fixers/test_luafmt_fixer_callback.vader35
-rw-r--r--test/fixers/test_ormolu_fixer_callback.vader24
-rw-r--r--test/fixers/test_phpcbf_fixer_callback.vader11
-rw-r--r--test/fixers/test_yamlfix_fixer_callback.vader50
-rw-r--r--test/handler/test_erlang_elvis_handler.vader37
-rw-r--r--test/handler/test_phpcs_handler.vader11
-rw-r--r--test/handler/test_tlint_handler.vader34
-rw-r--r--test/lsp/test_other_initialize_message_handling.vader6
-rw-r--r--test/lua_files/testfile.lua0
-rw-r--r--test/test_code_action.vader4
-rw-r--r--test/test_code_action_python.vader59
-rw-r--r--test/test_codefix.vader549
-rw-r--r--test/test_hover.vader4
-rw-r--r--test/test_lint_on_enter_when_file_changed.vader2
-rw-r--r--test/test_rename.vader6
-rw-r--r--test/test_shell_detection.vader48
29 files changed, 1002 insertions, 19 deletions
diff --git a/test/command_callback/php-intelephense-project/with-composer/composer.json b/test/command_callback/php-intelephense-project/with-composer/composer.json
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/test/command_callback/php-intelephense-project/with-composer/composer.json
diff --git a/test/command_callback/python_paths/with_virtualenv/env/Scripts/autoimport.exe b/test/command_callback/python_paths/with_virtualenv/env/Scripts/autoimport.exe
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/test/command_callback/python_paths/with_virtualenv/env/Scripts/autoimport.exe
diff --git a/test/command_callback/python_paths/with_virtualenv/env/Scripts/yamlfix.exe b/test/command_callback/python_paths/with_virtualenv/env/Scripts/yamlfix.exe
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/test/command_callback/python_paths/with_virtualenv/env/Scripts/yamlfix.exe
diff --git a/test/command_callback/python_paths/with_virtualenv/env/bin/autoimport b/test/command_callback/python_paths/with_virtualenv/env/bin/autoimport
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/test/command_callback/python_paths/with_virtualenv/env/bin/autoimport
diff --git a/test/command_callback/python_paths/with_virtualenv/env/bin/yamlfix b/test/command_callback/python_paths/with_virtualenv/env/bin/yamlfix
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/test/command_callback/python_paths/with_virtualenv/env/bin/yamlfix
diff --git a/test/command_callback/r_paths/.Rprofile b/test/command_callback/r_paths/.Rprofile
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/test/command_callback/r_paths/.Rprofile
diff --git a/test/command_callback/test_erlang_elvis_command_callback.vader b/test/command_callback/test_erlang_elvis_command_callback.vader
new file mode 100644
index 00000000..4aab49d6
--- /dev/null
+++ b/test/command_callback/test_erlang_elvis_command_callback.vader
@@ -0,0 +1,16 @@
+Before:
+ let b:file = fnamemodify(bufname(''), ':.')
+ call ale#assert#SetUpLinterTest('erlang', 'elvis')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Default command should be correct):
+ AssertLinter 'elvis',
+ \ ale#Escape('elvis') . ' rock --output-format=parsable ' . ale#Escape(b:file)
+
+Execute(Executable should be configurable):
+ let b:ale_erlang_elvis_executable = '/path/to/elvis'
+
+ AssertLinter '/path/to/elvis',
+ \ ale#Escape('/path/to/elvis') . ' rock --output-format=parsable ' . ale#Escape(b:file)
diff --git a/test/command_callback/test_php_intelephense_command_callback.vader b/test/command_callback/test_php_intelephense_command_callback.vader
new file mode 100644
index 00000000..dd6adb3d
--- /dev/null
+++ b/test/command_callback/test_php_intelephense_command_callback.vader
@@ -0,0 +1,26 @@
+Before:
+ call ale#assert#SetUpLinterTest('php', 'intelephense')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ AssertLinter 'intelephense',
+ \ ale#Escape('intelephense') . ' --stdio'
+
+Execute(The project path should be correct for .git directories):
+ call ale#test#SetFilename('php-intelephense-project/with-git/test.php')
+ silent! call mkdir('php-intelephense-project/with-git/.git', 'p')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/php-intelephense-project/with-git')
+
+Execute(The project path should be correct for composer.json file):
+ call ale#test#SetFilename('php-intelephense-project/with-composer/test.php')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/php-intelephense-project/with-composer')
+
+Execute(The project cache should be saved in a temp dir):
+ call ale#test#SetFilename('php-intelephense-project/with-composer/test.php')
+ let g:ale_php_intelephense_config = { 'storagePath': '/tmp/intelephense' }
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/php-intelephense-project/with-composer')
diff --git a/test/command_callback/test_r_languageserver_callbacks.vader b/test/command_callback/test_r_languageserver_callbacks.vader
new file mode 100644
index 00000000..9a4a1f87
--- /dev/null
+++ b/test/command_callback/test_r_languageserver_callbacks.vader
@@ -0,0 +1,22 @@
+Before:
+ call ale#assert#SetUpLinterTest('r', 'languageserver')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ AssertLinter 'Rscript', 'Rscript --vanilla -e ' . ale#Escape('languageserver::run()')
+
+Execute(The project root should be detected correctly):
+ AssertLSPProject '.'
+
+ call ale#test#SetFilename('r_paths/dummy/test.R')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/r_paths')
+
+Execute(Should accept configuration settings):
+ AssertLSPConfig {}
+
+ let b:ale_r_languageserver_config = {'r': {'lsp': {'debug': 'true', 'diagnostics': 'true'}}}
+
+ AssertLSPConfig {'r': {'lsp': {'debug': 'true', 'diagnostics': 'true'}}}
diff --git a/test/command_callback/test_sorbet_command_callback.vader b/test/command_callback/test_sorbet_command_callback.vader
index b46e90a4..fe758635 100644
--- a/test/command_callback/test_sorbet_command_callback.vader
+++ b/test/command_callback/test_sorbet_command_callback.vader
@@ -5,6 +5,7 @@ Before:
let g:ale_ruby_sorbet_executable = 'srb'
let g:ale_ruby_sorbet_options = ''
+ let g:ale_ruby_sorbet_enable_watchman = 0
After:
call ale#assert#TearDownLinterTest()
@@ -13,6 +14,12 @@ Execute(Executable should default to srb):
AssertLinter 'srb', ale#Escape('srb')
\ . ' tc --lsp --disable-watchman'
+Execute(Able to enable watchman):
+ let g:ale_ruby_sorbet_enable_watchman = 1
+
+ AssertLinter 'srb', ale#Escape('srb')
+ \ . ' tc --lsp'
+
Execute(Should be able to set a custom executable):
let g:ale_ruby_sorbet_executable = 'bin/srb'
diff --git a/test/completion/test_lsp_completion_parsing.vader b/test/completion/test_lsp_completion_parsing.vader
index d989aefe..36228c10 100644
--- a/test/completion/test_lsp_completion_parsing.vader
+++ b/test/completion/test_lsp_completion_parsing.vader
@@ -40,6 +40,7 @@ Execute(Should handle Rust completion results correctly):
\ {'word': 'from', 'menu': 'fn from(s: &''a str) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from', 'menu': 'fn from(s: Box<str>) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\ {'word': 'from', 'menu': 'fn from(s: Cow<''a, str>) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
+ \ {'word': 'to_vec', 'menu': 'pub fn to_vec(&self) -> Vec<T> where T: Clone,', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})},
\],
\ ale#completion#ParseLSPCompletions({
\ "jsonrpc":"2.0",
@@ -184,6 +185,11 @@ Execute(Should handle Rust completion results correctly):
\ "label":"from",
\ "kind":3,
\ "detail":"fn from(s: Cow<'a, str>) -> String"
+ \ },
+ \ {
+ \ "label":"to_vec",
+ \ "kind":3,
+ \ "detail":"pub fn to_vec(&self) -> Vec<T>\nwhere\n T: Clone,"
\ }
\ ]
\ })
diff --git a/test/fixers/test_autoimport_fixer_callback.vader b/test/fixers/test_autoimport_fixer_callback.vader
new file mode 100644
index 00000000..6952cbb8
--- /dev/null
+++ b/test/fixers/test_autoimport_fixer_callback.vader
@@ -0,0 +1,50 @@
+Before:
+ Save g:ale_python_autoimport_executable
+ Save g:ale_python_autoimport_options
+
+ " Use an invalid global executable, so we don't match it.
+ let g:ale_python_autoimport_executable = 'xxxinvalid'
+ let g:ale_python_autoimport_options = ''
+
+ call ale#test#SetDirectory('/testplugin/test/fixers')
+ silent cd ..
+ silent cd command_callback
+ let g:dir = getcwd()
+
+ let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+
+After:
+ Restore
+
+ unlet! b:bin_dir
+
+ call ale#test#RestoreDirectory()
+
+Execute(The autoimport callback should return the correct default values):
+ AssertEqual
+ \ 0,
+ \ ale#fixers#autoimport#Fix(bufnr(''))
+
+ silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py')
+ AssertEqual
+ \ {
+ \ 'command': ale#path#BufferCdString(bufnr(''))
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/autoimport')) . ' -',
+ \ },
+ \ ale#fixers#autoimport#Fix(bufnr(''))
+
+Execute(The autoimport callback should respect custom options):
+ let g:ale_python_autoimport_options = '--multi-line=3 --trailing-comma'
+
+ AssertEqual
+ \ 0,
+ \ ale#fixers#autoimport#Fix(bufnr(''))
+
+ silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py')
+ AssertEqual
+ \ {
+ \ 'command': ale#path#BufferCdString(bufnr(''))
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/autoimport'))
+ \ . ' --multi-line=3 --trailing-comma -',
+ \ },
+ \ ale#fixers#autoimport#Fix(bufnr(''))
diff --git a/test/fixers/test_gofmt_fixer_callback.vader b/test/fixers/test_gofmt_fixer_callback.vader
index 16659655..99407173 100644
--- a/test/fixers/test_gofmt_fixer_callback.vader
+++ b/test/fixers/test_gofmt_fixer_callback.vader
@@ -21,10 +21,7 @@ Execute(The gofmt callback should return the correct default values):
AssertEqual
\ {
- \ 'read_temporary_file': 1,
- \ 'command': ale#Escape('xxxinvalid')
- \ . ' -l -w'
- \ . ' %t',
+ \ 'command': ale#Escape('xxxinvalid'),
\ },
\ ale#fixers#gofmt#Fix(bufnr(''))
@@ -35,11 +32,8 @@ Execute(The gofmt callback should include custom gofmt options):
AssertEqual
\ {
- \ 'read_temporary_file': 1,
\ 'command': ale#Escape('xxxinvalid')
- \ . ' -l -w'
- \ . ' ' . g:ale_go_gofmt_options
- \ . ' %t',
+ \ . ' ' . g:ale_go_gofmt_options,
\ },
\ ale#fixers#gofmt#Fix(bufnr(''))
@@ -50,9 +44,7 @@ Execute(The gofmt callback should support Go environment variables):
AssertEqual
\ {
- \ 'read_temporary_file': 1,
\ 'command': ale#Env('GO111MODULE', 'off')
- \ . ale#Escape('xxxinvalid') . ' -l -w'
- \ . ' %t',
+ \ . ale#Escape('xxxinvalid')
\ },
\ ale#fixers#gofmt#Fix(bufnr(''))
diff --git a/test/fixers/test_luafmt_fixer_callback.vader b/test/fixers/test_luafmt_fixer_callback.vader
new file mode 100644
index 00000000..362da118
--- /dev/null
+++ b/test/fixers/test_luafmt_fixer_callback.vader
@@ -0,0 +1,35 @@
+Before:
+ Save g:ale_lua_luafmt_executable
+ Save g:ale_lua_luafmt_options
+
+ " Use an invalid global executable, so we don't match it.
+ let g:ale_lua_luafmt_executable = 'xxxinvalid'
+ let g:ale_lua_luafmt_options = ''
+
+ call ale#test#SetDirectory('/testplugin/test/fixers')
+
+After:
+ Restore
+
+ call ale#test#RestoreDirectory()
+
+Execute(The luafmt callback should return the correct default values):
+ call ale#test#SetFilename('../lua_files/testfile.lua')
+
+ AssertEqual
+ \ {
+ \ 'command': ale#Escape('xxxinvalid') . ' --stdin',
+ \ },
+ \ ale#fixers#luafmt#Fix(bufnr(''))
+
+Execute(The luafmt callback should include custom luafmt options):
+ let g:ale_lua_luafmt_options = "--skip-children"
+ call ale#test#SetFilename('../lua_files/testfile.lua')
+
+ AssertEqual
+ \ {
+ \ 'command': ale#Escape('xxxinvalid')
+ \ . ' ' . g:ale_lua_luafmt_options
+ \ . ' --stdin',
+ \ },
+ \ ale#fixers#luafmt#Fix(bufnr(''))
diff --git a/test/fixers/test_ormolu_fixer_callback.vader b/test/fixers/test_ormolu_fixer_callback.vader
new file mode 100644
index 00000000..8df3fca9
--- /dev/null
+++ b/test/fixers/test_ormolu_fixer_callback.vader
@@ -0,0 +1,24 @@
+Before:
+ Save g:ale_haskell_ormolu_executable
+ Save g:ale_haskell_ormolu_options
+
+After:
+ Restore
+
+Execute(The ormolu callback should return the correct default values):
+ AssertEqual
+ \ {
+ \ 'command': ale#Escape('ormolu')
+ \ },
+ \ ale#fixers#ormolu#Fix(bufnr(''))
+
+Execute(The ormolu executable and options should be configurable):
+ let g:ale_nix_nixpkgsfmt_executable = '/path/to/ormolu'
+ let g:ale_nix_nixpkgsfmt_options = '-h'
+
+ AssertEqual
+ \ {
+ \ 'command': ale#Escape('/path/to/ormolu')
+ \ . ' -h',
+ \ },
+ \ ale#fixers#nixpkgsfmt#Fix(bufnr(''))
diff --git a/test/fixers/test_phpcbf_fixer_callback.vader b/test/fixers/test_phpcbf_fixer_callback.vader
index 1663c89c..f7bcc2d8 100644
--- a/test/fixers/test_phpcbf_fixer_callback.vader
+++ b/test/fixers/test_phpcbf_fixer_callback.vader
@@ -5,6 +5,7 @@ Before:
let g:ale_php_phpcbf_executable = 'phpcbf_test'
let g:ale_php_phpcbf_standard = ''
+ let g:ale_php_phpcbf_options = ''
let g:ale_php_phpcbf_use_global = 0
call ale#test#SetDirectory('/testplugin/test/fixers')
@@ -54,6 +55,15 @@ Execute(The phpcbf callback should include the phpcbf_standard option):
\ {'command': ale#Escape(ale#path#Simplify(g:dir . '/php_paths/project-with-phpcbf/vendor/bin/phpcbf')) . ' --stdin-path=%s ' . '--standard=phpcbf_ruleset.xml' . ' -'},
\ ale#fixers#phpcbf#Fix(bufnr(''))
+Execute(User provided options should be used):
+ let g:ale_php_phpcbf_options = '--my-user-provided-option my-value'
+ call ale#test#SetFilename('php_paths/project-with-phpcbf/foo/test.php')
+
+ AssertEqual
+ \ {'command': ale#Escape(ale#path#Simplify(g:dir . '/php_paths/project-with-phpcbf/vendor/bin/phpcbf')) . ' --stdin-path=%s ' . ale#Pad('--my-user-provided-option my-value') . ' -'},
+ \ ale#fixers#phpcbf#Fix(bufnr(''))
+
+
Before:
Save g:ale_php_phpcbf_executable
Save g:ale_php_phpcbf_standard
@@ -61,6 +71,7 @@ Before:
let g:ale_php_phpcbf_executable = 'phpcbf_test'
let g:ale_php_phpcbf_standard = ''
+ let g:ale_php_phpcbf_options = ''
let g:ale_php_phpcbf_use_global = 0
call ale#test#SetDirectory('/testplugin/test/fixers')
diff --git a/test/fixers/test_yamlfix_fixer_callback.vader b/test/fixers/test_yamlfix_fixer_callback.vader
new file mode 100644
index 00000000..3ffda91e
--- /dev/null
+++ b/test/fixers/test_yamlfix_fixer_callback.vader
@@ -0,0 +1,50 @@
+Before:
+ Save g:ale_python_yamlfix_executable
+ Save g:ale_python_yamlfix_options
+
+ " Use an invalid global executable, so we don't match it.
+ let g:ale_python_yamlfix_executable = 'xxxinvalid'
+ let g:ale_python_yamlfix_options = ''
+
+ call ale#test#SetDirectory('/testplugin/test/fixers')
+ silent cd ..
+ silent cd command_callback
+ let g:dir = getcwd()
+
+ let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+
+After:
+ Restore
+
+ unlet! b:bin_dir
+
+ call ale#test#RestoreDirectory()
+
+Execute(The yamlfix callback should return the correct default values):
+ AssertEqual
+ \ 0,
+ \ ale#fixers#yamlfix#Fix(bufnr(''))
+
+ silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.yaml')
+ AssertEqual
+ \ {
+ \ 'command': ale#path#BufferCdString(bufnr(''))
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/yamlfix')) . ' -',
+ \ },
+ \ ale#fixers#yamlfix#Fix(bufnr(''))
+
+Execute(The yamlfix callback should respect custom options):
+ let g:ale_yaml_yamlfix_options = '--multi-line=3 --trailing-comma'
+
+ AssertEqual
+ \ 0,
+ \ ale#fixers#yamlfix#Fix(bufnr(''))
+
+ silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.yaml')
+ AssertEqual
+ \ {
+ \ 'command': ale#path#BufferCdString(bufnr(''))
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/yamlfix'))
+ \ . ' --multi-line=3 --trailing-comma -',
+ \ },
+ \ ale#fixers#yamlfix#Fix(bufnr(''))
diff --git a/test/handler/test_erlang_elvis_handler.vader b/test/handler/test_erlang_elvis_handler.vader
new file mode 100644
index 00000000..365376c8
--- /dev/null
+++ b/test/handler/test_erlang_elvis_handler.vader
@@ -0,0 +1,37 @@
+Before:
+ runtime ale_linters/erlang/elvis.vim
+
+After:
+ call ale#linter#Reset()
+
+Execute(Warning messages should be handled):
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 11,
+ \ 'text': "Replace the 'if' expression on line 11 with a 'case' expression or function clauses.",
+ \ 'type': 'W',
+ \ },
+ \ {
+ \ 'lnum': 20,
+ \ 'text': 'Remove the debug call to io:format/1 on line 20.',
+ \ 'type': 'W',
+ \ },
+ \ ],
+ \ ale_linters#erlang#elvis#Handle(bufnr(''), [
+ \ "src/foo.erl:11:no_if_expression:Replace the 'if' expression on line 11 with a 'case' expression or function clauses.",
+ \ 'src/foo.erl:20:no_debug_call:Remove the debug call to io:format/1 on line 20.',
+ \ ])
+
+Execute(Line length message shouldn't contain the line itself):
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 24,
+ \ 'text': 'Line 24 is too long.',
+ \ 'type': 'W',
+ \ },
+ \ ],
+ \ ale_linters#erlang#elvis#Handle(bufnr(''), [
+ \ 'src/foo.erl:24:line_length:Line 24 is too long: io:format("Look ma, too long!"),.',
+ \ ])
diff --git a/test/handler/test_phpcs_handler.vader b/test/handler/test_phpcs_handler.vader
index 18accece..26d35cb8 100644
--- a/test/handler/test_phpcs_handler.vader
+++ b/test/handler/test_phpcs_handler.vader
@@ -13,7 +13,16 @@ Execute(phpcs errors should be handled):
\ 'type': 'E',
\ 'sub_type': 'style',
\ 'text': 'Line indented incorrectly; expected 4 spaces, found 2 (Generic.WhiteSpace.ScopeIndent.IncorrectExact)',
- \ }],
+ \ },
+ \ {
+ \ 'lnum': 22,
+ \ 'col': 3,
+ \ 'type': 'E',
+ \ 'sub_type': 'style',
+ \ 'text': 'All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks)',
+ \ },
+ \ ],
\ ale_linters#php#phpcs#Handle(bufnr(''), [
\ '/path/to/some-filename.php:18:3: error - Line indented incorrectly; expected 4 spaces, found 2 (Generic.WhiteSpace.ScopeIndent.IncorrectExact)',
+ \ "/path/to/some-filename.php:22:3: error - All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks), found '\"\n'.",
\ ])
diff --git a/test/handler/test_tlint_handler.vader b/test/handler/test_tlint_handler.vader
new file mode 100644
index 00000000..e146346c
--- /dev/null
+++ b/test/handler/test_tlint_handler.vader
@@ -0,0 +1,34 @@
+Before:
+ runtime ale_linters/php/tlint.vim
+
+After:
+ call ale#linter#Reset()
+
+Execute(The tlint handler should calculate line numbers):
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': '5',
+ \ 'col': 0,
+ \ 'sub_type':
+ \ 'style',
+ \ 'type': 'W',
+ \ 'text': ['! There should be no unused imports.', 'There should be no unused imports.', '', '', '', '', '', '', '', '']
+ \ },
+ \ {
+ \ 'lnum': '15',
+ \ 'col': 0,
+ \ 'sub_type':
+ \ 'style',
+ \ 'type': 'W',
+ \ 'text': ['! There should be no method visibility in test methods.', 'There should be no method visibility in test methods.', '', '', '', '', '', '', '', '']
+ \ },
+ \ ],
+ \ ale_linters#php#tlint#Handle(347, [
+ \ "Lints for /Users/jose/Code/Tighten/tester/tests/Unit/ExampleTest.php",
+ \ "============",
+ \ "! There should be no unused imports.",
+ \ "5 : `use Illuminate\Foundation\Testing\RefreshDatabase;`",
+ \ "! There should be no method visibility in test methods.",
+ \ "15 : ` public function testBasicTest()`",
+ \ ])
diff --git a/test/lsp/test_other_initialize_message_handling.vader b/test/lsp/test_other_initialize_message_handling.vader
index b6ef852a..f3b53843 100644
--- a/test/lsp/test_other_initialize_message_handling.vader
+++ b/test/lsp/test_other_initialize_message_handling.vader
@@ -23,6 +23,7 @@ Before:
\ 'completion_trigger_characters': [],
\ 'definition': 0,
\ 'symbol_search': 0,
+ \ 'code_actions': 0,
\ },
\}
@@ -102,6 +103,7 @@ Execute(Capabilities should bet set up correctly):
\ 'definition': 1,
\ 'symbol_search': 1,
\ 'rename': 1,
+ \ 'code_actions': 1,
\ },
\ b:conn.capabilities
AssertEqual [[1, 'initialized', {}]], g:message_list
@@ -125,7 +127,7 @@ Execute(Disabled capabilities should be recognised correctly):
\ 'referencesProvider': v:false,
\ 'textDocumentSync': 2,
\ 'documentFormattingProvider': v:true,
- \ 'codeActionProvider': v:true,
+ \ 'codeActionProvider': v:false,
\ 'signatureHelpProvider': {
\ 'triggerCharacters': ['(', ','],
\ },
@@ -146,6 +148,7 @@ Execute(Disabled capabilities should be recognised correctly):
\ 'definition': 0,
\ 'symbol_search': 0,
\ 'rename': 0,
+ \ 'code_actions': 0,
\ },
\ b:conn.capabilities
AssertEqual [[1, 'initialized', {}]], g:message_list
@@ -197,6 +200,7 @@ Execute(Capabilities should be enabled when send as Dictionaries):
\ 'typeDefinition': 1,
\ 'symbol_search': 1,
\ 'rename': 1,
+ \ 'code_actions': 1,
\ },
\ b:conn.capabilities
AssertEqual [[1, 'initialized', {}]], g:message_list
diff --git a/test/lua_files/testfile.lua b/test/lua_files/testfile.lua
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/test/lua_files/testfile.lua
diff --git a/test/test_code_action.vader b/test/test_code_action.vader
index 2e5d1381..7eabb759 100644
--- a/test/test_code_action.vader
+++ b/test/test_code_action.vader
@@ -3,6 +3,9 @@ Before:
let g:ale_enabled = 0
+ " Enable fix end-of-line as tests below expect that
+ set fixeol
+
runtime autoload/ale/code_action.vim
runtime autoload/ale/util.vim
@@ -211,6 +214,7 @@ Execute(End of file can be modified):
\)
AssertEqual g:test.text + [
+ \ '',
\ 'type A: string',
\ 'type B: number',
\ '',
diff --git a/test/test_code_action_python.vader b/test/test_code_action_python.vader
new file mode 100644
index 00000000..fd30633d
--- /dev/null
+++ b/test/test_code_action_python.vader
@@ -0,0 +1,59 @@
+Given python(An example Python file):
+ def main():
+ a = 1
+ c = a + 1
+
+Execute():
+ let g:changes = [
+ \ {'end': {'offset': 7, 'line': 1}, 'newText': 'func_qtffgsv', 'start': {'offset': 5, 'line': 1}},
+ \ {'end': {'offset': 9, 'line': 1}, 'newText': '', 'start': {'offset': 8, 'line': 1}},
+ \ {'end': {'offset': 15, 'line': 3}, 'newText': " return c\n\n\ndef main():\n c = func_qtffgsvi()\n", 'start': {'offset': 15, 'line': 3}}
+ \]
+
+ call ale#code_action#ApplyChanges(expand('%:p'), g:changes, 0)
+
+Expect(The changes should be applied correctly):
+ def func_qtffgsvi():
+ a = 1
+ c = a + 1
+ return c
+
+
+ def main():
+ c = func_qtffgsvi()
+
+
+Given python(Second python example):
+ import sys
+ import exifread
+
+ def main():
+ with open(sys.argv[1], 'rb') as f:
+ exif = exifread.process_file(f)
+ dt = str(exif['Image DateTime'])
+ date = dt[:10].replace(':', '-')
+
+Execute():
+ let g:changes = [
+ \ {'end': {'offset': 16, 'line': 2}, 'newText': "\n\ndef func_ivlpdpao(f):\n exif = exifread.process_file(f)\n dt = str(exif['Image DateTime'])\n date = dt[:10].replace(':', '-')\n return date\n", 'start': {'offset': 16, 'line': 2}},
+ \ {'end': {'offset': 32, 'line': 6}, 'newText': 'date = func', 'start': {'offset': 9, 'line': 6}},
+ \ {'end': {'offset': 42, 'line': 8}, 'newText': "ivlpdpao(f)\n", 'start': {'offset': 33, 'line': 6}}
+ \]
+
+ call ale#code_action#ApplyChanges(expand('%:p'), g:changes, 0)
+
+Expect(The changes should be applied correctly):
+ import sys
+ import exifread
+
+
+ def func_ivlpdpao(f):
+ exif = exifread.process_file(f)
+ dt = str(exif['Image DateTime'])
+ date = dt[:10].replace(':', '-')
+ return date
+
+
+ def main():
+ with open(sys.argv[1], 'rb') as f:
+ date = func_ivlpdpao(f)
diff --git a/test/test_codefix.vader b/test/test_codefix.vader
new file mode 100644
index 00000000..fc5470aa
--- /dev/null
+++ b/test/test_codefix.vader
@@ -0,0 +1,549 @@
+Before:
+ call ale#test#SetDirectory('/testplugin/test')
+ call ale#test#SetFilename('dummy.txt')
+ Save g:ale_buffer_info
+
+ let g:ale_buffer_info = {}
+
+ let g:old_filename = expand('%:p')
+ let g:Callback = ''
+ let g:expr_list = []
+ let g:message_list = []
+ let g:handle_code_action_called = 0
+ let g:code_actions = []
+ let g:options = {}
+ let g:capability_checked = ''
+ let g:conn_id = v:null
+ let g:InitCallback = v:null
+
+ runtime autoload/ale/lsp_linter.vim
+ runtime autoload/ale/lsp.vim
+ runtime autoload/ale/util.vim
+ runtime autoload/ale/codefix.vim
+ runtime autoload/ale/code_action.vim
+
+ function! ale#lsp_linter#StartLSP(buffer, linter, Callback) abort
+ let g:conn_id = ale#lsp#Register('executable', '/foo/bar', {})
+ call ale#lsp#MarkDocumentAsOpen(g:conn_id, a:buffer)
+
+ if a:linter.lsp is# 'tsserver'
+ call ale#lsp#MarkConnectionAsTsserver(g:conn_id)
+ endif
+
+ let l:details = {
+ \ 'command': 'foobar',
+ \ 'buffer': a:buffer,
+ \ 'connection_id': g:conn_id,
+ \ 'project_root': '/foo/bar',
+ \}
+
+ let g:InitCallback = {-> ale#lsp_linter#OnInit(a:linter, l:details, a:Callback)}
+ endfunction
+
+ function! ale#lsp#HasCapability(conn_id, capability) abort
+ let g:capability_checked = a:capability
+
+ return 1
+ endfunction
+
+ function! ale#lsp#RegisterCallback(conn_id, callback) abort
+ let g:Callback = a:callback
+ endfunction
+
+ function! ale#lsp#Send(conn_id, message) abort
+ call add(g:message_list, a:message)
+
+ return 42
+ endfunction
+
+ function! ale#util#Execute(expr) abort
+ call add(g:expr_list, a:expr)
+ endfunction
+
+ function! ale#code_action#HandleCodeAction(code_action, options) abort
+ let g:handle_code_action_called = 1
+ Assert !get(a:options, 'should_save')
+ call add(g:code_actions, a:code_action)
+ endfunction
+
+ function! ale#util#Input(message, value) abort
+ return '2'
+ endfunction
+
+After:
+ Restore
+
+ if g:conn_id isnot v:null
+ call ale#lsp#RemoveConnectionWithID(g:conn_id)
+ endif
+
+ call ale#test#RestoreDirectory()
+ call ale#linter#Reset()
+
+ unlet! g:capability_checked
+ unlet! g:InitCallback
+ unlet! g:old_filename
+ unlet! g:conn_id
+ unlet! g:Callback
+ unlet! g:message_list
+ unlet! g:expr_list
+ unlet! b:ale_linters
+ unlet! g:options
+ unlet! g:code_actions
+ unlet! g:handle_code_action_called
+
+ runtime autoload/ale/lsp_linter.vim
+ runtime autoload/ale/lsp.vim
+ runtime autoload/ale/util.vim
+ runtime autoload/ale/codefix.vim
+ runtime autoload/ale/code_action.vim
+
+Execute(Failed codefix responses should be handled correctly):
+ call ale#codefix#HandleTSServerResponse(
+ \ 1,
+ \ {'command': 'getCodeFixes', 'request_seq': 3}
+ \)
+ AssertEqual g:handle_code_action_called, 0
+
+Given typescript(Some typescript file):
+ foo
+ somelongerline ()
+ bazxyzxyzxyz
+
+Execute(getCodeFixes from tsserver should be handled):
+ call ale#codefix#SetMap({3: {}})
+ call ale#codefix#HandleTSServerResponse(1, {
+ \ 'command': 'getCodeFixes',
+ \ 'request_seq': 3,
+ \ 'success': v:true,
+ \ 'type': 'response',
+ \ 'body': [
+ \ {
+ \ 'description': 'Import default "x" from module "./z"',
+ \ 'fixName': 'import',
+ \ 'changes': [
+ \ {
+ \ 'fileName': "/foo/bar/file1.ts",
+ \ 'textChanges': [
+ \ {
+ \ 'end': {
+ \ 'line': 2,
+ \ 'offset': 1,
+ \ },
+ \ 'newText': 'import x from "./z";^@',
+ \ 'start': {
+ \ 'line': 2,
+ \ 'offset': 1,
+ \ }
+ \ }
+ \ ]
+ \ }
+ \ ]
+ \ }
+ \ ]
+ \})
+
+ AssertEqual g:handle_code_action_called, 1
+ AssertEqual
+ \ [
+ \ {
+ \ 'description': 'codefix',
+ \ 'changes': [
+ \ {
+ \ 'fileName': "/foo/bar/file1.ts",
+ \ 'textChanges': [
+ \ {
+ \ 'end': {
+ \ 'line': 2,
+ \ 'offset': 1
+ \ },
+ \ 'newText': 'import x from "./z";^@',
+ \ 'start': {
+ \ 'line': 2,
+ \ 'offset': 1
+ \ }
+ \ }
+ \ ]
+ \ }
+ \ ]
+ \ }
+ \ ],
+ \ g:code_actions
+
+Execute(getCodeFixes from tsserver should be handled with user input if there are more than one action):
+ call ale#codefix#SetMap({3: {}})
+ call ale#codefix#HandleTSServerResponse(1, {
+ \ 'command': 'getCodeFixes',
+ \ 'request_seq': 3,
+ \ 'success': v:true,
+ \ 'type': 'response',
+ \ 'body': [
+ \ {
+ \ 'description': 'Import default "x" from module "./z"',
+ \ 'fixName': 'import',
+ \ 'changes': [
+ \ {
+ \ 'fileName': "/foo/bar/file1.ts",
+ \ 'textChanges': [
+ \ {
+ \ 'end': {
+ \ 'line': 2,
+ \ 'offset': 1,
+ \ },
+ \ 'newText': 'import x from "./z";^@',
+ \ 'start': {
+ \ 'line': 2,
+ \ 'offset': 1,
+ \ }
+ \ }
+ \ ]
+ \ }
+ \ ]
+ \ },
+ \ {
+ \ 'description': 'Import default "x" from module "./y"',
+ \ 'fixName': 'import',
+ \ 'changes': [
+ \ {
+ \ 'fileName': "/foo/bar/file1.ts",
+ \ 'textChanges': [
+ \ {
+ \ 'end': {
+ \ 'line': 2,
+ \ 'offset': 1,
+ \ },
+ \ 'newText': 'import x from "./y";^@',
+ \ 'start': {
+ \ 'line': 2,
+ \ 'offset': 1,
+ \ }
+ \ }
+ \ ]
+ \ }
+ \ ]
+ \ }
+ \ ]
+ \})
+
+ AssertEqual g:handle_code_action_called, 1
+ AssertEqual
+ \ [
+ \ {
+ \ 'description': 'codefix',
+ \ 'changes': [
+ \ {
+ \ 'fileName': "/foo/bar/file1.ts",
+ \ 'textChanges': [
+ \ {
+ \ 'end': {
+ \ 'line': 2,
+ \ 'offset': 1
+ \ },
+ \ 'newText': 'import x from "./y";^@',
+ \ 'start': {
+ \ 'line': 2,
+ \ 'offset': 1
+ \ }
+ \ }
+ \ ]
+ \ }
+ \ ]
+ \ }
+ \ ],
+ \ g:code_actions
+
+Execute(Prints a tsserver error message when getCodeFixes unsuccessful):
+ call ale#codefix#SetMap({3: {}})
+ call ale#codefix#HandleTSServerResponse(1, {
+ \ 'command': 'getCodeFixes',
+ \ 'request_seq': 3,
+ \ 'success': v:false,
+ \ 'message': 'something is wrong',
+ \})
+
+ AssertEqual g:handle_code_action_called, 0
+ AssertEqual ['echom ''Error while getting code fixes. Reason: something is wrong'''], g:expr_list
+
+Execute(Does nothing when where are no code fixes):
+ call ale#codefix#SetMap({3: {}})
+ call ale#codefix#HandleTSServerResponse(1, {
+ \ 'command': 'getCodeFixes',
+ \ 'request_seq': 3,
+ \ 'success': v:true,
+ \ 'body': []
+ \})
+
+ AssertEqual g:handle_code_action_called, 0
+ AssertEqual ['echom ''No code fixes available.'''], g:expr_list
+
+Execute(tsserver codefix requests should be sent):
+ call ale#linter#Reset()
+
+ runtime ale_linters/typescript/tsserver.vim
+ let g:ale_buffer_info = {bufnr(''): {'loclist': [{'lnum': 2, 'col': 5, 'code': 2304}]}}
+ call setpos('.', [bufnr(''), 2, 16, 0])
+
+ " ALECodeAction
+ call ale#codefix#Execute(0)
+
+ " We shouldn't register the callback yet.
+ AssertEqual '''''', string(g:Callback)
+
+ AssertEqual type(function('type')), type(g:InitCallback)
+ call g:InitCallback()
+
+ AssertEqual 'code_actions', g:capability_checked
+ AssertEqual
+ \ 'function(''ale#codefix#HandleTSServerResponse'')',
+ \ string(g:Callback)
+ AssertEqual
+ \ [
+ \ ale#lsp#tsserver_message#Change(bufnr('')),
+ \ [0, 'ts@getCodeFixes', {
+ \ 'startLine': 2,
+ \ 'startOffset': 16,
+ \ 'endLine': 2,
+ \ 'endOffset': 17,
+ \ 'file': expand('%:p'),
+ \ 'errorCodes': [2304],
+ \ }]
+ \ ],
+ \ g:message_list
+
+Execute(tsserver codefix requests should be sent only for error with code):
+ call ale#linter#Reset()
+
+ runtime ale_linters/typescript/tsserver.vim
+ let g:ale_buffer_info = {bufnr(''): {'loclist': [{'lnum': 2, 'col': 16}, {'lnum': 2, 'col': 16, 'code': 2304}]}}
+ call setpos('.', [bufnr(''), 2, 16, 0])
+
+ " ALECodeAction
+ call ale#codefix#Execute(0)
+
+ " We shouldn't register the callback yet.
+ AssertEqual '''''', string(g:Callback)
+
+ AssertEqual type(function('type')), type(g:InitCallback)
+ call g:InitCallback()
+
+ AssertEqual 'code_actions', g:capability_checked
+ AssertEqual
+ \ 'function(''ale#codefix#HandleTSServerResponse'')',
+ \ string(g:Callback)
+ AssertEqual
+ \ [
+ \ ale#lsp#tsserver_message#Change(bufnr('')),
+ \ [0, 'ts@getCodeFixes', {
+ \ 'startLine': 2,
+ \ 'startOffset': 16,
+ \ 'endLine': 2,
+ \ 'endOffset': 17,
+ \ 'file': expand('%:p'),
+ \ 'errorCodes': [2304],
+ \ }]
+ \ ],
+ \ g:message_list
+
+Execute(getApplicableRefactors from tsserver should be handled):
+ call ale#codefix#SetMap({3: {
+ \ 'buffer': expand('%:p'),
+ \ 'line': 1,
+ \ 'column': 2,
+ \ 'end_line': 3,
+ \ 'end_column': 4,
+ \ 'connection_id': 0,
+ \}})
+ call ale#codefix#HandleTSServerResponse(1,
+ \ {'seq': 0, 'request_seq': 3, 'type': 'response', 'success': v:true, 'body': [{'actions': [{'description': 'Extract to constant in enclosing scope', 'name': 'constant_scope_0'}], 'description': 'Extract constant', 'name': 'Extract Symbol'}, {'actions': [{'description': 'Extract to function in module scope', 'name': 'function_scope_1'}], 'description': 'Extract function', 'name': 'Extract Symbol'}], 'command': 'getApplicableRefactors'})
+
+ AssertEqual
+ \ [
+ \ [0, 'ts@getEditsForRefactor', {
+ \ 'startLine': 1,
+ \ 'startOffset': 2,
+ \ 'endLine': 3,
+ \ 'endOffset': 5,
+ \ 'file': expand('%:p'),
+ \ 'refactor': 'Extract Symbol',
+ \ 'action': 'function_scope_1',
+ \ }]
+ \ ],
+ \ g:message_list
+
+Execute(getApplicableRefactors should print error on failure):
+ call ale#codefix#SetMap({3: {
+ \ 'buffer': expand('%:p'),
+ \ 'line': 1,
+ \ 'column': 2,
+ \ 'end_line': 3,
+ \ 'end_column': 4,
+ \ 'connection_id': 0,
+ \}})
+ call ale#codefix#HandleTSServerResponse(1,
+ \ {'seq': 0, 'request_seq': 3, 'type': 'response', 'success': v:false, 'message': 'oops', 'command': 'getApplicableRefactors'})
+
+ AssertEqual ['echom ''Error while getting applicable refactors. Reason: oops'''], g:expr_list
+
+Execute(getApplicableRefactors should do nothing if there are no refactors):
+ call ale#codefix#SetMap({3: {
+ \ 'buffer': expand('%:p'),
+ \ 'line': 1,
+ \ 'column': 2,
+ \ 'end_line': 3,
+ \ 'end_column': 4,
+ \ 'connection_id': 0,
+ \}})
+ call ale#codefix#HandleTSServerResponse(1,
+ \ {'seq': 0, 'request_seq': 3, 'type': 'response', 'success': v:true, 'body': [], 'command': 'getApplicableRefactors'})
+
+ AssertEqual ['echom ''No applicable refactors available.'''], g:expr_list
+
+Execute(getEditsForRefactor from tsserver should be handled):
+ call ale#codefix#SetMap({3: {}})
+ call ale#codefix#HandleTSServerResponse(1,
+ \{'seq': 0, 'request_seq': 3, 'type': 'response', 'success': v:true, 'body': {'edits': [{'fileName': '/foo/bar/file.ts', 'textChanges': [{'end': {'offset': 35, 'line': 9}, 'newText': 'newFunction(app);', 'start': {'offset': 3, 'line': 8}}, {'end': {'offset': 4, 'line': 19}, 'newText': '^@function newFunction(app: Router) {^@ app.use(booExpressCsrf());^@ app.use(booExpressRequireHttps);^@}^@', 'start': {'offset': 4, 'line': 19}}]}], 'renameLocation': {'offset': 3, 'line': 8}, 'renameFilename': '/foo/bar/file.ts'}, 'command': 'getEditsForRefactor' }
+ \)
+
+ AssertEqual g:handle_code_action_called, 1
+ AssertEqual
+ \ [
+ \ {
+ \ 'description': 'editsForRefactor',
+ \ 'changes': [{'fileName': '/foo/bar/file.ts', 'textChanges': [{'end': {'offset': 35, 'line': 9}, 'newText': 'newFunction(app);', 'start': {'offset': 3, 'line': 8}}, {'end': {'offset': 4, 'line': 19}, 'newText': '^@function newFunction(app: Router) {^@ app.use(booExpressCsrf());^@ app.use(booExpressRequireHttps);^@}^@', 'start': {'offset': 4, 'line': 19}}]}],
+ \ }
+ \ ],
+ \ g:code_actions
+
+Execute(getEditsForRefactor should print error on failure):
+ call ale#codefix#SetMap({3: {}})
+ call ale#codefix#HandleTSServerResponse(1,
+ \{'seq': 0, 'request_seq': 3, 'type': 'response', 'success': v:false, 'message': 'oops', 'command': 'getEditsForRefactor' }
+ \)
+
+ AssertEqual ['echom ''Error while getting edits for refactor. Reason: oops'''], g:expr_list
+
+Execute(Failed LSP responses should be handled correctly):
+ call ale#codefix#HandleLSPResponse(
+ \ 1,
+ \ {'method': 'workspace/applyEdit', 'request_seq': 3}
+ \)
+ AssertEqual g:handle_code_action_called, 0
+
+Given python(Some python file):
+ def main():
+ a = 1
+ b = a + 2
+
+Execute("workspace/applyEdit" from LSP should be handled):
+ call ale#codefix#SetMap({3: {}})
+ call ale#codefix#HandleLSPResponse(1,
+ \ {'id': 0, 'jsonrpc': '2.0', 'method': 'workspace/applyEdit', 'params': {'edit': {'changes': {'file:///foo/bar/file.ts': [{'range': {'end': {'character': 27, 'line': 7}, 'start': {'character': 27, 'line': 7}}, 'newText': ', Config'}, {'range': {'end': {'character': 12, 'line': 96}, 'start': {'character': 2, 'line': 94}}, 'newText': 'await newFunction(redis, imageKey, cover, config);'}, {'range': {'end': {'character': 2, 'line': 99}, 'start': {'character': 2, 'line': 99}}, 'newText': '^@async function newFunction(redis: IRedis, imageKey: string, cover: Buffer, config: Config) {^@ try {^@ await redis.set(imageKey, cover, ''ex'', parseInt(config.coverKeyTTL, 10));^@ }^@ catch { }^@}^@'}]}}}})
+
+ AssertEqual g:handle_code_action_called, 1
+ AssertEqual
+ \ [{'description': 'applyEdit', 'changes': [{'fileName': '/foo/bar/file.ts', 'textChanges': [{'end': {'offset': 28, 'line': 8}, 'newText': ', Config', 'start': {'offset': 28, 'line': 8}}, {'end': {'offset': 13, 'line': 97}, 'newText': 'await newFunction(redis, imageKey, cover, config);', 'start': {'offset': 3, 'line': 95}}, {'end': {'offset': 3, 'line': 100}, 'newText': '^@async function newFunction(redis: IRedis, imageKey: string, cover: Buffer, config: Config) {^@ try {^@ await redis.set(imageKey, cover, ''ex'', parseInt(config.coverKeyTTL, 10));^@ }^@ catch { }^@}^@', 'start': {'offset': 3, 'line': 100}}]}]}],
+ \ g:code_actions
+
+Execute(Code Actions from LSP should be handled with user input if there are more than one action):
+ call ale#codefix#SetMap({2: {}})
+ call ale#codefix#HandleLSPResponse(1,
+ \ {'id': 2, 'jsonrpc': '2.0', 'result': [{'title': 'fake for testing'}, {'arguments': [{'documentChanges': [{'edits': [{'range': {'end': {'character': 31, 'line': 2}, 'start': {'character': 31, 'line': 2}}, 'newText': ', createVideo'}], 'textDocument': {'uri': 'file:///foo/bar/file.ts', 'version': 1}}]}], 'title': 'Add ''createVideo'' to existing import declaration from "./video"', 'command': '_typescript.applyWorkspaceEdit'}]})
+
+ AssertEqual g:handle_code_action_called, 1
+ AssertEqual
+ \ [{'description': 'codeaction', 'changes': [{'fileName': '/foo/bar/file.ts', 'textChanges': [{'end': {'offset': 32, 'line': 3}, 'newText': ', createVideo', 'start': {'offset': 32, 'line': 3}}]}]}],
+ \ g:code_actions
+
+Execute(Code Actions from LSP should be handled when returned with documentChanges):
+ call ale#codefix#SetMap({2: {}})
+ call ale#codefix#HandleLSPResponse(1,
+ \ {'id': 2, 'jsonrpc': '2.0', 'result': [{'diagnostics': v:null, 'edit': {'changes': v:null, 'documentChanges': [{'edits': [{'range': {'end': {'character': 4, 'line': 2}, 'start': {'character': 4, 'line': 1}}, 'newText': ''}, {'range': {'end': {'character': 9, 'line': 2}, 'start': {'character': 8, 'line': 2}}, 'newText': '(1)'}], 'textDocument': {'uri': 'file:///foo/bar/test.py', 'version': v:null}}]}, 'kind': 'refactor.inline', 'title': 'Inline variable', 'command': v:null}, {'diagnostics': v:null, 'edit': {'changes': v:null, 'documentChanges': [{'edits': [{'range': {'end': {'character': 0, 'line': 0}, 'start': {'character': 0, 'line': 0}}, 'newText': 'def func_bomdjnxh():^@ a = 1return a^@^@^@'}, {'range': {'end': {'character': 9, 'line': 1}, 'start': {'character': 8, 'line': 1}}, 'newText': 'func_bomdjnxh()^@'}], 'textDocument': {'uri': 'file:///foo/bar/test.py', 'version': v:null}}]}, 'kind': 'refactor.extract', 'title': 'Extract expression into function ''func_bomdjnxh''', 'command': v:null}]})
+
+ AssertEqual g:handle_code_action_called, 1
+ AssertEqual
+ \ [{'description': 'codeaction', 'changes': [{'fileName': '/foo/bar/test.py', 'textChanges': [{'end': {'offset': 1, 'line': 1}, 'newText': 'def func_bomdjnxh():^@ a = 1return a^@^@^@', 'start': {'offset': 1, 'line': 1}}, {'end': {'offset': 10, 'line': 2}, 'newText': 'func_bomdjnxh()^@', 'start': {'offset': 9, 'line': 2}}]}]}],
+ \ g:code_actions
+
+Execute(LSP Code Actions handles command responses):
+ call ale#codefix#SetMap({3: {
+ \ 'connection_id': 0,
+ \}})
+ call ale#codefix#HandleLSPResponse(1,
+ \ {'id': 3, 'jsonrpc': '2.0', 'result': [{'kind': 'refactor', 'title': 'Extract to inner function in function ''getVideo''', 'command': {'arguments': [{'file': '/foo/bar/file.ts', 'endOffset': 0, 'action': 'function_scope_0', 'startOffset': 1, 'startLine': 65, 'refactor': 'Extract Symbol', 'endLine': 68}], 'title': 'Extract to inner function in function ''getVideo''', 'command': '_typescript.applyRefactoring'}}, {'kind': 'refactor', 'title': 'Extract to function in module scope', 'command': {'arguments': [{'file': '/foo/bar/file.ts', 'endOffset': 0, 'action': 'function_scope_1', 'startOffset': 1, 'startLine': 65, 'refactor': 'Extract Symbol', 'endLine': 68}], 'title': 'Extract to function in module scope', 'command': '_typescript.applyRefactoring'}}]})
+
+ AssertEqual
+ \ [[0, 'workspace/executeCommand', {'arguments': [{'file': '/foo/bar/file.ts', 'action': 'function_scope_1', 'endOffset': 0, 'refactor': 'Extract Symbol', 'endLine': 68, 'startLine': 65, 'startOffset': 1}], 'command': '_typescript.applyRefactoring'}]],
+ \ g:message_list
+
+
+Execute(Prints message when LSP code action returns no results):
+ call ale#codefix#SetMap({3: {}})
+ call ale#codefix#HandleLSPResponse(1,
+ \ {'id': 3, 'jsonrpc': '2.0', 'result': []})
+
+ AssertEqual g:handle_code_action_called, 0
+ AssertEqual ['echom ''No code actions received from server'''], g:expr_list
+
+Execute(LSP code action requests should be sent):
+ call ale#linter#Reset()
+
+ runtime ale_linters/python/jedils.vim
+ let g:ale_buffer_info = {bufnr(''): {'loclist': [{'lnum': 2, 'col': 5, 'end_lnum': 2, 'end_col': 6, 'code': 2304, 'text': 'oops'}]}}
+ call setpos('.', [bufnr(''), 2, 5, 0])
+
+ " ALECodeAction
+ call ale#codefix#Execute(0)
+
+ " We shouldn't register the callback yet.
+ AssertEqual '''''', string(g:Callback)
+
+ AssertEqual type(function('type')), type(g:InitCallback)
+ call g:InitCallback()
+
+ AssertEqual 'code_actions', g:capability_checked
+ AssertEqual
+ \ 'function(''ale#codefix#HandleLSPResponse'')',
+ \ string(g:Callback)
+ AssertEqual
+ \ [
+ \ [0, 'textDocument/codeAction', {
+ \ 'context': {
+ \ 'diagnostics': [{'range': {'end': {'character': 6, 'line': 1}, 'start': {'character': 4, 'line': 1}}, 'code': 2304, 'message': 'oops'}]
+ \ },
+ \ 'range': {'end': {'character': 5, 'line': 1}, 'start': {'character': 4, 'line': 1}},
+ \ 'textDocument': {'uri': ale#path#ToURI(expand('%:p'))}
+ \ }]
+ \ ],
+ \ g:message_list[-1:]
+
+Execute(LSP code action requests should be sent only for error with code):
+ call ale#linter#Reset()
+
+ runtime ale_linters/python/jedils.vim
+ let g:ale_buffer_info = {bufnr(''): {'loclist': [{'lnum': 2, 'col': 5, 'end_lnum': 2, 'end_col': 6, 'code': 2304, 'text': 'oops'}]}}
+ call setpos('.', [bufnr(''), 2, 5, 0])
+
+ " ALECodeAction
+ call ale#codefix#Execute(0)
+
+ " We shouldn't register the callback yet.
+ AssertEqual '''''', string(g:Callback)
+
+ AssertEqual type(function('type')), type(g:InitCallback)
+ call g:InitCallback()
+
+ AssertEqual 'code_actions', g:capability_checked
+ AssertEqual
+ \ 'function(''ale#codefix#HandleLSPResponse'')',
+ \ string(g:Callback)
+ AssertEqual
+ \ [
+ \ [0, 'textDocument/codeAction', {
+ \ 'context': {
+ \ 'diagnostics': [{'range': {'end': {'character': 6, 'line': 1}, 'start': {'character': 4, 'line': 1}}, 'code': 2304, 'message': 'oops'}]
+ \ },
+ \ 'range': {'end': {'character': 5, 'line': 1}, 'start': {'character': 4, 'line': 1}},
+ \ 'textDocument': {'uri': ale#path#ToURI(expand('%:p'))}
+ \ }]
+ \ ],
+ \ g:message_list[-1:]
diff --git a/test/test_hover.vader b/test/test_hover.vader
index 9689cda2..ed756396 100644
--- a/test/test_hover.vader
+++ b/test/test_hover.vader
@@ -101,7 +101,7 @@ Execute(tsserver quickinfo responses will null missing bodies should be handled)
AssertEqual {}, ale#hover#GetMap()
Execute(tsserver quickinfo displayString values should be displayed):
- call ale#hover#SetMap({3: {}})
+ call ale#hover#SetMap({3: {'buffer': bufnr('')}})
call ale#hover#HandleTSServerResponse(
\ 1,
\ {
@@ -169,7 +169,7 @@ Execute(LSP hover response with lists of strings and marked strings should be ha
AssertEqual {}, ale#hover#GetMap()
Execute(tsserver responses for documentation requests should be handled):
- call ale#hover#SetMap({3: {'show_documentation': 1}})
+ call ale#hover#SetMap({3: {'show_documentation': 1, 'buffer': bufnr('')}})
call ale#hover#HandleTSServerResponse(
\ 1,
diff --git a/test/test_lint_on_enter_when_file_changed.vader b/test/test_lint_on_enter_when_file_changed.vader
index 88493005..0d4c4af8 100644
--- a/test/test_lint_on_enter_when_file_changed.vader
+++ b/test/test_lint_on_enter_when_file_changed.vader
@@ -35,7 +35,7 @@ After:
Execute(The file changed event function should set b:ale_file_changed):
let g:ale_lint_on_enter = 0
- if has('gui')
+ if has('gui_running')
new
else
e test
diff --git a/test/test_rename.vader b/test/test_rename.vader
index 2e8b746e..5bc655f4 100644
--- a/test/test_rename.vader
+++ b/test/test_rename.vader
@@ -269,7 +269,7 @@ Execute(tsserver rename requests should be sent):
\ }]
\ ],
\ g:message_list
- AssertEqual {'42': {'old_name': 'somelongerline', 'new_name': 'a-new-name', 'force_save': 0}},
+ AssertEqual {'42': {'old_name': 'somelongerline', 'new_name': 'a-new-name'}},
\ ale#rename#GetMap()
Given python(Some Python file):
@@ -470,7 +470,7 @@ Execute(LSP rename requests should be sent):
let b:ale_linters = ['pyls']
call setpos('.', [bufnr(''), 1, 5, 0])
- ALERename!
+ ALERename
" We shouldn't register the callback yet.
AssertEqual '''''', string(g:Callback)
@@ -500,5 +500,5 @@ Execute(LSP rename requests should be sent):
\ ],
\ g:message_list
- AssertEqual {'42': {'old_name': 'foo', 'new_name': 'a-new-name', 'force_save': 1}},
+ AssertEqual {'42': {'old_name': 'foo', 'new_name': 'a-new-name'}},
\ ale#rename#GetMap()
diff --git a/test/test_shell_detection.vader b/test/test_shell_detection.vader
index 697054d0..11d801c3 100644
--- a/test/test_shell_detection.vader
+++ b/test/test_shell_detection.vader
@@ -127,3 +127,51 @@ Execute(The dash dialect should be used for the shell and the base function):
Execute(dash should be used for shellcheck):
AssertEqual 'dash', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
+
+Given(A file with a Bash shellcheck shell directive):
+ # shellcheck shell=bash
+
+Execute(bash dialect should be detected appropriately):
+ AssertEqual 'bash', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
+
+Given(A file with a sh shellcheck shell directive):
+ #shellcheck shell=sh
+
+Execute(sh dialect should be detected appropriately):
+ AssertEqual 'sh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
+
+Given(A file with a tcsh shellcheck shell directive):
+ # shellcheck shell=tcsh
+
+Execute(tcsh dialect should be detected appropriately):
+ AssertEqual 'tcsh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
+
+Given(A file with a zsh shellcheck shell directive):
+ # shellcheck shell=zsh
+
+Execute(zsh dialect should be detected appropriately):
+ AssertEqual 'zsh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
+
+Given(A file with a csh shellcheck shell directive):
+ # shellcheck shell=csh
+
+Execute(zsh dialect should be detected appropriately):
+ AssertEqual 'csh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
+
+Given(A file with a ksh shellcheck shell directive):
+ # shellcheck shell=ksh
+
+Execute(ksh dialect should be detected appropriately):
+ AssertEqual 'ksh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
+
+Given(A file with a dash shellcheck shell directive):
+ # shellcheck shell=dash
+
+Execute(dash dialect should be detected appropriately):
+ AssertEqual 'dash', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
+
+Given(A file with a ash shellcheck shell directive):
+ # shellcheck shell=ash
+
+Execute(dash dialect should be detected for ash that shellcheck does not support):
+ AssertEqual 'dash', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))