aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorcoriocactus2026-04-10 15:20:22 +0100
committerGitHub2026-04-10 23:20:22 +0900
commit6ba798d2e773905feb609bf530e681acbdaea22c (patch)
treebb1c2fbf5e80bd61cc34934d4c2cc7c7cc74aed2
parentb1b027d5e60916ab2b814758708d59c26b3e4c20 (diff)
downloadale-6ba798d2e773905feb609bf530e681acbdaea22c.tar.gz

fix expert lsp stdio and register capability (#5113)

  • pass –stdio flag to expert lsp server

expert requires –stdio to use stdio transport but the linter definition launched it without the flag, so the server never entered lsp mode

  • handle client/registerCapability requests from lsp servers

some lsp servers like expert send a client/registerCapability request after initialization to dynamically register capabilities, if ale does not respond the server blocks and never processes further messages like textDocument/didOpen

-rw-r--r--ale_linters/elixir/expert.vim2
-rw-r--r--autoload/ale/lsp_linter.vim2
-rw-r--r--test/linter/test_elixir_expert.vader4
-rw-r--r--test/lsp/test_engine_lsp_response_handling.vader24
4 files changed, 29 insertions, 3 deletions
diff --git a/ale_linters/elixir/expert.vim b/ale_linters/elixir/expert.vim
index aba88ab06..521a59639 100644
--- a/ale_linters/elixir/expert.vim
+++ b/ale_linters/elixir/expert.vim
@@ -7,6 +7,6 @@ call ale#linter#Define('elixir', {
\ 'name': 'expert',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'elixir_expert_executable')},
-\ 'command': '%e',
+\ 'command': '%e --stdio',
\ 'project_root': function('ale#handlers#elixir#FindMixUmbrellaRoot'),
\})
diff --git a/autoload/ale/lsp_linter.vim b/autoload/ale/lsp_linter.vim
index fae9f7098..fdd492ddc 100644
--- a/autoload/ale/lsp_linter.vim
+++ b/autoload/ale/lsp_linter.vim
@@ -241,6 +241,8 @@ function! ale#lsp_linter#HandleLSPResponse(conn_id, response) abort
\ : a:response.result.items
call ale#lsp_linter#HandleLSPDiagnostics(a:conn_id, l:uri, l:diagnostics)
+ elseif l:method is# 'client/registerCapability'
+ call ale#lsp#SendResponse(a:conn_id, a:response.id, v:null)
elseif l:method is# 'workspace/configuration'
let l:items = get(get(a:response, 'params', {}), 'items', [])
let l:config = ale#lsp#GetConnectionConfig(a:conn_id)
diff --git a/test/linter/test_elixir_expert.vader b/test/linter/test_elixir_expert.vader
index a36f4e472..2e9c0ed84 100644
--- a/test/linter/test_elixir_expert.vader
+++ b/test/linter/test_elixir_expert.vader
@@ -5,12 +5,12 @@ After:
call ale#assert#TearDownLinterTest()
Execute(should set correct defaults):
- AssertLinter 'expert', ale#Escape('expert')
+ AssertLinter 'expert', ale#Escape('expert') . ' --stdio'
Execute(The executable should be configurable):
let b:ale_elixir_expert_executable = 'foobar'
- AssertLinter 'foobar', ale#Escape('foobar')
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --stdio'
Execute(should set correct LSP values):
call ale#test#SetFilename('../test-files/elixir/umbrella_project/apps/app1/lib/app.ex')
diff --git a/test/lsp/test_engine_lsp_response_handling.vader b/test/lsp/test_engine_lsp_response_handling.vader
index 153be2b0e..226051c44 100644
--- a/test/lsp/test_engine_lsp_response_handling.vader
+++ b/test/lsp/test_engine_lsp_response_handling.vader
@@ -562,6 +562,30 @@ Execute(workspace/configuration requests should be answered with the connection
unlet! g:sent_responses
runtime autoload/ale/lsp.vim
+Execute(client/registerCapability requests should be acknowledged):
+ let g:sent_responses = []
+
+ function! ale#lsp#SendResponse(conn_id, id, result) abort
+ call add(g:sent_responses, [a:conn_id, a:id, a:result])
+ endfunction
+
+ call ale#lsp_linter#SetLSPLinterMap({'1': {'name': 'expert', 'aliases': [], 'lsp': 'stdio'}})
+ call ale#lsp_linter#HandleLSPResponse(1, {
+ \ 'jsonrpc': '2.0',
+ \ 'id': 12,
+ \ 'method': 'client/registerCapability',
+ \ 'params': {
+ \ 'registrations': [{'id': 'abc', 'method': 'textDocument/didSave'}],
+ \ },
+ \})
+
+ AssertEqual
+ \ [[1, 12, v:null]],
+ \ g:sent_responses
+
+ unlet! g:sent_responses
+ runtime autoload/ale/lsp.vim
+
Execute(LSP errors should be logged in the history):
call ale#lsp_linter#SetLSPLinterMap({'347': {'name': 'foobar', 'aliases': [], 'lsp': 'stdio'}})
call ale#lsp_linter#HandleLSPResponse(347, {