Unnamed repository; edit this file 'description' to name the repository.
Ali Bektas 2023-11-23
parent 886eaa0 · commit 7e4aad5
-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 fb69e667ad..61a17da9aa 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 90dba008ad..0aeb0b0505 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 7815b9dda7..65c6f0b256 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 0000000000..3f627082f9
--- /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 0000000000..a2bf1af044
--- /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 423c07183e..d599142989 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"
- }
- ]
- },
- ]
- }),
- );
-}