about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-04-18 14:27:01 +0200
committerLukas Wirth <lukastw97@gmail.com>2023-04-18 14:27:01 +0200
commit9c408970eaff9c1b993903e5dea9f2558edfc013 (patch)
tree5d79bff2c5fe5785ce5b656d3aa80ad2e1494eba
parentf5f68e4dc73ba37eaa057b6b7e476b4bc4a06121 (diff)
Deduplicate loaded projects
-rw-r--r--crates/rust-analyzer/src/config.rs36
-rw-r--r--crates/rust-analyzer/src/reload.rs14
-rw-r--r--crates/rust-analyzer/tests/slow-tests/support.rs1
3 files changed, 29 insertions, 22 deletions
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 @@ impl Default for ConfigData {
 
 #[derive(Debug, Clone)]
 pub struct Config {
-    discovered_projects: Option<Vec<ProjectManifest>>,
+    discovered_projects: Vec<ProjectManifest>,
     /// The workspace roots as registered by the LSP client
     workspace_roots: Vec<AbsPathBuf>,
     caps: lsp_types::ClientCapabilities,
@@ -743,7 +743,7 @@ impl Config {
             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 @@ impl Config {
         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 @@ impl Config {
     pub fn linked_projects(&self) -> Vec<LinkedProject> {
         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 @@ impl GlobalState {
                     })
                     .collect::<Vec<_>>();
 
+                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 std::{
 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};