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 +++++++++++++++++++++++++++++++++++++++++++ crates/ra_hir_def/src/db.rs | 12 ++++- crates/ra_hir_def/src/lib.rs | 17 +++++++ 3 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 crates/ra_hir_def/src/adt.rs (limited to 'crates/ra_hir_def/src') 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, + } + } +} diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index b271636b0..f6027013f 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -5,7 +5,11 @@ use hir_expand::{db::AstDatabase, HirFileId}; use ra_db::{salsa, SourceDatabase}; use ra_syntax::ast; -use crate::nameres::raw::{ImportSourceMap, RawItems}; +use crate::{ + adt::{EnumData, StructData}, + nameres::raw::{ImportSourceMap, RawItems}, + EnumId, StructId, +}; #[salsa::query_group(InternDatabaseStorage)] pub trait InternDatabase: SourceDatabase { @@ -37,4 +41,10 @@ pub trait DefDatabase2: InternDatabase + AstDatabase { #[salsa::invoke(RawItems::raw_items_query)] fn raw_items(&self, file_id: HirFileId) -> Arc; + + #[salsa::invoke(StructData::struct_data_query)] + fn struct_data(&self, s: StructId) -> Arc; + + #[salsa::invoke(EnumData::enum_data_query)] + fn enum_data(&self, e: EnumId) -> Arc; } diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 93ad40005..76d5f1852 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -12,6 +12,7 @@ pub mod attr; pub mod path; pub mod type_ref; pub mod builtin_type; +pub mod adt; // FIXME: this should be private pub mod nameres; @@ -259,6 +260,22 @@ pub struct EnumVariantId { pub struct LocalEnumVariantId(RawId); impl_arena_id!(LocalEnumVariantId); +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum VariantId { + EnumVariantId(EnumVariantId), + StructId(StructId), +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct StructFieldId { + parent: VariantId, + local_id: LocalStructFieldId, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct LocalStructFieldId(RawId); +impl_arena_id!(LocalStructFieldId); + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ConstId(salsa::InternId); impl_intern_key!(ConstId); -- cgit v1.2.3