diff options
Diffstat (limited to 'crates/ra_hir_def/src/item_tree.rs')
-rw-r--r-- | crates/ra_hir_def/src/item_tree.rs | 70 |
1 files changed, 63 insertions, 7 deletions
diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs index d7bc64e6c..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; | |||
5 | mod tests; | 5 | mod tests; |
6 | 6 | ||
7 | use std::{ | 7 | use std::{ |
8 | any::type_name, | ||
8 | fmt::{self, Debug}, | 9 | fmt::{self, Debug}, |
9 | hash::{Hash, Hasher}, | 10 | hash::{Hash, Hasher}, |
10 | marker::PhantomData, | 11 | marker::PhantomData, |
@@ -178,8 +179,8 @@ impl ItemTree { | |||
178 | self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&Attrs::EMPTY) | 179 | self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&Attrs::EMPTY) |
179 | } | 180 | } |
180 | 181 | ||
181 | pub fn attrs(&self, of: ModItem) -> &Attrs { | 182 | pub fn attrs(&self, of: AttrOwner) -> &Attrs { |
182 | self.attrs.get(&AttrOwner::ModItem(of)).unwrap_or(&Attrs::EMPTY) | 183 | self.attrs.get(&of).unwrap_or(&Attrs::EMPTY) |
183 | } | 184 | } |
184 | 185 | ||
185 | /// Returns the lowered inner items that `ast` corresponds to. | 186 | /// Returns the lowered inner items that `ast` corresponds to. |
@@ -282,15 +283,32 @@ struct ItemTreeData { | |||
282 | } | 283 | } |
283 | 284 | ||
284 | #[derive(Debug, Eq, PartialEq, Hash)] | 285 | #[derive(Debug, Eq, PartialEq, Hash)] |
285 | enum AttrOwner { | 286 | pub enum AttrOwner { |
286 | /// Attributes on an item. | 287 | /// Attributes on an item. |
287 | ModItem(ModItem), | 288 | ModItem(ModItem), |
288 | /// Inner attributes of the source file. | 289 | /// Inner attributes of the source file. |
289 | TopLevel, | 290 | TopLevel, |
291 | |||
292 | Variant(Idx<Variant>), | ||
293 | Field(Idx<Field>), | ||
290 | // FIXME: Store variant and field attrs, and stop reparsing them in `attrs_query`. | 294 | // FIXME: Store variant and field attrs, and stop reparsing them in `attrs_query`. |
291 | } | 295 | } |
292 | 296 | ||
293 | /// Trait implemented by all nodes in the item tree. | 297 | macro_rules! from_attrs { |
298 | ( $( $var:ident($t:ty) ),+ ) => { | ||
299 | $( | ||
300 | impl From<$t> for AttrOwner { | ||
301 | fn from(t: $t) -> AttrOwner { | ||
302 | AttrOwner::$var(t) | ||
303 | } | ||
304 | } | ||
305 | )+ | ||
306 | }; | ||
307 | } | ||
308 | |||
309 | from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>)); | ||
310 | |||
311 | /// Trait implemented by all item nodes in the item tree. | ||
294 | pub trait ItemTreeNode: Clone { | 312 | pub trait ItemTreeNode: Clone { |
295 | type Source: AstNode + Into<ast::ModuleItem>; | 313 | type Source: AstNode + Into<ast::ModuleItem>; |
296 | 314 | ||
@@ -523,7 +541,7 @@ pub struct Enum { | |||
523 | pub name: Name, | 541 | pub name: Name, |
524 | pub visibility: RawVisibilityId, | 542 | pub visibility: RawVisibilityId, |
525 | pub generic_params: GenericParamsId, | 543 | pub generic_params: GenericParamsId, |
526 | pub variants: Range<Idx<Variant>>, | 544 | pub variants: IdRange<Variant>, |
527 | pub ast_id: FileAstId<ast::EnumDef>, | 545 | pub ast_id: FileAstId<ast::EnumDef>, |
528 | } | 546 | } |
529 | 547 | ||
@@ -681,10 +699,48 @@ pub struct Variant { | |||
681 | pub fields: Fields, | 699 | pub fields: Fields, |
682 | } | 700 | } |
683 | 701 | ||
702 | pub struct IdRange<T> { | ||
703 | range: Range<u32>, | ||
704 | _p: PhantomData<T>, | ||
705 | } | ||
706 | |||
707 | impl<T> IdRange<T> { | ||
708 | fn new(range: Range<Idx<T>>) -> Self { | ||
709 | Self { range: range.start.into_raw().into()..range.end.into_raw().into(), _p: PhantomData } | ||
710 | } | ||
711 | } | ||
712 | |||
713 | impl<T> Iterator for IdRange<T> { | ||
714 | type Item = Idx<T>; | ||
715 | fn next(&mut self) -> Option<Self::Item> { | ||
716 | self.range.next().map(|raw| Idx::from_raw(raw.into())) | ||
717 | } | ||
718 | } | ||
719 | |||
720 | impl<T> fmt::Debug for IdRange<T> { | ||
721 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
722 | f.debug_tuple(&format!("IdRange::<{}>", type_name::<T>())).field(&self.range).finish() | ||
723 | } | ||
724 | } | ||
725 | |||
726 | impl<T> Clone for IdRange<T> { | ||
727 | fn clone(&self) -> Self { | ||
728 | Self { range: self.range.clone(), _p: PhantomData } | ||
729 | } | ||
730 | } | ||
731 | |||
732 | impl<T> PartialEq for IdRange<T> { | ||
733 | fn eq(&self, other: &Self) -> bool { | ||
734 | self.range == other.range | ||
735 | } | ||
736 | } | ||
737 | |||
738 | impl<T> Eq for IdRange<T> {} | ||
739 | |||
684 | #[derive(Debug, Clone, PartialEq, Eq)] | 740 | #[derive(Debug, Clone, PartialEq, Eq)] |
685 | pub enum Fields { | 741 | pub enum Fields { |
686 | Record(Range<Idx<Field>>), | 742 | Record(IdRange<Field>), |
687 | Tuple(Range<Idx<Field>>), | 743 | Tuple(IdRange<Field>), |
688 | Unit, | 744 | Unit, |
689 | } | 745 | } |
690 | 746 | ||