diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 835bc785c4e..31651c3c269 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -535,7 +535,7 @@ fn default() -> Self { #[derive(Debug, Clone)] pub struct Config { - discovered_projects: Option>, + discovered_projects: Vec, /// The workspace roots as registered by the LSP client workspace_roots: Vec, caps: lsp_types::ClientCapabilities, @@ -743,7 +743,7 @@ pub fn new( caps, data: ConfigData::default(), detached_files: Vec::new(), - discovered_projects: None, + discovered_projects: Vec::new(), root_path, snippets: Default::default(), workspace_roots, @@ -756,7 +756,7 @@ pub fn rediscover_workspaces(&mut self) { if discovered.is_empty() { tracing::error!("failed to find any projects in {:?}", &self.workspace_roots); } - self.discovered_projects = Some(discovered); + self.discovered_projects = discovered; } pub fn remove_workspace(&mut self, path: &AbsPath) { @@ -871,25 +871,19 @@ pub fn has_linked_projects(&self) -> bool { pub fn linked_projects(&self) -> Vec { match self.data.linkedProjects.as_slice() { [] => { - match self.discovered_projects.as_ref() { - Some(discovered_projects) => { - let exclude_dirs: Vec<_> = self - .data - .files_excludeDirs - .iter() - .map(|p| self.root_path.join(p)) - .collect(); - discovered_projects - .iter() - .filter(|(ProjectManifest::ProjectJson(path) | ProjectManifest::CargoToml(path))| { + let exclude_dirs: Vec<_> = + self.data.files_excludeDirs.iter().map(|p| self.root_path.join(p)).collect(); + self.discovered_projects + .iter() + .filter( + |(ProjectManifest::ProjectJson(path) + | ProjectManifest::CargoToml(path))| { !exclude_dirs.iter().any(|p| path.starts_with(p)) - }) - .cloned() - .map(LinkedProject::from) - .collect() - } - None => Vec::new(), - } + }, + ) + .cloned() + .map(LinkedProject::from) + .collect() } linked_projects => linked_projects .iter() diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 00826754c3f..1c5de2f596a 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -212,6 +212,20 @@ pub(crate) fn fetch_workspaces(&mut self, cause: Cause) { }) .collect::>(); + let mut i = 0; + while i < workspaces.len() { + if let Ok(w) = &workspaces[i] { + if let Some(dupe) = workspaces[i + 1..] + .iter() + .filter_map(|it| it.as_ref().ok()) + .position(|ws| ws.eq_ignore_build_data(w)) + { + _ = workspaces.remove(dupe); + } + } + i += 1; + } + if !detached_files.is_empty() { workspaces.push(project_model::ProjectWorkspace::load_detached_files( detached_files, diff --git a/crates/rust-analyzer/tests/slow-tests/support.rs b/crates/rust-analyzer/tests/slow-tests/support.rs index f3481914ed1..d0eeee189c5 100644 --- a/crates/rust-analyzer/tests/slow-tests/support.rs +++ b/crates/rust-analyzer/tests/slow-tests/support.rs @@ -9,7 +9,6 @@ use crossbeam_channel::{after, select, Receiver}; use lsp_server::{Connection, Message, Notification, Request}; use lsp_types::{notification::Exit, request::Shutdown, TextDocumentIdentifier, Url}; -use project_model::ProjectManifest; use rust_analyzer::{config::Config, lsp_ext, main_loop}; use serde::Serialize; use serde_json::{json, to_string_pretty, Value};