fix issue 3444

This commit is contained in:
Josh Mcguigan 2020-03-10 19:58:17 -07:00
parent 05b4fc6d79
commit 7208498d54
6 changed files with 108 additions and 11 deletions

1
Cargo.lock generated
View file

@ -940,6 +940,7 @@ dependencies = [
name = "ra_hir" name = "ra_hir"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"arrayvec",
"either", "either",
"itertools", "itertools",
"log", "log",

View file

@ -11,6 +11,7 @@ doctest = false
log = "0.4.8" log = "0.4.8"
rustc-hash = "1.1.0" rustc-hash = "1.1.0"
either = "1.5.3" either = "1.5.3"
arrayvec = "0.5.1"
itertools = "0.8.2" itertools = "0.8.2"

View file

@ -1,6 +1,7 @@
//! FIXME: write short doc here //! FIXME: write short doc here
use std::sync::Arc; use std::sync::Arc;
use arrayvec::ArrayVec;
use either::Either; use either::Either;
use hir_def::{ use hir_def::{
adt::StructKind, adt::StructKind,
@ -226,7 +227,11 @@ impl Module {
Some((name, def)) 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() .collect()
} }
@ -1288,15 +1293,38 @@ pub enum ScopeDef {
Unknown, Unknown,
} }
impl From<PerNs> for ScopeDef { impl ScopeDef {
fn from(def: PerNs) -> Self { pub fn all_items(def: PerNs) -> ArrayVec<[Self; 3]> {
def.take_types() let mut items = ArrayVec::new();
.or_else(|| def.take_values())
.map(|module_def_id| ScopeDef::ModuleDef(module_def_id.into())) match (def.take_types(), def.take_values()) {
.or_else(|| { (Some(m1), None) =>
def.take_macros().map(|macro_def_id| ScopeDef::MacroDef(macro_def_id.into())) items.push(ScopeDef::ModuleDef(m1.into())),
}) (None, Some(m2)) =>
.unwrap_or(ScopeDef::Unknown) 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
} }
} }

View file

@ -344,7 +344,13 @@ impl<'a, DB: HirDatabase> SemanticsScope<'a, DB> {
resolver.process_all_names(self.db, &mut |name, def| { resolver.process_all_names(self.db, &mut |name, def| {
let def = match 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::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()),
resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()),
resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(TypeParam { id }), resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(TypeParam { id }),

View file

@ -101,6 +101,28 @@ fn crate_def_map_super_super() {
"###) "###)
} }
#[test]
fn crate_def_map_fn_mod_same_name() {
let map = def_map(
"
//- /lib.rs
mod m {
pub mod z {}
pub fn z() {}
}
",
);
assert_snapshot!(map, @r###"
crate
m: t
crate::m
z: t v
crate::m::z
"###)
}
#[test] #[test]
fn bogus_paths() { fn bogus_paths() {
covers!(bogus_paths); covers!(bogus_paths);

View file

@ -967,4 +967,43 @@ mod tests {
] ]
"###); "###);
} }
#[test]
fn function_mod_share_name() {
assert_debug_snapshot!(
do_reference_completion(
r"
fn foo() {
self::m::<|>
}
mod m {
pub mod z {}
pub fn z() {}
}
",
),
@r###"
[
CompletionItem {
label: "z",
source_range: [57; 57),
delete: [57; 57),
insert: "z",
kind: Module,
},
CompletionItem {
label: "z()",
source_range: [57; 57),
delete: [57; 57),
insert: "z()$0",
kind: Function,
lookup: "z",
detail: "pub fn z()",
},
]
"###
);
}
} }