diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 27445d1f712..835bc785c4e 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -27,7 +27,7 @@ use project_model::{ }; use rustc_hash::{FxHashMap, FxHashSet}; use serde::{de::DeserializeOwned, Deserialize}; -use vfs::AbsPathBuf; +use vfs::{AbsPath, AbsPathBuf}; use crate::{ caps::completion_item_edit_resolve, @@ -535,8 +535,9 @@ impl Default for ConfigData { #[derive(Debug, Clone)] pub struct Config { - pub discovered_projects: Option>, - pub workspace_roots: Vec, + discovered_projects: Option>, + /// The workspace roots as registered by the LSP client + workspace_roots: Vec, caps: lsp_types::ClientCapabilities, root_path: AbsPathBuf, data: ConfigData, @@ -758,6 +759,16 @@ impl Config { self.discovered_projects = Some(discovered); } + pub fn remove_workspace(&mut self, path: &AbsPath) { + if let Some(position) = self.workspace_roots.iter().position(|it| it == path) { + self.workspace_roots.remove(position); + } + } + + pub fn add_workspaces(&mut self, paths: impl Iterator) { + self.workspace_roots.extend(paths); + } + pub fn update(&mut self, mut json: serde_json::Value) -> Result<(), ConfigUpdateError> { tracing::info!("updating config from JSON: {:#}", json); if json.is_null() || json.as_object().map_or(false, |it| it.is_empty()) { diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 54df01580a6..bcc3eed4ff9 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -777,14 +777,7 @@ pub(crate) fn handle_runnables( } } None => { - if !snap.config.linked_projects().is_empty() - || !snap - .config - .discovered_projects - .as_ref() - .map(|projects| projects.is_empty()) - .unwrap_or(true) - { + if !snap.config.linked_projects().is_empty() { res.push(lsp_ext::Runnable { label: "cargo check --workspace".to_string(), location: None, diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index f9930fb2599..afbc2bb6c21 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -908,8 +908,10 @@ impl GlobalState { // Re-fetch workspaces if a workspace related file has changed if let Some(abs_path) = vfs_path.as_path() { if reload::should_refresh_for_change(abs_path, ChangeKind::Modify) { - this.fetch_workspaces_queue - .request_op(format!("DidSaveTextDocument {}", abs_path.display()), ()); + this.fetch_workspaces_queue.request_op( + format!("DidSaveTextDocument {}", abs_path.display()), + (), + ); } } @@ -972,8 +974,7 @@ impl GlobalState { for workspace in params.event.removed { let Ok(path) = workspace.uri.to_file_path() else { continue }; let Ok(path) = AbsPathBuf::try_from(path) else { continue }; - let Some(position) = config.workspace_roots.iter().position(|it| it == &path) else { continue }; - config.workspace_roots.remove(position); + config.remove_workspace(&path); } let added = params @@ -982,11 +983,12 @@ impl GlobalState { .into_iter() .filter_map(|it| it.uri.to_file_path().ok()) .filter_map(|it| AbsPathBuf::try_from(it).ok()); - config.workspace_roots.extend(added); - if !config.has_linked_projects() && config.detached_files().is_empty() { - config.rediscover_workspaces(); - this.fetch_workspaces_queue.request_op("client workspaces changed".to_string(), ()) - } + config.add_workspaces(added); + if !config.has_linked_projects() && config.detached_files().is_empty() { + config.rediscover_workspaces(); + this.fetch_workspaces_queue + .request_op("client workspaces changed".to_string(), ()) + } Ok(()) })? diff --git a/crates/rust-analyzer/tests/slow-tests/support.rs b/crates/rust-analyzer/tests/slow-tests/support.rs index df62dcd7ddc..f3481914ed1 100644 --- a/crates/rust-analyzer/tests/slow-tests/support.rs +++ b/crates/rust-analyzer/tests/slow-tests/support.rs @@ -101,10 +101,6 @@ impl<'a> Project<'a> { if roots.is_empty() { roots.push(tmp_dir_path.clone()); } - let discovered_projects = roots - .into_iter() - .map(|it| ProjectManifest::discover_single(&it).unwrap()) - .collect::>(); let mut config = Config::new( tmp_dir_path, @@ -144,10 +140,10 @@ impl<'a> Project<'a> { })), ..Default::default() }, - Vec::new(), + roots, ); - config.discovered_projects = Some(discovered_projects); config.update(self.config).expect("invalid config"); + config.rediscover_workspaces(); Server::new(tmp_dir, config) }