aboutsummaryrefslogtreecommitdiff
path: root/helix-lsp
diff options
context:
space:
mode:
authorEgor Karavaev2021-06-07 18:50:20 +0000
committerBlaž Hrastnik2021-06-08 01:02:41 +0000
commit960bc9f13446e1fbcc36f1a3be3541ec1b9ec5bd (patch)
treef63b8e528c8bcf6c0efbd3577c14f66ec274fdd6 /helix-lsp
parent08f50310bd698aaab1c44b3c2b900648e98bfa5c (diff)
Don't panic on LSP not starting
Diffstat (limited to 'helix-lsp')
-rw-r--r--helix-lsp/src/client.rs2
-rw-r--r--helix-lsp/src/lib.rs43
2 files changed, 23 insertions, 22 deletions
diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs
index a1c1134a..41c38fd9 100644
--- a/helix-lsp/src/client.rs
+++ b/helix-lsp/src/client.rs
@@ -153,7 +153,7 @@ impl Client {
timeout(Duration::from_secs(2), rx.recv())
.await
.map_err(|_| Error::Timeout)? // return Timeout
- .unwrap() // TODO: None if channel closed
+ .ok_or(Error::StreamClosed)?
}
}
diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs
index eeb2cdbb..af8c9005 100644
--- a/helix-lsp/src/lib.rs
+++ b/helix-lsp/src/lib.rs
@@ -13,7 +13,10 @@ use helix_core::syntax::LanguageConfiguration;
use thiserror::Error;
-use std::{collections::HashMap, sync::Arc};
+use std::{
+ collections::{hash_map::Entry, HashMap},
+ sync::Arc,
+};
use serde::{Deserialize, Serialize};
@@ -29,6 +32,10 @@ pub enum Error {
Parse(#[from] serde_json::Error),
#[error("request timed out")]
Timeout,
+ #[error("server closed the stream")]
+ StreamClosed,
+ #[error("LSP not defined")]
+ LspNotDefined,
#[error(transparent)]
Other(#[from] anyhow::Error),
}
@@ -173,7 +180,7 @@ type LanguageId = String;
use futures_util::stream::select_all::SelectAll;
pub struct Registry {
- inner: HashMap<LanguageId, Option<Arc<Client>>>,
+ inner: HashMap<LanguageId, Arc<Client>>,
pub incoming: SelectAll<UnboundedReceiverStream<Call>>,
}
@@ -192,35 +199,29 @@ impl Registry {
}
}
- pub fn get(&mut self, language_config: &LanguageConfiguration) -> Option<Arc<Client>> {
- // TODO: propagate the error
+ pub fn get(&mut self, language_config: &LanguageConfiguration) -> Result<Arc<Client>> {
if let Some(config) = &language_config.language_server {
// avoid borrow issues
let inner = &mut self.inner;
let s_incoming = &mut self.incoming;
- let language_server = inner
- .entry(language_config.scope.clone()) // can't use entry with Borrow keys: https://github.com/rust-lang/rfcs/pull/1769
- .or_insert_with(|| {
- // TODO: lookup defaults for id (name, args)
-
+ match inner.entry(language_config.scope.clone()) {
+ Entry::Occupied(language_server) => Ok(language_server.get().clone()),
+ Entry::Vacant(entry) => {
// initialize a new client
- let (mut client, incoming) =
- Client::start(&config.command, &config.args).ok()?;
-
+ let (mut client, incoming) = Client::start(&config.command, &config.args)?;
// TODO: run this async without blocking
- futures_executor::block_on(client.initialize()).unwrap();
-
+ futures_executor::block_on(client.initialize())?;
s_incoming.push(UnboundedReceiverStream::new(incoming));
+ let client = Arc::new(client);
- Some(Arc::new(client))
- })
- .clone();
-
- return language_server;
+ entry.insert(client.clone());
+ Ok(client)
+ }
+ }
+ } else {
+ Err(Error::LspNotDefined)
}
-
- None
}
}