summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorw0rp <devw0rp@gmail.com>2023-09-14 00:38:12 +0100
committerw0rp <devw0rp@gmail.com>2023-09-14 00:40:56 +0100
commitbe69af270547b0d1dd5fe947efb3f61455f709ed (patch)
tree3d72ab429ed3d6025fb88accbd2be753fb78f26a
parent9092af9ad6a5c93a759be571323ea1d0cafa8d6e (diff)
downloadale-be69af270547b0d1dd5fe947efb3f61455f709ed.zip
#4607 No conflicts with nvim-lspconfig by default
Default `g:ale_disable_lsp` to a new mode `'auto'` by default. With this setting applied, ALE will now check for the presence of nvim-lspconfig and automatically turn off particular LSP linters if already configured via nvim-lspconfig. For users that do not use `nvim-lspconfig`, everything should work as before.
-rw-r--r--README.md16
-rw-r--r--ale_linters/ansible/language_server.vim (renamed from ale_linters/ansible/ansible_language_server.vim)17
-rw-r--r--ale_linters/dafny/dafny.vim2
-rw-r--r--ale_linters/elixir/elixir_ls.vim3
-rw-r--r--ale_linters/elm/ls.vim (renamed from ale_linters/elm/elm_ls.vim)9
-rw-r--r--ale_linters/fortran/language_server.vim1
-rw-r--r--ale_linters/html/angular.vim2
-rw-r--r--ale_linters/java/javalsp.vim1
-rw-r--r--ale_linters/javascript/flow_ls.vim3
-rw-r--r--ale_linters/julia/languageserver.vim1
-rw-r--r--ale_linters/kotlin/languageserver.vim1
-rw-r--r--ale_linters/lua/lua_language_server.vim2
-rw-r--r--ale_linters/nix/rnix_lsp.vim1
-rw-r--r--ale_linters/ocaml/ols.vim1
-rw-r--r--ale_linters/puppet/languageserver.vim1
-rw-r--r--ale_linters/purescript/ls.vim1
-rw-r--r--ale_linters/python/jedils.vim1
-rw-r--r--ale_linters/r/languageserver.vim1
-rw-r--r--ale_linters/reason/ls.vim1
-rw-r--r--ale_linters/reason/ols.vim1
-rw-r--r--ale_linters/rust/analyzer.vim1
-rw-r--r--ale_linters/swift/sourcekitlsp.vim1
-rw-r--r--ale_linters/terraform/terraform_ls.vim1
-rw-r--r--ale_linters/vue/vls.vim1
-rw-r--r--ale_linters/yaml/ls.vim1
-rw-r--r--autoload/ale.vim22
-rw-r--r--autoload/ale/code_action.vim12
-rw-r--r--autoload/ale/codefix.vim14
-rw-r--r--autoload/ale/completion.vim10
-rw-r--r--autoload/ale/debugging.vim41
-rw-r--r--autoload/ale/definition.vim18
-rw-r--r--autoload/ale/engine.vim2
-rw-r--r--autoload/ale/engine/ignore.vim69
-rw-r--r--autoload/ale/filerename.vim4
-rw-r--r--autoload/ale/handlers/hdl_checker.vim4
-rw-r--r--autoload/ale/hover.vim5
-rw-r--r--autoload/ale/linter.vim10
-rw-r--r--autoload/ale/lsp/reset.vim2
-rw-r--r--autoload/ale/lsp_linter.vim93
-rw-r--r--autoload/ale/organize_imports.vim6
-rw-r--r--autoload/ale/references.vim6
-rw-r--r--autoload/ale/rename.vim14
-rw-r--r--autoload/ale/symbol.vim4
-rw-r--r--autoload/ale/uri/jdt.vim6
-rw-r--r--doc/ale.txt13
-rw-r--r--lspconfig.vim3
-rw-r--r--lua/ale/diagnostics.lua (renamed from lua/diagnostics.lua)0
-rw-r--r--lua/ale/util.lua14
-rw-r--r--plugin/ale.vim4
-rw-r--r--test/linter/test_ansible_language_server.vader2
-rw-r--r--test/linter/test_elm_ls.vader2
-rw-r--r--test/lsp/test_engine_lsp_response_handling.vader8
-rw-r--r--test/test_filetype_linter_defaults.vader2
-rw-r--r--test/test_ignoring_linters.vader320
54 files changed, 567 insertions, 214 deletions
diff --git a/README.md b/README.md
index a61358b4..a9d111ab 100644
--- a/README.md
+++ b/README.md
@@ -603,9 +603,19 @@ including the option `g:ale_lint_on_enter`, and you can run ALE manually with
ALE offers an API for letting any other plugin integrate with ALE. If you are
interested in writing an integration, see `:help ale-lint-other-sources`.
-If you are running ALE in combination with another LSP client, you may wish
-to disable ALE's LSP functionality entirely. You can add a setting to your
-vimrc/init.vim to do so.
+If you're running ALE in Neovim with
+[nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) for configuring
+particular language servers. ALE will automatically disable its LSP
+functionality for any language servers configured with nvim-lspconfig by
+default. The following setting is applied by default:
+
+```vim
+let g:ale_disable_lsp = 'auto'
+```
+
+If you are running ALE in combination with another LSP client, you may wish to
+disable ALE's LSP functionality entirely. You can change the setting to `1` to
+always disable all LSP functionality.
```vim
let g:ale_disable_lsp = 1
diff --git a/ale_linters/ansible/ansible_language_server.vim b/ale_linters/ansible/language_server.vim
index d1f3fb7d..0c064353 100644
--- a/ale_linters/ansible/ansible_language_server.vim
+++ b/ale_linters/ansible/language_server.vim
@@ -4,17 +4,17 @@
call ale#Set('ansible_language_server_executable', 'ansible-language-server')
call ale#Set('ansible_language_server_config', {})
-function! ale_linters#ansible#ansible_language_server#Executable(buffer) abort
+function! ale_linters#ansible#language_server#Executable(buffer) abort
return ale#Var(a:buffer, 'ansible_language_server_executable')
endfunction
-function! ale_linters#ansible#ansible_language_server#GetCommand(buffer) abort
- let l:executable = ale_linters#ansible#ansible_language_server#Executable(a:buffer)
+function! ale_linters#ansible#language_server#GetCommand(buffer) abort
+ let l:executable = ale_linters#ansible#language_server#Executable(a:buffer)
return ale#Escape(l:executable) . ' --stdio'
endfunction
-function! ale_linters#ansible#ansible_language_server#FindProjectRoot(buffer) abort
+function! ale_linters#ansible#language_server#FindProjectRoot(buffer) abort
let l:dir = fnamemodify(
\ ale#path#FindNearestFile(a:buffer, 'ansible.cfg'),
\ ':h'
@@ -37,10 +37,11 @@ function! ale_linters#ansible#ansible_language_server#FindProjectRoot(buffer) ab
endfunction
call ale#linter#Define('ansible', {
-\ 'name': 'ansible-language-server',
+\ 'name': 'language_server',
+\ 'aliases': ['ansible_language_server', 'ansible-language-server'],
\ 'lsp': 'stdio',
-\ 'executable': function('ale_linters#ansible#ansible_language_server#Executable'),
-\ 'command': function('ale_linters#ansible#ansible_language_server#GetCommand'),
-\ 'project_root': function('ale_linters#ansible#ansible_language_server#FindProjectRoot'),
+\ 'executable': function('ale_linters#ansible#language_server#Executable'),
+\ 'command': function('ale_linters#ansible#language_server#GetCommand'),
+\ 'project_root': function('ale_linters#ansible#language_server#FindProjectRoot'),
\ 'lsp_config': {b -> ale#Var(b, 'ansible_language_server_config')}
\})
diff --git a/ale_linters/dafny/dafny.vim b/ale_linters/dafny/dafny.vim
index 2a9f761a..8a114d22 100644
--- a/ale_linters/dafny/dafny.vim
+++ b/ale_linters/dafny/dafny.vim
@@ -1,4 +1,5 @@
" Author: Taylor Blau <me@ttaylorr.com>
+call ale#Set('dafny_dafny_timelimit', 10)
function! ale_linters#dafny#dafny#Handle(buffer, lines) abort
let l:pattern = '\v(.*)\((\d+),(\d+)\): (.*): (.*)'
@@ -31,7 +32,6 @@ function! ale_linters#dafny#dafny#GetCommand(buffer) abort
return printf('dafny %%s /compile:0 /timeLimit:%d', ale#Var(a:buffer, 'dafny_dafny_timelimit'))
endfunction
-call ale#Set('dafny_dafny_timelimit', 10)
call ale#linter#Define('dafny', {
\ 'name': 'dafny',
\ 'executable': 'dafny',
diff --git a/ale_linters/elixir/elixir_ls.vim b/ale_linters/elixir/elixir_ls.vim
index a7d7110c..c7dda600 100644
--- a/ale_linters/elixir/elixir_ls.vim
+++ b/ale_linters/elixir/elixir_ls.vim
@@ -12,7 +12,8 @@ function! ale_linters#elixir#elixir_ls#GetExecutable(buffer) abort
endfunction
call ale#linter#Define('elixir', {
-\ 'name': 'elixir-ls',
+\ 'name': 'elixir_ls',
+\ 'aliases': ['elixir-ls', 'elixirls'],
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#elixir#elixir_ls#GetExecutable'),
\ 'command': function('ale_linters#elixir#elixir_ls#GetExecutable'),
diff --git a/ale_linters/elm/elm_ls.vim b/ale_linters/elm/ls.vim
index a02dbf42..38a5b234 100644
--- a/ale_linters/elm/elm_ls.vim
+++ b/ale_linters/elm/ls.vim
@@ -10,13 +10,13 @@ call ale#Set('elm_ls_elm_format_path', '')
call ale#Set('elm_ls_elm_test_path', '')
call ale#Set('elm_ls_elm_analyse_trigger', 'change')
-function! elm_ls#GetRootDir(buffer) abort
+function! ale_linters#elm#ls#GetProjectRoot(buffer) abort
let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm.json')
return !empty(l:elm_json) ? fnamemodify(l:elm_json, ':p:h') : ''
endfunction
-function! elm_ls#GetOptions(buffer) abort
+function! ale_linters#elm#ls#GetOptions(buffer) abort
return {
\ 'elmPath': ale#Var(a:buffer, 'elm_ls_elm_path'),
\ 'elmFormatPath': ale#Var(a:buffer, 'elm_ls_elm_format_path'),
@@ -26,7 +26,8 @@ function! elm_ls#GetOptions(buffer) abort
endfunction
call ale#linter#Define('elm', {
-\ 'name': 'elm_ls',
+\ 'name': 'ls',
+\ 'aliases': ['elm_ls'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#path#FindExecutable(b, 'elm_ls', [
\ 'node_modules/.bin/elm-language-server',
@@ -34,7 +35,7 @@ call ale#linter#Define('elm', {
\ 'elm-lsp'
\ ])},
\ 'command': '%e --stdio',
-\ 'project_root': function('elm_ls#GetRootDir'),
+\ 'project_root': function('ale_linters#elm#ls#GetProjectRoot'),
\ 'language': 'elm',
\ 'initialization_options': function('elm_ls#GetOptions')
\})
diff --git a/ale_linters/fortran/language_server.vim b/ale_linters/fortran/language_server.vim
index 00aa0577..c885b699 100644
--- a/ale_linters/fortran/language_server.vim
+++ b/ale_linters/fortran/language_server.vim
@@ -12,6 +12,7 @@ endfunction
call ale#linter#Define('fortran', {
\ 'name': 'language_server',
+\ 'aliases': ['fortls'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'fortran_language_server_executable')},
\ 'command': '%e',
diff --git a/ale_linters/html/angular.vim b/ale_linters/html/angular.vim
index 4f368fb4..05caf59d 100644
--- a/ale_linters/html/angular.vim
+++ b/ale_linters/html/angular.vim
@@ -48,7 +48,7 @@ endfunction
call ale#linter#Define('html', {
\ 'name': 'angular',
-\ 'aliases': ['angular-language-server'],
+\ 'aliases': ['angular-language-server', 'angularls'],
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#html#angular#GetExecutable'),
\ 'command': function('ale_linters#html#angular#GetCommand'),
diff --git a/ale_linters/java/javalsp.vim b/ale_linters/java/javalsp.vim
index baf584c8..fa3b0e2c 100644
--- a/ale_linters/java/javalsp.vim
+++ b/ale_linters/java/javalsp.vim
@@ -46,6 +46,7 @@ endfunction
call ale#linter#Define('java', {
\ 'name': 'javalsp',
+\ 'aliases': ['java_language_server'],
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#java#javalsp#Executable'),
\ 'command': function('ale_linters#java#javalsp#Command'),
diff --git a/ale_linters/javascript/flow_ls.vim b/ale_linters/javascript/flow_ls.vim
index fec34011..9755ca4e 100644
--- a/ale_linters/javascript/flow_ls.vim
+++ b/ale_linters/javascript/flow_ls.vim
@@ -17,7 +17,8 @@ function! ale_linters#javascript#flow_ls#FindProjectRoot(buffer) abort
endfunction
call ale#linter#Define('javascript', {
-\ 'name': 'flow-language-server',
+\ 'name': 'flow_ls',
+\ 'aliaes': ['flow-language-server'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#path#FindExecutable(b, 'javascript_flow_ls', [
\ 'node_modules/.bin/flow',
diff --git a/ale_linters/julia/languageserver.vim b/ale_linters/julia/languageserver.vim
index 999ad815..fbfab517 100644
--- a/ale_linters/julia/languageserver.vim
+++ b/ale_linters/julia/languageserver.vim
@@ -13,6 +13,7 @@ endfunction
call ale#linter#Define('julia', {
\ 'name': 'languageserver',
+\ 'aliases': ['julials'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'julia_executable')},
\ 'command': function('ale_linters#julia#languageserver#GetCommand'),
diff --git a/ale_linters/kotlin/languageserver.vim b/ale_linters/kotlin/languageserver.vim
index af78c0e0..18b153ae 100644
--- a/ale_linters/kotlin/languageserver.vim
+++ b/ale_linters/kotlin/languageserver.vim
@@ -21,6 +21,7 @@ endfunction
call ale#linter#Define('kotlin', {
\ 'name': 'languageserver',
+\ 'aliaes': ['kotlin_language_server'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'kotlin_languageserver_executable')},
\ 'command': '%e',
diff --git a/ale_linters/lua/lua_language_server.vim b/ale_linters/lua/lua_language_server.vim
index ebddd4b5..0892ad3b 100644
--- a/ale_linters/lua/lua_language_server.vim
+++ b/ale_linters/lua/lua_language_server.vim
@@ -6,7 +6,7 @@ call ale#Set('lua_language_server_config', {})
call ale#linter#Define('lua', {
\ 'name': 'lua_language_server',
-\ 'aliases': ['lua-language-server'],
+\ 'aliases': ['lua-language-server', 'lua_ls'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'lua_language_server_executable')},
\ 'command': '%e',
diff --git a/ale_linters/nix/rnix_lsp.vim b/ale_linters/nix/rnix_lsp.vim
index 949bed1c..99c0fbfa 100644
--- a/ale_linters/nix/rnix_lsp.vim
+++ b/ale_linters/nix/rnix_lsp.vim
@@ -9,6 +9,7 @@ endfunction
call ale#linter#Define('nix', {
\ 'name': 'rnix_lsp',
+\ 'aliases': ['rnix'],
\ 'lsp': 'stdio',
\ 'executable': 'rnix-lsp',
\ 'command': '%e',
diff --git a/ale_linters/ocaml/ols.vim b/ale_linters/ocaml/ols.vim
index ec71bdb4..b26c7826 100644
--- a/ale_linters/ocaml/ols.vim
+++ b/ale_linters/ocaml/ols.vim
@@ -6,6 +6,7 @@ call ale#Set('ocaml_ols_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#linter#Define('ocaml', {
\ 'name': 'ols',
+\ 'aliases': ['ocaml-language-server'],
\ 'lsp': 'stdio',
\ 'executable': function('ale#handlers#ols#GetExecutable'),
\ 'command': function('ale#handlers#ols#GetCommand'),
diff --git a/ale_linters/puppet/languageserver.vim b/ale_linters/puppet/languageserver.vim
index 2078695f..c6b12662 100644
--- a/ale_linters/puppet/languageserver.vim
+++ b/ale_linters/puppet/languageserver.vim
@@ -29,6 +29,7 @@ endfunction
call ale#linter#Define('puppet', {
\ 'name': 'languageserver',
+\ 'aliases': ['puppet_languageserver'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'puppet_languageserver_executable')},
\ 'command': '%e --stdio',
diff --git a/ale_linters/purescript/ls.vim b/ale_linters/purescript/ls.vim
index a20fae47..1eaf2af7 100644
--- a/ale_linters/purescript/ls.vim
+++ b/ale_linters/purescript/ls.vim
@@ -41,6 +41,7 @@ endfunction
call ale#linter#Define('purescript', {
\ 'name': 'purescript-language-server',
+\ 'aliases': ['purescriptls'],
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#purescript#ls#GetExecutable'),
\ 'command': function('ale_linters#purescript#ls#GetCommand'),
diff --git a/ale_linters/python/jedils.vim b/ale_linters/python/jedils.vim
index d3e15bf2..e82abd1b 100644
--- a/ale_linters/python/jedils.vim
+++ b/ale_linters/python/jedils.vim
@@ -30,6 +30,7 @@ endfunction
call ale#linter#Define('python', {
\ 'name': 'jedils',
+\ 'aliases': ['jedi_language_server'],
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#python#jedils#GetExecutable'),
\ 'command': function('ale_linters#python#jedils#GetCommand'),
diff --git a/ale_linters/r/languageserver.vim b/ale_linters/r/languageserver.vim
index bab869d1..1ff23fa9 100644
--- a/ale_linters/r/languageserver.vim
+++ b/ale_linters/r/languageserver.vim
@@ -19,6 +19,7 @@ endfunction
call ale#linter#Define('r', {
\ 'name': 'languageserver',
+\ 'aliases': ['r_language_server'],
\ 'lsp': 'stdio',
\ 'lsp_config': {b -> ale#Var(b, 'r_languageserver_config')},
\ 'executable': 'Rscript',
diff --git a/ale_linters/reason/ls.vim b/ale_linters/reason/ls.vim
index fb1114ae..a831b506 100644
--- a/ale_linters/reason/ls.vim
+++ b/ale_linters/reason/ls.vim
@@ -15,6 +15,7 @@ endfunction
call ale#linter#Define('reason', {
\ 'name': 'reason-language-server',
+\ 'aliases': ['reason_ls'],
\ 'lsp': 'stdio',
\ 'executable': {buffer -> ale#Var(buffer, 'reason_ls_executable')},
\ 'command': '%e',
diff --git a/ale_linters/reason/ols.vim b/ale_linters/reason/ols.vim
index 9fbd9b4f..e1f408f0 100644
--- a/ale_linters/reason/ols.vim
+++ b/ale_linters/reason/ols.vim
@@ -6,6 +6,7 @@ call ale#Set('reason_ols_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#linter#Define('reason', {
\ 'name': 'ols',
+\ 'aliases': ['ocaml-language-server'],
\ 'lsp': 'stdio',
\ 'executable': function('ale#handlers#ols#GetExecutable'),
\ 'command': function('ale#handlers#ols#GetCommand'),
diff --git a/ale_linters/rust/analyzer.vim b/ale_linters/rust/analyzer.vim
index 3ead3871..e3141cd3 100644
--- a/ale_linters/rust/analyzer.vim
+++ b/ale_linters/rust/analyzer.vim
@@ -28,6 +28,7 @@ endfunction
call ale#linter#Define('rust', {
\ 'name': 'analyzer',
+\ 'aliases': ['rust_analyzer'],
\ 'lsp': 'stdio',
\ 'initialization_options': {b -> ale#Var(b, 'rust_analyzer_config')},
\ 'executable': {b -> ale#Var(b, 'rust_analyzer_executable')},
diff --git a/ale_linters/swift/sourcekitlsp.vim b/ale_linters/swift/sourcekitlsp.vim
index 560893bf..a403dcc1 100644
--- a/ale_linters/swift/sourcekitlsp.vim
+++ b/ale_linters/swift/sourcekitlsp.vim
@@ -5,6 +5,7 @@ call ale#Set('sourcekit_lsp_executable', 'sourcekit-lsp')
call ale#linter#Define('swift', {
\ 'name': 'sourcekitlsp',
+\ 'aliases': ['sourcekit'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'sourcekit_lsp_executable')},
\ 'command': '%e',
diff --git a/ale_linters/terraform/terraform_ls.vim b/ale_linters/terraform/terraform_ls.vim
index ab35126e..7dc77941 100644
--- a/ale_linters/terraform/terraform_ls.vim
+++ b/ale_linters/terraform/terraform_ls.vim
@@ -30,6 +30,7 @@ endfunction
call ale#linter#Define('terraform', {
\ 'name': 'terraform_ls',
+\ 'aliases': ['terraformls'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'terraform_ls_executable')},
\ 'command': function('ale_linters#terraform#terraform_ls#GetCommand'),
diff --git a/ale_linters/vue/vls.vim b/ale_linters/vue/vls.vim
index 4bd75286..009effd0 100644
--- a/ale_linters/vue/vls.vim
+++ b/ale_linters/vue/vls.vim
@@ -12,6 +12,7 @@ endfunction
call ale#linter#Define('vue', {
\ 'name': 'vls',
+\ 'aliases': ['vuels'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#path#FindExecutable(b, 'vue_vls', [
\ 'node_modules/.bin/vls',
diff --git a/ale_linters/yaml/ls.vim b/ale_linters/yaml/ls.vim
index 8e3f6d00..79510ffe 100644
--- a/ale_linters/yaml/ls.vim
+++ b/ale_linters/yaml/ls.vim
@@ -26,6 +26,7 @@ endfunction
call ale#linter#Define('yaml', {
\ 'name': 'yaml-language-server',
+\ 'aliases': ['yamlls'],
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#yaml#ls#GetExecutable'),
\ 'command': function('ale_linters#yaml#ls#GetCommand'),
diff --git a/autoload/ale.vim b/autoload/ale.vim
index 23315913..5212099e 100644
--- a/autoload/ale.vim
+++ b/autoload/ale.vim
@@ -7,9 +7,6 @@ let g:ale_echo_msg_error_str = get(g:, 'ale_echo_msg_error_str', 'Error')
let g:ale_echo_msg_info_str = get(g:, 'ale_echo_msg_info_str', 'Info')
let g:ale_echo_msg_log_str = get(g:, 'ale_echo_msg_log_str', 'Log')
let g:ale_echo_msg_warning_str = get(g:, 'ale_echo_msg_warning_str', 'Warning')
-" Ignoring linters, for disabling some, or ignoring LSP diagnostics.
-let g:ale_linters_ignore = get(g:, 'ale_linters_ignore', {})
-let g:ale_disable_lsp = get(g:, 'ale_disable_lsp', 0)
" LSP window/showMessage format
let g:ale_lsp_show_message_format = get(g:, 'ale_lsp_show_message_format', '%severity%:%linter%: %s')
@@ -100,7 +97,24 @@ function! s:Lint(buffer, should_lint_file, timer_id) abort
" Use the filetype from the buffer
let l:filetype = getbufvar(a:buffer, '&filetype')
let l:linters = ale#linter#Get(l:filetype)
- let l:linters = ale#linter#RemoveIgnored(a:buffer, l:filetype, l:linters)
+
+ let l:ignore_config = ale#Var(a:buffer, 'linters_ignore')
+ let l:disable_lsp = ale#Var(a:buffer, 'disable_lsp')
+
+ " Load code to ignore linters only if we need to.
+ if (
+ \ !empty(l:ignore_config)
+ \ || l:disable_lsp is 1
+ \ || l:disable_lsp is v:true
+ \ || (l:disable_lsp is# 'auto' && get(g:, 'lspconfig', 0))
+ \)
+ let l:linters = ale#engine#ignore#Exclude(
+ \ l:filetype,
+ \ l:linters,
+ \ l:ignore_config,
+ \ l:disable_lsp,
+ \)
+ endif
" Tell other sources that they can start checking the buffer now.
let g:ale_want_results_buffer = a:buffer
diff --git a/autoload/ale/code_action.vim b/autoload/ale/code_action.vim
index db31aad5..4167e907 100644
--- a/autoload/ale/code_action.vim
+++ b/autoload/ale/code_action.vim
@@ -339,17 +339,7 @@ function! ale#code_action#GetCodeActions(options) abort
silent! aunmenu PopUp.Refactor\.\.\.
" Only display the menu items if there's an LSP server.
- let l:has_lsp = 0
-
- for l:linter in ale#linter#Get(&filetype)
- if !empty(l:linter.lsp)
- let l:has_lsp = 1
-
- break
- endif
- endfor
-
- if l:has_lsp
+ if len(ale#lsp_linter#GetEnabled(bufnr(''))) > 0
if !empty(expand('<cword>'))
silent! anoremenu <silent> PopUp.Rename :ALERename<CR>
endif
diff --git a/autoload/ale/codefix.vim b/autoload/ale/codefix.vim
index 34ce3e15..6eaadb23 100644
--- a/autoload/ale/codefix.vim
+++ b/autoload/ale/codefix.vim
@@ -473,15 +473,9 @@ function! ale#codefix#Execute(range, ...) abort
endif
let l:MenuCallback = get(a:000, 0, v:null)
- let l:lsp_linters = []
+ let l:linters = ale#lsp_linter#GetEnabled(bufnr(''))
- for l:linter in ale#linter#Get(&filetype)
- if !empty(l:linter.lsp)
- call add(l:lsp_linters, l:linter)
- endif
- endfor
-
- if empty(l:lsp_linters)
+ if empty(l:linters)
if l:MenuCallback is v:null
call s:message('No active LSPs')
else
@@ -491,7 +485,7 @@ function! ale#codefix#Execute(range, ...) abort
return
endif
- for l:lsp_linter in l:lsp_linters
- call s:ExecuteGetCodeFix(l:lsp_linter, a:range, l:MenuCallback)
+ for l:linter in l:linters
+ call s:ExecuteGetCodeFix(l:linter, a:range, l:MenuCallback)
endfor
endfunction
diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim
index c05ca53d..4fd02721 100644
--- a/autoload/ale/completion.vim
+++ b/autoload/ale/completion.vim
@@ -824,6 +824,8 @@ endfunction
" the current buffer. 1 will be returned if there's a potential source of
" completion data ALE can use, and 0 will be returned otherwise.
function! ale#completion#CanProvideCompletions() abort
+ " NOTE: We can report that ALE can provide completions to Deoplete from
+ " here, and we might ignore linters still below.
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
return 1
@@ -890,11 +892,9 @@ function! ale#completion#GetCompletions(...) abort
let l:started = 0
- for l:linter in ale#linter#Get(&filetype)
- if !empty(l:linter.lsp)
- if ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
- let l:started = 1
- endif
+ for l:linter in ale#lsp_linter#GetEnabled(l:buffer)
+ if ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
+ let l:started = 1
endif
endfor
diff --git a/autoload/ale/debugging.vim b/autoload/ale/debugging.vim
index 1becf332..89f5258f 100644
--- a/autoload/ale/debugging.vim
+++ b/autoload/ale/debugging.vim
@@ -201,6 +201,35 @@ function! s:EchoLSPErrorMessages(all_linter_names) abort
endfor
endfunction
+function! s:GetIgnoredLinters(buffer, enabled_linters) abort
+ let l:filetype = &filetype
+ let l:ignore_config = ale#Var(a:buffer, 'linters_ignore')
+ let l:disable_lsp = ale#Var(a:buffer, 'disable_lsp')
+
+ if (
+ \ !empty(l:ignore_config)
+ \ || l:disable_lsp is 1
+ \ || l:disable_lsp is v:true
+ \ || (l:disable_lsp is# 'auto' && get(g:, 'lspconfig', 0))
+ \)
+ let l:non_ignored = ale#engine#ignore#Exclude(
+ \ l:filetype,
+ \ a:enabled_linters,
+ \ l:ignore_config,
+ \ l:disable_lsp,
+ \)
+ else
+ let l:non_ignored = copy(a:enabled_linters)
+ endif
+
+ call map(l:non_ignored, 'v:val.name')
+
+ return filter(
+ \ copy(a:enabled_linters),
+ \ 'index(l:non_ignored, v:val.name) < 0'
+ \)
+endfunction
+
function! ale#debugging#Info(...) abort
let l:options = (a:0 > 0) ? a:1 : {}
let l:show_preview_info = get(l:options, 'preview')
@@ -208,7 +237,6 @@ function! ale#debugging#Info(...) abort
let l:buffer = bufnr('')
let l:filetype = &filetype
- " We get the list of enabled linters for free by the above function.
let l:enabled_linters = deepcopy(ale#linter#Get(l:filetype))
" But have to build the list of available linters ourselves.
@@ -232,13 +260,10 @@ function! ale#debugging#Info(...) abort
let l:fixers = uniq(sort(l:fixers[0] + l:fixers[1]))
let l:fixers_string = join(map(copy(l:fixers), '"\n " . v:val'), '')
- let l:non_ignored_names = map(
- \ copy(ale#linter#RemoveIgnored(l:buffer, l:filetype, l:enabled_linters)),
- \ 'v:val[''name'']',
- \)
- let l:ignored_names = filter(
- \ copy(l:enabled_names),
- \ 'index(l:non_ignored_names, v:val) < 0'
+ " Get the names of ignored linters.
+ let l:ignored_names = map(
+ \ s:GetIgnoredLinters(l:buffer, l:enabled_linters),
+ \ 'v:val.name'
\)
call s:Echo(' Current Filetype: ' . l:filetype)
diff --git a/autoload/ale/definition.vim b/autoload/ale/definition.vim
index fd6cd2e1..251bdcc5 100644
--- a/autoload/ale/definition.vim
+++ b/autoload/ale/definition.vim
@@ -168,26 +168,20 @@ function! s:GoToLSPDefinition(linter, options, capability) abort
endfunction
function! ale#definition#GoTo(options) abort
- for l:linter in ale#linter#Get(&filetype)
- if !empty(l:linter.lsp)
- call s:GoToLSPDefinition(l:linter, a:options, 'definition')
- endif
+ for l:linter in ale#lsp_linter#GetEnabled(bufnr(''))
+ call s:GoToLSPDefinition(l:linter, a:options, 'definition')
endfor
endfunction
function! ale#definition#GoToType(options) abort
- for l:linter in ale#linter#Get(&filetype)
- if !empty(l:linter.lsp)
- call s:GoToLSPDefinition(l:linter, a:options, 'typeDefinition')
- endif
+ for l:linter in ale#lsp_linter#GetEnabled(bufnr(''))
+ call s:GoToLSPDefinition(l:linter, a:options, 'typeDefinition')
endfor
endfunction
function! ale#definition#GoToImpl(options) abort
- for l:linter in ale#linter#Get(&filetype)
- if !empty(l:linter.lsp)
- call s:GoToLSPDefinition(l:linter, a:options, 'implementation')
- endif
+ for l:linter in ale#lsp_linter#GetEnabled(bufnr(''))
+ call s:GoToLSPDefinition(l:linter, a:options, 'implementation')
endfor
endfunction
diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim
index 185d54db..7e337191 100644
--- a/autoload/ale/engine.vim
+++ b/autoload/ale/engine.vim
@@ -253,7 +253,7 @@ function! ale#engine#SendResultsToNeovimDiagnostics(buffer, loclist) abort
" Keep the Lua surface area really small in the VimL part of ALE,
" and just require the diagnostics.lua module on demand.
- let l:SendDiagnostics = luaeval('require("diagnostics").sendAleResultsToDiagnostics')
+ let l:SendDiagnostics = luaeval('require("ale.diagnostics").sendAleResultsToDiagnostics')
call l:SendDiagnostics(a:buffer, a:loclist)
endfunction
diff --git a/autoload/ale/engine/ignore.vim b/autoload/ale/engine/ignore.vim
index 80574656..8ac36eb5 100644
--- a/autoload/ale/engine/ignore.vim
+++ b/autoload/ale/engine/ignore.vim
@@ -1,6 +1,26 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Code for ignoring linters. Only loaded and if configured.
+" A map for remapping lspconfig server names to linter names or aliases in
+" ALE. We should change the names where they will conflict with names in ALE.
+"
+" Notes on names from nvim-lspconfig not included here.
+"
+" * 'rubocop' is run in a language server mode
+" * 'eslint' is run via 'vscode-eslint-language-server'
+let s:lspconfig_map = {
+\ 'als': 'adals',
+\ 'ansiblels': 'ansible-language-server',
+\ 'bicep': 'bicep_language_server',
+\ 'cmake': 'cmake_language_server',
+\ 'denols': 'deno',
+\ 'erlangls': 'erlang_ls',
+\ 'html': 'vscodehtml',
+\ 'ocamlls': 'ocaml-language-server',
+\ 'ols': 'odin-lsp',
+\ 'puppet': 'puppet_languageserver',
+\}
+
" Given a filetype and a configuration for ignoring linters, return a List of
" Strings for linter names to ignore.
function! ale#engine#ignore#GetList(filetype, config) abort
@@ -21,24 +41,51 @@ function! ale#engine#ignore#GetList(filetype, config) abort
return []
endfunction
+" This function can be mocked in tests.
+function! ale#engine#ignore#GetLSPConfigNames() abort
+ return luaeval('require ''ale.util''.configured_lspconfig_servers()')
+endfunction
+
+function! s:GetMappedLSPConfigNames() abort
+ " Check the lspconfig flag before calling luaeval.
+ if !get(g:, 'lspconfig', 0)
+ return []
+ endif
+
+ let l:lspconfig_servers = ale#engine#ignore#GetLSPConfigNames()
+
+ return map(
+ \ !empty(l:lspconfig_servers) ? l:lspconfig_servers : [],
+ \ {_, val -> get(s:lspconfig_map, val, val) }
+ \)
+endfunction
+
" Given a List of linter descriptions, exclude the linters to be ignored.
function! ale#engine#ignore#Exclude(filetype, all_linters, config, disable_lsp) abort
let l:names_to_remove = ale#engine#ignore#GetList(a:filetype, a:config)
+
+ " If configured to automatically ignore otherwise configured LSP linter
+ " names, add them to the names to remove. This could ignore linters
+ " with matching names that are not marked as LSP linters.
+ if a:disable_lsp is# 'auto'
+ call extend(l:names_to_remove, s:GetMappedLSPConfigNames())
+ endif
+
+ let l:ignore_all_lsps = a:disable_lsp is 1 || a:disable_lsp is v:true
let l:filtered_linters = []
for l:linter in a:all_linters
- let l:name_list = [l:linter.name] + l:linter.aliases
- let l:should_include = 1
-
- for l:name in l:name_list
- if index(l:names_to_remove, l:name) >= 0
- let l:should_include = 0
- break
- endif
- endfor
+ let l:should_include = index(l:names_to_remove, l:linter.name) == -1
+ let l:i = 0
+
+ while l:should_include && l:i < len(l:linter.aliases)
+ let l:name = l:linter.aliases[l:i]
+ let l:should_include = index(l:names_to_remove, l:name) == -1
+ let l:i += 1
+ endwhile
- if a:disable_lsp && has_key(l:linter, 'lsp') && l:linter.lsp isnot# ''
- let l:should_include = 0
+ if l:should_include && l:ignore_all_lsps
+ let l:should_include = empty(get(l:linter, 'lsp'))
endif
if l:should_include
diff --git a/autoload/ale/filerename.vim b/autoload/ale/filerename.vim
index ec20d279..93cf78e1 100644
--- a/autoload/ale/filerename.vim
+++ b/autoload/ale/filerename.vim
@@ -94,9 +94,10 @@ function! s:ExecuteFileRename(linter, options) abort
endfunction
function! ale#filerename#Execute() abort
+ let l:buffer = bufnr('')
let l:lsp_linters = []
- for l:linter in ale#linter#Get(&filetype)
+ for l:linter in ale#lsp_linter#GetEnabled(l:buffer)
if l:linter.lsp is# 'tsserver'
call add(l:lsp_linters, l:linter)
endif
@@ -108,7 +109,6 @@ function! ale#filerename#Execute() abort
return
endif
- let l:buffer = bufnr('')
let l:old_name = expand('#' . l:buffer . ':p')
let l:new_name = ale#util#Input('New file name: ', l:old_name, 'file')
diff --git a/autoload/ale/handlers/hdl_checker.vim b/autoload/ale/handlers/hdl_checker.vim
index e871b083..d45f86e1 100644
--- a/autoload/ale/handlers/hdl_checker.vim
+++ b/autoload/ale/handlers/hdl_checker.vim
@@ -61,7 +61,8 @@ endfunction
" Define the hdl_checker linter for a given filetype.
function! ale#handlers#hdl_checker#DefineLinter(filetype) abort
call ale#linter#Define(a:filetype, {
- \ 'name': 'hdl-checker',
+ \ 'name': 'hdl_checker',
+ \ 'aliases': ['hdl-checker'],
\ 'lsp': 'stdio',
\ 'language': a:filetype,
\ 'executable': function('ale#handlers#hdl_checker#GetExecutable'),
@@ -70,4 +71,3 @@ function! ale#handlers#hdl_checker#DefineLinter(filetype) abort
\ 'initialization_options': function('ale#handlers#hdl_checker#GetInitOptions'),
\ })
endfunction
-
diff --git a/autoload/ale/hover.vim b/autoload/ale/hover.vim
index 6ad43316..7070b86d 100644
--- a/autoload/ale/hover.vim
+++ b/autoload/ale/hover.vim
@@ -329,10 +329,9 @@ function! ale#hover#Show(buffer, line, col, opt) abort
let l:show_documentation = get(a:opt, 'show_documentation', 0)
let l:Callback = function('s:OnReady', [a:line, a:col, a:opt])
- for l:linter in ale#linter#Get(getbufvar(a:buffer, '&filetype'))
+ for l:linter in ale#lsp_linter#GetEnabled(a:buffer)
" Only tsserver supports documentation requests at the moment.
- if !empty(l:linter.lsp)
- \&& (!l:show_documentation || l:linter.lsp is# 'tsserver')
+ if !l:show_documentation || l:linter.lsp is# 'tsserver'
call ale#lsp_linter#StartLSP(a:buffer, l:linter, l:Callback)
endif
endfor
diff --git a/autoload/ale/linter.vim b/autoload/ale/linter.vim
index 73c47109..20104fbc 100644
--- a/autoload/ale/linter.vim
+++ b/autoload/ale/linter.vim
@@ -417,16 +417,6 @@ function! ale#linter#Get(original_filetypes) abort
return reverse(l:combined_linters)
endfunction
-function! ale#linter#RemoveIgnored(buffer, filetype, linters) abort
- " Apply ignore lists for linters only if needed.
- let l:ignore_config = ale#Var(a:buffer, 'linters_ignore')
- let l:disable_lsp = ale#Var(a:buffer, 'disable_lsp')
-
- return !empty(l:ignore_config) || l:disable_lsp
- \ ? ale#engine#ignore#Exclude(a:filetype, a:linters, l:ignore_config, l:disable_lsp)
- \ : a:linters
-endfunction
-
" Given a buffer and linter, get the executable String for the linter.
function! ale#linter#GetExecutable(buffer, linter) abort
let l:Executable = a:linter.executable
diff --git a/autoload/ale/lsp/reset.vim b/autoload/ale/lsp/reset.vim
index 2fc7f0a2..85188b5a 100644
--- a/autoload/ale/lsp/reset.vim
+++ b/autoload/ale/lsp/reset.vim
@@ -15,6 +15,8 @@ function! ale#lsp#reset#StopAllLSPs() abort
for l:buffer_string in keys(g:ale_buffer_info)
let l:buffer = str2nr(l:buffer_string)
+ " Non-ignored and disabled linters are included here so we can
+ " clear results for them after we ignore or disable them.
for l:linter in ale#linter#Get(getbufvar(l:buffer, '&filetype'))
if !empty(l:linter.lsp)
call ale#engine#HandleLoclist(l:linter.name, l:buffer, [], 0)
diff --git a/autoload/ale/lsp_linter.vim b/autoload/ale/lsp_linter.vim
index 1c98d628..05a0294c 100644
--- a/autoload/ale/lsp_linter.vim
+++ b/autoload/ale/lsp_linter.vim
@@ -27,28 +27,62 @@ function! ale#lsp_linter#SetLSPLinterMap(replacement_map) abort
let s:lsp_linter_map = a:replacement_map
endfunction
-" Check if diagnostics for a particular linter should be ignored.
-function! s:ShouldIgnore(buffer, linter_name) abort
- " Ignore all diagnostics if LSP integration is disabled.
- if ale#Var(a:buffer, 'disable_lsp')
- return 1
+" Get all enabled LSP linters.
+" This list still includes linters ignored with `ale_linters_ignore`.
+"
+" `ale_linters_ignore` is designed to allow language servers to be used for
+" their functionality while ignoring the diagnostics they return.
+function! ale#lsp_linter#GetEnabled(buffer) abort
+ let l:filetype = getbufvar(a:buffer, '&filetype')
+ " Only LSP linters are included here.
+ let l:linters = filter(ale#linter#Get(l:filetype), '!empty(v:val.lsp)')
+ let l:disable_lsp = ale#Var(a:buffer, 'disable_lsp')
+
+ " Only load code for ignoring linters if we need it.
+ if (
+ \ l:disable_lsp is 1
+ \ || l:disable_lsp is v:true
+ \ || (l:disable_lsp is# 'auto' && get(g:, 'lspconfig', 0))
+ \)
+ let l:linters = ale#engine#ignore#Exclude(
+ \ l:filetype,
+ \ l:linters,
+ \ [],
+ \ l:disable_lsp,
+ \)
endif
- let l:config = ale#Var(a:buffer, 'linters_ignore')
+ return l:linters
+endfunction
- " Don't load code for ignoring diagnostics if there's nothing to ignore.
- if empty(l:config)
- return 0
+" Check if diagnostics for a particular linter should be ignored.
+function! s:ShouldIgnoreDiagnostics(buffer, linter) abort
+ let l:config = ale#Var(a:buffer, 'linters_ignore')
+ let l:disable_lsp = ale#Var(a:buffer, 'disable_lsp')
+
+ " Only load code for ignoring linters if we need it.
+ if (
+ \ !empty(l:config)
+ \ || l:disable_lsp is 1
+ \ || l:disable_lsp is v:true
+ \ || (l:disable_lsp is# 'auto' && get(g:, 'lspconfig', 0))
+ \)
+ " Re-use the ignore implementation just for this linter.
+ return empty(
+ \ ale#engine#ignore#Exclude(
+ \ getbufvar(a:buffer, '&filetype'),
+ \ [a:linter],
+ \ l:config,
+ \ l:disable_lsp,
+ \ )
+ \)
endif
- let l:filetype = getbufvar(a:buffer, '&filetype')
- let l:ignore_list = ale#engine#ignore#GetList(l:filetype, l:config)
-
- return index(l:ignore_list, a:linter_name) >= 0
+ return 0
endfunction
function! s:HandleLSPDiagnostics(conn_id, response) abort
- let l:linter_name = s:lsp_linter_map[a:conn_id]
+ let l:linter = s:lsp_linter_map[a:conn_id]
let l:filename = ale#util#ToResource(a:response.params.uri)
let l:escaped_name = escape(
\ fnameescape(l:filename),
@@ -61,17 +95,22 @@ function! s:HandleLSPDiagnostics(conn_id, response) abort
return
endif
- if s:ShouldIgnore(l:buffer, l:linter_name)
+ if s:ShouldIgnoreDiagnostics(l:buffer, l:linter)
return
endif
let l:loclist = ale#lsp#response#ReadDiagnostics(a:response)
- call ale#engine#HandleLoclist(l:linter_name, l:buffer, l:loclist, 0)
+ call ale#engine#HandleLoclist(l:linter.name, l:buffer, l:loclist, 0)
endfunction
function! s:HandleTSServerDiagnostics(response, error_type) abort
- let l:linter_name = 'tsserver'
+ " Re-create a fake linter object for tsserver.
+ let l:linter = {
+ \ 'name': 'tsserver',
+ \ 'aliases': [],
+ \ 'lsp': 'tsserver',
+ \}
let l:escaped_name = escape(
\ fnameescape(a:response.body.file),
\ has('win32') ? '^' : '^,}]'
@@ -83,9 +122,9 @@ function! s:HandleTSServerDiagnostics(response, error_type) abort
return
endif
- call ale#engine#MarkLinterInactive(l:info, l:linter_name)
+ call ale#engine#MarkLinterInactive(l:info, l:linter.name)
- if s:ShouldIgnore(l:buffer, l:linter_name)
+ if s:ShouldIgnoreDiagnostics(l:buffer, l:linter)
return
endif
@@ -123,15 +162,15 @@ function! s:HandleTSServerDiagnostics(response, error_type) abort
\ + get(l:info, 'suggestion_loclist', [])
\ + get(l:info, 'syntax_loclist', [])
- call ale#engine#HandleLoclist(l:linter_name, l:buffer, l:loclist, 0)
+ call ale#engine#HandleLoclist(l:linter.name, l:buffer, l:loclist, 0)
endfunction
-function! s:HandleLSPErrorMessage(linter_name, response) abort
+function! s:HandleLSPErrorMessage(linter, response) abort
if !g:ale_history_enabled || !g:ale_history_log_output
return
endif
- if empty(a:linter_name)
+ if empty(a:linter)
return
endif
@@ -141,7 +180,7 @@ function! s:HandleLSPErrorMessage(linter_name, response) abort
return
endif
- call ale#lsp_linter#AddErrorMessage(a:linter_name, l:message)
+ call ale#lsp_linter#AddErrorMessage(a:linter.name, l:message)
endfunction
function! ale#lsp_linter#AddErrorMessage(linter_name, message) abort
@@ -160,14 +199,14 @@ function! ale#lsp_linter#HandleLSPResponse(conn_id, response) abort
let l:method = get(a:response, 'method', '')
if get(a:response, 'jsonrpc', '') is# '2.0' && has_key(a:response, 'error')
- let l:linter_name = get(s:lsp_linter_map, a:conn_id, '')
+ let l:linter = get(s:lsp_linter_map, a:conn_id, {})
- call s:HandleLSPErrorMessage(l:linter_name, a:response)
+ call s:HandleLSPErrorMessage(l:linter, a:response)
elseif l:method is# 'textDocument/publishDiagnostics'
call s:HandleLSPDiagnostics(a:conn_id, a:response)
elseif l:method is# 'window/showMessage'
call ale#lsp_window#HandleShowMessage(
- \ s:lsp_linter_map[a:conn_id],
+ \ s:lsp_linter_map[a:conn_id].name,
\ g:ale_lsp_show_message_format,
\ a:response.params
\)
@@ -472,7 +511,7 @@ function! s:CheckWithLSP(linter, details) abort
call ale#lsp#RegisterCallback(l:id, l:Callback)
" Remember the linter this connection is for.
- let s:lsp_linter_map[l:id] = a:linter.name
+ let s:lsp_linter_map[l:id] = a:linter
if a:linter.lsp is# 'tsserver'
let l:message = ale#lsp#tsserver_message#Geterr(l:buffer)
diff --git a/autoload/ale/organize_imports.vim b/autoload/ale/organize_imports.vim
index 395e6fbd..fb00bc21 100644
--- a/autoload/ale/organize_imports.vim
+++ b/autoload/ale/organize_imports.vim
@@ -57,9 +57,7 @@ function! s:OrganizeImports(linter) abort
endfunction
function! ale#organize_imports#Execute() abort
- for l:linter in ale#linter#Get(&filetype)
- if !empty(l:linter.lsp)
- call s:OrganizeImports(l:linter)
- endif
+ for l:linter in ale#lsp_linter#GetEnabled(bufnr(''))
+ call s:OrganizeImports(l:linter)
endfor
endfunction
diff --git a/autoload/ale/references.vim b/autoload/ale/references.vim
index c32663fe..df253c9c 100644
--- a/autoload/ale/references.vim
+++ b/autoload/ale/references.vim
@@ -179,9 +179,7 @@ function! ale#references#Find(...) abort
let l:column = min([l:column, len(getline(l:line))])
let l:Callback = function('s:OnReady', [l:line, l:column, l:options])
- for l:linter in ale#linter#Get(&filetype)
- if !empty(l:linter.lsp)
- call ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
- endif
+ for l:linter in ale#lsp_linter#GetEnabled(l:buffer)
+ call ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
endfor
endfunction
diff --git a/autoload/ale/rename.vim b/autoload/ale/rename.vim
index 53c9fb5c..d7bc8699 100644
--- a/autoload/ale/rename.vim
+++ b/autoload/ale/rename.vim
@@ -178,15 +178,9 @@ function! s:ExecuteRename(linter, options) abort
endfunction
function! ale#rename#Execute() abort
- let l:lsp_linters = []
+ let l:linters = ale#lsp_linter#GetEnabled(bufnr(''))
- for l:linter in ale#linter#Get(&filetype)
- if !empty(l:linter.lsp)
- call add(l:lsp_linters, l:linter)
- endif
- endfor
-
- if empty(l:lsp_linters)
+ if empty(l:linters)
call s:message('No active LSPs')
return
@@ -201,8 +195,8 @@ function! ale#rename#Execute() abort
return
endif
- for l:lsp_linter in l:lsp_linters
- call s:ExecuteRename(l:lsp_linter, {
+ for l:linter in l:linters
+ call s:ExecuteRename(l:linter, {
\ 'old_name': l:old_name,
\ 'new_name': l:new_name,
\})
diff --git a/autoload/ale/symbol.vim b/autoload/ale/symbol.vim
index 6c65f1b2..ba971e74 100644
--- a/autoload/ale/symbol.vim
+++ b/autoload/ale/symbol.vim
@@ -102,8 +102,8 @@ function! ale#symbol#Search(args) abort
call setbufvar(l:buffer, 'ale_symbol_request_made', 0)
let l:Callback = function('s:OnReady', [l:query, l:options])
- for l:linter in ale#linter#Get(getbufvar(l:buffer, '&filetype'))
- if !empty(l:linter.lsp) && l:linter.lsp isnot# 'tsserver'
+ for l:linter in ale#lsp_linter#GetEnabled(l:buffer)
+ if l:linter.lsp isnot# 'tsserver'
call ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
endif
endfor
diff --git a/autoload/ale/uri/jdt.vim b/autoload/ale/uri/jdt.vim
index 46cea268..11a22d34 100644
--- a/autoload/ale/uri/jdt.vim
+++ b/autoload/ale/uri/jdt.vim
@@ -39,6 +39,8 @@ endfunction
function! ale#uri#jdt#OpenJDTLink(encoded_uri, line, column, options, conn_id) abort
let l:found_eclipselsp = v:false
+ " We should only arrive here from a 'go to definition' request, so we'll
+ " assume the eclipselsp linter is enabled.
for l:linter in ale#linter#Get('java')
if l:linter.name is# 'eclipselsp'
let l:found_eclipselsp = v:true
@@ -87,8 +89,8 @@ function! ale#uri#jdt#ReadJDTLink(encoded_uri) abort
let l:linter_map = ale#lsp_linter#GetLSPLinterMap()
- for l:conn_id in keys(l:linter_map)
- if l:linter_map[l:conn_id] is# 'eclipselsp'
+ for [l:conn_id, l:linter] in items(l:linter_map)
+ if l:linter.name is# 'eclipselsp'
let l:root = l:conn_id[stridx(l:conn_id, ':')+1:]
endif
endfor
diff --git a/doc/ale.txt b/doc/ale.txt
index 423204a3..211ac1c3 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -1002,11 +1002,16 @@ g:ale_detail_to_floating_preview *g:ale_detail_to_floating_preview*
g:ale_disable_lsp *g:ale_disable_lsp*
*b:ale_disable_lsp*
- Type: |Number|
- Default: `0`
+ Type: |Number| OR |String|
+ Default: `'auto'`
+
+ When this option is set to `'auto'`, ALE will automatically disable linters
+ that it detects as having already been configured with the nvim-lspconfig
+ plugin. When this option is set to `1`, ALE ignores all linters powered by
+ LSP, and also `tsserver`.
- When this option is set to `1`, ALE ignores all linters powered by LSP,
- and also `tsserver`.
+ Any linters that are disabled will also not be usable for LSP functionality
+ other than just linting.
Please see also |ale-lsp|.
diff --git a/lspconfig.vim b/lspconfig.vim
new file mode 100644
index 00000000..0e25fdc2
--- /dev/null
+++ b/lspconfig.vim
@@ -0,0 +1,3 @@
+if get(g:, 'lspconfig', 0)
+ " lspconfig is installed.
+endif
diff --git a/lua/diagnostics.lua b/lua/ale/diagnostics.lua
index 21f81e2a..21f81e2a 100644
--- a/lua/diagnostics.lua
+++ b/lua/ale/diagnostics.lua
diff --git a/lua/ale/util.lua b/lua/ale/util.lua
new file mode 100644
index 00000000..98b3bbd9
--- /dev/null
+++ b/lua/ale/util.lua
@@ -0,0 +1,14 @@
+local M = {}
+
+function M.configured_lspconfig_servers()
+ local configs = require 'lspconfig.configs'
+ local keys = {}
+
+ for key, _ in pairs(configs) do
+ table.insert(keys, key)
+ end
+
+ return keys
+end
+
+return M
diff --git a/plugin/ale.vim b/plugin/ale.vim
index 2a58707d..a721bd89 100644
--- a/plugin/ale.vim
+++ b/plugin/ale.vim
@@ -60,6 +60,10 @@ let g:ale_filetype_blacklist = [
let g:ale_linters = get(g:, 'ale_linters', {})
" This option can be changed to only enable explicitly selected linters.
let g:ale_linters_explicit = get(g:, 'ale_linters_explicit', 0)
+" Ignoring linters, for disabling some, or ignoring LSP diagnostics.
+let g:ale_linters_ignore = get(g:, 'ale_linters_ignore', {})
+" Disabling all language server functionality.
+let g:ale_disable_lsp = get(g:, 'ale_disable_lsp', 'auto')
" This Dictionary configures which functions will be used for fixing problems.
let g:ale_fixers = get(g:, 'ale_fixers', {})
diff --git a/test/linter/test_ansible_language_server.vader b/test/linter/test_ansible_language_server.vader
index 3766972e..33634274 100644
--- a/test/linter/test_ansible_language_server.vader
+++ b/test/linter/test_ansible_language_server.vader
@@ -1,5 +1,5 @@
Before:
- call ale#assert#SetUpLinterTest('ansible', 'ansible_language_server')
+ call ale#assert#SetUpLinterTest('ansible', 'language_server')
After:
call ale#assert#TearDownLinterTest()
diff --git a/test/linter/test_elm_ls.vader b/test/linter/test_elm_ls.vader
index 98b01c96..69ae2170 100644
--- a/test/linter/test_elm_ls.vader
+++ b/test/linter/test_elm_ls.vader
@@ -1,5 +1,5 @@
Before:
- call ale#assert#SetUpLinterTest('elm', 'elm_ls')
+ call ale#assert#SetUpLinterTest('elm', 'ls')
After:
call ale#assert#TearDownLinterTest()
diff --git a/test/lsp/test_engine_lsp_response_handling.vader b/test/lsp/test_engine_lsp_response_handling.vader
index 50ceef4d..b00a6942 100644
--- a/test/lsp/test_engine_lsp_response_handling.vader
+++ b/test/lsp/test_engine_lsp_response_handling.vader
@@ -302,7 +302,7 @@ Execute(LSP diagnostics responses should be handled correctly):
endif
call ale#engine#InitBufferInfo(bufnr(''))
- call ale#lsp_linter#SetLSPLinterMap({'1': 'eclipselsp'})
+ call ale#lsp_linter#SetLSPLinterMap({'1': {'name': 'eclipselsp', 'aliases': [], 'lsp': 'stdio'}})
if has('win32')
AssertEqual 'filename,[]^$.ts', expand('%:p:t')
@@ -357,7 +357,7 @@ Execute(LSP diagnostics responses on project root should not populate loclist):
runtime ale_linters/java/eclipselsp.vim
call ale#test#SetFilename('filename.java')
call ale#engine#InitBufferInfo(bufnr(''))
- call ale#lsp_linter#SetLSPLinterMap({'1': 'eclipselsp'})
+ call ale#lsp_linter#SetLSPLinterMap({'1': {'name': 'eclipselsp', 'aliases': [], 'lsp': 'stdio'}})
call ale#lsp_linter#HandleLSPResponse(1, {
\ 'jsonrpc':'2.0',
@@ -395,7 +395,7 @@ Execute(LSP errors should mark linters no longer active):
runtime ale_linters/python/pylsp.vim
call ale#test#SetFilename('filename.py')
call ale#engine#InitBufferInfo(bufnr(''))
- call ale#lsp_linter#SetLSPLinterMap({1: 'pylsp'})
+ call ale#lsp_linter#SetLSPLinterMap({'1': {'name': 'pylsp', 'aliases': [], 'lsp': 'stdio'}})
let g:ale_buffer_info[bufnr('')].active_linter_list = ale#linter#Get('python')
Assert !empty(g:ale_buffer_info[bufnr('')].active_linter_list)
@@ -411,7 +411,7 @@ Execute(LSP errors should mark linters no longer active):
AssertEqual [], g:ale_buffer_info[bufnr('')].active_linter_list
Execute(LSP errors should be logged in the history):
- call ale#lsp_linter#SetLSPLinterMap({'347': 'foobar'})
+ call ale#lsp_linter#SetLSPLinterMap({'347': {'name': 'foobar', 'aliases': [], 'lsp': 'stdio'}})
call ale#lsp_linter#HandleLSPResponse(347, {
\ 'jsonrpc': '2.0',
\ 'error': {
diff --git a/test/test_filetype_linter_defaults.vader b/test/test_filetype_linter_defaults.vader
index 4de77bad..3f183f86 100644
--- a/test/test_filetype_linter_defaults.vader
+++ b/test/test_filetype_linter_defaults.vader
@@ -119,7 +119,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 ['hdl-checker', 'iverilog', 'verilator', 'vlog', 'xvlog', 'yosys'], GetLinterNames('verilog')
+ AssertEqual ['hdl_checker', 'iverilog', 'verilator', 'vlog', 'xvlog', 'yosys'], GetLinterNames('verilog')
let g:ale_linters_explicit = 1
diff --git a/test/test_ignoring_linters.vader b/test/test_ignoring_linters.vader
index f97a0cf6..c84a8943 100644
--- a/test/test_ignoring_linters.vader
+++ b/test/test_ignoring_linters.vader
@@ -1,10 +1,60 @@
Before:
+ Save g:lspconfig
+ Save g:ale_linters_ignore
+ Save g:ale_buffer_info
Save g:ale_disable_lsp
+ let g:lspconfig = 0
+ let g:lspconfig_names = {}
+ let g:ale_disable_lsp = 0
+ let g:linters = []
+ let g:loclist = []
+ let g:run_linters_called = 0
+
+ runtime autoload/ale/engine.vim
+ runtime autoload/ale/engine/ignore.vim
+
+ " Mock the engine function so we can set it up.
+ function! ale#engine#RunLinters(buffer, linters, should_lint_file) abort
+ let g:linters = a:linters
+ let g:run_linters_called = 1
+ endfunction
+
+ function! ale#engine#HandleLoclist(linter_name, buffer, loclist, from_other_source) abort
+ let g:loclist = a:loclist
+ endfunction
+
+ function! ale#engine#ignore#GetLSPConfigNames() abort
+ return g:lspconfig_names
+ endfunction
+
+ call ale#linter#Define('foobar', {
+ \ 'name': 'testlinter',
+ \ 'callback': 'TestCallback',
+ \ 'executable': has('win32') ? 'cmd' : 'true',
+ \ 'command': has('win32') ? 'echo' : 'true',
+ \})
+ call ale#test#SetDirectory('/testplugin/test')
+
After:
+ unlet! b:ale_linted
+ unlet! b:ale_linters_ignore
+ unlet! b:ale_quitting
+ unlet! b:ale_save_event_fired
+ unlet! b:ale_disable_lsp
+ unlet! g:linters
+ unlet! g:loclist
+ unlet! g:lsp_message
+ unlet! g:lspconfig_names
+
Restore
- unlet! b:ale_disable_lsp
+ call ale#test#RestoreDirectory()
+ call ale#linter#Reset()
+ call ale#lsp_linter#ClearLSPData()
+
+ runtime autoload/ale/engine.vim
+ runtime autoload/ale/engine/ignore.vim
Execute(GetList should ignore some invalid values):
AssertEqual [], ale#engine#ignore#GetList('', 'foo')
@@ -105,7 +155,7 @@ Execute(Exclude should handle Dictionaries):
\ 0,
\ )
-Execute(Exclude should filter LSP linters when g:ale_disable_lsp is set to 1):
+Execute(Exclude should filter LSP linters when ale_disable_lsp is set to 1):
AssertEqual
\ [
\ {'name': 'linter1', 'aliases': [], 'lsp': ''},
@@ -122,70 +172,81 @@ Execute(Exclude should filter LSP linters when g:ale_disable_lsp is set to 1):
\ 1,
\ )
-Execute(Exclude should filter LSP linters when b:ale_disable_lsp is set to 1):
+Execute(Exclude should remove lspconfig linters with ale_disable_lsp = 'auto'):
+ let g:lspconfig = 1
+ " A map is used here so you can easily see what the ignore mapping should be
+ " remapping the nvim-lspconfig names to.
+ let g:lspconfig_names = keys({
+ \ 'als': 'adals',
+ \ 'ansiblels': 'ansible-language-server',
+ \ 'bicep': 'bicep_language_server',
+ \ 'cmake': 'cmake_language_server',
+ \ 'denols': 'deno',
+ \ 'erlangls': 'erlang_ls',
+ \ 'html': 'vscodehtml',
+ \ 'ocamlls': 'ocaml-language-server',
+ \ 'puppet': 'puppet_languageserver',
+ \ 'pyright': 'pyright',
+ \})
+
+ " We should keep bicep, as it's different tool.
AssertEqual
\ [
- \ {'name': 'linter1', 'aliases': [], 'lsp': ''},
- \ {'name': 'linter2', 'aliases': []},
+ \ {'name': 'bicep', 'aliases': []},
\ ],
\ ale#engine#ignore#Exclude(
\ 'foo',
\ [
- \ {'name': 'linter1', 'aliases': [], 'lsp': ''},
- \ {'name': 'linter2', 'aliases': []},
- \ {'name': 'linter3', 'aliases': [], 'lsp': 'stdio'},
+ \ {'name': 'adals', 'aliases': []},
+ \ {'name': 'language_server', 'aliases': ['ansible-language-server']},
+ \ {'name': 'cmake_language_server', 'aliases': []},
+ \ {'name': 'deno', 'aliases': []},
+ \ {'name': 'erlang_ls', 'aliases': []},
+ \ {'name': 'vscodehtml', 'aliases': []},
+ \ {'name': 'bicep', 'aliases': []},
+ \ {'name': 'ols', 'aliases': ['ocaml-language-server']},
+ \ {'name': 'languageserver', 'aliases': ['puppet_languageserver']},
+ \ {'name': 'pyright', 'aliases': []},
\ ],
\ [],
- \ 1,
+ \ 'auto',
\ )
-Before:
- Save g:ale_linters_ignore
- Save g:ale_buffer_info
- Save g:ale_disable_lsp
+Execute(Exclude should check that the nvim-lspconfig plugin is installed with ale_disable_lsp = 'auto'):
+ let g:lspconfig = 0
+ let g:lspconfig_names = ['pyright']
- let g:ale_disable_lsp = 0
-
- let g:linters = []
- let g:loclist = []
- let g:run_linters_called = 0
-
- runtime autoload/ale/engine.vim
-
- " Mock the engine function so we can set it up.
- function! ale#engine#RunLinters(buffer, linters, should_lint_file) abort
- let g:linters = a:linters
- let g:run_linters_called = 1
- endfunction
-
- function! ale#engine#HandleLoclist(linter_name, buffer, loclist, from_other_source) abort
- let g:loclist = a:loclist
- endfunction
-
- call ale#linter#Define('foobar', {
- \ 'name': 'testlinter',
- \ 'callback': 'TestCallback',
- \ 'executable': has('win32') ? 'cmd' : 'true',
- \ 'command': has('win32') ? 'echo' : 'true',
- \})
- call ale#test#SetDirectory('/testplugin/test')
-
-After:
- Restore
+ " We should keep pyright here, because g:lspconfig is 0.
+ AssertEqual
+ \ [
+ \ {'name': 'pyright', 'aliases': []},
+ \ ],
+ \ ale#engine#ignore#Exclude(
+ \ 'foo',
+ \ [
+ \ {'name': 'pyright', 'aliases': []},
+ \ ],
+ \ [],
+ \ 'auto',
+ \ )
- unlet! b:ale_linted
- unlet! b:ale_linters_ignore
- unlet! b:ale_quitting
- unlet! b:ale_save_event_fired
- unlet! b:ale_disable_lsp
- unlet! g:linters
- unlet! g:loclist
- unlet! g:lsp_message
+Execute(Exclude should handle the lspconfig result being a Dictionary):
+ let g:lspconfig = 1
+ let g:lspconfig_names = {}
- call ale#test#RestoreDirectory()
- call ale#linter#Reset()
- call ale#lsp_linter#ClearLSPData()
- runtime autoload/ale/engine.vim
+ " We should keep pyright here, because the configuration is empty.
+ AssertEqual
+ \ [
+ \ {'name': 'pyright', 'aliases': []},
+ \ ],
+ \ ale#engine#ignore#Exclude(
+ \ 'foo',
+ \ [
+ \ {'name': 'pyright', 'aliases': []},
+ \ ],
+ \ [],
+ \ 'auto',
+ \ )
Given foobar(An empty file):
Execute(Global ignore lists should be applied for linters):
@@ -265,7 +326,7 @@ Execute(Buffer ignore lists should be applied for tsserver):
Execute(Buffer ignore lists should be applied for LSP linters):
call ale#test#SetFilename('filename.py')
call ale#engine#InitBufferInfo(bufnr(''))
- call ale#lsp_linter#SetLSPLinterMap({'347': 'lsplinter'})
+ call ale#lsp_linter#SetLSPLinterMap({'347': {'name': 'lsplinter', 'aliases': [], 'lsp': 'stdio'}})
let g:lsp_message = {
\ 'jsonrpc': '2.0',
@@ -357,10 +418,63 @@ Execute(ale_disable_lsp should be applied for tsserver):
AssertEqual [], g:loclist
+Execute(ale_disable_lsp = 'auto' should be applied for tsserver):
+ let g:lspconfig = 1
+ let g:lspconfig_names = ['tsserver']
+
+ call ale#test#SetFilename('filename.ts')
+ call ale#engine#InitBufferInfo(bufnr(''))
+
+ let g:lsp_message = {
+ \ 'seq': 0,
+ \ 'type': 'event',
+ \ 'event': 'syntaxDiag',
+ \ 'body': {
+ \ 'file': g:dir . '/filename.ts',
+ \ 'diagnostics':[
+ \ {
+ \ 'start': {
+ \ 'line':2,
+ \ 'offset':14,
+ \ },
+ \ 'end': {
+ \ 'line':2,
+ \ 'offset':15,
+ \ },
+ \ 'text': ''','' expected.',
+ \ "code":1005
+ \ },
+ \ ],
+ \ },
+ \}
+
+ call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message)
+
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 2,
+ \ 'col': 14,
+ \ 'nr': 1005,
+ \ 'code': '1005',
+ \ 'type': 'E',
+ \ 'end_col': 14,
+ \ 'end_lnum': 2,
+ \ 'text': ''','' expected.',
+ \ },
+ \ ],
+ \ g:loclist
+
+ let g:loclist = []
+ let g:ale_disable_lsp = 'auto'
+ call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message)
+
+ AssertEqual [], g:loclist
+
Execute(ale_disable_lsp should be applied for LSP linters):
call ale#test#SetFilename('filename.py')
call ale#engine#InitBufferInfo(bufnr(''))
- call ale#lsp_linter#SetLSPLinterMap({'347': 'lsplinter'})
+ call ale#lsp_linter#SetLSPLinterMap({'347': {'name': 'lsplinter', 'aliases': [], 'lsp': 'stdio'}})
let g:lsp_message = {
\ 'jsonrpc': '2.0',
@@ -401,3 +515,99 @@ Execute(ale_disable_lsp should be applied for LSP linters):
call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message)
AssertEqual [], g:loclist
+
+Execute(ale_disable_lsp = 'auto' should be applied for LSP linters):
+ let g:lspconfig = 1
+ let g:lspconfig_names = ['lsplinter']
+
+ call ale#test#SetFilename('filename.py')
+ call ale#engine#InitBufferInfo(bufnr(''))
+ call ale#lsp_linter#SetLSPLinterMap({'347': {'name': 'lsplinter', 'aliases': [], 'lsp': 'stdio'}})
+
+ let g:lsp_message = {
+ \ 'jsonrpc': '2.0',
+ \ 'method': 'textDocument/publishDiagnostics',
+ \ 'params': {
+ \ 'uri': ale#path#ToFileURI(expand('%:p')),
+ \ 'diagnostics': [
+ \ {
+ \ 'severity': 1,
+ \ 'message': 'x',
+ \ 'range': {
+ \ 'start': {'line': 0, 'character': 9},
+ \ 'end': {'line': 0, 'character': 9},
+ \ },
+ \ }
+ \ ],
+ \ },
+ \}
+
+ call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message)
+
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 10,
+ \ 'type': 'E',
+ \ 'end_col': 9,
+ \ 'end_lnum': 1,
+ \ 'text': 'x',
+ \ }
+ \ ],
+ \ g:loclist
+
+ let g:ale_disable_lsp = 'auto'
+ let g:loclist = []
+
+ call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message)
+
+ AssertEqual [], g:loclist
+
+Execute(ale_disable_lsp = 'auto' should ignore LSP linters by alias too):
+ let g:lspconfig = 1
+ let g:lspconfig_names = ['lsplinter']
+
+ call ale#test#SetFilename('filename.py')
+ call ale#engine#InitBufferInfo(bufnr(''))
+ call ale#lsp_linter#SetLSPLinterMap({'347': {'name': 'notthis', 'aliases': ['lsplinter'], 'lsp': 'stdio'}})
+
+ let g:lsp_message = {
+ \ 'jsonrpc': '2.0',
+ \ 'method': 'textDocument/publishDiagnostics',
+ \ 'params': {
+ \ 'uri': ale#path#ToFileURI(expand('%:p')),
+ \ 'diagnostics': [
+ \ {
+ \ 'severity': 1,
+ \ 'message': 'x',
+ \ 'range': {
+ \ 'start': {'line': 0, 'character': 9},
+ \ 'end': {'line': 0, 'character': 9},
+ \ },
+ \ }
+ \ ],
+ \ },
+ \}
+
+ call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message)
+
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 10,
+ \ 'type': 'E',
+ \ 'end_col': 9,
+ \ 'end_lnum': 1,
+ \ 'text': 'x',
+ \ }
+ \ ],
+ \ g:loclist
+
+ let g:ale_disable_lsp = 'auto'
+ let g:loclist = []
+
+ call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message)
+
+ AssertEqual [], g:loclist