aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs11
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs31
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs62
-rw-r--r--crates/ra_project_model/src/lib.rs10
-rw-r--r--crates/ra_project_model/src/sysroot.rs4
5 files changed, 112 insertions, 6 deletions
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 7e6083961..6db9937a4 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -36,11 +36,12 @@ pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) ->
36 ); 36 );
37 37
38 // look for the prelude 38 // look for the prelude
39 if def_map.prelude.is_none() { 39 // If the dependency defines a prelude, we overwrite an already defined
40 let map = db.crate_def_map(dep.crate_id); 40 // prelude. This is necessary to import the "std" prelude if a crate
41 if map.prelude.is_some() { 41 // depends on both "core" and "std".
42 def_map.prelude = map.prelude; 42 let dep_def_map = db.crate_def_map(dep.crate_id);
43 } 43 if dep_def_map.prelude.is_some() {
44 def_map.prelude = dep_def_map.prelude;
44 } 45 }
45 } 46 }
46 47
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index 52bd0aa91..256f7d4be 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -464,6 +464,37 @@ fn values_dont_shadow_extern_crates() {
464} 464}
465 465
466#[test] 466#[test]
467fn std_prelude_takes_precedence_above_core_prelude() {
468 let map = def_map(
469 r#"
470 //- /main.rs crate:main deps:core,std
471 use {Foo, Bar};
472
473 //- /std.rs crate:std deps:core
474 #[prelude_import]
475 pub use self::prelude::*;
476 mod prelude {
477 pub struct Foo;
478 pub use core::prelude::Bar;
479 }
480
481 //- /core.rs crate:core
482 #[prelude_import]
483 pub use self::prelude::*;
484 mod prelude {
485 pub struct Bar;
486 }
487 "#,
488 );
489
490 assert_snapshot!(map, @r###"
491 ⋮crate
492 ⋮Bar: t v
493 ⋮Foo: t v
494 "###);
495}
496
497#[test]
467fn cfg_not_test() { 498fn cfg_not_test() {
468 let map = def_map( 499 let map = def_map(
469 r#" 500 r#"
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
index 4e56de3f5..3e205efd1 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -598,6 +598,68 @@ mod tests {
598 } 598 }
599 599
600 #[test] 600 #[test]
601 fn completes_std_prelude_if_core_is_defined() {
602 assert_debug_snapshot!(
603 do_reference_completion(
604 "
605 //- /main.rs
606 fn foo() { let x: <|> }
607
608 //- /core/lib.rs
609 #[prelude_import]
610 use prelude::*;
611
612 mod prelude {
613 struct Option;
614 }
615
616 //- /std/lib.rs
617 #[prelude_import]
618 use prelude::*;
619
620 mod prelude {
621 struct String;
622 }
623 "
624 ),
625 @r###"
626 [
627 CompletionItem {
628 label: "String",
629 source_range: [18; 18),
630 delete: [18; 18),
631 insert: "String",
632 kind: Struct,
633 },
634 CompletionItem {
635 label: "core",
636 source_range: [18; 18),
637 delete: [18; 18),
638 insert: "core",
639 kind: Module,
640 },
641 CompletionItem {
642 label: "foo()",
643 source_range: [18; 18),
644 delete: [18; 18),
645 insert: "foo()$0",
646 kind: Function,
647 lookup: "foo",
648 detail: "fn foo()",
649 },
650 CompletionItem {
651 label: "std",
652 source_range: [18; 18),
653 delete: [18; 18),
654 insert: "std",
655 kind: Module,
656 },
657 ]
658 "###
659 );
660 }
661
662 #[test]
601 fn completes_macros_as_value() { 663 fn completes_macros_as_value() {
602 assert_debug_snapshot!( 664 assert_debug_snapshot!(
603 do_reference_completion( 665 do_reference_completion(
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 8b8663a78..0e14f1b70 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -199,6 +199,7 @@ impl ProjectWorkspace {
199 } 199 }
200 } 200 }
201 201
202 let libcore = sysroot.core().and_then(|it| sysroot_crates.get(&it).copied());
202 let libstd = sysroot.std().and_then(|it| sysroot_crates.get(&it).copied()); 203 let libstd = sysroot.std().and_then(|it| sysroot_crates.get(&it).copied());
203 204
204 let mut pkg_to_lib_crate = FxHashMap::default(); 205 let mut pkg_to_lib_crate = FxHashMap::default();
@@ -226,7 +227,7 @@ impl ProjectWorkspace {
226 } 227 }
227 } 228 }
228 229
229 // Set deps to the std and to the lib target of the current package 230 // Set deps to the core, std and to the lib target of the current package
230 for &from in pkg_crates.get(&pkg).into_iter().flatten() { 231 for &from in pkg_crates.get(&pkg).into_iter().flatten() {
231 if let Some(to) = lib_tgt { 232 if let Some(to) = lib_tgt {
232 if to != from { 233 if to != from {
@@ -240,6 +241,13 @@ impl ProjectWorkspace {
240 } 241 }
241 } 242 }
242 } 243 }
244 // core is added as a dependency before std in order to
245 // mimic rustcs dependency order
246 if let Some(core) = libcore {
247 if let Err(_) = crate_graph.add_dep(from, "core".into(), core) {
248 log::error!("cyclic dependency on core for {}", pkg.name(&cargo))
249 }
250 }
243 if let Some(std) = libstd { 251 if let Some(std) = libstd {
244 if let Err(_) = crate_graph.add_dep(from, "std".into(), std) { 252 if let Err(_) = crate_graph.add_dep(from, "std".into(), std) {
245 log::error!("cyclic dependency on std for {}", pkg.name(&cargo)) 253 log::error!("cyclic dependency on std for {}", pkg.name(&cargo))
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs
index 35d6df5cb..3d827809e 100644
--- a/crates/ra_project_model/src/sysroot.rs
+++ b/crates/ra_project_model/src/sysroot.rs
@@ -27,6 +27,10 @@ struct SysrootCrateData {
27} 27}
28 28
29impl Sysroot { 29impl Sysroot {
30 pub fn core(&self) -> Option<SysrootCrate> {
31 self.by_name("core")
32 }
33
30 pub fn std(&self) -> Option<SysrootCrate> { 34 pub fn std(&self) -> Option<SysrootCrate> {
31 self.by_name("std") 35 self.by_name("std")
32 } 36 }