aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r--crates/ra_hir/src/code_model.rs56
1 files changed, 44 insertions, 12 deletions
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
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use arrayvec::ArrayVec;
4use either::Either; 5use either::Either;
5use hir_def::{ 6use 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
1291impl From<PerNs> for ScopeDef { 1302impl 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