@@ -9,11 +9,17 @@ use lsp_types as lsp;
99use serde_json::Value;
1010use std::future::Future;
1111use std::process::Stdio;
12−use std::sync::atomic::{AtomicU64, Ordering};
12+use std::sync::{
13+ atomic::{AtomicU64, Ordering},
14+ Arc,
15+};
1316use tokio::{
1417 io::{BufReader, BufWriter},
1518 process::{Child, Command},
16− sync::mpsc::{channel, UnboundedReceiver, UnboundedSender},
19+ sync::{
20+ mpsc::{channel, UnboundedReceiver, UnboundedSender},
21+ Notify, OnceCell,
22+ },
1723};
1824
1925#[derive(Debug)]
@@ -22,18 +28,19 @@ pub struct Client {
2228 _process: Child,
2329 server_tx: UnboundedSender<Payload>,
2430 request_counter: AtomicU64,
25− capabilities: Option<lsp::ServerCapabilities>,
31+ pub(crate) capabilities: OnceCell<lsp::ServerCapabilities>,
2632 offset_encoding: OffsetEncoding,
2733 config: Option<Value>,
2834}
2935
3036impl Client {
37+ #[allow(clippy::type_complexity)]
3138 pub fn start(
3239 cmd: &str,
3340 args: &[String],
3441 config: Option<Value>,
3542 id: usize,
36− ) -> Result<(Self, UnboundedReceiver<(usize, Call)>)> {
43+ ) -> Result<(Self, UnboundedReceiver<(usize, Call)>, Arc<Notify>)> {
3744 let process = Command::new(cmd)
3845 .args(args)
3946 .stdin(Stdio::piped())
@@ -50,22 +57,20 @@ impl Client {
5057 let reader = BufReader::new(process.stdout.take().expect("Failed to open stdout"));
5158 let stderr = BufReader::new(process.stderr.take().expect("Failed to open stderr"));
5259
53− let (server_rx, server_tx) = Transport::start(reader, writer, stderr, id);
60+ let (server_rx, server_tx, initialize_notify) =
61+ Transport::start(reader, writer, stderr, id);
5462
5563 let client = Self {
5664 id,
5765 _process: process,
5866 server_tx,
5967 request_counter: AtomicU64::new(0),
60− capabilities: None,
68+ capabilities: OnceCell::new(),
6169 offset_encoding: OffsetEncoding::Utf8,
6270 config,
6371 };
6472
65− // TODO: async client.initialize()
66− // maybe use an arc<atomic> flag
67−
68− Ok((client, server_rx))
73+ Ok((client, server_rx, initialize_notify))
6974 }
7075
7176 pub fn id(&self) -> usize {
@@ -88,9 +93,13 @@ impl Client {
8893 }
8994 }
9095
96+ pub fn is_initialized(&self) -> bool {
97+ self.capabilities.get().is_some()
98+ }
99+
91100 pub fn capabilities(&self) -> &lsp::ServerCapabilities {
92101 self.capabilities
93− .as_ref()
102+ .get()
94103 .expect("language server not yet initialized!")
95104 }
96105
@@ -143,7 +152,8 @@ impl Client {
143152 })
144153 .map_err(|e| Error::Other(e.into()))?;
145154
146− timeout(Duration::from_secs(2), rx.recv())
155+ // TODO: specifiable timeout, delay other calls until initialize success
156+ timeout(Duration::from_secs(20), rx.recv())
147157 .await
148158 .map_err(|_| Error::Timeout)? // return Timeout
149159 .ok_or(Error::StreamClosed)?
@@ -151,7 +161,7 @@ impl Client {
151161 }
152162
153163 /// Send a RPC notification to the language server.
154− fn notify<R: lsp::notification::Notification>(
164+ pub fn notify<R: lsp::notification::Notification>(
155165 &self,
156166 params: R::Params,
157167 ) -> impl Future<Output = Result<()>>
@@ -213,7 +223,7 @@ impl Client {
213223 // General messages
214224 // -------------------------------------------------------------------------------------------
215225
216− pub(crate) async fn initialize(&mut self) -> Result<()> {
226+ pub(crate) async fn initialize(&self) -> Result<lsp::InitializeResult> {
217227 // TODO: delay any requests that are triggered prior to initialize
218228 let root = find_root(None).and_then(|root| lsp::Url::from_file_path(root).ok());
219229
@@ -281,14 +291,7 @@ impl Client {
281291 locale: None, // TODO
282292 };
283293
284− let response = self.request::<lsp::request::Initialize>(params).await?;
285− self.capabilities = Some(response.capabilities);
286−
287− // next up, notify<initialized>
288− self.notify::<lsp::notification::Initialized>(lsp::InitializedParams {})
289− .await?;
290−
291− Ok(())
294+ self.request::<lsp::request::Initialize>(params).await
292295 }
293296
294297 pub async fn shutdown(&self) -> Result<()> {
@@ -445,7 +448,7 @@ impl Client {
445448 ) -> Option<impl Future<Output = Result<()>>> {
446449 // figure out what kind of sync the server supports
447450
448− let capabilities = self.capabilities.as_ref().unwrap();
451+ let capabilities = self.capabilities.get().unwrap();
449452
450453 let sync_capabilities = match capabilities.text_document_sync {
451454 Some(lsp::TextDocumentSyncCapability::Kind(kind))
@@ -463,7 +466,7 @@ impl Client {
463466 // range = None -> whole document
464467 range: None, //Some(Range)
465468 range_length: None, // u64 apparently deprecated
466− text: "".to_string(),
469+ text: new_text.to_string(),
467470 }]
468471 }
469472 lsp::TextDocumentSyncKind::Incremental => {
@@ -491,12 +494,12 @@ impl Client {
491494
492495 // will_save / will_save_wait_until
493496
494− pub async fn text_document_did_save(
497+ pub fn text_document_did_save(
495498 &self,
496499 text_document: lsp::TextDocumentIdentifier,
497500 text: &Rope,
498− ) -> Result<()> {
499− let capabilities = self.capabilities.as_ref().unwrap();
501+ ) -> Option<impl Future<Output = Result<()>>> {
502+ let capabilities = self.capabilities.get().unwrap();
500503
501504 let include_text = match &capabilities.text_document_sync {
502505 Some(lsp::TextDocumentSyncCapability::Options(lsp::TextDocumentSyncOptions {
@@ -508,17 +511,18 @@ impl Client {
508511 include_text,
509512 }) => include_text.unwrap_or(false),
510513 // Supported(false)
511− _ => return Ok(()),
514+ _ => return None,
512515 },
513516 // unsupported
514− _ => return Ok(()),
517+ _ => return None,
515518 };
516519
517− self.notify::<lsp::notification::DidSaveTextDocument>(lsp::DidSaveTextDocumentParams {
518− text_document,
519− text: include_text.then(|| text.into()),
520− })
521− .await
520+ Some(self.notify::<lsp::notification::DidSaveTextDocument>(
521+ lsp::DidSaveTextDocumentParams {
522+ text_document,
523+ text: include_text.then(|| text.into()),
524+ },
525+ ))
522526 }
523527
524528 pub fn completion(
@@ -584,19 +588,19 @@ impl Client {
584588
585589 // formatting
586590
587− pub async fn text_document_formatting(
591+ pub fn text_document_formatting(
588592 &self,
589593 text_document: lsp::TextDocumentIdentifier,
590594 options: lsp::FormattingOptions,
591595 work_done_token: Option<lsp::ProgressToken>,
592− ) -> anyhow::Result<Vec<lsp::TextEdit>> {
593− let capabilities = self.capabilities.as_ref().unwrap();
596+ ) -> Option<impl Future<Output = Result<Vec<lsp::TextEdit>>>> {
597+ let capabilities = self.capabilities.get().unwrap();
594598
595599 // check if we're able to format
596600 match capabilities.document_formatting_provider {
597601 Some(lsp::OneOf::Left(true)) | Some(lsp::OneOf::Right(_)) => (),
598602 // None | Some(false)
599− _ => return Ok(Vec::new()),
603+ _ => return None,
600604 };
601605 // TODO: return err::unavailable so we can fall back to tree sitter formatting
602606
@@ -606,9 +610,13 @@ impl Client {
606610 work_done_progress_params: lsp::WorkDoneProgressParams { work_done_token },
607611 };
608612
609− let response = self.request::<lsp::request::Formatting>(params).await?;
613+ let request = self.call::<lsp::request::Formatting>(params);
610614
611− Ok(response.unwrap_or_default())
615+ Some(async move {
616+ let json = request.await?;
617+ let response: Vec<lsp::TextEdit> = serde_json::from_value(json)?;
618+ Ok(response)
619+ })
612620 }
613621
614622 pub async fn text_document_range_formatting(
@@ -618,7 +626,7 @@ impl Client {
618626 options: lsp::FormattingOptions,
619627 work_done_token: Option<lsp::ProgressToken>,
620628 ) -> anyhow::Result<Vec<lsp::TextEdit>> {
621− let capabilities = self.capabilities.as_ref().unwrap();
629+ let capabilities = self.capabilities.get().unwrap();
622630
623631 // check if we're able to format
624632 match capabilities.document_range_formatting_provider {