aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-02-11 12:39:26 +0000
committerAleksey Kladov <[email protected]>2019-02-11 12:41:39 +0000
commit58ed8ee6650058d5dc4ce511e2d9c04fdfa09aaf (patch)
tree1a45d04e9cef82dd57967e99e9af9b923a193836 /crates/ra_hir
parent2babbbb97800b526cc29f244bb6ea58b213d24f3 (diff)
use extern prelude in Resolver
This fixes two bugs: - completion for paths works again - we handle extern prelude shadowing more correctly
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/nameres.rs22
-rw-r--r--crates/ra_hir/src/nameres/tests.rs32
-rw-r--r--crates/ra_hir/src/resolve.rs7
3 files changed, 43 insertions, 18 deletions
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 94f7db024..4b8097235 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -434,6 +434,14 @@ impl ItemMap {
434 self.resolve_path_fp(db, original_module, path).0 434 self.resolve_path_fp(db, original_module, path).0
435 } 435 }
436 436
437 pub(crate) fn resolve_name_in_module(&self, module: Module, name: &Name) -> PerNs<ModuleDef> {
438 let from_scope = self[module.module_id].items.get(name).map_or(PerNs::none(), |it| it.def);
439 let from_extern_prelude =
440 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
441
442 from_scope.combine(from_extern_prelude)
443 }
444
437 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change 445 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
438 // the result. 446 // the result.
439 fn resolve_path_fp( 447 fn resolve_path_fp(
@@ -451,19 +459,7 @@ impl ItemMap {
451 Some((_, segment)) => segment, 459 Some((_, segment)) => segment,
452 None => return (PerNs::none(), ReachedFixedPoint::Yes), 460 None => return (PerNs::none(), ReachedFixedPoint::Yes),
453 }; 461 };
454 // Resolve in: 462 self.resolve_name_in_module(original_module, &segment.name)
455 // - current module / scope
456 // - extern prelude
457 match self[original_module.module_id].items.get(&segment.name) {
458 Some(res) if !res.def.is_none() => res.def,
459 _ => {
460 if let Some(def) = self.extern_prelude.get(&segment.name) {
461 PerNs::types(*def)
462 } else {
463 return (PerNs::none(), ReachedFixedPoint::No);
464 }
465 }
466 }
467 } 463 }
468 PathKind::Super => { 464 PathKind::Super => {
469 if let Some(p) = original_module.parent(db) { 465 if let Some(p) = original_module.parent(db) {
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index 9b621fbc2..f1a1f5b76 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -536,6 +536,38 @@ fn reexport_across_crates() {
536 ); 536 );
537} 537}
538 538
539#[test]
540fn values_dont_shadow_extern_crates() {
541 let mut db = MockDatabase::with_files(
542 "
543 //- /main.rs
544 fn foo() {}
545 use foo::Bar;
546
547 //- /foo/lib.rs
548 pub struct Bar;
549 ",
550 );
551 db.set_crate_graph_from_fixture(crate_graph! {
552 "main": ("/main.rs", ["foo"]),
553 "foo": ("/foo/lib.rs", []),
554 });
555 let main_id = db.file_id_of("/main.rs");
556
557 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
558 let krate = module.krate(&db).unwrap();
559 let item_map = db.item_map(krate);
560
561 check_module_item_map(
562 &item_map,
563 module.module_id,
564 "
565 Bar: t v
566 foo: v
567 ",
568 );
569}
570
539fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { 571fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) {
540 let (mut db, pos) = MockDatabase::with_position(initial); 572 let (mut db, pos) = MockDatabase::with_position(initial);
541 let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); 573 let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap();
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 3d7ec5683..e8abac5bc 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -149,10 +149,7 @@ impl Scope {
149 if let Some(KnownName::SelfParam) = name.as_known_name() { 149 if let Some(KnownName::SelfParam) = name.as_known_name() {
150 PerNs::types(Resolution::Def(m.module.into())) 150 PerNs::types(Resolution::Def(m.module.into()))
151 } else { 151 } else {
152 match m.item_map[m.module.module_id].get(name) { 152 m.item_map.resolve_name_in_module(m.module, name).map(Resolution::Def)
153 Some(res) => res.def.map(Resolution::Def),
154 None => PerNs::none(),
155 }
156 } 153 }
157 } 154 }
158 Scope::GenericParams(gp) => match gp.find_by_name(name) { 155 Scope::GenericParams(gp) => match gp.find_by_name(name) {
@@ -177,7 +174,7 @@ impl Scope {
177 } 174 }
178 } 175 }
179 176
180 fn collect_names(&self, f: &mut FnMut(Name, PerNs<Resolution>)) { 177 fn collect_names(&self, f: &mut dyn FnMut(Name, PerNs<Resolution>)) {
181 match self { 178 match self {
182 Scope::ModuleScope(m) => { 179 Scope::ModuleScope(m) => {
183 // TODO: should we provide `self` here? 180 // TODO: should we provide `self` here?