about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAli Bektas <bektasali@protonmail.com>2023-10-15 17:32:12 +0200
committerAli Bektas <bektasali@protonmail.com>2023-11-23 02:15:47 +0100
commit7e4aad5ba570745ef8924f1fa6ad90aedf6aa51e (patch)
treee96101ae314dd168367bb80d8f12a9e6e3710e7c
parent886eaa0a7d2b1d7098fd49ec56e3b6f65a457449 (diff)
downloadrust-7e4aad5ba570745ef8924f1fa6ad90aedf6aa51e.tar.gz
rust-7e4aad5ba570745ef8924f1fa6ad90aedf6aa51e.zip
v2
-rw-r--r--crates/base-db/src/input.rs52
-rw-r--r--crates/cfg/src/lib.rs4
-rw-r--r--crates/project-model/src/tests.rs50
-rw-r--r--crates/project-model/test_data/deduplication_crate_graph_A.json66
-rw-r--r--crates/project-model/test_data/deduplication_crate_graph_B.json140
-rw-r--r--crates/rust-analyzer/tests/slow-tests/main.rs208
6 files changed, 282 insertions, 238 deletions
diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs
index fb69e667ad9..61a17da9aa6 100644
--- a/crates/base-db/src/input.rs
+++ b/crates/base-db/src/input.rs
@@ -329,12 +329,10 @@ pub struct CrateData {
 }
 
 impl CrateData {
-    /**
-    Check if [`other`] is almost equal to [`self`].
-    This method has some obscure bits. These are mostly there to be compliant with
-    some patches. References to the patches are given.
-    */
-    pub fn almost_eq(&self, other: &CrateData) -> bool {
+    /// Check if [`other`] is almost equal to [`self`] ignoring `CrateOrigin` value.
+    pub fn eq_ignoring_origin(&self, other: &CrateData) -> bool {
+        // This method has some obscure bits. These are mostly there to be compliant with
+        // some patches. References to the patches are given.
         if self.root_file_id != other.root_file_id {
             return false;
         }
@@ -356,16 +354,16 @@ impl CrateData {
         }
 
         let mut opts = self.cfg_options.clone();
-        opts.apply_diff(CfgDiff {
-            disable: other.cfg_options.clone().into_iter().collect(),
-            enable: vec![],
-        });
+        opts.apply_diff(
+            CfgDiff::new(vec![], other.cfg_options.clone().into_iter().collect())
+                .expect("CfgOptions were expected to contain no duplicates."),
+        );
 
         let mut cfgs = opts.into_iter();
         if let Some(cfg) = cfgs.next() {
             // Don't care if rust_analyzer CfgAtom is the only cfg in the difference set of self's and other's cfgs.
             // https://github.com/rust-lang/rust-analyzer/blob/0840038f02daec6ba3238f05d8caa037d28701a0/crates/project-model/src/workspace.rs#L894
-            if !cfgs.next().is_none() || cfg.to_string() != "rust_analyzer" {
+            if cfgs.next().is_some() || cfg.to_string() != "rust_analyzer" {
                 return false;
             }
         }
@@ -686,41 +684,35 @@ impl CrateGraph {
     /// Note that for deduplication to fully work, `self`'s crate dependencies must be sorted by crate id.
     /// If the crate dependencies were sorted, the resulting graph from this `extend` call will also have the crate dependencies sorted.
     pub fn extend(&mut self, mut other: CrateGraph, proc_macros: &mut ProcMacroPaths) {
-        enum ExtendStrategy {
-            Dedup(CrateId),
-            Replace(CrateId),
-        }
-
         let topo = other.crates_in_topological_order();
         let mut id_map: FxHashMap<CrateId, CrateId> = FxHashMap::default();
         for topo in topo {
             let crate_data = &mut other.arena[topo];
 
-            crate_data.dependencies.iter_mut().for_each(|dep| {
-                dep.crate_id = id_map[&dep.crate_id];
-            });
+            crate_data.dependencies.iter_mut().for_each(|dep| dep.crate_id = id_map[&dep.crate_id]);
             crate_data.dependencies.sort_by_key(|dep| dep.crate_id);
             let res = self.arena.iter().find_map(|(id, data)| {
-                if data.almost_eq(crate_data) {
+                if data.eq_ignoring_origin(crate_data) {
                     if data.origin.is_lib() && crate_data.origin.is_local() {
                         // See #15656 for a relevant example.
-                        return Some(ExtendStrategy::Replace(id));
+                        return Some((id, true));
                     }
 
-                    return Some(ExtendStrategy::Dedup(id));
+                    return Some((id, false));
                 }
                 None
             });
 
-            if let Some(res) = res {
-                match res {
-                    ExtendStrategy::Dedup(res) => id_map.insert(topo, res),
-                    ExtendStrategy::Replace(res) => {
-                        let id = self.arena.alloc(crate_data.clone());
-                        let _ = self.remove_and_replace(res, id);
-                        id_map.insert(topo, id)
+            if let Some((res, should_update_lib_to_local)) = res {
+                id_map.insert(topo, res);
+                if should_update_lib_to_local {
+                    let origin_old = self.arena[res].origin.clone();
+                    assert!(origin_old.is_lib());
+
+                    if let CrateOrigin::Library { repo, name } = origin_old {
+                        self.arena[res].origin = CrateOrigin::Local { repo, name: Some(name) };
                     }
-                };
+                }
             } else {
                 let id = self.arena.alloc(crate_data.clone());
                 id_map.insert(topo, id);
diff --git a/crates/cfg/src/lib.rs b/crates/cfg/src/lib.rs
index 90dba008ad7..0aeb0b05052 100644
--- a/crates/cfg/src/lib.rs
+++ b/crates/cfg/src/lib.rs
@@ -115,8 +115,8 @@ impl<'a> IntoIterator for &'a CfgOptions {
 #[derive(Default, Clone, Debug, PartialEq, Eq)]
 pub struct CfgDiff {
     // Invariants: No duplicates, no atom that's both in `enable` and `disable`.
-    pub enable: Vec<CfgAtom>,
-    pub disable: Vec<CfgAtom>,
+    enable: Vec<CfgAtom>,
+    disable: Vec<CfgAtom>,
 }
 
 impl CfgDiff {
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index 7815b9dda77..65c6f0b2562 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -249,3 +249,53 @@ fn crate_graph_dedup() {
     crate_graph.extend(regex_crate_graph, &mut regex_proc_macros);
     assert_eq!(crate_graph.iter().count(), 118);
 }
+
+#[test]
+fn test_deduplicate_crate_differing_in_origin() {
+    let path_map = &mut Default::default();
+    let (mut crate_graph, _proc_macros) =
+        load_cargo_with_sysroot(path_map, "deduplication_crate_graph_A.json");
+    crate_graph.sort_deps();
+    let (crate_graph_1, mut _proc_macros_2) =
+        load_cargo_with_sysroot(path_map, "deduplication_crate_graph_B.json");
+
+    crate_graph.extend(crate_graph_1, &mut _proc_macros_2);
+
+    let mut crates_named_p1 = vec![];
+    for id in crate_graph.iter() {
+        let krate = &crate_graph[id];
+        if let Some(name) = krate.display_name.as_ref() {
+            if name.to_string() == "p1" {
+                crates_named_p1.push(krate);
+            }
+        }
+    }
+
+    assert!(crates_named_p1.len() == 1);
+    assert!(crates_named_p1[0].origin.is_local());
+}
+
+#[test]
+fn test_deduplicate_crate_differing_in_origin_in_rev_resolution_order() {
+    let path_map = &mut Default::default();
+    let (mut crate_graph, _proc_macros) =
+        load_cargo_with_sysroot(path_map, "deduplication_crate_graph_B.json");
+    crate_graph.sort_deps();
+    let (crate_graph_1, mut _proc_macros_2) =
+        load_cargo_with_sysroot(path_map, "deduplication_crate_graph_A.json");
+
+    crate_graph.extend(crate_graph_1, &mut _proc_macros_2);
+
+    let mut crates_named_p1 = vec![];
+    for id in crate_graph.iter() {
+        let krate = &crate_graph[id];
+        if let Some(name) = krate.display_name.as_ref() {
+            if name.to_string() == "p1" {
+                crates_named_p1.push(krate);
+            }
+        }
+    }
+
+    assert!(crates_named_p1.len() == 1);
+    assert!(crates_named_p1[0].origin.is_local());
+}
diff --git a/crates/project-model/test_data/deduplication_crate_graph_A.json b/crates/project-model/test_data/deduplication_crate_graph_A.json
new file mode 100644
index 00000000000..3f627082f9f
--- /dev/null
+++ b/crates/project-model/test_data/deduplication_crate_graph_A.json
@@ -0,0 +1,66 @@
+{
+  "packages": [
+    {
+      "name": "p1",
+      "version": "0.1.0",
+      "id": "p1 0.1.0 (path+file:///path/to/project/projects/p1)",
+      "license": null,
+      "license_file": null,
+      "description": null,
+      "source": null,
+      "dependencies": [],
+      "targets": [
+        {
+          "kind": [
+            "lib"
+          ],
+          "crate_types": [
+            "lib"
+          ],
+          "name": "p1",
+          "src_path": "/path/to/project/projects/p1/src/lib.rs",
+          "edition": "2021",
+          "doc": true,
+          "doctest": true,
+          "test": true
+        }
+      ],
+      "features": {},
+      "manifest_path": "/path/to/project/projects/p1/Cargo.toml",
+      "metadata": null,
+      "publish": null,
+      "authors": [],
+      "categories": [],
+      "keywords": [],
+      "readme": null,
+      "repository": null,
+      "homepage": null,
+      "documentation": null,
+      "edition": "2021",
+      "links": null,
+      "default_run": null,
+      "rust_version": null
+    }
+  ],
+  "workspace_members": [
+    "p1 0.1.0 (path+file:///path/to/project/projects/p1)"
+  ],
+  "workspace_default_members": [
+    "p1 0.1.0 (path+file:///path/to/project/projects/p1)"
+  ],
+  "resolve": {
+    "nodes": [
+      {
+        "id": "p1 0.1.0 (path+file:///path/to/project/projects/p1)",
+        "dependencies": [],
+        "deps": [],
+        "features": []
+      }
+    ],
+    "root": "p1 0.1.0 (path+file:///path/to/project/projects/p1)"
+  },
+  "target_directory": "/path/to/project/projects/p1/target",
+  "version": 1,
+  "workspace_root": "/path/to/project/projects/p1",
+  "metadata": null
+}
\ No newline at end of file
diff --git a/crates/project-model/test_data/deduplication_crate_graph_B.json b/crates/project-model/test_data/deduplication_crate_graph_B.json
new file mode 100644
index 00000000000..a2bf1af0440
--- /dev/null
+++ b/crates/project-model/test_data/deduplication_crate_graph_B.json
@@ -0,0 +1,140 @@
+{
+  "packages": [
+    {
+      "name": "p1",
+      "version": "0.1.0",
+      "id": "p1 0.1.0 (path+file:///path/to/project/projects/p1)",
+      "license": null,
+      "license_file": null,
+      "description": null,
+      "source": null,
+      "dependencies": [],
+      "targets": [
+        {
+          "kind": [
+            "lib"
+          ],
+          "crate_types": [
+            "lib"
+          ],
+          "name": "p1",
+          "src_path": "/path/to/project/projects/p1/src/lib.rs",
+          "edition": "2021",
+          "doc": true,
+          "doctest": true,
+          "test": true
+        }
+      ],
+      "features": {},
+      "manifest_path": "/path/to/project/projects/p1/Cargo.toml",
+      "metadata": null,
+      "publish": null,
+      "authors": [],
+      "categories": [],
+      "keywords": [],
+      "readme": null,
+      "repository": null,
+      "homepage": null,
+      "documentation": null,
+      "edition": "2021",
+      "links": null,
+      "default_run": null,
+      "rust_version": null
+    },
+    {
+      "name": "p2",
+      "version": "0.1.0",
+      "id": "p2 0.1.0 (path+file:///path/to/project/projects/p2)",
+      "license": null,
+      "license_file": null,
+      "description": null,
+      "source": null,
+      "dependencies": [
+        {
+          "name": "p1",
+          "source": null,
+          "req": "*",
+          "kind": null,
+          "rename": null,
+          "optional": false,
+          "uses_default_features": true,
+          "features": [],
+          "target": null,
+          "registry": null,
+          "path": "/path/to/project/projects/p1"
+        }
+      ],
+      "targets": [
+        {
+          "kind": [
+            "lib"
+          ],
+          "crate_types": [
+            "lib"
+          ],
+          "name": "p2",
+          "src_path": "/path/to/project/projects/p2/src/lib.rs",
+          "edition": "2021",
+          "doc": true,
+          "doctest": true,
+          "test": true
+        }
+      ],
+      "features": {},
+      "manifest_path": "/path/to/project/projects/p2/Cargo.toml",
+      "metadata": null,
+      "publish": null,
+      "authors": [],
+      "categories": [],
+      "keywords": [],
+      "readme": null,
+      "repository": null,
+      "homepage": null,
+      "documentation": null,
+      "edition": "2021",
+      "links": null,
+      "default_run": null,
+      "rust_version": null
+    }
+  ],
+  "workspace_members": [
+    "p2 0.1.0 (path+file:///path/to/project/projects/p2)"
+  ],
+  "workspace_default_members": [
+    "p2 0.1.0 (path+file:///path/to/project/projects/p2)"
+  ],
+  "resolve": {
+    "nodes": [
+      {
+        "id": "p1 0.1.0 (path+file:///path/to/project/projects/p1)",
+        "dependencies": [],
+        "deps": [],
+        "features": []
+      },
+      {
+        "id": "p2 0.1.0 (path+file:///path/to/project/projects/p2)",
+        "dependencies": [
+          "p1 0.1.0 (path+file:///path/to/project/projects/p1)"
+        ],
+        "deps": [
+          {
+            "name": "p1",
+            "pkg": "p1 0.1.0 (path+file:///path/to/project/projects/p1)",
+            "dep_kinds": [
+              {
+                "kind": null,
+                "target": null
+              }
+            ]
+          }
+        ],
+        "features": []
+      }
+    ],
+    "root": "p2 0.1.0 (path+file:///path/to/project/projects/p2)"
+  },
+  "target_directory": "/path/to/project/projects/p2/target",
+  "version": 1,
+  "workspace_root": "/path/to/project/projects/p2",
+  "metadata": null
+}
\ No newline at end of file
diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs
index 423c07183e2..d5991429899 100644
--- a/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -21,12 +21,12 @@ use std::{collections::HashMap, path::PathBuf, time::Instant};
 use lsp_types::{
     notification::DidOpenTextDocument,
     request::{
-        CodeActionRequest, Completion, Formatting, GotoTypeDefinition, HoverRequest, Rename,
+        CodeActionRequest, Completion, Formatting, GotoTypeDefinition, HoverRequest,
         WillRenameFiles, WorkspaceSymbolRequest,
     },
     CodeActionContext, CodeActionParams, CompletionParams, DidOpenTextDocumentParams,
     DocumentFormattingParams, FileRename, FormattingOptions, GotoDefinitionParams, HoverParams,
-    PartialResultParams, Position, Range, RenameFilesParams, RenameParams, TextDocumentItem,
+    PartialResultParams, Position, Range, RenameFilesParams, TextDocumentItem,
     TextDocumentPositionParams, WorkDoneProgressParams,
 };
 use rust_analyzer::lsp::ext::{OnEnter, Runnables, RunnablesParams};
@@ -1131,207 +1131,3 @@ version = "0.0.0"
 
     server.request::<WorkspaceSymbolRequest>(Default::default(), json!([]));
 }
-
-#[test]
-fn test_deduplicate_crate_differing_in_origin() {
-    let fixture = r#"
-//- /projects/p1/Cargo.toml
-[package]
-name = "p1"
-version = "0.0.0"
-
-//- /projects/p1/src/lib.rs
-pub fn add2(left: usize, right: usize) -> usize {
-    left + right
-}
-
-//- /projects/p2/Cargo.toml
-[package]
-name = "p2"
-version = "0.0.0"
-
-[dependencies]
-p1 = { path = "../p1" }
-
-//- /projects/p2/src/lib.rs
-use p1::add2;
-
-pub fn bar() {}
-    "#;
-
-    let server = Project::with_fixture(fixture)
-        .with_config(serde_json::json!({
-                "linkedProjects" : [
-                    "./projects/p1/Cargo.toml",
-                    "./projects/p2/Cargo.toml"
-                ],
-            }
-        ))
-        .with_config(serde_json::json!({
-            "cargo": { "sysroot": null },
-        }))
-        .server()
-        .wait_until_workspace_is_loaded();
-
-    let doc_id = server.doc_id("./projects/p2/src/lib.rs");
-    let doc2_id = server.doc_id("./projects/p1/src/lib.rs");
-
-    server.request::<Rename>(
-        RenameParams {
-            text_document_position: TextDocumentPositionParams {
-                text_document: doc_id.clone(),
-                position: Position { line: 0, character: 8 },
-            },
-            new_name: "ABC".to_owned(),
-            work_done_progress_params: WorkDoneProgressParams { work_done_token: None },
-        },
-        json!({
-            "documentChanges": [
-                {
-                  "textDocument": {
-                    "uri": doc2_id.uri,
-                    "version": null
-                  },
-                  "edits": [
-                    {
-                      "range": {
-                        "start": {
-                          "line": 0,
-                          "character": 7
-                        },
-                        "end": {
-                          "line": 0,
-                          "character": 11
-                        }
-                      },
-                      "newText": "ABC"
-                    }
-                  ]
-                },
-                {
-                  "textDocument": {
-                    "uri": doc_id.uri,
-                    "version": null
-                  },
-                  "edits": [
-                    {
-                      "range": {
-                        "start": {
-                          "line": 0,
-                          "character": 8
-                        },
-                        "end": {
-                          "line": 0,
-                          "character": 12
-                        }
-                      },
-                      "newText": "ABC"
-                    }
-                  ]
-                },
-            ]
-        }),
-    );
-}
-
-#[test]
-fn test_deduplicate_crate_differing_in_origin_in_rev_resolution_order() {
-    let fixture = r#"
-//- /projects/p1/Cargo.toml
-[package]
-name = "p1"
-version = "0.0.0"
-
-//- /projects/p1/src/lib.rs
-pub fn add2(left: usize, right: usize) -> usize {
-    left + right
-}
-
-//- /projects/p2/Cargo.toml
-[package]
-name = "p2"
-version = "0.0.0"
-
-[dependencies]
-p1 = { path = "../p1" }
-
-//- /projects/p2/src/lib.rs
-use p1::add2;
-
-pub fn bar() {}
-    "#;
-
-    let server = Project::with_fixture(fixture)
-        .with_config(serde_json::json!({
-                "linkedProjects" : [
-                    "./projects/p2/Cargo.toml",
-                    "./projects/p1/Cargo.toml",
-                ],
-            }
-        ))
-        .with_config(serde_json::json!({
-            "cargo": { "sysroot": null },
-        }))
-        .server()
-        .wait_until_workspace_is_loaded();
-
-    let doc_id = server.doc_id("./projects/p2/src/lib.rs");
-    let doc2_id = server.doc_id("./projects/p1/src/lib.rs");
-
-    server.request::<Rename>(
-        RenameParams {
-            text_document_position: TextDocumentPositionParams {
-                text_document: doc_id.clone(),
-                position: Position { line: 0, character: 8 },
-            },
-            new_name: "ABC".to_owned(),
-            work_done_progress_params: WorkDoneProgressParams { work_done_token: None },
-        },
-        json!({
-            "documentChanges": [
-                {
-                  "textDocument": {
-                    "uri": doc2_id.uri,
-                    "version": null
-                  },
-                  "edits": [
-                    {
-                      "range": {
-                        "start": {
-                          "line": 0,
-                          "character": 7
-                        },
-                        "end": {
-                          "line": 0,
-                          "character": 11
-                        }
-                      },
-                      "newText": "ABC"
-                    }
-                  ]
-                },
-                {
-                  "textDocument": {
-                    "uri": doc_id.uri,
-                    "version": null
-                  },
-                  "edits": [
-                    {
-                      "range": {
-                        "start": {
-                          "line": 0,
-                          "character": 8
-                        },
-                        "end": {
-                          "line": 0,
-                          "character": 12
-                        }
-                      },
-                      "newText": "ABC"
-                    }
-                  ]
-                },
-            ]
-        }),
-    );
-}