From 9ba772657950cb8353f37bc2576b78c4f0c8996f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 25 Jun 2020 13:50:27 +0200 Subject: Allow iterating fields in the ItemTree --- crates/ra_hir_def/src/item_tree.rs | 22 ++++++++++++++++++++-- crates/ra_hir_def/src/item_tree/lower.rs | 10 +++++----- crates/ra_hir_def/src/item_tree/tests.rs | 6 +++--- 3 files changed, 28 insertions(+), 10 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs index d7bc64e6c..f99e05432 100644 --- a/crates/ra_hir_def/src/item_tree.rs +++ b/crates/ra_hir_def/src/item_tree.rs @@ -681,10 +681,28 @@ pub struct Variant { pub fields: Fields, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct FieldIds { + range: Range, +} + +impl FieldIds { + fn new(range: Range>) -> Self { + Self { range: range.start.into_raw().into()..range.end.into_raw().into() } + } +} + +impl Iterator for FieldIds { + type Item = Idx; + fn next(&mut self) -> Option { + self.range.next().map(|raw| Idx::from_raw(raw.into())) + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub enum Fields { - Record(Range>), - Tuple(Range>), + Record(FieldIds), + Tuple(FieldIds), Unit, } diff --git a/crates/ra_hir_def/src/item_tree/lower.rs b/crates/ra_hir_def/src/item_tree/lower.rs index f10ad25f7..e2e00323c 100644 --- a/crates/ra_hir_def/src/item_tree/lower.rs +++ b/crates/ra_hir_def/src/item_tree/lower.rs @@ -196,7 +196,7 @@ impl Ctx { } } - fn lower_record_fields(&mut self, fields: &ast::RecordFieldDefList) -> Range> { + fn lower_record_fields(&mut self, fields: &ast::RecordFieldDefList) -> FieldIds { let start = self.next_field_idx(); for field in fields.fields() { if let Some(data) = self.lower_record_field(&field) { @@ -204,7 +204,7 @@ impl Ctx { } } let end = self.next_field_idx(); - start..end + FieldIds::new(start..end) } fn lower_record_field(&mut self, field: &ast::RecordFieldDef) -> Option { @@ -215,7 +215,7 @@ impl Ctx { Some(res) } - fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldDefList) -> Range> { + fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldDefList) -> FieldIds { let start = self.next_field_idx(); for (i, field) in fields.fields().enumerate() { if let Some(data) = self.lower_tuple_field(i, &field) { @@ -223,7 +223,7 @@ impl Ctx { } } let end = self.next_field_idx(); - start..end + FieldIds::new(start..end) } fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleFieldDef) -> Option { @@ -242,7 +242,7 @@ impl Ctx { Some(record_field_def_list) => { self.lower_fields(&StructKind::Record(record_field_def_list)) } - None => Fields::Record(self.next_field_idx()..self.next_field_idx()), + None => Fields::Record(FieldIds::new(self.next_field_idx()..self.next_field_idx())), }; let ast_id = self.source_ast_id_map.ast_id(union); let res = Union { name, visibility, generic_params, fields, ast_id }; diff --git a/crates/ra_hir_def/src/item_tree/tests.rs b/crates/ra_hir_def/src/item_tree/tests.rs index dc035d809..fd7ffee24 100644 --- a/crates/ra_hir_def/src/item_tree/tests.rs +++ b/crates/ra_hir_def/src/item_tree/tests.rs @@ -237,13 +237,13 @@ Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generi #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct0"))] }, input: None }]) }] Struct { name: Name(Text("Struct0")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), fields: Unit, ast_id: FileAstId::(3), kind: Unit } #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct1"))] }, input: None }]) }] -Struct { name: Name(Text("Struct1")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(2), fields: Tuple(Idx::(0)..Idx::(1)), ast_id: FileAstId::(4), kind: Tuple } +Struct { name: Name(Text("Struct1")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(2), fields: Tuple(FieldIds { range: 0..1 }), ast_id: FileAstId::(4), kind: Tuple } #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct2"))] }, input: None }]) }] -Struct { name: Name(Text("Struct2")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(3), fields: Record(Idx::(1)..Idx::(2)), ast_id: FileAstId::(5), kind: Record } +Struct { name: Name(Text("Struct2")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(3), fields: Record(FieldIds { range: 1..2 }), ast_id: FileAstId::(5), kind: Record } #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("en"))] }, input: None }]) }] Enum { name: Name(Text("En")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), variants: Idx::(0)..Idx::(1), ast_id: FileAstId::(6) } #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("un"))] }, input: None }]) }] -Union { name: Name(Text("Un")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), fields: Record(Idx::(3)..Idx::(4)), ast_id: FileAstId::(7) } +Union { name: Name(Text("Un")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), fields: Record(FieldIds { range: 3..4 }), ast_id: FileAstId::(7) } "###); } -- cgit v1.2.3 From d84b3ff6a1c42df0e349dc8ec3fc08e8c1251777 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 25 Jun 2020 14:39:27 +0200 Subject: Collect field/variant attrs in ItemTree --- crates/ra_hir_def/src/attr.rs | 2 +- crates/ra_hir_def/src/data.rs | 4 ++-- crates/ra_hir_def/src/item_tree.rs | 25 +++++++++++++++++++++---- crates/ra_hir_def/src/item_tree/lower.rs | 23 +++++++++++++---------- crates/ra_hir_def/src/item_tree/tests.rs | 2 +- crates/ra_hir_def/src/nameres/collector.rs | 4 ++-- 6 files changed, 40 insertions(+), 20 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 197737ffc..e228e2145 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -208,5 +208,5 @@ where fn attrs_from_item_tree(id: ItemTreeId, db: &dyn DefDatabase) -> Attrs { let tree = db.item_tree(id.file_id); let mod_item = N::id_to_mod_item(id.value); - tree.attrs(mod_item).clone() + tree.attrs(mod_item.into()).clone() } diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index f9e5701db..282ade2a3 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -40,7 +40,7 @@ impl FunctionData { name: func.name.clone(), params: func.params.to_vec(), ret_type: func.ret_type.clone(), - attrs: item_tree.attrs(loc.id.value.into()).clone(), + attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(), has_self_param: func.has_self_param, is_unsafe: func.is_unsafe, visibility: item_tree[func.visibility].clone(), @@ -224,7 +224,7 @@ fn collect_items( match item { AssocItem::Function(id) => { let item = &item_tree[id]; - let attrs = item_tree.attrs(id.into()); + let attrs = item_tree.attrs(ModItem::from(id).into()); if !attrs.is_cfg_enabled(&cfg_options) { continue; } diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs index f99e05432..fd874750e 100644 --- a/crates/ra_hir_def/src/item_tree.rs +++ b/crates/ra_hir_def/src/item_tree.rs @@ -178,8 +178,8 @@ impl ItemTree { self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&Attrs::EMPTY) } - pub fn attrs(&self, of: ModItem) -> &Attrs { - self.attrs.get(&AttrOwner::ModItem(of)).unwrap_or(&Attrs::EMPTY) + pub fn attrs(&self, of: AttrOwner) -> &Attrs { + self.attrs.get(&of).unwrap_or(&Attrs::EMPTY) } /// Returns the lowered inner items that `ast` corresponds to. @@ -282,15 +282,32 @@ struct ItemTreeData { } #[derive(Debug, Eq, PartialEq, Hash)] -enum AttrOwner { +pub enum AttrOwner { /// Attributes on an item. ModItem(ModItem), /// Inner attributes of the source file. TopLevel, + + Variant(Idx), + Field(Idx), // FIXME: Store variant and field attrs, and stop reparsing them in `attrs_query`. } -/// Trait implemented by all nodes in the item tree. +macro_rules! from_attrs { + ( $( $var:ident($t:ty) ),+ ) => { + $( + impl From<$t> for AttrOwner { + fn from(t: $t) -> AttrOwner { + AttrOwner::$var(t) + } + } + )+ + }; +} + +from_attrs!(ModItem(ModItem), Variant(Idx), Field(Idx)); + +/// Trait implemented by all item nodes in the item tree. pub trait ItemTreeNode: Clone { type Source: AstNode + Into; diff --git a/crates/ra_hir_def/src/item_tree/lower.rs b/crates/ra_hir_def/src/item_tree/lower.rs index e2e00323c..230e1f768 100644 --- a/crates/ra_hir_def/src/item_tree/lower.rs +++ b/crates/ra_hir_def/src/item_tree/lower.rs @@ -126,15 +126,15 @@ impl Ctx { if !attrs.is_empty() { for item in items.iter().flat_map(|items| &items.0) { - self.add_attrs(*item, attrs.clone()); + self.add_attrs((*item).into(), attrs.clone()); } } items } - fn add_attrs(&mut self, item: ModItem, attrs: Attrs) { - match self.tree.attrs.entry(AttrOwner::ModItem(item)) { + fn add_attrs(&mut self, item: AttrOwner, attrs: Attrs) { + match self.tree.attrs.entry(item) { Entry::Occupied(mut entry) => { *entry.get_mut() = entry.get().merge(attrs); } @@ -200,7 +200,8 @@ impl Ctx { let start = self.next_field_idx(); for field in fields.fields() { if let Some(data) = self.lower_record_field(&field) { - self.data().fields.alloc(data); + let idx = self.data().fields.alloc(data); + self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene)); } } let end = self.next_field_idx(); @@ -219,7 +220,8 @@ impl Ctx { let start = self.next_field_idx(); for (i, field) in fields.fields().enumerate() { if let Some(data) = self.lower_tuple_field(i, &field) { - self.data().fields.alloc(data); + let idx = self.data().fields.alloc(data); + self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene)); } } let end = self.next_field_idx(); @@ -266,7 +268,8 @@ impl Ctx { let start = self.next_variant_idx(); for variant in variants.variants() { if let Some(data) = self.lower_variant(&variant) { - self.data().variants.alloc(data); + let idx = self.data().variants.alloc(data); + self.add_attrs(idx.into(), Attrs::new(&variant, &self.hygiene)); } } let end = self.next_variant_idx(); @@ -419,7 +422,7 @@ impl Ctx { let attrs = Attrs::new(&item, &this.hygiene); this.collect_inner_items(item.syntax()); this.lower_assoc_item(&item).map(|item| { - this.add_attrs(item.into(), attrs); + this.add_attrs(ModItem::from(item).into(), attrs); item }) }) @@ -453,7 +456,7 @@ impl Ctx { self.collect_inner_items(item.syntax()); let assoc = self.lower_assoc_item(&item)?; let attrs = Attrs::new(&item, &self.hygiene); - self.add_attrs(assoc.into(), attrs); + self.add_attrs(ModItem::from(assoc).into(), attrs); Some(assoc) }) .collect(); @@ -539,7 +542,7 @@ impl Ctx { .filter_map(|item| { self.collect_inner_items(item.syntax()); let attrs = Attrs::new(&item, &self.hygiene); - let id = match item { + let id: ModItem = match item { ast::ExternItem::FnDef(ast) => { let func = self.lower_function(&ast)?; func.into() @@ -549,7 +552,7 @@ impl Ctx { statik.into() } }; - self.add_attrs(id, attrs); + self.add_attrs(id.into(), attrs); Some(id) }) .collect() diff --git a/crates/ra_hir_def/src/item_tree/tests.rs b/crates/ra_hir_def/src/item_tree/tests.rs index fd7ffee24..18df42050 100644 --- a/crates/ra_hir_def/src/item_tree/tests.rs +++ b/crates/ra_hir_def/src/item_tree/tests.rs @@ -92,7 +92,7 @@ fn print_item_tree(ra_fixture: &str) -> String { } fn fmt_mod_item(out: &mut String, tree: &ItemTree, item: ModItem) { - let attrs = tree.attrs(item); + let attrs = tree.attrs(item.into()); if !attrs.is_empty() { format_to!(out, "#[{:?}]\n", attrs); } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 94da700ad..2ced4f66b 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -742,7 +742,7 @@ impl ModCollector<'_, '_> { // `#[macro_use] extern crate` is hoisted to imports macros before collecting // any other items. for item in items { - if self.is_cfg_enabled(self.item_tree.attrs(*item)) { + if self.is_cfg_enabled(self.item_tree.attrs((*item).into())) { if let ModItem::ExternCrate(id) = item { let import = self.item_tree[*id].clone(); if import.is_macro_use { @@ -753,7 +753,7 @@ impl ModCollector<'_, '_> { } for &item in items { - let attrs = self.item_tree.attrs(item); + let attrs = self.item_tree.attrs(item.into()); if self.is_cfg_enabled(attrs) { let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id }; -- cgit v1.2.3 From 2a8fc9e6829c15a54e9094b940312e9485c6b79a Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 25 Jun 2020 16:41:08 +0200 Subject: adt.rs: fetch struct/union data from item tree --- crates/ra_hir_def/src/adt.rs | 68 +++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 19 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index 2bc34d449..65546b339 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs @@ -14,6 +14,7 @@ use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; use crate::{ body::{CfgExpander, LowerCtx}, db::DefDatabase, + item_tree::{Field, Fields, ItemTree}, src::HasChildSource, src::HasSource, trace::Trace, @@ -22,6 +23,7 @@ use crate::{ EnumId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId, VariantId, }; +use ra_cfg::CfgOptions; /// Note that we use `StructData` for unions as well! #[derive(Debug, Clone, PartialEq, Eq)] @@ -59,28 +61,24 @@ pub struct FieldData { impl StructData { pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc { - let src = id.lookup(db).source(db); + let loc = id.lookup(db); + let item_tree = db.item_tree(loc.id.file_id); + let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); - let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); - let variant_data = - VariantData::new(db, src.map(|s| s.kind()), id.lookup(db).container.module(db)); - let variant_data = Arc::new(variant_data); - Arc::new(StructData { name, variant_data }) + let strukt = &item_tree[loc.id.value]; + let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields); + + Arc::new(StructData { name: strukt.name.clone(), variant_data: Arc::new(variant_data) }) } pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc { - let src = id.lookup(db).source(db); - let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); - let variant_data = VariantData::new( - db, - src.map(|s| { - s.record_field_def_list() - .map(ast::StructKind::Record) - .unwrap_or(ast::StructKind::Unit) - }), - id.lookup(db).container.module(db), - ); - let variant_data = Arc::new(variant_data); - Arc::new(StructData { name, variant_data }) + let loc = id.lookup(db); + let item_tree = db.item_tree(loc.id.file_id); + let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); + + let union = &item_tree[loc.id.value]; + let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields); + + Arc::new(StructData { name: union.name.clone(), variant_data: Arc::new(variant_data) }) } } @@ -251,3 +249,35 @@ fn lower_struct( ast::StructKind::Unit => StructKind::Unit, } } + +fn lower_fields(item_tree: &ItemTree, cfg_options: &CfgOptions, fields: &Fields) -> VariantData { + match fields { + Fields::Record(flds) => { + let mut arena = Arena::new(); + for field_id in flds.clone() { + if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) { + arena.alloc(lower_field(item_tree, &item_tree[field_id])); + } + } + VariantData::Record(arena) + } + Fields::Tuple(flds) => { + let mut arena = Arena::new(); + for field_id in flds.clone() { + if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) { + arena.alloc(lower_field(item_tree, &item_tree[field_id])); + } + } + VariantData::Tuple(arena) + } + Fields::Unit => VariantData::Unit, + } +} + +fn lower_field(item_tree: &ItemTree, field: &Field) -> FieldData { + FieldData { + name: field.name.clone(), + type_ref: field.type_ref.clone(), + visibility: item_tree[field.visibility].clone(), + } +} -- cgit v1.2.3 From b06214d16408e0b699f9d6051ba244e5fe766578 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 25 Jun 2020 16:42:59 +0200 Subject: Generalize FieldIds -> IdRange --- crates/ra_hir_def/src/item_tree.rs | 17 +++++++++-------- crates/ra_hir_def/src/item_tree/lower.rs | 10 +++++----- 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs index fd874750e..8c93e3adf 100644 --- a/crates/ra_hir_def/src/item_tree.rs +++ b/crates/ra_hir_def/src/item_tree.rs @@ -699,18 +699,19 @@ pub struct Variant { } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct FieldIds { +pub struct IdRange { range: Range, + _p: PhantomData, } -impl FieldIds { - fn new(range: Range>) -> Self { - Self { range: range.start.into_raw().into()..range.end.into_raw().into() } +impl IdRange { + fn new(range: Range>) -> Self { + Self { range: range.start.into_raw().into()..range.end.into_raw().into(), _p: PhantomData } } } -impl Iterator for FieldIds { - type Item = Idx; +impl Iterator for IdRange { + type Item = Idx; fn next(&mut self) -> Option { self.range.next().map(|raw| Idx::from_raw(raw.into())) } @@ -718,8 +719,8 @@ impl Iterator for FieldIds { #[derive(Debug, Clone, PartialEq, Eq)] pub enum Fields { - Record(FieldIds), - Tuple(FieldIds), + Record(IdRange), + Tuple(IdRange), Unit, } diff --git a/crates/ra_hir_def/src/item_tree/lower.rs b/crates/ra_hir_def/src/item_tree/lower.rs index 230e1f768..93e8cc0c8 100644 --- a/crates/ra_hir_def/src/item_tree/lower.rs +++ b/crates/ra_hir_def/src/item_tree/lower.rs @@ -196,7 +196,7 @@ impl Ctx { } } - fn lower_record_fields(&mut self, fields: &ast::RecordFieldDefList) -> FieldIds { + fn lower_record_fields(&mut self, fields: &ast::RecordFieldDefList) -> IdRange { let start = self.next_field_idx(); for field in fields.fields() { if let Some(data) = self.lower_record_field(&field) { @@ -205,7 +205,7 @@ impl Ctx { } } let end = self.next_field_idx(); - FieldIds::new(start..end) + IdRange::new(start..end) } fn lower_record_field(&mut self, field: &ast::RecordFieldDef) -> Option { @@ -216,7 +216,7 @@ impl Ctx { Some(res) } - fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldDefList) -> FieldIds { + fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldDefList) -> IdRange { let start = self.next_field_idx(); for (i, field) in fields.fields().enumerate() { if let Some(data) = self.lower_tuple_field(i, &field) { @@ -225,7 +225,7 @@ impl Ctx { } } let end = self.next_field_idx(); - FieldIds::new(start..end) + IdRange::new(start..end) } fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleFieldDef) -> Option { @@ -244,7 +244,7 @@ impl Ctx { Some(record_field_def_list) => { self.lower_fields(&StructKind::Record(record_field_def_list)) } - None => Fields::Record(FieldIds::new(self.next_field_idx()..self.next_field_idx())), + None => Fields::Record(IdRange::new(self.next_field_idx()..self.next_field_idx())), }; let ast_id = self.source_ast_id_map.ast_id(union); let res = Union { name, visibility, generic_params, fields, ast_id }; -- cgit v1.2.3 From 563d58559400c4e5b67377bd10f40fee7695ea46 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 25 Jun 2020 16:47:21 +0200 Subject: Use IdRange for variants --- crates/ra_hir_def/src/item_tree.rs | 24 ++++++++++++++++++++++-- crates/ra_hir_def/src/item_tree/lower.rs | 6 +++--- crates/ra_hir_def/src/item_tree/tests.rs | 8 ++++---- 3 files changed, 29 insertions(+), 9 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs index 8c93e3adf..3e603bd55 100644 --- a/crates/ra_hir_def/src/item_tree.rs +++ b/crates/ra_hir_def/src/item_tree.rs @@ -5,6 +5,7 @@ mod lower; mod tests; use std::{ + any::type_name, fmt::{self, Debug}, hash::{Hash, Hasher}, marker::PhantomData, @@ -540,7 +541,7 @@ pub struct Enum { pub name: Name, pub visibility: RawVisibilityId, pub generic_params: GenericParamsId, - pub variants: Range>, + pub variants: IdRange, pub ast_id: FileAstId, } @@ -698,7 +699,6 @@ pub struct Variant { pub fields: Fields, } -#[derive(Debug, Clone, PartialEq, Eq)] pub struct IdRange { range: Range, _p: PhantomData, @@ -717,6 +717,26 @@ impl Iterator for IdRange { } } +impl fmt::Debug for IdRange { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple(&format!("IdRange::<{}>", type_name::())).field(&self.range).finish() + } +} + +impl Clone for IdRange { + fn clone(&self) -> Self { + Self { range: self.range.clone(), _p: PhantomData } + } +} + +impl PartialEq for IdRange { + fn eq(&self, other: &Self) -> bool { + self.range == other.range + } +} + +impl Eq for IdRange {} + #[derive(Debug, Clone, PartialEq, Eq)] pub enum Fields { Record(IdRange), diff --git a/crates/ra_hir_def/src/item_tree/lower.rs b/crates/ra_hir_def/src/item_tree/lower.rs index 93e8cc0c8..5149dd141 100644 --- a/crates/ra_hir_def/src/item_tree/lower.rs +++ b/crates/ra_hir_def/src/item_tree/lower.rs @@ -257,14 +257,14 @@ impl Ctx { let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_); let variants = match &enum_.variant_list() { Some(variant_list) => self.lower_variants(variant_list), - None => self.next_variant_idx()..self.next_variant_idx(), + None => IdRange::new(self.next_variant_idx()..self.next_variant_idx()), }; let ast_id = self.source_ast_id_map.ast_id(enum_); let res = Enum { name, visibility, generic_params, variants, ast_id }; Some(id(self.data().enums.alloc(res))) } - fn lower_variants(&mut self, variants: &ast::EnumVariantList) -> Range> { + fn lower_variants(&mut self, variants: &ast::EnumVariantList) -> IdRange { let start = self.next_variant_idx(); for variant in variants.variants() { if let Some(data) = self.lower_variant(&variant) { @@ -273,7 +273,7 @@ impl Ctx { } } let end = self.next_variant_idx(); - start..end + IdRange::new(start..end) } fn lower_variant(&mut self, variant: &ast::EnumVariant) -> Option { diff --git a/crates/ra_hir_def/src/item_tree/tests.rs b/crates/ra_hir_def/src/item_tree/tests.rs index 18df42050..08559fb92 100644 --- a/crates/ra_hir_def/src/item_tree/tests.rs +++ b/crates/ra_hir_def/src/item_tree/tests.rs @@ -237,13 +237,13 @@ Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generi #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct0"))] }, input: None }]) }] Struct { name: Name(Text("Struct0")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), fields: Unit, ast_id: FileAstId::(3), kind: Unit } #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct1"))] }, input: None }]) }] -Struct { name: Name(Text("Struct1")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(2), fields: Tuple(FieldIds { range: 0..1 }), ast_id: FileAstId::(4), kind: Tuple } +Struct { name: Name(Text("Struct1")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(2), fields: Tuple(IdRange::(0..1)), ast_id: FileAstId::(4), kind: Tuple } #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct2"))] }, input: None }]) }] -Struct { name: Name(Text("Struct2")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(3), fields: Record(FieldIds { range: 1..2 }), ast_id: FileAstId::(5), kind: Record } +Struct { name: Name(Text("Struct2")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(3), fields: Record(IdRange::(1..2)), ast_id: FileAstId::(5), kind: Record } #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("en"))] }, input: None }]) }] -Enum { name: Name(Text("En")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), variants: Idx::(0)..Idx::(1), ast_id: FileAstId::(6) } +Enum { name: Name(Text("En")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), variants: IdRange::(0..1), ast_id: FileAstId::(6) } #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("un"))] }, input: None }]) }] -Union { name: Name(Text("Un")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), fields: Record(FieldIds { range: 3..4 }), ast_id: FileAstId::(7) } +Union { name: Name(Text("Un")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), fields: Record(IdRange::(3..4)), ast_id: FileAstId::(7) } "###); } -- cgit v1.2.3 From dad2f75b91bcc6ac7620326fec082aca7edea7ce Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 25 Jun 2020 16:52:47 +0200 Subject: Use ItemTree to answer enum_data query --- crates/ra_hir_def/src/adt.rs | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index 65546b339..4994a2125 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs @@ -8,7 +8,6 @@ use hir_expand::{ InFile, }; use ra_arena::{map::ArenaMap, Arena}; -use ra_prof::profile; use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; use crate::{ @@ -84,12 +83,25 @@ impl StructData { impl EnumData { pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc { - let _p = profile("enum_data_query"); - let src = e.lookup(db).source(db); - let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); - let mut trace = Trace::new_for_arena(); - lower_enum(db, &mut trace, &src, e.lookup(db).container.module(db)); - Arc::new(EnumData { name, variants: trace.into_arena() }) + let loc = e.lookup(db); + let item_tree = db.item_tree(loc.id.file_id); + let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); + + let enum_ = &item_tree[loc.id.value]; + let mut variants = Arena::new(); + for var_id in enum_.variants.clone() { + if item_tree.attrs(var_id.into()).is_cfg_enabled(&cfg_options) { + let var = &item_tree[var_id]; + let var_data = lower_fields(&item_tree, &cfg_options, &var.fields); + + variants.alloc(EnumVariantData { + name: var.name.clone(), + variant_data: Arc::new(var_data), + }); + } + } + + Arc::new(EnumData { name: enum_.name.clone(), variants }) } pub fn variant(&self, name: &Name) -> Option { -- cgit v1.2.3