aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Davis2023-06-29 15:25:23 +0000
committerGitHub2023-06-29 15:25:23 +0000
commite0bb032f0e6dcc9b84e571c345928fba4054855e (patch)
tree06be3467b5ea95ad24aecb1d247b2550db928d72
parentb745fb255195b874b61b5bd92244c8a7b0bb7d46 (diff)
LSP: Forcefully shutdown uninitialized servers (#7449)
The LSP spec has this to say about initialize: > Until the server has responded to the `initialize` request with an > `InitializeResult`, the client must not send any additional requests > or notifications to the server. (https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize) The spec is not really explicit about how to handle this scenario. Before a client sends the 'initialize' request we are allowed to send an 'exit' notification, but after 'initialize' we can't send any requests (like shutdown) or notifications (like exit). So my intepretation is that we should forcefully close the server in this state. This matches the behavior of Neovim's built-in LSP client: https://github.com/neovim/neovim/blob/5ceb2238d3685255cd517ca87fd7edae9ed88811/runtime/lua/vim/lsp.lua#L1610-L1628
-rw-r--r--helix-lsp/src/transport.rs10
1 files changed, 9 insertions, 1 deletions
diff --git a/helix-lsp/src/transport.rs b/helix-lsp/src/transport.rs
index 8c38c177..9fdd30aa 100644
--- a/helix-lsp/src/transport.rs
+++ b/helix-lsp/src/transport.rs
@@ -353,6 +353,11 @@ impl Transport {
}
}
+ fn is_shutdown(payload: &Payload) -> bool {
+ use lsp_types::request::{Request, Shutdown};
+ matches!(payload, Payload::Request { value: jsonrpc::MethodCall { method, .. }, .. } if method == Shutdown::METHOD)
+ }
+
// TODO: events that use capabilities need to do the right thing
loop {
@@ -391,7 +396,10 @@ impl Transport {
}
msg = client_rx.recv() => {
if let Some(msg) = msg {
- if is_pending && !is_initialize(&msg) {
+ if is_pending && is_shutdown(&msg) {
+ log::info!("Language server not initialized, shutting down");
+ break;
+ } else if is_pending && !is_initialize(&msg) {
// ignore notifications
if let Payload::Notification(_) = msg {
continue;