@@ -1,7 +1,7 @@
1use crate::{Error, Result};
1use crate::{Error, Result};
2use anyhow::Context;
2use anyhow::Context;
3use jsonrpc_core as jsonrpc;
3use jsonrpc_core as jsonrpc;
4−use log::{debug, error, info, warn};
4+use log::{error, info};
5use serde::{Deserialize, Serialize};
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
6use serde_json::Value;
7use std::collections::HashMap;
7use std::collections::HashMap;
@@ -11,7 +11,7 @@ use tokio::{
11 process::{ChildStderr, ChildStdin, ChildStdout},
11 process::{ChildStderr, ChildStdin, ChildStdout},
13 mpsc::{unbounded_channel, Sender, UnboundedReceiver, UnboundedSender},
13 mpsc::{unbounded_channel, Sender, UnboundedReceiver, UnboundedSender},
14− Mutex,
14+ Mutex, Notify,
@@ -51,9 +51,11 @@ impl Transport {
52 UnboundedReceiver<(usize, jsonrpc::Call)>,
52 UnboundedReceiver<(usize, jsonrpc::Call)>,
53 UnboundedSender<Payload>,
53 UnboundedSender<Payload>,
55 let (client_tx, rx) = unbounded_channel();
56 let (client_tx, rx) = unbounded_channel();
56 let (tx, client_rx) = unbounded_channel();
57 let (tx, client_rx) = unbounded_channel();
58+ let notify = Arc::new(Notify::new());
58 let transport = Self {
60 let transport = Self {
@@ -64,9 +66,14 @@ impl Transport {
65 tokio::spawn(Self::recv(transport.clone(), server_stdout, client_tx));
67 tokio::spawn(Self::recv(transport.clone(), server_stdout, client_tx));
66 tokio::spawn(Self::err(transport.clone(), server_stderr));
68 tokio::spawn(Self::err(transport.clone(), server_stderr));
67− tokio::spawn(Self::send(transport, server_stdin, client_rx));
69+ tokio::spawn(Self::send(
69− (rx, tx)
76+ (rx, tx, notify)
72 async fn recv_server_message(
79 async fn recv_server_message(
@@ -82,7 +89,8 @@ impl Transport {
83 // debug!("<- header {:?}", buffer);
90 // debug!("<- header {:?}", buffer);
85− if header.is_empty() {
92+ if buffer == "\r\n" {
93+ // look for an empty CRLF line
@@ -99,7 +107,8 @@ impl Transport {
99 // Workaround: Some non-conformant language servers will output logging and other garbage
107 // Workaround: Some non-conformant language servers will output logging and other garbage
100 // into the same stream as JSON-RPC messages. This can also happen from shell scripts that spawn
108 // into the same stream as JSON-RPC messages. This can also happen from shell scripts that spawn
101 // the server. Skip such lines and log a warning.
109 // the server. Skip such lines and log a warning.
102− warn!("Failed to parse header: {:?}", header);
111+ // warn!("Failed to parse header: {:?}", header);
@@ -261,15 +270,67 @@ impl Transport {
261 transport: Arc<Self>,
270 transport: Arc<Self>,
262 mut server_stdin: BufWriter<ChildStdin>,
271 mut server_stdin: BufWriter<ChildStdin>,
263 mut client_rx: UnboundedReceiver<Payload>,
272 mut client_rx: UnboundedReceiver<Payload>,
273+ initialize_notify: Arc<Notify>,
275+ let mut pending_messages: Vec<Payload> = Vec::new();
276+ let mut is_pending = true;
278+ // Determine if a message is allowed to be sent early
279+ fn is_initialize(payload: &Payload) -> bool {
281+ notification::{Initialized, Notification},
282+ request::{Initialize, Request},
286+ value: jsonrpc::MethodCall { method, .. },
288+ } if method == Initialize::METHOD => true,
289+ Payload::Notification(jsonrpc::Notification { method, .. })
290+ if method == Initialized::METHOD =>
298+ // TODO: events that use capabilities need to do the right thing
303+ _ = initialize_notify.notified() => { // TODO: notified is technically not cancellation safe
304+ // server successfully initialized
306+ // drain the pending queue and send payloads to server
307+ for msg in pending_messages.drain(..) {
308+ log::info!("Draining pending message {:?}", msg);
309+ match transport.send_payload_to_server(&mut server_stdin, msg).await {
312+ error!("err: <- {:?}", err);
265− while let Some(msg) = client_rx.recv().await {
317+ msg = client_rx.recv() => {
266− match transport
318+ if let Some(msg) = msg {
319+ if is_pending && !is_initialize(&msg) {
320+ log::info!("Language server not initialized, delaying request");
321+ pending_messages.push(msg);
267− .send_payload_to_server(&mut server_stdin, msg)
323+ match transport.send_payload_to_server(&mut server_stdin, msg).await {
270− Ok(_) => {}
324+ Ok(_) => {}
271− Err(err) => {
325+ Err(err) => {
272− error!("err: <- {:?}", err);
326+ error!("err: <- {:?}", err);