Show a notification when unable to start elixir-ls
This commit is contained in:
parent
57c2d85c66
commit
1215de0c42
3 changed files with 85 additions and 13 deletions
|
@ -130,12 +130,20 @@ impl CachedLspAdapter {
|
||||||
self.adapter.fetch_latest_server_version(delegate).await
|
self.adapter.fetch_latest_server_version(delegate).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn will_fetch_server_binary(
|
pub fn will_fetch_server(
|
||||||
&self,
|
&self,
|
||||||
delegate: &Arc<dyn LspAdapterDelegate>,
|
delegate: &Arc<dyn LspAdapterDelegate>,
|
||||||
cx: &mut AsyncAppContext,
|
cx: &mut AsyncAppContext,
|
||||||
) -> Option<Task<Result<()>>> {
|
) -> Option<Task<Result<()>>> {
|
||||||
self.adapter.will_fetch_server_binary(delegate, cx)
|
self.adapter.will_fetch_server(delegate, cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn will_start_server(
|
||||||
|
&self,
|
||||||
|
delegate: &Arc<dyn LspAdapterDelegate>,
|
||||||
|
cx: &mut AsyncAppContext,
|
||||||
|
) -> Option<Task<Result<()>>> {
|
||||||
|
self.adapter.will_start_server(delegate, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn fetch_server_binary(
|
pub async fn fetch_server_binary(
|
||||||
|
@ -212,7 +220,15 @@ pub trait LspAdapter: 'static + Send + Sync {
|
||||||
delegate: &dyn LspAdapterDelegate,
|
delegate: &dyn LspAdapterDelegate,
|
||||||
) -> Result<Box<dyn 'static + Send + Any>>;
|
) -> Result<Box<dyn 'static + Send + Any>>;
|
||||||
|
|
||||||
fn will_fetch_server_binary(
|
fn will_fetch_server(
|
||||||
|
&self,
|
||||||
|
_: &Arc<dyn LspAdapterDelegate>,
|
||||||
|
_: &mut AsyncAppContext,
|
||||||
|
) -> Option<Task<Result<()>>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn will_start_server(
|
||||||
&self,
|
&self,
|
||||||
_: &Arc<dyn LspAdapterDelegate>,
|
_: &Arc<dyn LspAdapterDelegate>,
|
||||||
_: &mut AsyncAppContext,
|
_: &mut AsyncAppContext,
|
||||||
|
@ -891,7 +907,7 @@ impl LanguageRegistry {
|
||||||
let lsp_binary_statuses = self.lsp_binary_statuses_tx.clone();
|
let lsp_binary_statuses = self.lsp_binary_statuses_tx.clone();
|
||||||
let login_shell_env_loaded = self.login_shell_env_loaded.clone();
|
let login_shell_env_loaded = self.login_shell_env_loaded.clone();
|
||||||
|
|
||||||
let task = cx.spawn(|cx| async move {
|
let task = cx.spawn(|mut cx| async move {
|
||||||
login_shell_env_loaded.await;
|
login_shell_env_loaded.await;
|
||||||
|
|
||||||
let entry = this
|
let entry = this
|
||||||
|
@ -903,7 +919,7 @@ impl LanguageRegistry {
|
||||||
get_binary(
|
get_binary(
|
||||||
adapter.clone(),
|
adapter.clone(),
|
||||||
language.clone(),
|
language.clone(),
|
||||||
delegate,
|
delegate.clone(),
|
||||||
download_dir,
|
download_dir,
|
||||||
lsp_binary_statuses,
|
lsp_binary_statuses,
|
||||||
cx,
|
cx,
|
||||||
|
@ -915,6 +931,10 @@ impl LanguageRegistry {
|
||||||
.clone();
|
.clone();
|
||||||
let binary = entry.clone().map_err(|e| anyhow!(e)).await?;
|
let binary = entry.clone().map_err(|e| anyhow!(e)).await?;
|
||||||
|
|
||||||
|
if let Some(task) = adapter.will_start_server(&delegate, &mut cx) {
|
||||||
|
task.await?;
|
||||||
|
}
|
||||||
|
|
||||||
let server = lsp::LanguageServer::new(
|
let server = lsp::LanguageServer::new(
|
||||||
server_id,
|
server_id,
|
||||||
&binary.path,
|
&binary.path,
|
||||||
|
@ -996,7 +1016,7 @@ async fn get_binary(
|
||||||
.context("failed to create container directory")?;
|
.context("failed to create container directory")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(task) = adapter.will_fetch_server_binary(&delegate, &mut cx) {
|
if let Some(task) = adapter.will_fetch_server(&delegate, &mut cx) {
|
||||||
task.await?;
|
task.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
|
use gpui::{AsyncAppContext, Task};
|
||||||
pub use language::*;
|
pub use language::*;
|
||||||
use lsp::{CompletionItemKind, SymbolKind};
|
use lsp::{CompletionItemKind, SymbolKind};
|
||||||
use smol::fs::{self, File};
|
use smol::fs::{self, File};
|
||||||
use std::{any::Any, path::PathBuf, sync::Arc};
|
use std::{
|
||||||
|
any::Any,
|
||||||
|
path::PathBuf,
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering::SeqCst},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
|
};
|
||||||
use util::{
|
use util::{
|
||||||
fs::remove_matching,
|
fs::remove_matching,
|
||||||
github::{latest_github_release, GitHubLspBinaryVersion},
|
github::{latest_github_release, GitHubLspBinaryVersion},
|
||||||
|
@ -19,6 +27,37 @@ impl LspAdapter for ElixirLspAdapter {
|
||||||
LanguageServerName("elixir-ls".into())
|
LanguageServerName("elixir-ls".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn will_start_server(
|
||||||
|
&self,
|
||||||
|
delegate: &Arc<dyn LspAdapterDelegate>,
|
||||||
|
cx: &mut AsyncAppContext,
|
||||||
|
) -> Option<Task<Result<()>>> {
|
||||||
|
static DID_SHOW_NOTIFICATION: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
|
const NOTIFICATION_MESSAGE: &str = "Could not run the elixir language server, `elixir-ls`, because `elixir` was not found.";
|
||||||
|
|
||||||
|
let delegate = delegate.clone();
|
||||||
|
Some(cx.spawn(|mut cx| async move {
|
||||||
|
let elixir_output = smol::process::Command::new("elixir")
|
||||||
|
.args(["--version"])
|
||||||
|
.output()
|
||||||
|
.await;
|
||||||
|
if elixir_output.is_err() {
|
||||||
|
if DID_SHOW_NOTIFICATION
|
||||||
|
.compare_exchange(false, true, SeqCst, SeqCst)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
cx.update(|cx| {
|
||||||
|
delegate.show_notification(NOTIFICATION_MESSAGE, cx);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return Err(anyhow!("cannot run elixir-ls"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
async fn fetch_latest_server_version(
|
async fn fetch_latest_server_version(
|
||||||
&self,
|
&self,
|
||||||
delegate: &dyn LspAdapterDelegate,
|
delegate: &dyn LspAdapterDelegate,
|
||||||
|
|
|
@ -12,7 +12,10 @@ use std::{
|
||||||
ops::Range,
|
ops::Range,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
str,
|
str,
|
||||||
sync::Arc,
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering::SeqCst},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use util::{fs::remove_matching, github::latest_github_release, ResultExt};
|
use util::{fs::remove_matching, github::latest_github_release, ResultExt};
|
||||||
|
|
||||||
|
@ -48,19 +51,29 @@ impl super::LspAdapter for GoLspAdapter {
|
||||||
Ok(Box::new(version) as Box<_>)
|
Ok(Box::new(version) as Box<_>)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn will_fetch_server_binary(
|
fn will_fetch_server(
|
||||||
&self,
|
&self,
|
||||||
delegate: &Arc<dyn LspAdapterDelegate>,
|
delegate: &Arc<dyn LspAdapterDelegate>,
|
||||||
cx: &mut AsyncAppContext,
|
cx: &mut AsyncAppContext,
|
||||||
) -> Option<Task<Result<()>>> {
|
) -> Option<Task<Result<()>>> {
|
||||||
|
static DID_SHOW_NOTIFICATION: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
|
const NOTIFICATION_MESSAGE: &str =
|
||||||
|
"Could not install the Go language server `gopls`, because `go` was not found.";
|
||||||
|
|
||||||
let delegate = delegate.clone();
|
let delegate = delegate.clone();
|
||||||
Some(cx.spawn(|mut cx| async move {
|
Some(cx.spawn(|mut cx| async move {
|
||||||
let install_output = process::Command::new("go").args(["version"]).output().await;
|
let install_output = process::Command::new("go").args(["version"]).output().await;
|
||||||
if install_output.is_err() {
|
if install_output.is_err() {
|
||||||
cx.update(|cx| {
|
if DID_SHOW_NOTIFICATION
|
||||||
delegate
|
.compare_exchange(false, true, SeqCst, SeqCst)
|
||||||
.show_notification("go is not installed. gopls will not be available.", cx);
|
.is_ok()
|
||||||
})
|
{
|
||||||
|
cx.update(|cx| {
|
||||||
|
delegate.show_notification(NOTIFICATION_MESSAGE, cx);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return Err(anyhow!("cannot install gopls"));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}))
|
}))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue