diff options
author | Aleksey Kladov <[email protected]> | 2019-02-11 12:39:26 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-02-11 12:41:39 +0000 |
commit | 58ed8ee6650058d5dc4ce511e2d9c04fdfa09aaf (patch) | |
tree | 1a45d04e9cef82dd57967e99e9af9b923a193836 /crates/ra_hir | |
parent | 2babbbb97800b526cc29f244bb6ea58b213d24f3 (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.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 7 |
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] | ||
540 | fn 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 | |||
539 | fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { | 571 | fn 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? |