From 58ed8ee6650058d5dc4ce511e2d9c04fdfa09aaf Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 11 Feb 2019 15:39:26 +0300 Subject: use extern prelude in Resolver This fixes two bugs: - completion for paths works again - we handle extern prelude shadowing more correctly --- crates/ra_hir/src/nameres.rs | 22 +++++++++------------- crates/ra_hir/src/nameres/tests.rs | 32 ++++++++++++++++++++++++++++++++ crates/ra_hir/src/resolve.rs | 7 ++----- 3 files changed, 43 insertions(+), 18 deletions(-) (limited to 'crates/ra_hir/src') 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 { self.resolve_path_fp(db, original_module, path).0 } + pub(crate) fn resolve_name_in_module(&self, module: Module, name: &Name) -> PerNs { + let from_scope = self[module.module_id].items.get(name).map_or(PerNs::none(), |it| it.def); + let from_extern_prelude = + self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); + + from_scope.combine(from_extern_prelude) + } + // Returns Yes if we are sure that additions to `ItemMap` wouldn't change // the result. fn resolve_path_fp( @@ -451,19 +459,7 @@ impl ItemMap { Some((_, segment)) => segment, None => return (PerNs::none(), ReachedFixedPoint::Yes), }; - // Resolve in: - // - current module / scope - // - extern prelude - match self[original_module.module_id].items.get(&segment.name) { - Some(res) if !res.def.is_none() => res.def, - _ => { - if let Some(def) = self.extern_prelude.get(&segment.name) { - PerNs::types(*def) - } else { - return (PerNs::none(), ReachedFixedPoint::No); - } - } - } + self.resolve_name_in_module(original_module, &segment.name) } PathKind::Super => { 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() { ); } +#[test] +fn values_dont_shadow_extern_crates() { + let mut db = MockDatabase::with_files( + " + //- /main.rs + fn foo() {} + use foo::Bar; + + //- /foo/lib.rs + pub struct Bar; + ", + ); + db.set_crate_graph_from_fixture(crate_graph! { + "main": ("/main.rs", ["foo"]), + "foo": ("/foo/lib.rs", []), + }); + let main_id = db.file_id_of("/main.rs"); + + let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); + let krate = module.krate(&db).unwrap(); + let item_map = db.item_map(krate); + + check_module_item_map( + &item_map, + module.module_id, + " + Bar: t v + foo: v + ", + ); +} + fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { let (mut db, pos) = MockDatabase::with_position(initial); 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 { if let Some(KnownName::SelfParam) = name.as_known_name() { PerNs::types(Resolution::Def(m.module.into())) } else { - match m.item_map[m.module.module_id].get(name) { - Some(res) => res.def.map(Resolution::Def), - None => PerNs::none(), - } + m.item_map.resolve_name_in_module(m.module, name).map(Resolution::Def) } } Scope::GenericParams(gp) => match gp.find_by_name(name) { @@ -177,7 +174,7 @@ impl Scope { } } - fn collect_names(&self, f: &mut FnMut(Name, PerNs)) { + fn collect_names(&self, f: &mut dyn FnMut(Name, PerNs)) { match self { Scope::ModuleScope(m) => { // TODO: should we provide `self` here? -- cgit v1.2.3