diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 56 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 8 |
3 files changed, 52 insertions, 13 deletions
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..ff041150b 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,9 @@ 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).into_iter().map(move |item| (name.clone(), item)) | ||
232 | }) | ||
230 | .collect() | 233 | .collect() |
231 | } | 234 | } |
232 | 235 | ||
@@ -308,7 +311,11 @@ impl StructField { | |||
308 | self.parent.variant_data(db).fields()[self.id].name.clone() | 311 | self.parent.variant_data(db).fields()[self.id].name.clone() |
309 | } | 312 | } |
310 | 313 | ||
311 | pub fn ty(&self, db: &impl HirDatabase) -> Type { | 314 | /// Returns the type as in the signature of the struct (i.e., with |
315 | /// placeholder types for type parameters). This is good for showing | ||
316 | /// signature help, but not so good to actually get the type of the field | ||
317 | /// when you actually have a variable of the struct. | ||
318 | pub fn signature_ty(&self, db: &impl HirDatabase) -> Type { | ||
312 | let var_id = self.parent.into(); | 319 | let var_id = self.parent.into(); |
313 | let generic_def_id: GenericDefId = match self.parent { | 320 | let generic_def_id: GenericDefId = match self.parent { |
314 | VariantDef::Struct(it) => it.id.into(), | 321 | VariantDef::Struct(it) => it.id.into(), |
@@ -482,6 +489,10 @@ impl Adt { | |||
482 | let subst = db.generic_defaults(self.into()); | 489 | let subst = db.generic_defaults(self.into()); |
483 | subst.iter().any(|ty| ty == &Ty::Unknown) | 490 | subst.iter().any(|ty| ty == &Ty::Unknown) |
484 | } | 491 | } |
492 | |||
493 | /// Turns this ADT into a type. Any type parameters of the ADT will be | ||
494 | /// turned into unknown types, which is good for e.g. finding the most | ||
495 | /// general set of completions, but will not look very nice when printed. | ||
485 | pub fn ty(self, db: &impl HirDatabase) -> Type { | 496 | pub fn ty(self, db: &impl HirDatabase) -> Type { |
486 | let id = AdtId::from(self); | 497 | let id = AdtId::from(self); |
487 | Type::from_def(db, id.module(db).krate, id) | 498 | Type::from_def(db, id.module(db).krate, id) |
@@ -1028,7 +1039,7 @@ impl Type { | |||
1028 | krate: CrateId, | 1039 | krate: CrateId, |
1029 | def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>, | 1040 | def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>, |
1030 | ) -> Type { | 1041 | ) -> Type { |
1031 | let substs = Substs::type_params(db, def); | 1042 | let substs = Substs::build_for_def(db, def).fill_with_unknown().build(); |
1032 | let ty = db.ty(def.into()).subst(&substs); | 1043 | let ty = db.ty(def.into()).subst(&substs); |
1033 | Type::new(db, krate, def, ty) | 1044 | Type::new(db, krate, def, ty) |
1034 | } | 1045 | } |
@@ -1288,15 +1299,36 @@ pub enum ScopeDef { | |||
1288 | Unknown, | 1299 | Unknown, |
1289 | } | 1300 | } |
1290 | 1301 | ||
1291 | impl From<PerNs> for ScopeDef { | 1302 | impl ScopeDef { |
1292 | fn from(def: PerNs) -> Self { | 1303 | pub fn all_items(def: PerNs) -> ArrayVec<[Self; 3]> { |
1293 | def.take_types() | 1304 | let mut items = ArrayVec::new(); |
1294 | .or_else(|| def.take_values()) | 1305 | |
1295 | .map(|module_def_id| ScopeDef::ModuleDef(module_def_id.into())) | 1306 | match (def.take_types(), def.take_values()) { |
1296 | .or_else(|| { | 1307 | (Some(m1), None) => items.push(ScopeDef::ModuleDef(m1.into())), |
1297 | def.take_macros().map(|macro_def_id| ScopeDef::MacroDef(macro_def_id.into())) | 1308 | (None, Some(m2)) => items.push(ScopeDef::ModuleDef(m2.into())), |
1298 | }) | 1309 | (Some(m1), Some(m2)) => { |
1299 | .unwrap_or(ScopeDef::Unknown) | 1310 | // Some items, like unit structs and enum variants, are |
1311 | // returned as both a type and a value. Here we want | ||
1312 | // to de-duplicate them. | ||
1313 | if m1 != m2 { | ||
1314 | items.push(ScopeDef::ModuleDef(m1.into())); | ||
1315 | items.push(ScopeDef::ModuleDef(m2.into())); | ||
1316 | } else { | ||
1317 | items.push(ScopeDef::ModuleDef(m1.into())); | ||
1318 | } | ||
1319 | } | ||
1320 | (None, None) => {} | ||
1321 | }; | ||
1322 | |||
1323 | if let Some(macro_def_id) = def.take_macros() { | ||
1324 | items.push(ScopeDef::MacroDef(macro_def_id.into())); | ||
1325 | } | ||
1326 | |||
1327 | if items.is_empty() { | ||
1328 | items.push(ScopeDef::Unknown); | ||
1329 | } | ||
1330 | |||
1331 | items | ||
1300 | } | 1332 | } |
1301 | } | 1333 | } |
1302 | 1334 | ||
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 3782a9984..788bb3eb7 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 }), |