Merge branch 'main' into fix-broken-lsp-installations

This commit is contained in:
Julia 2023-06-20 17:04:58 -04:00
commit f91e95f24a
54 changed files with 1827 additions and 595 deletions

View file

@ -17,7 +17,7 @@ use futures::{
future::{BoxFuture, Shared},
FutureExt, TryFutureExt as _,
};
use gpui::{executor::Background, AppContext, Task};
use gpui::{executor::Background, AppContext, AsyncAppContext, Task};
use highlight_map::HighlightMap;
use lazy_static::lazy_static;
use lsp::{CodeActionKind, LanguageServerBinaries, LanguageServerBinary};
@ -118,27 +118,46 @@ impl CachedLspAdapter {
pub async fn fetch_latest_server_version(
&self,
http: Arc<dyn HttpClient>,
delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
self.adapter.fetch_latest_server_version(http).await
self.adapter.fetch_latest_server_version(delegate).await
}
pub fn will_fetch_server(
&self,
delegate: &Arc<dyn LspAdapterDelegate>,
cx: &mut AsyncAppContext,
) -> Option<Task<Result<()>>> {
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(
&self,
version: Box<dyn 'static + Send + Any>,
http: Arc<dyn HttpClient>,
container_dir: PathBuf,
delegate: &dyn LspAdapterDelegate,
) -> Result<LanguageServerBinary> {
self.adapter
.fetch_server_binary(version, http, container_dir)
.fetch_server_binary(version, container_dir, delegate)
.await
}
pub async fn cached_server_binary(
&self,
container_dir: PathBuf,
delegate: &dyn LspAdapterDelegate,
) -> Option<LanguageServerBinary> {
self.adapter.cached_server_binary(container_dir).await
self.adapter
.cached_server_binary(container_dir, delegate)
.await
}
pub async fn installation_test_binary(
@ -187,23 +206,48 @@ impl CachedLspAdapter {
}
}
pub trait LspAdapterDelegate: Send + Sync {
fn show_notification(&self, message: &str, cx: &mut AppContext);
fn http_client(&self) -> Arc<dyn HttpClient>;
}
#[async_trait]
pub trait LspAdapter: 'static + Send + Sync {
async fn name(&self) -> LanguageServerName;
async fn fetch_latest_server_version(
&self,
http: Arc<dyn HttpClient>,
delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>>;
fn will_fetch_server(
&self,
_: &Arc<dyn LspAdapterDelegate>,
_: &mut AsyncAppContext,
) -> Option<Task<Result<()>>> {
None
}
fn will_start_server(
&self,
_: &Arc<dyn LspAdapterDelegate>,
_: &mut AsyncAppContext,
) -> Option<Task<Result<()>>> {
None
}
async fn fetch_server_binary(
&self,
version: Box<dyn 'static + Send + Any>,
http: Arc<dyn HttpClient>,
container_dir: PathBuf,
delegate: &dyn LspAdapterDelegate,
) -> Result<LanguageServerBinary>;
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary>;
async fn cached_server_binary(
&self,
container_dir: PathBuf,
delegate: &dyn LspAdapterDelegate,
) -> Option<LanguageServerBinary>;
async fn installation_test_binary(
&self,
@ -523,7 +567,7 @@ pub struct LanguageRegistry {
lsp_binary_paths: Mutex<
HashMap<
LanguageServerName,
Shared<BoxFuture<'static, Result<LanguageServerBinaries, Arc<anyhow::Error>>>>,
Shared<Task<Result<LanguageServerBinaries, Arc<anyhow::Error>>>>,
>,
>,
executor: Option<Arc<Background>>,
@ -821,7 +865,7 @@ impl LanguageRegistry {
language: Arc<Language>,
adapter: Arc<CachedLspAdapter>,
root_path: Arc<Path>,
http_client: Arc<dyn HttpClient>,
delegate: Arc<dyn LspAdapterDelegate>,
cx: &mut AppContext,
) -> Option<PendingLanguageServer> {
let server_id = self.state.write().next_language_server_id();
@ -873,7 +917,6 @@ impl LanguageRegistry {
.log_err()?;
let this = self.clone();
let language = language.clone();
let http_client = http_client.clone();
let container_dir: Arc<Path> = Arc::from(download_dir.join(adapter.name.0.as_ref()));
let root_path = root_path.clone();
let adapter = adapter.clone();
@ -882,28 +925,35 @@ impl LanguageRegistry {
let task = {
let container_dir = container_dir.clone();
cx.spawn(|cx| async move {
cx.spawn(|mut cx| async move {
login_shell_env_loaded.await;
let mut lock = this.lsp_binary_paths.lock();
let entry = lock
.entry(adapter.name.clone())
.or_insert_with(|| {
get_binaries(
adapter.clone(),
language.clone(),
http_client,
container_dir,
lsp_binary_statuses,
)
.map_err(Arc::new)
.boxed()
cx.spawn(|cx| {
get_binaries(
adapter.clone(),
language.clone(),
delegate.clone(),
container_dir,
lsp_binary_statuses,
cx,
)
.map_err(Arc::new)
})
.shared()
})
.clone();
drop(lock);
let binaries = entry.clone().map_err(|e| anyhow!(e)).await?;
if let Some(task) = adapter.will_start_server(&delegate, &mut cx) {
task.await?;
}
println!("starting server");
let server = lsp::LanguageServer::new(
server_id,
@ -1001,9 +1051,10 @@ impl Default for LanguageRegistry {
async fn get_binaries(
adapter: Arc<CachedLspAdapter>,
language: Arc<Language>,
http_client: Arc<dyn HttpClient>,
delegate: Arc<dyn LspAdapterDelegate>,
container_dir: Arc<Path>,
statuses: async_broadcast::Sender<(Arc<Language>, LanguageServerBinaryStatus)>,
mut cx: AsyncAppContext,
) -> Result<LanguageServerBinaries> {
if !container_dir.exists() {
smol::fs::create_dir_all(&container_dir)
@ -1011,11 +1062,15 @@ async fn get_binaries(
.context("failed to create container directory")?;
}
if let Some(task) = adapter.will_fetch_server(&delegate, &mut cx) {
task.await?;
}
println!("fetching binary");
let binary = fetch_latest_binary(
adapter.clone(),
language.clone(),
http_client,
delegate.as_ref(),
&container_dir,
statuses.clone(),
)
@ -1023,7 +1078,7 @@ async fn get_binaries(
if let Err(error) = binary.as_ref() {
if let Some(binary) = adapter
.cached_server_binary(container_dir.to_path_buf())
.cached_server_binary(container_dir.to_path_buf(), delegate.as_ref())
.await
{
statuses
@ -1054,7 +1109,7 @@ async fn get_binaries(
async fn fetch_latest_binary(
adapter: Arc<CachedLspAdapter>,
language: Arc<Language>,
http_client: Arc<dyn HttpClient>,
delegate: &dyn LspAdapterDelegate,
container_dir: &Path,
lsp_binary_statuses_tx: async_broadcast::Sender<(Arc<Language>, LanguageServerBinaryStatus)>,
) -> Result<LanguageServerBinaries> {
@ -1066,15 +1121,13 @@ async fn fetch_latest_binary(
))
.await?;
let version_info = adapter
.fetch_latest_server_version(http_client.clone())
.await?;
let version_info = adapter.fetch_latest_server_version(delegate).await?;
lsp_binary_statuses_tx
.broadcast((language.clone(), LanguageServerBinaryStatus::Downloading))
.await?;
let binary = adapter
.fetch_server_binary(version_info, http_client, container_dir.to_path_buf())
.fetch_server_binary(version_info, container_dir.to_path_buf(), delegate)
.await?;
let installation_test_binary = adapter
.installation_test_binary(container_dir.to_path_buf())
@ -1605,7 +1658,7 @@ impl LspAdapter for Arc<FakeLspAdapter> {
async fn fetch_latest_server_version(
&self,
_: Arc<dyn HttpClient>,
_: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
unreachable!();
}
@ -1613,13 +1666,17 @@ impl LspAdapter for Arc<FakeLspAdapter> {
async fn fetch_server_binary(
&self,
_: Box<dyn 'static + Send + Any>,
_: Arc<dyn HttpClient>,
_: PathBuf,
_: &dyn LspAdapterDelegate,
) -> Result<LanguageServerBinary> {
unreachable!();
}
async fn cached_server_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {
async fn cached_server_binary(
&self,
_: PathBuf,
_: &dyn LspAdapterDelegate,
) -> Option<LanguageServerBinary> {
unreachable!();
}