aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/adt.rs176
-rw-r--r--crates/ra_hir/src/code_model.rs31
-rw-r--r--crates/ra_hir/src/code_model/src.rs42
-rw-r--r--crates/ra_hir/src/db.rs15
-rw-r--r--crates/ra_hir/src/ty/lower.rs8
-rw-r--r--crates/ra_hir_def/src/adt.rs114
-rw-r--r--crates/ra_hir_def/src/db.rs12
-rw-r--r--crates/ra_hir_def/src/lib.rs17
8 files changed, 214 insertions, 201 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index 4fa2062bd..0436d20b7 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -3,152 +3,16 @@
3 3
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use hir_def::{type_ref::TypeRef, LocalEnumVariantId}; 6use hir_def::adt::VariantData;
7use hir_expand::name::AsName;
8use ra_arena::{impl_arena_id, Arena, RawId};
9use ra_syntax::ast::{self, NameOwner, StructKind, TypeAscriptionOwner};
10 7
11use crate::{ 8use crate::{
12 db::{AstDatabase, DefDatabase, HirDatabase}, 9 db::{DefDatabase, HirDatabase},
13 Enum, EnumVariant, FieldSource, HasSource, Module, Name, Source, Struct, StructField, 10 EnumVariant, Module, Name, Struct, StructField,
14}; 11};
15 12
16impl Struct { 13impl Struct {
17 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { 14 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
18 db.struct_data(self).variant_data.clone() 15 db.struct_data(self.id).variant_data.clone()
19 }
20}
21
22/// Note that we use `StructData` for unions as well!
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub struct StructData {
25 pub(crate) name: Option<Name>,
26 pub(crate) variant_data: Arc<VariantData>,
27}
28
29impl StructData {
30 fn new(struct_def: &ast::StructDef) -> StructData {
31 let name = struct_def.name().map(|n| n.as_name());
32 let variant_data = VariantData::new(struct_def.kind());
33 let variant_data = Arc::new(variant_data);
34 StructData { name, variant_data }
35 }
36
37 pub(crate) fn struct_data_query(
38 db: &(impl DefDatabase + AstDatabase),
39 struct_: Struct,
40 ) -> Arc<StructData> {
41 let src = struct_.source(db);
42 Arc::new(StructData::new(&src.ast))
43 }
44}
45
46fn variants(enum_def: &ast::EnumDef) -> impl Iterator<Item = ast::EnumVariant> {
47 enum_def.variant_list().into_iter().flat_map(|it| it.variants())
48}
49
50impl EnumVariant {
51 pub(crate) fn source_impl(
52 self,
53 db: &(impl DefDatabase + AstDatabase),
54 ) -> Source<ast::EnumVariant> {
55 let src = self.parent.source(db);
56 let ast = variants(&src.ast)
57 .zip(db.enum_data(self.parent).variants.iter())
58 .find(|(_syntax, (id, _))| *id == self.id)
59 .unwrap()
60 .0;
61 Source { file_id: src.file_id, ast }
62 }
63 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
64 db.enum_data(self.parent).variants[self.id].variant_data.clone()
65 }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq)]
69pub struct EnumData {
70 pub(crate) name: Option<Name>,
71 pub(crate) variants: Arena<LocalEnumVariantId, EnumVariantData>,
72}
73
74impl EnumData {
75 pub(crate) fn enum_data_query(db: &(impl DefDatabase + AstDatabase), e: Enum) -> Arc<EnumData> {
76 let src = e.source(db);
77 let name = src.ast.name().map(|n| n.as_name());
78 let variants = variants(&src.ast)
79 .map(|var| EnumVariantData {
80 name: var.name().map(|it| it.as_name()),
81 variant_data: Arc::new(VariantData::new(var.kind())),
82 })
83 .collect();
84 Arc::new(EnumData { name, variants })
85 }
86}
87
88#[derive(Debug, Clone, PartialEq, Eq)]
89pub(crate) struct EnumVariantData {
90 pub(crate) name: Option<Name>,
91 variant_data: Arc<VariantData>,
92}
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
95pub(crate) struct StructFieldId(RawId);
96impl_arena_id!(StructFieldId);
97
98/// A single field of an enum variant or struct
99#[derive(Debug, Clone, PartialEq, Eq)]
100pub struct StructFieldData {
101 pub(crate) name: Name,
102 pub(crate) type_ref: TypeRef,
103}
104
105/// Fields of an enum variant or struct
106#[derive(Debug, Clone, PartialEq, Eq)]
107pub(crate) struct VariantData(VariantDataInner);
108
109#[derive(Debug, Clone, PartialEq, Eq)]
110enum VariantDataInner {
111 Struct(Arena<StructFieldId, StructFieldData>),
112 Tuple(Arena<StructFieldId, StructFieldData>),
113 Unit,
114}
115
116impl VariantData {
117 pub(crate) fn fields(&self) -> Option<&Arena<StructFieldId, StructFieldData>> {
118 match &self.0 {
119 VariantDataInner::Struct(fields) | VariantDataInner::Tuple(fields) => Some(fields),
120 _ => None,
121 }
122 }
123}
124
125impl VariantData {
126 fn new(flavor: StructKind) -> Self {
127 let inner = match flavor {
128 ast::StructKind::Tuple(fl) => {
129 let fields = fl
130 .fields()
131 .enumerate()
132 .map(|(i, fd)| StructFieldData {
133 name: Name::new_tuple_field(i),
134 type_ref: TypeRef::from_ast_opt(fd.type_ref()),
135 })
136 .collect();
137 VariantDataInner::Tuple(fields)
138 }
139 ast::StructKind::Named(fl) => {
140 let fields = fl
141 .fields()
142 .map(|fd| StructFieldData {
143 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
144 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()),
145 })
146 .collect();
147 VariantDataInner::Struct(fields)
148 }
149 ast::StructKind::Unit => VariantDataInner::Unit,
150 };
151 VariantData(inner)
152 } 16 }
153} 17}
154 18
@@ -188,35 +52,3 @@ impl VariantDef {
188 } 52 }
189 } 53 }
190} 54}
191
192impl StructField {
193 pub(crate) fn source_impl(&self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> {
194 let var_data = self.parent.variant_data(db);
195 let fields = var_data.fields().unwrap();
196 let ss;
197 let es;
198 let (file_id, struct_kind) = match self.parent {
199 VariantDef::Struct(s) => {
200 ss = s.source(db);
201 (ss.file_id, ss.ast.kind())
202 }
203 VariantDef::EnumVariant(e) => {
204 es = e.source(db);
205 (es.file_id, es.ast.kind())
206 }
207 };
208
209 let field_sources = match struct_kind {
210 ast::StructKind::Tuple(fl) => fl.fields().map(|it| FieldSource::Pos(it)).collect(),
211 ast::StructKind::Named(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(),
212 ast::StructKind::Unit => Vec::new(),
213 };
214 let ast = field_sources
215 .into_iter()
216 .zip(fields.iter())
217 .find(|(_syntax, (id, _))| *id == self.id)
218 .unwrap()
219 .0;
220 Source { file_id, ast }
221 }
222}
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index b32aa145e..ae6ef7606 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -6,16 +6,17 @@ pub(crate) mod docs;
6use std::sync::Arc; 6use std::sync::Arc;
7 7
8use hir_def::{ 8use hir_def::{
9 adt::VariantData,
9 builtin_type::BuiltinType, 10 builtin_type::BuiltinType,
10 type_ref::{Mutability, TypeRef}, 11 type_ref::{Mutability, TypeRef},
11 CrateModuleId, LocalEnumVariantId, ModuleId, 12 CrateModuleId, LocalEnumVariantId, LocalStructFieldId, ModuleId,
12}; 13};
13use hir_expand::name::{self, AsName}; 14use hir_expand::name::{self, AsName};
14use ra_db::{CrateId, Edition}; 15use ra_db::{CrateId, Edition};
15use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 16use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
16 17
17use crate::{ 18use crate::{
18 adt::{StructFieldId, VariantDef}, 19 adt::VariantDef,
19 db::{AstDatabase, DefDatabase, HirDatabase}, 20 db::{AstDatabase, DefDatabase, HirDatabase},
20 diagnostics::DiagnosticSink, 21 diagnostics::DiagnosticSink,
21 expr::{validation::ExprValidator, Body, BodySourceMap}, 22 expr::{validation::ExprValidator, Body, BodySourceMap},
@@ -250,7 +251,7 @@ impl Module {
250#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 251#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
251pub struct StructField { 252pub struct StructField {
252 pub(crate) parent: VariantDef, 253 pub(crate) parent: VariantDef,
253 pub(crate) id: StructFieldId, 254 pub(crate) id: LocalStructFieldId,
254} 255}
255 256
256#[derive(Debug, PartialEq, Eq)] 257#[derive(Debug, PartialEq, Eq)]
@@ -288,11 +289,11 @@ impl Struct {
288 } 289 }
289 290
290 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 291 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
291 db.struct_data(self).name.clone() 292 db.struct_data(self.id).name.clone()
292 } 293 }
293 294
294 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { 295 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
295 db.struct_data(self) 296 db.struct_data(self.id)
296 .variant_data 297 .variant_data
297 .fields() 298 .fields()
298 .into_iter() 299 .into_iter()
@@ -302,7 +303,7 @@ impl Struct {
302 } 303 }
303 304
304 pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { 305 pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
305 db.struct_data(self) 306 db.struct_data(self.id)
306 .variant_data 307 .variant_data
307 .fields() 308 .fields()
308 .into_iter() 309 .into_iter()
@@ -338,7 +339,7 @@ pub struct Union {
338 339
339impl Union { 340impl Union {
340 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 341 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
341 db.struct_data(Struct { id: self.id }).name.clone() 342 db.struct_data(self.id).name.clone()
342 } 343 }
343 344
344 pub fn module(self, db: &impl HirDatabase) -> Module { 345 pub fn module(self, db: &impl HirDatabase) -> Module {
@@ -376,15 +377,19 @@ impl Enum {
376 } 377 }
377 378
378 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 379 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
379 db.enum_data(self).name.clone() 380 db.enum_data(self.id).name.clone()
380 } 381 }
381 382
382 pub fn variants(self, db: &impl DefDatabase) -> Vec<EnumVariant> { 383 pub fn variants(self, db: &impl DefDatabase) -> Vec<EnumVariant> {
383 db.enum_data(self).variants.iter().map(|(id, _)| EnumVariant { parent: self, id }).collect() 384 db.enum_data(self.id)
385 .variants
386 .iter()
387 .map(|(id, _)| EnumVariant { parent: self, id })
388 .collect()
384 } 389 }
385 390
386 pub fn variant(self, db: &impl DefDatabase, name: &Name) -> Option<EnumVariant> { 391 pub fn variant(self, db: &impl DefDatabase, name: &Name) -> Option<EnumVariant> {
387 db.enum_data(self) 392 db.enum_data(self.id)
388 .variants 393 .variants
389 .iter() 394 .iter()
390 .find(|(_id, data)| data.name.as_ref() == Some(name)) 395 .find(|(_id, data)| data.name.as_ref() == Some(name))
@@ -422,7 +427,7 @@ impl EnumVariant {
422 } 427 }
423 428
424 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 429 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
425 db.enum_data(self.parent).variants[self.id].name.clone() 430 db.enum_data(self.parent.id).variants[self.id].name.clone()
426 } 431 }
427 432
428 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { 433 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
@@ -442,6 +447,10 @@ impl EnumVariant {
442 .find(|(_id, data)| data.name == *name) 447 .find(|(_id, data)| data.name == *name)
443 .map(|(id, _)| StructField { parent: self.into(), id }) 448 .map(|(id, _)| StructField { parent: self.into(), id })
444 } 449 }
450
451 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
452 db.enum_data(self.parent.id).variants[self.id].variant_data.clone()
453 }
445} 454}
446 455
447/// A Data Type 456/// A Data Type
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index 5c7f61eef..0f4c78df7 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -3,6 +3,7 @@
3use ra_syntax::ast::{self, AstNode}; 3use ra_syntax::ast::{self, AstNode};
4 4
5use crate::{ 5use crate::{
6 adt::VariantDef,
6 db::{AstDatabase, DefDatabase, HirDatabase}, 7 db::{AstDatabase, DefDatabase, HirDatabase},
7 ids::AstItemDef, 8 ids::AstItemDef,
8 Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module, 9 Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module,
@@ -45,7 +46,33 @@ impl Module {
45impl HasSource for StructField { 46impl HasSource for StructField {
46 type Ast = FieldSource; 47 type Ast = FieldSource;
47 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> { 48 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> {
48 self.source_impl(db) 49 let var_data = self.parent.variant_data(db);
50 let fields = var_data.fields().unwrap();
51 let ss;
52 let es;
53 let (file_id, struct_kind) = match self.parent {
54 VariantDef::Struct(s) => {
55 ss = s.source(db);
56 (ss.file_id, ss.ast.kind())
57 }
58 VariantDef::EnumVariant(e) => {
59 es = e.source(db);
60 (es.file_id, es.ast.kind())
61 }
62 };
63
64 let field_sources = match struct_kind {
65 ast::StructKind::Tuple(fl) => fl.fields().map(|it| FieldSource::Pos(it)).collect(),
66 ast::StructKind::Named(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(),
67 ast::StructKind::Unit => Vec::new(),
68 };
69 let ast = field_sources
70 .into_iter()
71 .zip(fields.iter())
72 .find(|(_syntax, (id, _))| *id == self.id)
73 .unwrap()
74 .0;
75 Source { file_id, ast }
49 } 76 }
50} 77}
51impl HasSource for Struct { 78impl HasSource for Struct {
@@ -69,7 +96,18 @@ impl HasSource for Enum {
69impl HasSource for EnumVariant { 96impl HasSource for EnumVariant {
70 type Ast = ast::EnumVariant; 97 type Ast = ast::EnumVariant;
71 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumVariant> { 98 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumVariant> {
72 self.source_impl(db) 99 let enum_data = db.enum_data(self.parent.id);
100 let src = self.parent.id.source(db);
101 let ast = src
102 .ast
103 .variant_list()
104 .into_iter()
105 .flat_map(|it| it.variants())
106 .zip(enum_data.variants.iter())
107 .find(|(_syntax, (id, _))| *id == self.id)
108 .unwrap()
109 .0;
110 Source { file_id: src.file_id, ast }
73 } 111 }
74} 112}
75impl HasSource for Function { 113impl HasSource for Function {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index ebfd970eb..89ca4e39f 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -6,7 +6,6 @@ use ra_db::salsa;
6use ra_syntax::SmolStr; 6use ra_syntax::SmolStr;
7 7
8use crate::{ 8use crate::{
9 adt::{EnumData, StructData},
10 debug::HirDebugDatabase, 9 debug::HirDebugDatabase,
11 generics::{GenericDef, GenericParams}, 10 generics::{GenericDef, GenericParams},
12 ids, 11 ids,
@@ -19,13 +18,13 @@ use crate::{
19 InferenceResult, Substs, Ty, TypableDef, TypeCtor, 18 InferenceResult, Substs, Ty, TypableDef, TypeCtor,
20 }, 19 },
21 type_alias::TypeAliasData, 20 type_alias::TypeAliasData,
22 Const, ConstData, Crate, DefWithBody, Enum, ExprScopes, FnData, Function, Module, Static, 21 Const, ConstData, Crate, DefWithBody, ExprScopes, FnData, Function, Module, Static,
23 Struct, StructField, Trait, TypeAlias, 22 StructField, Trait, TypeAlias,
24}; 23};
25 24
26pub use hir_def::db::{ 25pub use hir_def::db::{
27 DefDatabase2, DefDatabase2Storage, InternDatabase, InternDatabaseStorage, RawItemsQuery, 26 DefDatabase2, DefDatabase2Storage, EnumDataQuery, InternDatabase, InternDatabaseStorage,
28 RawItemsWithSourceMapQuery, 27 RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery,
29}; 28};
30pub use hir_expand::db::{ 29pub use hir_expand::db::{
31 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, 30 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
@@ -36,12 +35,6 @@ pub use hir_expand::db::{
36#[salsa::query_group(DefDatabaseStorage)] 35#[salsa::query_group(DefDatabaseStorage)]
37#[salsa::requires(AstDatabase)] 36#[salsa::requires(AstDatabase)]
38pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { 37pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
39 #[salsa::invoke(crate::adt::StructData::struct_data_query)]
40 fn struct_data(&self, s: Struct) -> Arc<StructData>;
41
42 #[salsa::invoke(crate::adt::EnumData::enum_data_query)]
43 fn enum_data(&self, e: Enum) -> Arc<EnumData>;
44
45 #[salsa::invoke(crate::traits::TraitData::trait_data_query)] 38 #[salsa::invoke(crate::traits::TraitData::trait_data_query)]
46 fn trait_data(&self, t: Trait) -> Arc<TraitData>; 39 fn trait_data(&self, t: Trait) -> Arc<TraitData>;
47 40
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index dd7cd979f..8e2834307 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -655,8 +655,8 @@ fn type_for_builtin(def: BuiltinType) -> Ty {
655} 655}
656 656
657fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { 657fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
658 let var_data = def.variant_data(db); 658 let struct_data = db.struct_data(def.id);
659 let fields = match var_data.fields() { 659 let fields = match struct_data.variant_data.fields() {
660 Some(fields) => fields, 660 Some(fields) => fields,
661 None => panic!("fn_sig_for_struct_constructor called on unit struct"), 661 None => panic!("fn_sig_for_struct_constructor called on unit struct"),
662 }; 662 };
@@ -671,8 +671,8 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
671 671
672/// Build the type of a tuple struct constructor. 672/// Build the type of a tuple struct constructor.
673fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { 673fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
674 let var_data = def.variant_data(db); 674 let struct_data = db.struct_data(def.id);
675 if var_data.fields().is_none() { 675 if struct_data.variant_data.fields().is_none() {
676 return type_for_adt(db, def); // Unit struct 676 return type_for_adt(db, def); // Unit struct
677 } 677 }
678 let generics = def.generic_params(db); 678 let generics = def.generic_params(db);
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}
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};
5use ra_db::{salsa, SourceDatabase}; 5use ra_db::{salsa, SourceDatabase};
6use ra_syntax::ast; 6use ra_syntax::ast;
7 7
8use crate::nameres::raw::{ImportSourceMap, RawItems}; 8use crate::{
9 adt::{EnumData, StructData},
10 nameres::raw::{ImportSourceMap, RawItems},
11 EnumId, StructId,
12};
9 13
10#[salsa::query_group(InternDatabaseStorage)] 14#[salsa::query_group(InternDatabaseStorage)]
11pub trait InternDatabase: SourceDatabase { 15pub trait InternDatabase: SourceDatabase {
@@ -37,4 +41,10 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
37 41
38 #[salsa::invoke(RawItems::raw_items_query)] 42 #[salsa::invoke(RawItems::raw_items_query)]
39 fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>; 43 fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>;
44
45 #[salsa::invoke(StructData::struct_data_query)]
46 fn struct_data(&self, s: StructId) -> Arc<StructData>;
47
48 #[salsa::invoke(EnumData::enum_data_query)]
49 fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
40} 50}
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;
12pub mod path; 12pub mod path;
13pub mod type_ref; 13pub mod type_ref;
14pub mod builtin_type; 14pub mod builtin_type;
15pub mod adt;
15 16
16// FIXME: this should be private 17// FIXME: this should be private
17pub mod nameres; 18pub mod nameres;
@@ -260,6 +261,22 @@ pub struct LocalEnumVariantId(RawId);
260impl_arena_id!(LocalEnumVariantId); 261impl_arena_id!(LocalEnumVariantId);
261 262
262#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 263#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
264pub enum VariantId {
265 EnumVariantId(EnumVariantId),
266 StructId(StructId),
267}
268
269#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
270pub struct StructFieldId {
271 parent: VariantId,
272 local_id: LocalStructFieldId,
273}
274
275#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
276pub struct LocalStructFieldId(RawId);
277impl_arena_id!(LocalStructFieldId);
278
279#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
263pub struct ConstId(salsa::InternId); 280pub struct ConstId(salsa::InternId);
264impl_intern_key!(ConstId); 281impl_intern_key!(ConstId);
265impl AstItemDef<ast::ConstDef> for ConstId { 282impl AstItemDef<ast::ConstDef> for ConstId {