Hi I am using GitHub - oxalica/async-lsp: Asynchronous Language Server Protocol framework to build a connection to a LSP server.
I am trying to build a function that returns the LSP client for use in my application. My problem is that the connection is dropped as soon as I call the server outside of my main function.
I have the following code in language_server_client.rs:
pub async fn get_client() -> ServerSocket {
let root_dir = Path::new(TEST_ROOT)
.canonicalize()
.expect("test root should be valid");
let (indexed_tx, _indexed_rx) = oneshot::channel();
let (mainloop, mut server) = async_lsp::MainLoop::new_client(|_server| {
let mut router = Router::new(ClientState {
indexed_tx: Some(indexed_tx),
});
router
.notification::<PublishDiagnostics>(|_, _| ControlFlow::Continue(()))
.notification::<ShowMessage>(|_, params| {
info!("Message {:?}: {}", params.typ, params.message);
ControlFlow::Continue(())
})
.unhandled_notification(|_, _| ControlFlow::Continue(()))
// .unhandled_request(|_, _| )
.unhandled_event(|_, _| ControlFlow::Continue(()))
.event(|_, _: Stop| ControlFlow::Break(Ok(())));
ServiceBuilder::new()
.layer(TracingLayer::default())
.layer(CatchUnwindLayer::default())
.layer(ConcurrencyLayer::default())
.service(router)
});
let child = async_process::Command::new(
"rust-analyzer",
)
// .args([])
.current_dir(&root_dir)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::inherit())
.kill_on_drop(true)
.spawn()
.expect("Failed run rzls");
let stdout = child.stdout.unwrap();
let stdin = child.stdin.unwrap();
let _mainloop_fut = tokio::spawn(async move { mainloop.run_buffered(stdout, stdin).await });
server
.initialize(InitializeParams {
workspace_folders: Some(vec![WorkspaceFolder {
uri: Url::from_file_path(&root_dir).unwrap(),
name: "root".into(),
}]),
capabilities: ClientCapabilities {
window: Some(WindowClientCapabilities {
work_done_progress: Some(true),
..WindowClientCapabilities::default()
}),
..ClientCapabilities::default()
},
..InitializeParams::default()
})
.await
.unwrap();
server.initialized(InitializedParams {}).unwrap();
server
}
This is how I use the server in another file:
async fn main_loop(
connection: Connection,
params: serde_json::Value,
client: &mut ServerSocket,
) -> Result<()> {
client.initialized(InitializedParams {}).unwrap();
}
pub async fn start_lsp() -> Result<()> {
let mut client = get_client().await;
main_loop(connection, initialization_params, &mut client).await?;
// ...
}
However, I keep getting a ServiceStopped Error. I guess the reason is that the child connection is dropped after get_client has been called, but I can't figure out how to solve the problem.
Ideally I would like the to have a struct that I can use for communicating with the server, something like this:
let mut client = LanguageServerClient::new().await;
client.initialize().await;
// When calling client in this function, the connection has been dropped.
some_function(client);