From 09f9733ca67b74057c55b6e96f38223a73db6a6e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 31 Oct 2019 16:40:36 +0300 Subject: move struct & enum data to hir_def --- crates/ra_hir_def/src/adt.rs | 114 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 crates/ra_hir_def/src/adt.rs (limited to 'crates/ra_hir_def/src/adt.rs') diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs new file mode 100644 index 000000000..22bd469f0 --- /dev/null +++ b/crates/ra_hir_def/src/adt.rs @@ -0,0 +1,114 @@ +//! Defines hir-level representation of structs, enums and unions + +use std::sync::Arc; + +use hir_expand::name::{AsName, Name}; +use ra_arena::Arena; +use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; + +use crate::{ + db::DefDatabase2, type_ref::TypeRef, AstItemDef, EnumId, LocalEnumVariantId, + LocalStructFieldId, StructId, +}; + +/// Note that we use `StructData` for unions as well! +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct StructData { + pub name: Option, + pub variant_data: Arc, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct EnumData { + pub name: Option, + pub variants: Arena, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct EnumVariantData { + pub name: Option, + pub variant_data: Arc, +} + +/// Fields of an enum variant or struct +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct VariantData(VariantDataInner); + +#[derive(Debug, Clone, PartialEq, Eq)] +enum VariantDataInner { + Struct(Arena), + Tuple(Arena), + Unit, +} + +/// A single field of an enum variant or struct +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct StructFieldData { + pub name: Name, + pub type_ref: TypeRef, +} + +impl StructData { + pub(crate) fn struct_data_query(db: &impl DefDatabase2, struct_: StructId) -> Arc { + let src = struct_.source(db); + let name = src.ast.name().map(|n| n.as_name()); + let variant_data = VariantData::new(src.ast.kind()); + let variant_data = Arc::new(variant_data); + Arc::new(StructData { name, variant_data }) + } +} + +impl EnumData { + pub(crate) fn enum_data_query(db: &impl DefDatabase2, e: EnumId) -> Arc { + let src = e.source(db); + let name = src.ast.name().map(|n| n.as_name()); + let variants = src + .ast + .variant_list() + .into_iter() + .flat_map(|it| it.variants()) + .map(|var| EnumVariantData { + name: var.name().map(|it| it.as_name()), + variant_data: Arc::new(VariantData::new(var.kind())), + }) + .collect(); + Arc::new(EnumData { name, variants }) + } +} + +impl VariantData { + fn new(flavor: ast::StructKind) -> Self { + let inner = match flavor { + ast::StructKind::Tuple(fl) => { + let fields = fl + .fields() + .enumerate() + .map(|(i, fd)| StructFieldData { + name: Name::new_tuple_field(i), + type_ref: TypeRef::from_ast_opt(fd.type_ref()), + }) + .collect(); + VariantDataInner::Tuple(fields) + } + ast::StructKind::Named(fl) => { + let fields = fl + .fields() + .map(|fd| StructFieldData { + name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), + type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), + }) + .collect(); + VariantDataInner::Struct(fields) + } + ast::StructKind::Unit => VariantDataInner::Unit, + }; + VariantData(inner) + } + + pub fn fields(&self) -> Option<&Arena> { + match &self.0 { + VariantDataInner::Struct(fields) | VariantDataInner::Tuple(fields) => Some(fields), + _ => None, + } + } +} -- cgit v1.2.3