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.rs94
1 files changed, 68 insertions, 26 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 2bc34d449..4994a2125 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -8,12 +8,12 @@ use hir_expand::{
8 InFile, 8 InFile,
9}; 9};
10use ra_arena::{map::ArenaMap, Arena}; 10use ra_arena::{map::ArenaMap, Arena};
11use ra_prof::profile;
12use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; 11use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner};
13 12
14use crate::{ 13use crate::{
15 body::{CfgExpander, LowerCtx}, 14 body::{CfgExpander, LowerCtx},
16 db::DefDatabase, 15 db::DefDatabase,
16 item_tree::{Field, Fields, ItemTree},
17 src::HasChildSource, 17 src::HasChildSource,
18 src::HasSource, 18 src::HasSource,
19 trace::Trace, 19 trace::Trace,
@@ -22,6 +22,7 @@ use crate::{
22 EnumId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId, 22 EnumId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId,
23 VariantId, 23 VariantId,
24}; 24};
25use ra_cfg::CfgOptions;
25 26
26/// Note that we use `StructData` for unions as well! 27/// Note that we use `StructData` for unions as well!
27#[derive(Debug, Clone, PartialEq, Eq)] 28#[derive(Debug, Clone, PartialEq, Eq)]
@@ -59,39 +60,48 @@ pub struct FieldData {
59 60
60impl StructData { 61impl StructData {
61 pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { 62 pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
62 let src = id.lookup(db).source(db); 63 let loc = id.lookup(db);
64 let item_tree = db.item_tree(loc.id.file_id);
65 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
63 66
64 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 67 let strukt = &item_tree[loc.id.value];
65 let variant_data = 68 let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields);
66 VariantData::new(db, src.map(|s| s.kind()), id.lookup(db).container.module(db)); 69
67 let variant_data = Arc::new(variant_data); 70 Arc::new(StructData { name: strukt.name.clone(), variant_data: Arc::new(variant_data) })
68 Arc::new(StructData { name, variant_data })
69 } 71 }
70 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { 72 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
71 let src = id.lookup(db).source(db); 73 let loc = id.lookup(db);
72 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 74 let item_tree = db.item_tree(loc.id.file_id);
73 let variant_data = VariantData::new( 75 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
74 db, 76
75 src.map(|s| { 77 let union = &item_tree[loc.id.value];
76 s.record_field_def_list() 78 let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields);
77 .map(ast::StructKind::Record) 79
78 .unwrap_or(ast::StructKind::Unit) 80 Arc::new(StructData { name: union.name.clone(), variant_data: Arc::new(variant_data) })
79 }),
80 id.lookup(db).container.module(db),
81 );
82 let variant_data = Arc::new(variant_data);
83 Arc::new(StructData { name, variant_data })
84 } 81 }
85} 82}
86 83
87impl EnumData { 84impl EnumData {
88 pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> { 85 pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
89 let _p = profile("enum_data_query"); 86 let loc = e.lookup(db);
90 let src = e.lookup(db).source(db); 87 let item_tree = db.item_tree(loc.id.file_id);
91 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 88 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
92 let mut trace = Trace::new_for_arena(); 89
93 lower_enum(db, &mut trace, &src, e.lookup(db).container.module(db)); 90 let enum_ = &item_tree[loc.id.value];
94 Arc::new(EnumData { name, variants: trace.into_arena() }) 91 let mut variants = Arena::new();
92 for var_id in enum_.variants.clone() {
93 if item_tree.attrs(var_id.into()).is_cfg_enabled(&cfg_options) {
94 let var = &item_tree[var_id];
95 let var_data = lower_fields(&item_tree, &cfg_options, &var.fields);
96
97 variants.alloc(EnumVariantData {
98 name: var.name.clone(),
99 variant_data: Arc::new(var_data),
100 });
101 }
102 }
103
104 Arc::new(EnumData { name: enum_.name.clone(), variants })
95 } 105 }
96 106
97 pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> { 107 pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
@@ -251,3 +261,35 @@ fn lower_struct(
251 ast::StructKind::Unit => StructKind::Unit, 261 ast::StructKind::Unit => StructKind::Unit,
252 } 262 }
253} 263}
264
265fn lower_fields(item_tree: &ItemTree, cfg_options: &CfgOptions, fields: &Fields) -> VariantData {
266 match fields {
267 Fields::Record(flds) => {
268 let mut arena = Arena::new();
269 for field_id in flds.clone() {
270 if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) {
271 arena.alloc(lower_field(item_tree, &item_tree[field_id]));
272 }
273 }
274 VariantData::Record(arena)
275 }
276 Fields::Tuple(flds) => {
277 let mut arena = Arena::new();
278 for field_id in flds.clone() {
279 if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) {
280 arena.alloc(lower_field(item_tree, &item_tree[field_id]));
281 }
282 }
283 VariantData::Tuple(arena)
284 }
285 Fields::Unit => VariantData::Unit,
286 }
287}
288
289fn lower_field(item_tree: &ItemTree, field: &Field) -> FieldData {
290 FieldData {
291 name: field.name.clone(),
292 type_ref: field.type_ref.clone(),
293 visibility: item_tree[field.visibility].clone(),
294 }
295}