aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/adt.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/adt.rs')
-rw-r--r--crates/ra_hir_def/src/adt.rs114
1 files changed, 114 insertions, 0 deletions
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 @@
1//! Defines hir-level representation of structs, enums and unions
2
3use std::sync::Arc;
4
5use hir_expand::name::{AsName, Name};
6use ra_arena::Arena;
7use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
8
9use crate::{
10 db::DefDatabase2, type_ref::TypeRef, AstItemDef, EnumId, LocalEnumVariantId,
11 LocalStructFieldId, StructId,
12};
13
14/// Note that we use `StructData` for unions as well!
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct StructData {
17 pub name: Option<Name>,
18 pub variant_data: Arc<VariantData>,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct EnumData {
23 pub name: Option<Name>,
24 pub variants: Arena<LocalEnumVariantId, EnumVariantData>,
25}
26
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct EnumVariantData {
29 pub name: Option<Name>,
30 pub variant_data: Arc<VariantData>,
31}
32
33/// Fields of an enum variant or struct
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct VariantData(VariantDataInner);
36
37#[derive(Debug, Clone, PartialEq, Eq)]
38enum VariantDataInner {
39 Struct(Arena<LocalStructFieldId, StructFieldData>),
40 Tuple(Arena<LocalStructFieldId, StructFieldData>),
41 Unit,
42}
43
44/// A single field of an enum variant or struct
45#[derive(Debug, Clone, PartialEq, Eq)]
46pub struct StructFieldData {
47 pub name: Name,
48 pub type_ref: TypeRef,
49}
50
51impl StructData {
52 pub(crate) fn struct_data_query(db: &impl DefDatabase2, struct_: StructId) -> Arc<StructData> {
53 let src = struct_.source(db);
54 let name = src.ast.name().map(|n| n.as_name());
55 let variant_data = VariantData::new(src.ast.kind());
56 let variant_data = Arc::new(variant_data);
57 Arc::new(StructData { name, variant_data })
58 }
59}
60
61impl EnumData {
62 pub(crate) fn enum_data_query(db: &impl DefDatabase2, e: EnumId) -> Arc<EnumData> {
63 let src = e.source(db);
64 let name = src.ast.name().map(|n| n.as_name());
65 let variants = src
66 .ast
67 .variant_list()
68 .into_iter()
69 .flat_map(|it| it.variants())
70 .map(|var| EnumVariantData {
71 name: var.name().map(|it| it.as_name()),
72 variant_data: Arc::new(VariantData::new(var.kind())),
73 })
74 .collect();
75 Arc::new(EnumData { name, variants })
76 }
77}
78
79impl VariantData {
80 fn new(flavor: ast::StructKind) -> Self {
81 let inner = match flavor {
82 ast::StructKind::Tuple(fl) => {
83 let fields = fl
84 .fields()
85 .enumerate()
86 .map(|(i, fd)| StructFieldData {
87 name: Name::new_tuple_field(i),
88 type_ref: TypeRef::from_ast_opt(fd.type_ref()),
89 })
90 .collect();
91 VariantDataInner::Tuple(fields)
92 }
93 ast::StructKind::Named(fl) => {
94 let fields = fl
95 .fields()
96 .map(|fd| StructFieldData {
97 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
98 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()),
99 })
100 .collect();
101 VariantDataInner::Struct(fields)
102 }
103 ast::StructKind::Unit => VariantDataInner::Unit,
104 };
105 VariantData(inner)
106 }
107
108 pub fn fields(&self) -> Option<&Arena<LocalStructFieldId, StructFieldData>> {
109 match &self.0 {
110 VariantDataInner::Struct(fields) | VariantDataInner::Tuple(fields) => Some(fields),
111 _ => None,
112 }
113 }
114}