Don't panic on LSP not starting

pull/71/head
Egor Karavaev 4 years ago committed by Blaž Hrastnik
parent 08f50310bd
commit 960bc9f134

@ -153,7 +153,7 @@ impl Client {
timeout(Duration::from_secs(2), rx.recv()) timeout(Duration::from_secs(2), rx.recv())
.await .await
.map_err(|_| Error::Timeout)? // return Timeout .map_err(|_| Error::Timeout)? // return Timeout
.unwrap() // TODO: None if channel closed .ok_or(Error::StreamClosed)?
} }
} }

@ -13,7 +13,10 @@ use helix_core::syntax::LanguageConfiguration;
use thiserror::Error; use thiserror::Error;
use std::{collections::HashMap, sync::Arc}; use std::{
collections::{hash_map::Entry, HashMap},
sync::Arc,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -29,6 +32,10 @@ pub enum Error {
Parse(#[from] serde_json::Error), Parse(#[from] serde_json::Error),
#[error("request timed out")] #[error("request timed out")]
Timeout, Timeout,
#[error("server closed the stream")]
StreamClosed,
#[error("LSP not defined")]
LspNotDefined,
#[error(transparent)] #[error(transparent)]
Other(#[from] anyhow::Error), Other(#[from] anyhow::Error),
} }
@ -173,7 +180,7 @@ type LanguageId = String;
use futures_util::stream::select_all::SelectAll; use futures_util::stream::select_all::SelectAll;
pub struct Registry { pub struct Registry {
inner: HashMap<LanguageId, Option<Arc<Client>>>, inner: HashMap<LanguageId, Arc<Client>>,
pub incoming: SelectAll<UnboundedReceiverStream<Call>>, pub incoming: SelectAll<UnboundedReceiverStream<Call>>,
} }
@ -192,35 +199,29 @@ impl Registry {
} }
} }
pub fn get(&mut self, language_config: &LanguageConfiguration) -> Option<Arc<Client>> { pub fn get(&mut self, language_config: &LanguageConfiguration) -> Result<Arc<Client>> {
// TODO: propagate the error
if let Some(config) = &language_config.language_server { if let Some(config) = &language_config.language_server {
// avoid borrow issues // avoid borrow issues
let inner = &mut self.inner; let inner = &mut self.inner;
let s_incoming = &mut self.incoming; let s_incoming = &mut self.incoming;
let language_server = inner match inner.entry(language_config.scope.clone()) {
.entry(language_config.scope.clone()) // can't use entry with Borrow keys: https://github.com/rust-lang/rfcs/pull/1769 Entry::Occupied(language_server) => Ok(language_server.get().clone()),
.or_insert_with(|| { Entry::Vacant(entry) => {
// TODO: lookup defaults for id (name, args)
// initialize a new client // initialize a new client
let (mut client, incoming) = let (mut client, incoming) = Client::start(&config.command, &config.args)?;
Client::start(&config.command, &config.args).ok()?;
// TODO: run this async without blocking // 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)); s_incoming.push(UnboundedReceiverStream::new(incoming));
let client = Arc::new(client);
Some(Arc::new(client)) entry.insert(client.clone());
}) Ok(client)
.clone(); }
}
return language_server; } else {
Err(Error::LspNotDefined)
} }
None
} }
} }

@ -155,7 +155,7 @@ impl Editor {
let language_server = doc let language_server = doc
.language .language
.as_ref() .as_ref()
.and_then(|language| self.language_servers.get(language)); .and_then(|language| self.language_servers.get(language).ok());
if let Some(language_server) = language_server { if let Some(language_server) = language_server {
doc.set_language_server(Some(language_server.clone())); doc.set_language_server(Some(language_server.clone()));
@ -196,7 +196,7 @@ impl Editor {
let language_server = doc let language_server = doc
.language .language
.as_ref() .as_ref()
.and_then(|language| language_servers.get(language)); .and_then(|language| language_servers.get(language).ok());
if let Some(language_server) = language_server { if let Some(language_server) = language_server {
tokio::spawn(language_server.text_document_did_close(doc.identifier())); tokio::spawn(language_server.text_document_did_close(doc.identifier()));
} }

Loading…
Cancel
Save