diff options
author | Josh Mcguigan <[email protected]> | 2020-03-11 02:58:17 +0000 |
---|---|---|
committer | Josh Mcguigan <[email protected]> | 2020-03-13 00:16:28 +0000 |
commit | 7208498d54b9f3d386b58f901c911a35170057ce (patch) | |
tree | a2af022a5b52794e9deacfca24b77b3a1e980336 | |
parent | 05b4fc6d79060fc3120f92b01119e3a851c37829 (diff) |
fix issue 3444
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | crates/ra_hir/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 48 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests.rs | 22 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_path.rs | 39 |
6 files changed, 108 insertions, 11 deletions
diff --git a/Cargo.lock b/Cargo.lock index 330bdd1cb..f3707f116 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -940,6 +940,7 @@ dependencies = [ | |||
940 | name = "ra_hir" | 940 | name = "ra_hir" |
941 | version = "0.1.0" | 941 | version = "0.1.0" |
942 | dependencies = [ | 942 | dependencies = [ |
943 | "arrayvec", | ||
943 | "either", | 944 | "either", |
944 | "itertools", | 945 | "itertools", |
945 | "log", | 946 | "log", |
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 | |||
11 | log = "0.4.8" | 11 | log = "0.4.8" |
12 | rustc-hash = "1.1.0" | 12 | rustc-hash = "1.1.0" |
13 | either = "1.5.3" | 13 | either = "1.5.3" |
14 | arrayvec = "0.5.1" | ||
14 | 15 | ||
15 | itertools = "0.8.2" | 16 | itertools = "0.8.2" |
16 | 17 | ||
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 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use arrayvec::ArrayVec; | ||
4 | use either::Either; | 5 | use either::Either; |
5 | use hir_def::{ | 6 | use hir_def::{ |
6 | adt::StructKind, | 7 | adt::StructKind, |
@@ -226,7 +227,11 @@ impl Module { | |||
226 | Some((name, def)) | 227 | Some((name, def)) |
227 | } | 228 | } |
228 | }) | 229 | }) |
229 | .map(|(name, def)| (name.clone(), def.into())) | 230 | .flat_map(|(name, def)| |
231 | ScopeDef::all_items(def) | ||
232 | .into_iter() | ||
233 | .map(move |item| (name.clone(), item)) | ||
234 | ) | ||
230 | .collect() | 235 | .collect() |
231 | } | 236 | } |
232 | 237 | ||
@@ -1288,15 +1293,38 @@ pub enum ScopeDef { | |||
1288 | Unknown, | 1293 | Unknown, |
1289 | } | 1294 | } |
1290 | 1295 | ||
1291 | impl From<PerNs> for ScopeDef { | 1296 | impl ScopeDef { |
1292 | fn from(def: PerNs) -> Self { | 1297 | pub fn all_items(def: PerNs) -> ArrayVec<[Self; 3]> { |
1293 | def.take_types() | 1298 | let mut items = ArrayVec::new(); |
1294 | .or_else(|| def.take_values()) | 1299 | |
1295 | .map(|module_def_id| ScopeDef::ModuleDef(module_def_id.into())) | 1300 | match (def.take_types(), def.take_values()) { |
1296 | .or_else(|| { | 1301 | (Some(m1), None) => |
1297 | def.take_macros().map(|macro_def_id| ScopeDef::MacroDef(macro_def_id.into())) | 1302 | items.push(ScopeDef::ModuleDef(m1.into())), |
1298 | }) | 1303 | (None, Some(m2)) => |
1299 | .unwrap_or(ScopeDef::Unknown) | 1304 | items.push(ScopeDef::ModuleDef(m2.into())), |
1305 | (Some(m1), Some(m2)) => { | ||
1306 | // Some items, like unit structs and enum variants, are | ||
1307 | // returned as both a type and a value. Here we want | ||
1308 | // to de-duplicate them. | ||
1309 | if m1 != m2 { | ||
1310 | items.push(ScopeDef::ModuleDef(m1.into())); | ||
1311 | items.push(ScopeDef::ModuleDef(m2.into())); | ||
1312 | } else { | ||
1313 | items.push(ScopeDef::ModuleDef(m1.into())); | ||
1314 | } | ||
1315 | }, | ||
1316 | (None, None) => {}, | ||
1317 | }; | ||
1318 | |||
1319 | if let Some(macro_def_id) = def.take_macros() { | ||
1320 | items.push(ScopeDef::MacroDef(macro_def_id.into())); | ||
1321 | } | ||
1322 | |||
1323 | if items.is_empty() { | ||
1324 | items.push(ScopeDef::Unknown); | ||
1325 | } | ||
1326 | |||
1327 | items | ||
1300 | } | 1328 | } |
1301 | } | 1329 | } |
1302 | 1330 | ||
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> { | |||
344 | 344 | ||
345 | resolver.process_all_names(self.db, &mut |name, def| { | 345 | resolver.process_all_names(self.db, &mut |name, def| { |
346 | let def = match def { | 346 | let def = match def { |
347 | resolver::ScopeDef::PerNs(it) => it.into(), | 347 | resolver::ScopeDef::PerNs(it) => { |
348 | let items = ScopeDef::all_items(it); | ||
349 | for item in items { | ||
350 | f(name.clone(), item); | ||
351 | } | ||
352 | return | ||
353 | }, | ||
348 | resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), | 354 | resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), |
349 | resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), | 355 | resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), |
350 | resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(TypeParam { id }), | 356 | resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(TypeParam { id }), |
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index dda5ed699..3f33a75b9 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs | |||
@@ -102,6 +102,28 @@ fn crate_def_map_super_super() { | |||
102 | } | 102 | } |
103 | 103 | ||
104 | #[test] | 104 | #[test] |
105 | fn crate_def_map_fn_mod_same_name() { | ||
106 | let map = def_map( | ||
107 | " | ||
108 | //- /lib.rs | ||
109 | mod m { | ||
110 | pub mod z {} | ||
111 | pub fn z() {} | ||
112 | } | ||
113 | ", | ||
114 | ); | ||
115 | assert_snapshot!(map, @r###" | ||
116 | ⋮crate | ||
117 | ⋮m: t | ||
118 | ⋮ | ||
119 | ⋮crate::m | ||
120 | ⋮z: t v | ||
121 | ⋮ | ||
122 | ⋮crate::m::z | ||
123 | "###) | ||
124 | } | ||
125 | |||
126 | #[test] | ||
105 | fn bogus_paths() { | 127 | fn bogus_paths() { |
106 | covers!(bogus_paths); | 128 | covers!(bogus_paths); |
107 | let map = def_map( | 129 | let map = def_map( |
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs index d588ee364..648c1d39b 100644 --- a/crates/ra_ide/src/completion/complete_path.rs +++ b/crates/ra_ide/src/completion/complete_path.rs | |||
@@ -967,4 +967,43 @@ mod tests { | |||
967 | ] | 967 | ] |
968 | "###); | 968 | "###); |
969 | } | 969 | } |
970 | |||
971 | #[test] | ||
972 | fn function_mod_share_name() { | ||
973 | assert_debug_snapshot!( | ||
974 | do_reference_completion( | ||
975 | r" | ||
976 | fn foo() { | ||
977 | self::m::<|> | ||
978 | } | ||
979 | |||
980 | mod m { | ||
981 | pub mod z {} | ||
982 | pub fn z() {} | ||
983 | } | ||
984 | ", | ||
985 | ), | ||
986 | @r###" | ||
987 | [ | ||
988 | CompletionItem { | ||
989 | label: "z", | ||
990 | source_range: [57; 57), | ||
991 | delete: [57; 57), | ||
992 | insert: "z", | ||
993 | kind: Module, | ||
994 | }, | ||
995 | CompletionItem { | ||
996 | label: "z()", | ||
997 | source_range: [57; 57), | ||
998 | delete: [57; 57), | ||
999 | insert: "z()$0", | ||
1000 | kind: Function, | ||
1001 | lookup: "z", | ||
1002 | detail: "pub fn z()", | ||
1003 | }, | ||
1004 | ] | ||
1005 | "### | ||
1006 | ); | ||
1007 | } | ||
1008 | |||
970 | } | 1009 | } |