diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 6a40c7974c..1d22d7773b 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -38,7 +38,7 @@ use std::{ path::{Path, PathBuf}, str, sync::{ - atomic::{AtomicUsize, Ordering::SeqCst}, + atomic::{AtomicU64, AtomicUsize, Ordering::SeqCst}, Arc, }, }; @@ -115,6 +115,7 @@ pub struct CachedLspAdapter { pub disk_based_diagnostics_progress_token: Option, pub language_ids: HashMap, pub adapter: Arc, + pub reinstall_attempt_count: AtomicU64, } impl CachedLspAdapter { @@ -133,6 +134,7 @@ impl CachedLspAdapter { disk_based_diagnostics_progress_token, language_ids, adapter, + reinstall_attempt_count: AtomicU64::new(0), }) } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 924c3d0095..3e5bcef00c 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -91,6 +91,8 @@ pub use fs::*; pub use prettier::FORMAT_SUFFIX as TEST_PRETTIER_FORMAT_SUFFIX; pub use worktree::*; +const MAX_SERVER_REINSTALL_ATTEMPT_COUNT: u64 = 4; + pub trait Item { fn entry_id(&self, cx: &AppContext) -> Option; fn project_path(&self, cx: &AppContext) -> Option; @@ -2722,6 +2724,10 @@ impl Project { language: Arc, cx: &mut ModelContext, ) { + if adapter.reinstall_attempt_count.load(SeqCst) > MAX_SERVER_REINSTALL_ATTEMPT_COUNT { + return; + } + let key = (worktree_id, adapter.name.clone()); if self.language_server_ids.contains_key(&key) { return; @@ -2772,27 +2778,35 @@ impl Project { } Err(err) => { - log::error!("failed to start language server {:?}: {}", server_name, err); + log::error!("failed to start language server {server_name:?}: {err}"); log::error!("server stderr: {:?}", stderr_capture.lock().take()); - if let Some(this) = this.upgrade(&cx) { - if let Some(container_dir) = container_dir { - let installation_test_binary = adapter - .installation_test_binary(container_dir.to_path_buf()) - .await; + let this = this.upgrade(&cx)?; + let container_dir = container_dir?; - this.update(&mut cx, |_, cx| { - Self::check_errored_server( - language, - adapter, - server_id, - installation_test_binary, - cx, - ) - }); - } + let attempt_count = adapter.reinstall_attempt_count.fetch_add(1, SeqCst); + if attempt_count >= MAX_SERVER_REINSTALL_ATTEMPT_COUNT { + let max = MAX_SERVER_REINSTALL_ATTEMPT_COUNT; + log::error!( + "Hit {max} max reinstallation attempts for {server_name:?}" + ); + return None; } + let installation_test_binary = adapter + .installation_test_binary(container_dir.to_path_buf()) + .await; + + this.update(&mut cx, |_, cx| { + Self::check_errored_server( + language, + adapter, + server_id, + installation_test_binary, + cx, + ) + }); + None } }