From 7208498d54b9f3d386b58f901c911a35170057ce Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Tue, 10 Mar 2020 19:58:17 -0700 Subject: fix issue 3444 --- crates/ra_hir/Cargo.toml | 1 + crates/ra_hir/src/code_model.rs | 48 ++++++++++++++++++++++++++++++++--------- crates/ra_hir/src/semantics.rs | 8 ++++++- 3 files changed, 46 insertions(+), 11 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml index 266c4cff3..42193b492 100644 --- a/crates/ra_hir/Cargo.toml +++ b/crates/ra_hir/Cargo.toml @@ -11,6 +11,7 @@ doctest = false log = "0.4.8" rustc-hash = "1.1.0" either = "1.5.3" +arrayvec = "0.5.1" itertools = "0.8.2" diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 41d4e2ed3..9e2fa03f8 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -1,6 +1,7 @@ //! FIXME: write short doc here use std::sync::Arc; +use arrayvec::ArrayVec; use either::Either; use hir_def::{ adt::StructKind, @@ -226,7 +227,11 @@ impl Module { Some((name, def)) } }) - .map(|(name, def)| (name.clone(), def.into())) + .flat_map(|(name, def)| + ScopeDef::all_items(def) + .into_iter() + .map(move |item| (name.clone(), item)) + ) .collect() } @@ -1288,15 +1293,38 @@ pub enum ScopeDef { Unknown, } -impl From for ScopeDef { - fn from(def: PerNs) -> Self { - def.take_types() - .or_else(|| def.take_values()) - .map(|module_def_id| ScopeDef::ModuleDef(module_def_id.into())) - .or_else(|| { - def.take_macros().map(|macro_def_id| ScopeDef::MacroDef(macro_def_id.into())) - }) - .unwrap_or(ScopeDef::Unknown) +impl ScopeDef { + pub fn all_items(def: PerNs) -> ArrayVec<[Self; 3]> { + let mut items = ArrayVec::new(); + + match (def.take_types(), def.take_values()) { + (Some(m1), None) => + items.push(ScopeDef::ModuleDef(m1.into())), + (None, Some(m2)) => + items.push(ScopeDef::ModuleDef(m2.into())), + (Some(m1), Some(m2)) => { + // Some items, like unit structs and enum variants, are + // returned as both a type and a value. Here we want + // to de-duplicate them. + if m1 != m2 { + items.push(ScopeDef::ModuleDef(m1.into())); + items.push(ScopeDef::ModuleDef(m2.into())); + } else { + items.push(ScopeDef::ModuleDef(m1.into())); + } + }, + (None, None) => {}, + }; + + if let Some(macro_def_id) = def.take_macros() { + items.push(ScopeDef::MacroDef(macro_def_id.into())); + } + + if items.is_empty() { + items.push(ScopeDef::Unknown); + } + + items } } diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 3782a9984..e83eb1fdc 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs @@ -344,7 +344,13 @@ impl<'a, DB: HirDatabase> SemanticsScope<'a, DB> { resolver.process_all_names(self.db, &mut |name, def| { let def = match def { - resolver::ScopeDef::PerNs(it) => it.into(), + resolver::ScopeDef::PerNs(it) => { + let items = ScopeDef::all_items(it); + for item in items { + f(name.clone(), item); + } + return + }, resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(TypeParam { id }), -- cgit v1.2.3