diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-11-10 21:35:19 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-11-10 21:35:19 +0000 |
commit | 7973fd66e9a7f178b0963675c62233474dcec954 (patch) | |
tree | e55d40fa70e9e1122aecbe66f258073b2c3d7a43 | |
parent | 9d786ea221b27fbdf7c7f7beea0290db448e0611 (diff) | |
parent | d634364462931c0a4944de29b38681a482817b6b (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.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests.rs | 31 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_scope.rs | 62 | ||||
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 10 | ||||
-rw-r--r-- | crates/ra_project_model/src/sysroot.rs | 4 |
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] |
467 | fn 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] | ||
467 | fn cfg_not_test() { | 498 | fn 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 | ||
29 | impl Sysroot { | 29 | impl 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 | } |