Correctly handle network issues during LSP server installation (#9460)
Closes https://github.com/zed-industries/zed/issues/9458 When flying in a plane being totally offline, I've discovered that my Rust projects do not have any LSP support and rust-analyzer disappeared out of `~/Library/Application Support/Zed/languages/rust-analyzer/` directory. Looking at the [bad.log](https://github.com/zed-industries/zed/files/14627508/bad.log), it appears that `get_language_server_command` tries to find a newer LSP server version and fails on80bc6c8cc8/crates/language/src/language.rs (L339)
bailing out of all installation related-methods up to here:80bc6c8cc8/crates/project/src/project.rs (L2916)
where the code thinks that the binary installation process had failed, cleans the existing directory and tries to install the language server again: ```log [2024-03-17T15:14:13+02:00 WARN isahc::handler] request completed with error: failed to resolve host name [2024-03-17T15:14:13+02:00 ERROR project] failed to start language server "rust-analyzer": error fetching latest release [2024-03-17T15:14:13+02:00 ERROR project] server stderr: Some("") [2024-03-17T15:14:13+02:00 INFO project] retrying installation of language server "rust-analyzer" in 1s [2024-03-17T15:14:13+02:00 ERROR util] crates/lsp/src/lsp.rs:720: oneshot canceled [2024-03-17T15:14:14+02:00 INFO project] About to spawn test binary [2024-03-17T15:14:14+02:00 WARN project] test binary failed to launch [2024-03-17T15:14:14+02:00 WARN project] test binary check failed [2024-03-17T15:14:14+02:00 INFO project] beginning to reinstall server [2024-03-17T15:14:14+02:00 INFO language::language_registry] deleting server container [2024-03-17T15:14:14+02:00 INFO language::language_registry] starting language server "rust-analyzer", path: "/Users/someonetoignore/work/other/local_test", id: 2 [2024-03-17T15:14:14+02:00 INFO language] fetching latest version of language server "rust-analyzer" [2024-03-17T15:14:14+02:00 WARN isahc::handler] request completed with error: failed to resolve host name [2024-03-17T15:14:14+02:00 ERROR project] failed to start language server "rust-analyzer": error fetching latest release [2024-03-17T15:14:14+02:00 ERROR project] server stderr: Some("") [2024-03-17T15:14:14+02:00 INFO project] retrying installation of language server "rust-analyzer" in 1s [2024-03-17T15:14:15+02:00 ERROR util] crates/languages/src/rust.rs:335: no cached binary [2024-03-17T15:14:15+02:00 INFO project] About to spawn test binary ............ ``` The PR extracts away all binary fetching-related code into a single method that does not fail the entire `get_language_server_command` and allows it to recover and reuse the existing binary: [good.log](https://github.com/zed-industries/zed/files/14627507/good.log) ```log [2024-03-17T15:12:24+02:00 INFO language::language_registry] starting language server "rust-analyzer", path: "/Users/someonetoignore/work/other/local_test", id: 1 [2024-03-17T15:12:24+02:00 INFO language] fetching latest version of language server "rust-analyzer" [2024-03-17T15:12:24+02:00 WARN isahc::handler] request completed with error: failed to resolve host name [2024-03-17T15:12:24+02:00 INFO language] failed to fetch newest version of language server LanguageServerName("rust-analyzer"). falling back to using "/Users/someonetoignore/Library/Application Support/Zed/languages/rust-analyzer/rust-analyzer-2024-03-11" [2024-03-17T15:12:24+02:00 INFO lsp] starting language server. binary path: "/Users/someonetoignore/Library/Application Support/Zed/languages/rust-analyzer/rust-analyzer-2024-03-11", working directory: "/Users/someonetoignore/work/other/local_test", args: [] ``` Release Notes: - Fixed language servers erased from the disk when project is opened offline
This commit is contained in:
parent
80bc6c8cc8
commit
9df92c3fb6
2 changed files with 35 additions and 26 deletions
|
@ -326,43 +326,25 @@ pub trait LspAdapter: 'static + Send + Sync {
|
|||
.context("failed to create container directory")?;
|
||||
}
|
||||
|
||||
if let Some(task) = self.will_fetch_server(&delegate, cx) {
|
||||
task.await?;
|
||||
}
|
||||
|
||||
let name = self.name();
|
||||
log::info!("fetching latest version of language server {:?}", name.0);
|
||||
delegate.update_status(
|
||||
name.clone(),
|
||||
LanguageServerBinaryStatus::CheckingForUpdate,
|
||||
);
|
||||
let latest_version = self.fetch_latest_server_version(delegate.as_ref()).await?;
|
||||
|
||||
log::info!("downloading language server {:?}", name.0);
|
||||
delegate.update_status(self.name(), LanguageServerBinaryStatus::Downloading);
|
||||
let mut binary = self
|
||||
.fetch_server_binary(latest_version, container_dir.to_path_buf(), delegate.as_ref())
|
||||
.await;
|
||||
|
||||
delegate.update_status(name.clone(), LanguageServerBinaryStatus::Downloaded);
|
||||
let mut binary = try_fetch_server_binary(self.as_ref(), &delegate, container_dir.to_path_buf(), cx).await;
|
||||
|
||||
if let Err(error) = binary.as_ref() {
|
||||
if let Some(prev_downloaded_binary) = self
|
||||
.cached_server_binary(container_dir.to_path_buf(), delegate.as_ref())
|
||||
.await
|
||||
{
|
||||
delegate.update_status(name.clone(), LanguageServerBinaryStatus::Cached);
|
||||
delegate.update_status(self.name(), LanguageServerBinaryStatus::Cached);
|
||||
log::info!(
|
||||
"failed to fetch newest version of language server {:?}. falling back to using {:?}",
|
||||
name.clone(),
|
||||
prev_downloaded_binary.path.display()
|
||||
self.name(),
|
||||
prev_downloaded_binary.path
|
||||
);
|
||||
binary = Ok(prev_downloaded_binary);
|
||||
} else {
|
||||
delegate.update_status(
|
||||
name.clone(),
|
||||
self.name(),
|
||||
LanguageServerBinaryStatus::Failed {
|
||||
error: format!("{:?}", error),
|
||||
error: format!("{error:?}"),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -500,6 +482,33 @@ pub trait LspAdapter: 'static + Send + Sync {
|
|||
}
|
||||
}
|
||||
|
||||
async fn try_fetch_server_binary<L: LspAdapter + 'static + Send + Sync + ?Sized>(
|
||||
adapter: &L,
|
||||
delegate: &Arc<dyn LspAdapterDelegate>,
|
||||
container_dir: PathBuf,
|
||||
cx: &mut AsyncAppContext,
|
||||
) -> Result<LanguageServerBinary> {
|
||||
if let Some(task) = adapter.will_fetch_server(delegate, cx) {
|
||||
task.await?;
|
||||
}
|
||||
|
||||
let name = adapter.name();
|
||||
log::info!("fetching latest version of language server {:?}", name.0);
|
||||
delegate.update_status(name.clone(), LanguageServerBinaryStatus::CheckingForUpdate);
|
||||
let latest_version = adapter
|
||||
.fetch_latest_server_version(delegate.as_ref())
|
||||
.await?;
|
||||
|
||||
log::info!("downloading language server {:?}", name.0);
|
||||
delegate.update_status(adapter.name(), LanguageServerBinaryStatus::Downloading);
|
||||
let binary = adapter
|
||||
.fetch_server_binary(latest_version, container_dir, delegate.as_ref())
|
||||
.await;
|
||||
|
||||
delegate.update_status(name.clone(), LanguageServerBinaryStatus::Downloaded);
|
||||
binary
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct CodeLabel {
|
||||
/// The text to display.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue