Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-lsp/src/transport.rs')
-rw-r--r--helix-lsp/src/transport.rs56
1 files changed, 24 insertions, 32 deletions
diff --git a/helix-lsp/src/transport.rs b/helix-lsp/src/transport.rs
index fa4966c4..bd671abe 100644
--- a/helix-lsp/src/transport.rs
+++ b/helix-lsp/src/transport.rs
@@ -1,8 +1,4 @@
-use crate::{
- jsonrpc,
- lsp::{self, notification::Notification as _},
- Error, LanguageServerId, Result,
-};
+use crate::{jsonrpc, Error, LanguageServerId, Result};
use anyhow::Context;
use log::{error, info};
use serde::{Deserialize, Serialize};
@@ -90,15 +86,14 @@ impl Transport {
async fn recv_server_message(
reader: &mut (impl AsyncBufRead + Unpin + Send),
buffer: &mut String,
- content: &mut Vec<u8>,
language_server_name: &str,
) -> Result<ServerMessage> {
let mut content_length = None;
loop {
- buffer.clear();
+ buffer.truncate(0);
if reader.read_line(buffer).await? == 0 {
return Err(Error::StreamClosed);
- }
+ };
// debug!("<- header {:?}", buffer);
@@ -127,20 +122,18 @@ impl Transport {
}
let content_length = content_length.context("missing content length")?;
- content.resize(content_length, 0);
- reader.read_exact(content).await?;
- let msg = std::str::from_utf8(content).context("invalid utf8 from server")?;
- info!("{language_server_name} <- {msg}");
+ //TODO: reuse vector
+ let mut content = vec![0; content_length];
+ reader.read_exact(&mut content).await?;
+ let msg = std::str::from_utf8(&content).context("invalid utf8 from server")?;
- // NOTE: We avoid using `?` here, since it would return early on error
- // and skip clearing `content`. By returning the result directly instead,
- // we ensure `content.clear()` is always called.
- let output = sonic_rs::from_slice(content).map_err(Into::into);
+ info!("{language_server_name} <- {msg}");
- content.clear();
+ // try parsing as output (server response) or call (server request)
+ let output: serde_json::Result<ServerMessage> = serde_json::from_str(msg);
- output
+ Ok(output?)
}
async fn recv_server_error(
@@ -226,7 +219,10 @@ impl Transport {
language_server_name: &str,
) -> Result<()> {
let (id, result) = match output {
- jsonrpc::Output::Success(jsonrpc::Success { id, result, .. }) => (id, Ok(result)),
+ jsonrpc::Output::Success(jsonrpc::Success { id, result, .. }) => {
+ info!("{language_server_name} <- {}", result);
+ (id, Ok(result))
+ }
jsonrpc::Output::Failure(jsonrpc::Failure { id, error, .. }) => {
error!("{language_server_name} <- {error}");
(id, Err(error.into()))
@@ -258,15 +254,9 @@ impl Transport {
client_tx: UnboundedSender<(LanguageServerId, jsonrpc::Call)>,
) {
let mut recv_buffer = String::new();
- let mut content_buffer = Vec::new();
loop {
- match Self::recv_server_message(
- &mut server_stdout,
- &mut recv_buffer,
- &mut content_buffer,
- &transport.name,
- )
- .await
+ match Self::recv_server_message(&mut server_stdout, &mut recv_buffer, &transport.name)
+ .await
{
Ok(msg) => {
match transport
@@ -299,10 +289,11 @@ impl Transport {
}
// Hack: inject a terminated notification so we trigger code that needs to happen after exit
+ use lsp_types::notification::Notification as _;
let notification =
ServerMessage::Call(jsonrpc::Call::Notification(jsonrpc::Notification {
jsonrpc: None,
- method: lsp::notification::Exit::METHOD.to_string(),
+ method: lsp_types::notification::Exit::METHOD.to_string(),
params: jsonrpc::Params::None,
}));
match transport
@@ -347,8 +338,8 @@ impl Transport {
// Determine if a message is allowed to be sent early
fn is_initialize(payload: &Payload) -> bool {
- use lsp::{
- notification::Initialized,
+ use lsp_types::{
+ notification::{Initialized, Notification},
request::{Initialize, Request},
};
match payload {
@@ -366,7 +357,7 @@ impl Transport {
}
fn is_shutdown(payload: &Payload) -> bool {
- use lsp::request::{Request, Shutdown};
+ use lsp_types::request::{Request, Shutdown};
matches!(payload, Payload::Request { value: jsonrpc::MethodCall { method, .. }, .. } if method == Shutdown::METHOD)
}
@@ -379,11 +370,12 @@ impl Transport {
// server successfully initialized
is_pending = false;
+ use lsp_types::notification::Notification;
// Hack: inject an initialized notification so we trigger code that needs to happen after init
let notification = ServerMessage::Call(jsonrpc::Call::Notification(jsonrpc::Notification {
jsonrpc: None,
- method: lsp::notification::Initialized::METHOD.to_string(),
+ method: lsp_types::notification::Initialized::METHOD.to_string(),
params: jsonrpc::Params::None,
}));
let language_server_name = &transport.name;