From 07a72859650254d8ba326e2c9683ae52164cb3b5 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Tue, 25 Dec 2018 13:31:30 +0100 Subject: Collect field data for structs/enum variants --- crates/ra_hir/src/adt.rs | 69 ++++++++++++++++++++++++++++++---- crates/ra_hir/src/function.rs | 3 +- crates/ra_hir/src/lib.rs | 6 +++ crates/ra_hir/src/query_definitions.rs | 10 ++++- crates/ra_hir/src/ty.rs | 11 +++++- 5 files changed, 87 insertions(+), 12 deletions(-) diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index ee270ac45..b44f59f0b 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -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 { 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 { 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::>()? + } 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 { + 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::>()?; + 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::>()?; + VariantData::Struct(fields) + } + StructFlavor::Unit => VariantData::Unit, + }) + } pub fn fields(&self) -> &[StructField] { match *self { VariantData::Struct(ref fields) | VariantData::Tuple(ref fields) => fields, diff --git a/crates/ra_hir/src/function.rs b/crates/ra_hir/src/function.rs index d36477b48..01f0f3a66 100644 --- a/crates/ra_hir/src/function.rs +++ b/crates/ra_hir/src/function.rs @@ -46,8 +46,7 @@ impl Function { } pub fn module(&self, db: &impl HirDatabase) -> Cancelable { - let loc = self.fn_id.0.loc(db); - Module::new(db, loc.source_root_id, loc.module_id) + self.fn_id.0.module(db) } } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 81526fe9c..796970d8a 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -135,6 +135,12 @@ impl DefId { }; Ok(res) } + + /// For a module, returns that module; for any other def, returns the containing module. + pub fn module(self, db: &impl HirDatabase) -> Cancelable { + 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 diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index 72440d1d6..405e359f1 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs @@ -52,7 +52,12 @@ pub(super) fn struct_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable Cancelable> { @@ -61,7 +66,8 @@ pub(super) fn enum_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable Arc { diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 386af8120..e2428a37f 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -156,6 +156,15 @@ impl Ty { Ok(ty) } + pub(crate) fn new_opt( + db: &impl HirDatabase, + module: &Module, + node: Option, + ) -> Cancelable { + 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 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { 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() { -- cgit v1.2.3