aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-11-10 21:35:19 +0000
committerGitHub <[email protected]>2019-11-10 21:35:19 +0000
commit7973fd66e9a7f178b0963675c62233474dcec954 (patch)
treee55d40fa70e9e1122aecbe66f258073b2c3d7a43
parent9d786ea221b27fbdf7c7f7beea0290db448e0611 (diff)
parentd634364462931c0a4944de29b38681a482817b6b (diff)
Merge #2201
2201: Resolve core types r=matklad a=Matthias247 This adds support for completion and goto definition of types defined within the "core" crate. The core crate is added as a dependency to each crate in the project. The core crate exported it's own prelude. This caused now all crates to inherit the core crates prelude instead of the std crates. In order to avoid the problem the prelude resolution has been changed to overwrite an already resolved prelude if this was set to a crate named core - in order to pick a better prelude like std. Fixes #2199 Co-authored-by: Matthias Einwag <[email protected]>
-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 }