]> git.lizzy.rs Git - rust.git/commitdiff
Collect field data for structs/enum variants
authorFlorian Diebold <flodiebold@gmail.com>
Tue, 25 Dec 2018 12:31:30 +0000 (13:31 +0100)
committerFlorian Diebold <flodiebold@gmail.com>
Tue, 25 Dec 2018 14:16:42 +0000 (15:16 +0100)
crates/ra_hir/src/adt.rs
crates/ra_hir/src/function.rs
crates/ra_hir/src/lib.rs
crates/ra_hir/src/query_definitions.rs
crates/ra_hir/src/ty.rs

index ee270ac459d7001443aa860af556804d6667314a..b44f59f0b899b21c7f9ff6021b01f8ab90091f7d 100644 (file)
@@ -1,10 +1,11 @@
 use std::sync::Arc;
 
-use ra_syntax::{SmolStr, ast::{self, NameOwner}};
+use ra_syntax::{SmolStr, ast::{self, NameOwner, StructFlavor}};
 
 use crate::{
     DefId, Cancelable,
     db::{HirDatabase},
+    module::Module,
     ty::{Ty},
 };
 
@@ -37,14 +38,18 @@ pub struct StructData {
 }
 
 impl StructData {
-    pub(crate) fn new(struct_def: ast::StructDef) -> StructData {
+    pub(crate) fn new(
+        db: &impl HirDatabase,
+        module: &Module,
+        struct_def: ast::StructDef,
+    ) -> Cancelable<StructData> {
         let name = struct_def
             .name()
             .map(|n| n.text())
             .unwrap_or(SmolStr::new("[error]"));
-        let variant_data = VariantData::Unit; // TODO implement this
+        let variant_data = VariantData::new(db, module, struct_def.flavor())?;
         let variant_data = Arc::new(variant_data);
-        StructData { name, variant_data }
+        Ok(StructData { name, variant_data })
     }
 
     pub fn name(&self) -> &SmolStr {
@@ -81,13 +86,30 @@ pub struct EnumData {
 }
 
 impl EnumData {
-    pub(crate) fn new(enum_def: ast::EnumDef) -> Self {
+    pub(crate) fn new(
+        db: &impl HirDatabase,
+        module: &Module,
+        enum_def: ast::EnumDef,
+    ) -> Cancelable<Self> {
         let name = enum_def
             .name()
             .map(|n| n.text())
             .unwrap_or(SmolStr::new("[error]"));
-        let variants = Vec::new(); // TODO implement this
-        EnumData { name, variants }
+        let variants = if let Some(evl) = enum_def.variant_list() {
+            evl.variants()
+                .map(|v| {
+                    Ok((
+                        v.name()
+                            .map(|n| n.text())
+                            .unwrap_or_else(|| SmolStr::new("[error]")),
+                        Arc::new(VariantData::new(db, module, v.flavor())?),
+                    ))
+                })
+                .collect::<Cancelable<_>>()?
+        } else {
+            Vec::new()
+        };
+        Ok(EnumData { name, variants })
     }
 }
 
@@ -107,6 +129,39 @@ pub enum VariantData {
 }
 
 impl VariantData {
+    pub fn new(db: &impl HirDatabase, module: &Module, flavor: StructFlavor) -> Cancelable<Self> {
+        Ok(match flavor {
+            StructFlavor::Tuple(fl) => {
+                let fields = fl
+                    .fields()
+                    .enumerate()
+                    .map(|(i, fd)| {
+                        Ok(StructField {
+                            name: SmolStr::new(i.to_string()),
+                            ty: Ty::new_opt(db, &module, fd.type_ref())?,
+                        })
+                    })
+                    .collect::<Cancelable<_>>()?;
+                VariantData::Tuple(fields)
+            }
+            StructFlavor::Named(fl) => {
+                let fields = fl
+                    .fields()
+                    .map(|fd| {
+                        Ok(StructField {
+                            name: fd
+                                .name()
+                                .map(|n| n.text())
+                                .unwrap_or_else(|| SmolStr::new("[error]")),
+                            ty: Ty::new_opt(db, &module, fd.type_ref())?,
+                        })
+                    })
+                    .collect::<Cancelable<_>>()?;
+                VariantData::Struct(fields)
+            }
+            StructFlavor::Unit => VariantData::Unit,
+        })
+    }
     pub fn fields(&self) -> &[StructField] {
         match *self {
             VariantData::Struct(ref fields) | VariantData::Tuple(ref fields) => fields,
index d36477b48d1dbb045fbda5f524d5fcb082fcc7c4..01f0f3a662545a36346fae98b9b295b5030665ed 100644 (file)
@@ -46,8 +46,7 @@ pub fn infer(&self, db: &impl HirDatabase) -> Cancelable<Arc<InferenceResult>> {
     }
 
     pub fn module(&self, db: &impl HirDatabase) -> Cancelable<Module> {
-        let loc = self.fn_id.0.loc(db);
-        Module::new(db, loc.source_root_id, loc.module_id)
+        self.fn_id.0.module(db)
     }
 }
 
index 81526fe9cab91c3d2662694d803b9a7714bbb0a1..796970d8a2de608194c257dcac6028955c453249 100644 (file)
@@ -135,6 +135,12 @@ pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
         };
         Ok(res)
     }
+
+    /// For a module, returns that module; for any other def, returns the containing module.
+    pub fn module(self, db: &impl HirDatabase) -> Cancelable<Module> {
+        let loc = self.loc(db);
+        Module::new(db, loc.source_root_id, loc.module_id)
+    }
 }
 
 /// Identifier of item within a specific file. This is stable over reparses, so
index 72440d1d6f3896cc6f632977f72b3c18fc7b9eaa..405e359f1ce0be41f13a64bf3679c13ee302e9b3 100644 (file)
@@ -52,7 +52,12 @@ pub(super) fn struct_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ar
     let syntax = db.file_item(def_loc.source_item_id);
     let struct_def =
         ast::StructDef::cast(syntax.borrowed()).expect("struct def should point to StructDef node");
-    Ok(Arc::new(StructData::new(struct_def.borrowed())))
+    let module = def_id.module(db)?;
+    Ok(Arc::new(StructData::new(
+        db,
+        &module,
+        struct_def.borrowed(),
+    )?))
 }
 
 pub(super) fn enum_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<EnumData>> {
@@ -61,7 +66,8 @@ pub(super) fn enum_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<
     let syntax = db.file_item(def_loc.source_item_id);
     let enum_def =
         ast::EnumDef::cast(syntax.borrowed()).expect("enum def should point to EnumDef node");
-    Ok(Arc::new(EnumData::new(enum_def.borrowed())))
+    let module = def_id.module(db)?;
+    Ok(Arc::new(EnumData::new(db, &module, enum_def.borrowed())?))
 }
 
 pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFileItems> {
index 386af8120abf074b63616622c0e88200d40e75f2..e2428a37f63ee76bebc1cc5dd0db3d3cd1672a98 100644 (file)
@@ -156,6 +156,15 @@ pub(crate) fn new_from_ast_path(
         Ok(ty)
     }
 
+    pub(crate) fn new_opt(
+        db: &impl HirDatabase,
+        module: &Module,
+        node: Option<ast::TypeRef>,
+    ) -> Cancelable<Self> {
+        node.map(|n| Ty::new(db, module, n))
+            .unwrap_or(Ok(Ty::Unknown))
+    }
+
     pub(crate) fn new(
         db: &impl HirDatabase,
         module: &Module,
@@ -534,7 +543,7 @@ fn infer_expr(&mut self, expr: ast::Expr) -> Cancelable<Ty> {
                 Ty::Unknown
             }
             ast::Expr::StructLit(e) => {
-                let (ty, variant_data) = self.resolve_variant(e.path())?;
+                let (ty, _variant_data) = self.resolve_variant(e.path())?;
                 if let Some(nfl) = e.named_field_list() {
                     for field in nfl.fields() {
                         if let Some(e) = field.expr() {