|
|
@ -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
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|