@@ -9,7 +9,8 @@ pub use lsp::{Position, Url};
99pub use lsp_types as lsp;
1010
1111use futures_util::stream::select_all::SelectAll;
12−use helix_core::syntax::LanguageConfiguration;
12+use helix_core::syntax::{LanguageConfiguration, LanguageServerConfiguration};
13+use tokio::sync::mpsc::UnboundedReceiver;
1314
1415use std::{
1516 collections::{hash_map::Entry, HashMap},
@@ -335,6 +336,33 @@ impl Registry {
335336 .map(|(_, client)| client.as_ref())
336337 }
337338
339+ pub fn restart(
340+ &mut self,
341+ language_config: &LanguageConfiguration,
342+ ) -> Result<Option<Arc<Client>>> {
343+ let config = match &language_config.language_server {
344+ Some(config) => config,
345+ None => return Ok(None),
346+ };
347+
348+ let scope = language_config.scope.clone();
349+
350+ match self.inner.entry(scope) {
351+ Entry::Vacant(_) => Ok(None),
352+ Entry::Occupied(mut entry) => {
353+ // initialize a new client
354+ let id = self.counter.fetch_add(1, Ordering::Relaxed);
355+
356+ let NewClientResult(client, incoming) = start_client(id, language_config, config)?;
357+ self.incoming.push(UnboundedReceiverStream::new(incoming));
358+
359+ entry.insert((id, client.clone()));
360+
361+ Ok(Some(client))
362+ }
363+ }
364+ }
365+
338366 pub fn get(&mut self, language_config: &LanguageConfiguration) -> Result<Option<Arc<Client>>> {
339367 let config = match &language_config.language_server {
340368 Some(config) => config,
@@ -346,43 +374,9 @@ impl Registry {
346374 Entry::Vacant(entry) => {
347375 // initialize a new client
348376 let id = self.counter.fetch_add(1, Ordering::Relaxed);
349− let (client, incoming, initialize_notify) = Client::start(
350− &config.command,
351− &config.args,
352− language_config.config.clone(),
353− &language_config.roots,
354− id,
355− config.timeout,
356− )?;
377+
378+ let NewClientResult(client, incoming) = start_client(id, language_config, config)?;
357379 self.incoming.push(UnboundedReceiverStream::new(incoming));
358− let client = Arc::new(client);
359−
360− // Initialize the client asynchronously
361− let _client = client.clone();
362− tokio::spawn(async move {
363− use futures_util::TryFutureExt;
364− let value = _client
365− .capabilities
366− .get_or_try_init(|| {
367− _client
368− .initialize()
369− .map_ok(|response| response.capabilities)
370− })
371− .await;
372−
373− if let Err(e) = value {
374− log::error!("failed to initialize language server: {}", e);
375− return;
376− }
377−
378− // next up, notify<initialized>
379− _client
380− .notify::<lsp::notification::Initialized>(lsp::InitializedParams {})
381− .await
382− .unwrap();
383−
384− initialize_notify.notify_one();
385− });
386380
387381 entry.insert((id, client.clone()));
388382 Ok(Some(client))
@@ -473,6 +467,56 @@ impl LspProgressMap {
473467 }
474468}
475469
470+struct NewClientResult(Arc<Client>, UnboundedReceiver<(usize, Call)>);
471+
472+/// start_client takes both a LanguageConfiguration and a LanguageServerConfiguration to ensure that
473+/// it is only called when it makes sense.
474+fn start_client(
475+ id: usize,
476+ config: &LanguageConfiguration,
477+ ls_config: &LanguageServerConfiguration,
478+) -> Result<NewClientResult> {
479+ let (client, incoming, initialize_notify) = Client::start(
480+ &ls_config.command,
481+ &ls_config.args,
482+ config.config.clone(),
483+ &config.roots,
484+ id,
485+ ls_config.timeout,
486+ )?;
487+
488+ let client = Arc::new(client);
489+
490+ // Initialize the client asynchronously
491+ let _client = client.clone();
492+ tokio::spawn(async move {
493+ use futures_util::TryFutureExt;
494+ let value = _client
495+ .capabilities
496+ .get_or_try_init(|| {
497+ _client
498+ .initialize()
499+ .map_ok(|response| response.capabilities)
500+ })
501+ .await;
502+
503+ if let Err(e) = value {
504+ log::error!("failed to initialize language server: {}", e);
505+ return;
506+ }
507+
508+ // next up, notify<initialized>
509+ _client
510+ .notify::<lsp::notification::Initialized>(lsp::InitializedParams {})
511+ .await
512+ .unwrap();
513+
514+ initialize_notify.notify_one();
515+ });
516+
517+ Ok(NewClientResult(client, incoming))
518+}
519+
476520#[cfg(test)]
477521mod tests {
478522 use super::{lsp, util::*, OffsetEncoding};