6 use base_db::{CrateGraph, FileId};
7 use cfg::{CfgAtom, CfgDiff};
8 use expect_test::{expect, Expect};
9 use paths::{AbsPath, AbsPathBuf};
10 use serde::de::DeserializeOwned;
13 CargoWorkspace, CfgOverrides, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot,
14 WorkspaceBuildScripts,
17 fn load_cargo(file: &str) -> CrateGraph {
18 load_cargo_with_overrides(file, CfgOverrides::default())
21 fn load_cargo_with_overrides(file: &str, cfg_overrides: CfgOverrides) -> CrateGraph {
22 let meta = get_test_json_file(file);
23 let cargo_workspace = CargoWorkspace::new(meta);
24 let project_workspace = ProjectWorkspace::Cargo {
25 cargo: cargo_workspace,
26 build_scripts: WorkspaceBuildScripts::default(),
29 rustc_cfg: Vec::new(),
32 to_crate_graph(project_workspace)
35 fn load_rust_project(file: &str) -> CrateGraph {
36 let data = get_test_json_file(file);
37 let project = rooted_project_json(data);
38 let sysroot = Some(get_fake_sysroot());
39 let project_workspace = ProjectWorkspace::Json { project, sysroot, rustc_cfg: Vec::new() };
40 to_crate_graph(project_workspace)
43 fn get_test_json_file<T: DeserializeOwned>(file: &str) -> T {
44 let file = get_test_path(file);
45 let data = std::fs::read_to_string(file).unwrap();
46 let mut json = data.parse::<serde_json::Value>().unwrap();
47 fixup_paths(&mut json);
48 return serde_json::from_value(json).unwrap();
50 fn fixup_paths(val: &mut serde_json::Value) {
52 serde_json::Value::String(s) => replace_root(s, true),
53 serde_json::Value::Array(vals) => vals.iter_mut().for_each(fixup_paths),
54 serde_json::Value::Object(kvals) => kvals.values_mut().for_each(fixup_paths),
55 serde_json::Value::Null | serde_json::Value::Bool(_) | serde_json::Value::Number(_) => {
61 fn replace_root(s: &mut String, direction: bool) {
63 let root = if cfg!(windows) { r#"C:\\ROOT\"# } else { "/ROOT/" };
64 *s = s.replace("$ROOT$", root)
66 let root = if cfg!(windows) { r#"C:\\\\ROOT\\"# } else { "/ROOT/" };
67 *s = s.replace(root, "$ROOT$")
71 fn get_test_path(file: &str) -> PathBuf {
72 let base = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
73 base.join("test_data").join(file)
76 fn get_fake_sysroot() -> Sysroot {
77 let sysroot_path = get_test_path("fake-sysroot");
78 let sysroot_src_dir = AbsPathBuf::assert(sysroot_path);
79 Sysroot::load(sysroot_src_dir).unwrap()
82 fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
83 let mut root = "$ROOT$".to_string();
84 replace_root(&mut root, true);
85 let path = Path::new(&root);
86 let base = AbsPath::assert(path);
87 ProjectJson::new(base, data)
90 fn to_crate_graph(project_workspace: ProjectWorkspace) -> CrateGraph {
91 project_workspace.to_crate_graph(&Default::default(), &mut |_, _| Vec::new(), &mut {
100 fn check_crate_graph(crate_graph: CrateGraph, expect: Expect) {
101 let mut crate_graph = format!("{:#?}", crate_graph);
102 replace_root(&mut crate_graph, false);
103 expect.assert_eq(&crate_graph);
107 fn cargo_hello_world_project_model_with_wildcard_overrides() {
108 let cfg_overrides = CfgOverrides::Wildcard(
109 CfgDiff::new(Vec::new(), vec![CfgAtom::Flag("test".into())]).unwrap(),
111 let crate_graph = load_cargo_with_overrides("hello-world-metadata.json", cfg_overrides);
120 root_file_id: FileId(
123 edition: Edition2018,
129 crate_name: CrateName(
132 canonical_name: "hello-world",
135 cfg_options: CfgOptions(
140 potential_cfg_options: CfgOptions(
147 "CARGO_PKG_LICENSE": "",
148 "CARGO_PKG_VERSION_MAJOR": "0",
149 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
150 "CARGO_PKG_VERSION": "0.1.0",
151 "CARGO_PKG_AUTHORS": "",
152 "CARGO_CRATE_NAME": "hello_world",
153 "CARGO_PKG_LICENSE_FILE": "",
154 "CARGO_PKG_HOMEPAGE": "",
155 "CARGO_PKG_DESCRIPTION": "",
156 "CARGO_PKG_NAME": "hello-world",
157 "CARGO_PKG_VERSION_PATCH": "0",
159 "CARGO_PKG_REPOSITORY": "",
160 "CARGO_PKG_VERSION_MINOR": "1",
161 "CARGO_PKG_VERSION_PRE": "",
183 root_file_id: FileId(
186 edition: Edition2018,
192 crate_name: CrateName(
195 canonical_name: "an-example",
198 cfg_options: CfgOptions(
203 potential_cfg_options: CfgOptions(
210 "CARGO_PKG_LICENSE": "",
211 "CARGO_PKG_VERSION_MAJOR": "0",
212 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
213 "CARGO_PKG_VERSION": "0.1.0",
214 "CARGO_PKG_AUTHORS": "",
215 "CARGO_CRATE_NAME": "hello_world",
216 "CARGO_PKG_LICENSE_FILE": "",
217 "CARGO_PKG_HOMEPAGE": "",
218 "CARGO_PKG_DESCRIPTION": "",
219 "CARGO_PKG_NAME": "hello-world",
220 "CARGO_PKG_VERSION_PATCH": "0",
222 "CARGO_PKG_REPOSITORY": "",
223 "CARGO_PKG_VERSION_MINOR": "1",
224 "CARGO_PKG_VERSION_PRE": "",
255 root_file_id: FileId(
258 edition: Edition2015,
264 crate_name: CrateName(
267 canonical_name: "libc",
270 cfg_options: CfgOptions(
277 potential_cfg_options: CfgOptions(
281 "feature=const-extern-fn",
283 "feature=extra_traits",
284 "feature=rustc-dep-of-std",
291 "CARGO_PKG_LICENSE": "",
292 "CARGO_PKG_VERSION_MAJOR": "0",
293 "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
294 "CARGO_PKG_VERSION": "0.2.98",
295 "CARGO_PKG_AUTHORS": "",
296 "CARGO_CRATE_NAME": "libc",
297 "CARGO_PKG_LICENSE_FILE": "",
298 "CARGO_PKG_HOMEPAGE": "",
299 "CARGO_PKG_DESCRIPTION": "",
300 "CARGO_PKG_NAME": "libc",
301 "CARGO_PKG_VERSION_PATCH": "98",
303 "CARGO_PKG_REPOSITORY": "",
304 "CARGO_PKG_VERSION_MINOR": "2",
305 "CARGO_PKG_VERSION_PRE": "",
312 "https://github.com/rust-lang/libc",
319 root_file_id: FileId(
322 edition: Edition2018,
328 crate_name: CrateName(
331 canonical_name: "hello-world",
334 cfg_options: CfgOptions(
339 potential_cfg_options: CfgOptions(
346 "CARGO_PKG_LICENSE": "",
347 "CARGO_PKG_VERSION_MAJOR": "0",
348 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
349 "CARGO_PKG_VERSION": "0.1.0",
350 "CARGO_PKG_AUTHORS": "",
351 "CARGO_CRATE_NAME": "hello_world",
352 "CARGO_PKG_LICENSE_FILE": "",
353 "CARGO_PKG_HOMEPAGE": "",
354 "CARGO_PKG_DESCRIPTION": "",
355 "CARGO_PKG_NAME": "hello-world",
356 "CARGO_PKG_VERSION_PATCH": "0",
358 "CARGO_PKG_REPOSITORY": "",
359 "CARGO_PKG_VERSION_MINOR": "1",
360 "CARGO_PKG_VERSION_PRE": "",
391 root_file_id: FileId(
394 edition: Edition2018,
400 crate_name: CrateName(
403 canonical_name: "it",
406 cfg_options: CfgOptions(
411 potential_cfg_options: CfgOptions(
418 "CARGO_PKG_LICENSE": "",
419 "CARGO_PKG_VERSION_MAJOR": "0",
420 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
421 "CARGO_PKG_VERSION": "0.1.0",
422 "CARGO_PKG_AUTHORS": "",
423 "CARGO_CRATE_NAME": "hello_world",
424 "CARGO_PKG_LICENSE_FILE": "",
425 "CARGO_PKG_HOMEPAGE": "",
426 "CARGO_PKG_DESCRIPTION": "",
427 "CARGO_PKG_NAME": "hello-world",
428 "CARGO_PKG_VERSION_PATCH": "0",
430 "CARGO_PKG_REPOSITORY": "",
431 "CARGO_PKG_VERSION_MINOR": "1",
432 "CARGO_PKG_VERSION_PRE": "",
466 fn cargo_hello_world_project_model_with_selective_overrides() {
467 let cfg_overrides = {
468 CfgOverrides::Selective(
471 CfgDiff::new(Vec::new(), vec![CfgAtom::Flag("test".into())]).unwrap(),
476 let crate_graph = load_cargo_with_overrides("hello-world-metadata.json", cfg_overrides);
485 root_file_id: FileId(
488 edition: Edition2018,
494 crate_name: CrateName(
497 canonical_name: "hello-world",
500 cfg_options: CfgOptions(
506 potential_cfg_options: CfgOptions(
514 "CARGO_PKG_LICENSE": "",
515 "CARGO_PKG_VERSION_MAJOR": "0",
516 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
517 "CARGO_PKG_VERSION": "0.1.0",
518 "CARGO_PKG_AUTHORS": "",
519 "CARGO_CRATE_NAME": "hello_world",
520 "CARGO_PKG_LICENSE_FILE": "",
521 "CARGO_PKG_HOMEPAGE": "",
522 "CARGO_PKG_DESCRIPTION": "",
523 "CARGO_PKG_NAME": "hello-world",
524 "CARGO_PKG_VERSION_PATCH": "0",
526 "CARGO_PKG_REPOSITORY": "",
527 "CARGO_PKG_VERSION_MINOR": "1",
528 "CARGO_PKG_VERSION_PRE": "",
550 root_file_id: FileId(
553 edition: Edition2018,
559 crate_name: CrateName(
562 canonical_name: "an-example",
565 cfg_options: CfgOptions(
571 potential_cfg_options: CfgOptions(
579 "CARGO_PKG_LICENSE": "",
580 "CARGO_PKG_VERSION_MAJOR": "0",
581 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
582 "CARGO_PKG_VERSION": "0.1.0",
583 "CARGO_PKG_AUTHORS": "",
584 "CARGO_CRATE_NAME": "hello_world",
585 "CARGO_PKG_LICENSE_FILE": "",
586 "CARGO_PKG_HOMEPAGE": "",
587 "CARGO_PKG_DESCRIPTION": "",
588 "CARGO_PKG_NAME": "hello-world",
589 "CARGO_PKG_VERSION_PATCH": "0",
591 "CARGO_PKG_REPOSITORY": "",
592 "CARGO_PKG_VERSION_MINOR": "1",
593 "CARGO_PKG_VERSION_PRE": "",
624 root_file_id: FileId(
627 edition: Edition2015,
633 crate_name: CrateName(
636 canonical_name: "libc",
639 cfg_options: CfgOptions(
646 potential_cfg_options: CfgOptions(
650 "feature=const-extern-fn",
652 "feature=extra_traits",
653 "feature=rustc-dep-of-std",
660 "CARGO_PKG_LICENSE": "",
661 "CARGO_PKG_VERSION_MAJOR": "0",
662 "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
663 "CARGO_PKG_VERSION": "0.2.98",
664 "CARGO_PKG_AUTHORS": "",
665 "CARGO_CRATE_NAME": "libc",
666 "CARGO_PKG_LICENSE_FILE": "",
667 "CARGO_PKG_HOMEPAGE": "",
668 "CARGO_PKG_DESCRIPTION": "",
669 "CARGO_PKG_NAME": "libc",
670 "CARGO_PKG_VERSION_PATCH": "98",
672 "CARGO_PKG_REPOSITORY": "",
673 "CARGO_PKG_VERSION_MINOR": "2",
674 "CARGO_PKG_VERSION_PRE": "",
681 "https://github.com/rust-lang/libc",
688 root_file_id: FileId(
691 edition: Edition2018,
697 crate_name: CrateName(
700 canonical_name: "hello-world",
703 cfg_options: CfgOptions(
709 potential_cfg_options: CfgOptions(
717 "CARGO_PKG_LICENSE": "",
718 "CARGO_PKG_VERSION_MAJOR": "0",
719 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
720 "CARGO_PKG_VERSION": "0.1.0",
721 "CARGO_PKG_AUTHORS": "",
722 "CARGO_CRATE_NAME": "hello_world",
723 "CARGO_PKG_LICENSE_FILE": "",
724 "CARGO_PKG_HOMEPAGE": "",
725 "CARGO_PKG_DESCRIPTION": "",
726 "CARGO_PKG_NAME": "hello-world",
727 "CARGO_PKG_VERSION_PATCH": "0",
729 "CARGO_PKG_REPOSITORY": "",
730 "CARGO_PKG_VERSION_MINOR": "1",
731 "CARGO_PKG_VERSION_PRE": "",
762 root_file_id: FileId(
765 edition: Edition2018,
771 crate_name: CrateName(
774 canonical_name: "it",
777 cfg_options: CfgOptions(
783 potential_cfg_options: CfgOptions(
791 "CARGO_PKG_LICENSE": "",
792 "CARGO_PKG_VERSION_MAJOR": "0",
793 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
794 "CARGO_PKG_VERSION": "0.1.0",
795 "CARGO_PKG_AUTHORS": "",
796 "CARGO_CRATE_NAME": "hello_world",
797 "CARGO_PKG_LICENSE_FILE": "",
798 "CARGO_PKG_HOMEPAGE": "",
799 "CARGO_PKG_DESCRIPTION": "",
800 "CARGO_PKG_NAME": "hello-world",
801 "CARGO_PKG_VERSION_PATCH": "0",
803 "CARGO_PKG_REPOSITORY": "",
804 "CARGO_PKG_VERSION_MINOR": "1",
805 "CARGO_PKG_VERSION_PRE": "",
839 fn cargo_hello_world_project_model() {
840 let crate_graph = load_cargo("hello-world-metadata.json");
849 root_file_id: FileId(
852 edition: Edition2018,
858 crate_name: CrateName(
861 canonical_name: "hello-world",
864 cfg_options: CfgOptions(
870 potential_cfg_options: CfgOptions(
878 "CARGO_PKG_LICENSE": "",
879 "CARGO_PKG_VERSION_MAJOR": "0",
880 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
881 "CARGO_PKG_VERSION": "0.1.0",
882 "CARGO_PKG_AUTHORS": "",
883 "CARGO_CRATE_NAME": "hello_world",
884 "CARGO_PKG_LICENSE_FILE": "",
885 "CARGO_PKG_HOMEPAGE": "",
886 "CARGO_PKG_DESCRIPTION": "",
887 "CARGO_PKG_NAME": "hello-world",
888 "CARGO_PKG_VERSION_PATCH": "0",
890 "CARGO_PKG_REPOSITORY": "",
891 "CARGO_PKG_VERSION_MINOR": "1",
892 "CARGO_PKG_VERSION_PRE": "",
914 root_file_id: FileId(
917 edition: Edition2018,
923 crate_name: CrateName(
926 canonical_name: "an-example",
929 cfg_options: CfgOptions(
935 potential_cfg_options: CfgOptions(
943 "CARGO_PKG_LICENSE": "",
944 "CARGO_PKG_VERSION_MAJOR": "0",
945 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
946 "CARGO_PKG_VERSION": "0.1.0",
947 "CARGO_PKG_AUTHORS": "",
948 "CARGO_CRATE_NAME": "hello_world",
949 "CARGO_PKG_LICENSE_FILE": "",
950 "CARGO_PKG_HOMEPAGE": "",
951 "CARGO_PKG_DESCRIPTION": "",
952 "CARGO_PKG_NAME": "hello-world",
953 "CARGO_PKG_VERSION_PATCH": "0",
955 "CARGO_PKG_REPOSITORY": "",
956 "CARGO_PKG_VERSION_MINOR": "1",
957 "CARGO_PKG_VERSION_PRE": "",
988 root_file_id: FileId(
991 edition: Edition2015,
997 crate_name: CrateName(
1000 canonical_name: "libc",
1003 cfg_options: CfgOptions(
1011 potential_cfg_options: CfgOptions(
1015 "feature=const-extern-fn",
1017 "feature=extra_traits",
1018 "feature=rustc-dep-of-std",
1026 "CARGO_PKG_LICENSE": "",
1027 "CARGO_PKG_VERSION_MAJOR": "0",
1028 "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
1029 "CARGO_PKG_VERSION": "0.2.98",
1030 "CARGO_PKG_AUTHORS": "",
1031 "CARGO_CRATE_NAME": "libc",
1032 "CARGO_PKG_LICENSE_FILE": "",
1033 "CARGO_PKG_HOMEPAGE": "",
1034 "CARGO_PKG_DESCRIPTION": "",
1035 "CARGO_PKG_NAME": "libc",
1036 "CARGO_PKG_VERSION_PATCH": "98",
1038 "CARGO_PKG_REPOSITORY": "",
1039 "CARGO_PKG_VERSION_MINOR": "2",
1040 "CARGO_PKG_VERSION_PRE": "",
1047 "https://github.com/rust-lang/libc",
1054 root_file_id: FileId(
1057 edition: Edition2018,
1063 crate_name: CrateName(
1066 canonical_name: "hello-world",
1069 cfg_options: CfgOptions(
1075 potential_cfg_options: CfgOptions(
1083 "CARGO_PKG_LICENSE": "",
1084 "CARGO_PKG_VERSION_MAJOR": "0",
1085 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
1086 "CARGO_PKG_VERSION": "0.1.0",
1087 "CARGO_PKG_AUTHORS": "",
1088 "CARGO_CRATE_NAME": "hello_world",
1089 "CARGO_PKG_LICENSE_FILE": "",
1090 "CARGO_PKG_HOMEPAGE": "",
1091 "CARGO_PKG_DESCRIPTION": "",
1092 "CARGO_PKG_NAME": "hello-world",
1093 "CARGO_PKG_VERSION_PATCH": "0",
1095 "CARGO_PKG_REPOSITORY": "",
1096 "CARGO_PKG_VERSION_MINOR": "1",
1097 "CARGO_PKG_VERSION_PRE": "",
1128 root_file_id: FileId(
1131 edition: Edition2018,
1137 crate_name: CrateName(
1140 canonical_name: "it",
1143 cfg_options: CfgOptions(
1149 potential_cfg_options: CfgOptions(
1157 "CARGO_PKG_LICENSE": "",
1158 "CARGO_PKG_VERSION_MAJOR": "0",
1159 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
1160 "CARGO_PKG_VERSION": "0.1.0",
1161 "CARGO_PKG_AUTHORS": "",
1162 "CARGO_CRATE_NAME": "hello_world",
1163 "CARGO_PKG_LICENSE_FILE": "",
1164 "CARGO_PKG_HOMEPAGE": "",
1165 "CARGO_PKG_DESCRIPTION": "",
1166 "CARGO_PKG_NAME": "hello-world",
1167 "CARGO_PKG_VERSION_PATCH": "0",
1169 "CARGO_PKG_REPOSITORY": "",
1170 "CARGO_PKG_VERSION_MINOR": "1",
1171 "CARGO_PKG_VERSION_PRE": "",
1205 fn rust_project_hello_world_project_model() {
1206 let crate_graph = load_rust_project("hello-world-project.json");
1215 root_file_id: FileId(
1218 edition: Edition2018,
1222 crate_name: CrateName(
1225 canonical_name: "alloc",
1228 cfg_options: CfgOptions(
1231 potential_cfg_options: CfgOptions(
1254 root_file_id: FileId(
1257 edition: Edition2018,
1261 crate_name: CrateName(
1264 canonical_name: "unwind",
1267 cfg_options: CfgOptions(
1270 potential_cfg_options: CfgOptions(
1283 root_file_id: FileId(
1286 edition: Edition2018,
1290 crate_name: CrateName(
1293 canonical_name: "std_detect",
1296 cfg_options: CfgOptions(
1299 potential_cfg_options: CfgOptions(
1312 root_file_id: FileId(
1315 edition: Edition2018,
1319 crate_name: CrateName(
1322 canonical_name: "proc_macro",
1325 cfg_options: CfgOptions(
1328 potential_cfg_options: CfgOptions(
1351 root_file_id: FileId(
1354 edition: Edition2018,
1358 crate_name: CrateName(
1361 canonical_name: "core",
1364 cfg_options: CfgOptions(
1367 potential_cfg_options: CfgOptions(
1380 root_file_id: FileId(
1383 edition: Edition2018,
1387 crate_name: CrateName(
1390 canonical_name: "hello_world",
1393 cfg_options: CfgOptions(
1396 potential_cfg_options: CfgOptions(
1448 root_file_id: FileId(
1451 edition: Edition2018,
1455 crate_name: CrateName(
1458 canonical_name: "term",
1461 cfg_options: CfgOptions(
1464 potential_cfg_options: CfgOptions(
1477 root_file_id: FileId(
1480 edition: Edition2018,
1484 crate_name: CrateName(
1485 "profiler_builtins",
1487 canonical_name: "profiler_builtins",
1490 cfg_options: CfgOptions(
1493 potential_cfg_options: CfgOptions(
1506 root_file_id: FileId(
1509 edition: Edition2018,
1513 crate_name: CrateName(
1516 canonical_name: "panic_abort",
1519 cfg_options: CfgOptions(
1522 potential_cfg_options: CfgOptions(
1535 root_file_id: FileId(
1538 edition: Edition2018,
1542 crate_name: CrateName(
1545 canonical_name: "test",
1548 cfg_options: CfgOptions(
1551 potential_cfg_options: CfgOptions(
1564 root_file_id: FileId(
1567 edition: Edition2018,
1571 crate_name: CrateName(
1574 canonical_name: "std",
1577 cfg_options: CfgOptions(
1580 potential_cfg_options: CfgOptions(
1628 "profiler_builtins",
1675 root_file_id: FileId(
1678 edition: Edition2018,
1682 crate_name: CrateName(
1685 canonical_name: "panic_unwind",
1688 cfg_options: CfgOptions(
1691 potential_cfg_options: CfgOptions(
1707 fn rust_project_is_proc_macro_has_proc_macro_dep() {
1708 let crate_graph = load_rust_project("is-proc-macro-project.json");
1709 // Since the project only defines one crate (outside the sysroot crates),
1710 // it should be the one with the biggest Id.
1711 let crate_id = crate_graph.iter().max().unwrap();
1712 let crate_data = &crate_graph[crate_id];
1713 // Assert that the project crate with `is_proc_macro` has a dependency
1714 // on the proc_macro sysroot crate.
1715 crate_data.dependencies.iter().find(|&dep| dep.name.deref() == "proc_macro").unwrap();