Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/item_tree.rs')
-rw-r--r--crates/hir-def/src/item_tree.rs157
1 files changed, 61 insertions, 96 deletions
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 4b3890ae96..b295767399 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -89,11 +89,12 @@ impl fmt::Debug for RawVisibilityId {
/// The item tree of a source file.
#[derive(Debug, Default, Eq, PartialEq)]
pub struct ItemTree {
- top_level: SmallVec<[ModItem; 1]>,
+ top_level: SmallVec<[ModItemId; 1]>,
// Consider splitting this into top level RawAttrs and the map?
attrs: FxHashMap<AttrOwner, RawAttrs>,
- data: Option<Box<ItemTreeData>>,
+ vis: ItemVisibilities,
+ data: FxHashMap<FileAstId<ast::Item>, ModItem>,
}
impl ItemTree {
@@ -130,14 +131,15 @@ impl ItemTree {
if let Some(attrs) = top_attrs {
item_tree.attrs.insert(AttrOwner::TopLevel, attrs);
}
- if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
+ if item_tree.data.is_empty() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
{
EMPTY
.get_or_init(|| {
Arc::new(ItemTree {
top_level: SmallVec::new_const(),
attrs: FxHashMap::default(),
- data: None,
+ data: FxHashMap::default(),
+ vis: ItemVisibilities { arena: Box::new([]) },
})
})
.clone()
@@ -156,14 +158,15 @@ impl ItemTree {
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
let mut item_tree = ctx.lower_block(&block);
- if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
+ if item_tree.data.is_empty() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
{
EMPTY
.get_or_init(|| {
Arc::new(ItemTree {
top_level: SmallVec::new_const(),
attrs: FxHashMap::default(),
- data: None,
+ data: FxHashMap::default(),
+ vis: ItemVisibilities { arena: Box::new([]) },
})
})
.clone()
@@ -175,7 +178,7 @@ impl ItemTree {
/// Returns an iterator over all items located at the top level of the `HirFileId` this
/// `ItemTree` was created from.
- pub(crate) fn top_level_items(&self) -> &[ModItem] {
+ pub(crate) fn top_level_items(&self) -> &[ModItemId] {
&self.top_level
}
@@ -200,74 +203,33 @@ impl ItemTree {
///
/// For more detail, see [`ItemTreeDataStats`].
pub fn item_tree_stats(&self) -> ItemTreeDataStats {
- match self.data {
- Some(ref data) => ItemTreeDataStats {
- traits: data.traits.len(),
- impls: data.impls.len(),
- mods: data.mods.len(),
- macro_calls: data.macro_calls.len(),
- macro_rules: data.macro_rules.len(),
- },
- None => ItemTreeDataStats::default(),
+ let mut traits = 0;
+ let mut impls = 0;
+ let mut mods = 0;
+ let mut macro_calls = 0;
+ let mut macro_rules = 0;
+ for item in self.data.values() {
+ match item {
+ ModItem::Trait(_) => traits += 1,
+ ModItem::Impl(_) => impls += 1,
+ ModItem::Mod(_) => mods += 1,
+ ModItem::MacroCall(_) => macro_calls += 1,
+ ModItem::MacroRules(_) => macro_rules += 1,
+ _ => {}
+ }
}
+ ItemTreeDataStats { traits, impls, mods, macro_calls, macro_rules }
}
pub fn pretty_print(&self, db: &dyn DefDatabase, edition: Edition) -> String {
pretty::print_item_tree(db, self, edition)
}
- fn data(&self) -> &ItemTreeData {
- self.data.as_ref().expect("attempted to access data of empty ItemTree")
- }
-
- fn data_mut(&mut self) -> &mut ItemTreeData {
- self.data.get_or_insert_with(Box::default)
- }
-
fn shrink_to_fit(&mut self) {
- let ItemTree { top_level, attrs, data } = self;
+ let ItemTree { top_level, attrs, data, vis: _ } = self;
top_level.shrink_to_fit();
attrs.shrink_to_fit();
- if let Some(data) = data {
- let ItemTreeData {
- uses,
- extern_crates,
- extern_blocks,
- functions,
- structs,
- unions,
- enums,
- consts,
- statics,
- traits,
- trait_aliases,
- impls,
- type_aliases,
- mods,
- macro_calls,
- macro_rules,
- macro_defs,
- vis: _,
- } = &mut **data;
-
- uses.shrink_to_fit();
- extern_crates.shrink_to_fit();
- extern_blocks.shrink_to_fit();
- functions.shrink_to_fit();
- structs.shrink_to_fit();
- unions.shrink_to_fit();
- enums.shrink_to_fit();
- consts.shrink_to_fit();
- statics.shrink_to_fit();
- traits.shrink_to_fit();
- trait_aliases.shrink_to_fit();
- impls.shrink_to_fit();
- type_aliases.shrink_to_fit();
- mods.shrink_to_fit();
- macro_calls.shrink_to_fit();
- macro_rules.shrink_to_fit();
- macro_defs.shrink_to_fit();
- }
+ data.shrink_to_fit();
}
}
@@ -276,29 +238,26 @@ struct ItemVisibilities {
arena: Box<[RawVisibility]>,
}
-#[derive(Default, Debug, Eq, PartialEq)]
-struct ItemTreeData {
- uses: FxHashMap<ItemTreeAstId<Use>, Use>,
- extern_crates: FxHashMap<ItemTreeAstId<ExternCrate>, ExternCrate>,
- extern_blocks: FxHashMap<ItemTreeAstId<ExternBlock>, ExternBlock>,
- functions: FxHashMap<ItemTreeAstId<Function>, Function>,
- structs: FxHashMap<ItemTreeAstId<Struct>, Struct>,
- unions: FxHashMap<ItemTreeAstId<Union>, Union>,
- enums: FxHashMap<ItemTreeAstId<Enum>, Enum>,
- consts: FxHashMap<ItemTreeAstId<Const>, Const>,
- statics: FxHashMap<ItemTreeAstId<Static>, Static>,
- traits: FxHashMap<ItemTreeAstId<Trait>, Trait>,
- trait_aliases: FxHashMap<ItemTreeAstId<TraitAlias>, TraitAlias>,
- impls: FxHashMap<ItemTreeAstId<Impl>, Impl>,
- type_aliases: FxHashMap<ItemTreeAstId<TypeAlias>, TypeAlias>,
- mods: FxHashMap<ItemTreeAstId<Mod>, Mod>,
- macro_calls: FxHashMap<ItemTreeAstId<MacroCall>, MacroCall>,
- macro_rules: FxHashMap<ItemTreeAstId<MacroRules>, MacroRules>,
- macro_defs: FxHashMap<ItemTreeAstId<Macro2>, Macro2>,
-
- vis: ItemVisibilities,
+#[derive(Debug, Clone, Eq, PartialEq)]
+enum ModItem {
+ Const(Const),
+ Enum(Enum),
+ ExternBlock(ExternBlock),
+ ExternCrate(ExternCrate),
+ Function(Function),
+ Impl(Impl),
+ Macro2(Macro2),
+ MacroCall(MacroCall),
+ MacroRules(MacroRules),
+ Mod(Mod),
+ Static(Static),
+ Struct(Struct),
+ Trait(Trait),
+ TraitAlias(TraitAlias),
+ TypeAlias(TypeAlias),
+ Union(Union),
+ Use(Use),
}
-
#[derive(Default, Debug, Eq, PartialEq)]
pub struct ItemTreeDataStats {
pub traits: usize,
@@ -316,9 +275,9 @@ pub enum AttrOwner {
TopLevel,
}
-impl From<ModItem> for AttrOwner {
+impl From<ModItemId> for AttrOwner {
#[inline]
- fn from(value: ModItem) -> Self {
+ fn from(value: ModItemId) -> Self {
AttrOwner::Item(value.ast_id().erase())
}
}
@@ -385,7 +344,7 @@ macro_rules! mod_items {
$(
impl From<FileAstId<$ast>> for $mod_item {
fn from(id: FileAstId<$ast>) -> $mod_item {
- ModItem::$typ(id)
+ ModItemId::$typ(id)
}
}
)+
@@ -399,7 +358,10 @@ macro_rules! mod_items {
}
fn lookup(tree: &ItemTree, index: FileAstId<$ast>) -> &Self {
- &tree.data().$fld[&index]
+ match &tree.data[&index.upcast()] {
+ ModItem::$typ(item) => item,
+ _ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index),
+ }
}
}
@@ -407,7 +369,10 @@ macro_rules! mod_items {
type Output = $typ;
fn index(&self, index: FileAstId<$ast>) -> &Self::Output {
- &self.data().$fld[&index]
+ match &self.data[&index.upcast()] {
+ ModItem::$typ(item) => item,
+ _ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index),
+ }
}
}
)+
@@ -415,7 +380,7 @@ macro_rules! mod_items {
}
mod_items! {
-ModItem ->
+ModItemId ->
Use in uses -> ast::Use,
ExternCrate in extern_crates -> ast::ExternCrate,
ExternBlock in extern_blocks -> ast::ExternBlock,
@@ -463,7 +428,7 @@ impl Index<RawVisibilityId> for ItemTree {
VisibilityExplicitness::Explicit,
)
}),
- _ => &self.data().vis.arena[index.0 as usize],
+ _ => &self.vis.arena[index.0 as usize],
}
}
}
@@ -541,7 +506,7 @@ pub struct ExternCrate {
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ExternBlock {
pub ast_id: FileAstId<ast::ExternBlock>,
- pub(crate) children: Box<[ModItem]>,
+ pub(crate) children: Box<[ModItemId]>,
}
#[derive(Debug, Clone, Eq, PartialEq)]
@@ -656,7 +621,7 @@ pub struct Mod {
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) enum ModKind {
/// `mod m { ... }`
- Inline { items: Box<[ModItem]> },
+ Inline { items: Box<[ModItemId]> },
/// `mod m;`
Outline,
}