aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/item_tree.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/item_tree.rs')
-rw-r--r--crates/hir_def/src/item_tree.rs41
1 files changed, 21 insertions, 20 deletions
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 9a433b61c..b8d7608e7 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -21,6 +21,7 @@ use hir_expand::{
21 HirFileId, InFile, 21 HirFileId, InFile,
22}; 22};
23use la_arena::{Arena, Idx, RawIdx}; 23use la_arena::{Arena, Idx, RawIdx};
24use profile::Count;
24use rustc_hash::FxHashMap; 25use rustc_hash::FxHashMap;
25use smallvec::SmallVec; 26use smallvec::SmallVec;
26use syntax::{ast, match_ast}; 27use syntax::{ast, match_ast};
@@ -67,15 +68,16 @@ impl GenericParamsId {
67/// The item tree of a source file. 68/// The item tree of a source file.
68#[derive(Debug, Eq, PartialEq)] 69#[derive(Debug, Eq, PartialEq)]
69pub struct ItemTree { 70pub struct ItemTree {
71 _c: Count<Self>,
72
70 top_level: SmallVec<[ModItem; 1]>, 73 top_level: SmallVec<[ModItem; 1]>,
71 attrs: FxHashMap<AttrOwner, RawAttrs>, 74 attrs: FxHashMap<AttrOwner, RawAttrs>,
72 inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>,
73 75
74 data: Option<Box<ItemTreeData>>, 76 data: Option<Box<ItemTreeData>>,
75} 77}
76 78
77impl ItemTree { 79impl ItemTree {
78 pub fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { 80 pub(crate) fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> {
79 let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id)); 81 let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id));
80 let syntax = if let Some(node) = db.parse_or_expand(file_id) { 82 let syntax = if let Some(node) = db.parse_or_expand(file_id) {
81 node 83 node
@@ -118,9 +120,9 @@ impl ItemTree {
118 120
119 fn empty() -> Self { 121 fn empty() -> Self {
120 Self { 122 Self {
123 _c: Count::new(),
121 top_level: Default::default(), 124 top_level: Default::default(),
122 attrs: Default::default(), 125 attrs: Default::default(),
123 inner_items: Default::default(),
124 data: Default::default(), 126 data: Default::default(),
125 } 127 }
126 } 128 }
@@ -145,9 +147,9 @@ impl ItemTree {
145 macro_calls, 147 macro_calls,
146 macro_rules, 148 macro_rules,
147 macro_defs, 149 macro_defs,
148 exprs,
149 vis, 150 vis,
150 generics, 151 generics,
152 inner_items,
151 } = &mut **data; 153 } = &mut **data;
152 154
153 imports.shrink_to_fit(); 155 imports.shrink_to_fit();
@@ -167,10 +169,11 @@ impl ItemTree {
167 macro_calls.shrink_to_fit(); 169 macro_calls.shrink_to_fit();
168 macro_rules.shrink_to_fit(); 170 macro_rules.shrink_to_fit();
169 macro_defs.shrink_to_fit(); 171 macro_defs.shrink_to_fit();
170 exprs.shrink_to_fit();
171 172
172 vis.arena.shrink_to_fit(); 173 vis.arena.shrink_to_fit();
173 generics.arena.shrink_to_fit(); 174 generics.arena.shrink_to_fit();
175
176 inner_items.shrink_to_fit();
174 } 177 }
175 } 178 }
176 179
@@ -193,16 +196,18 @@ impl ItemTree {
193 self.raw_attrs(of).clone().filter(db, krate) 196 self.raw_attrs(of).clone().filter(db, krate)
194 } 197 }
195 198
196 /// Returns the lowered inner items that `ast` corresponds to. 199 pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ {
197 /// 200 match &self.data {
198 /// Most AST items are lowered to a single `ModItem`, but some (eg. `use` items) may be lowered 201 Some(data) => Some(data.inner_items.values().flatten().copied()).into_iter().flatten(),
199 /// to multiple items in the `ItemTree`. 202 None => None.into_iter().flatten(),
200 pub fn inner_items(&self, ast: FileAstId<ast::Item>) -> &[ModItem] { 203 }
201 &self.inner_items[&ast]
202 } 204 }
203 205
204 pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ { 206 pub fn inner_items_of_block(&self, block: FileAstId<ast::BlockExpr>) -> &[ModItem] {
205 self.inner_items.values().flatten().copied() 207 match &self.data {
208 Some(data) => data.inner_items.get(&block).map(|it| &**it).unwrap_or(&[]),
209 None => &[],
210 }
206 } 211 }
207 212
208 pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source { 213 pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source {
@@ -296,10 +301,11 @@ struct ItemTreeData {
296 macro_calls: Arena<MacroCall>, 301 macro_calls: Arena<MacroCall>,
297 macro_rules: Arena<MacroRules>, 302 macro_rules: Arena<MacroRules>,
298 macro_defs: Arena<MacroDef>, 303 macro_defs: Arena<MacroDef>,
299 exprs: Arena<Expr>,
300 304
301 vis: ItemVisibilities, 305 vis: ItemVisibilities,
302 generics: GenericParamsStorage, 306 generics: GenericParamsStorage,
307
308 inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>,
303} 309}
304 310
305#[derive(Debug, Eq, PartialEq, Hash)] 311#[derive(Debug, Eq, PartialEq, Hash)]
@@ -461,7 +467,7 @@ macro_rules! impl_index {
461 }; 467 };
462} 468}
463 469
464impl_index!(fields: Field, variants: Variant, exprs: Expr); 470impl_index!(fields: Field, variants: Variant);
465 471
466impl Index<RawVisibilityId> for ItemTree { 472impl Index<RawVisibilityId> for ItemTree {
467 type Output = RawVisibility; 473 type Output = RawVisibility;
@@ -664,11 +670,6 @@ pub struct MacroDef {
664 pub ast_id: FileAstId<ast::MacroDef>, 670 pub ast_id: FileAstId<ast::MacroDef>,
665} 671}
666 672
667// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
668// lengths, but we don't do much with them yet.
669#[derive(Debug, Clone, Eq, PartialEq)]
670pub struct Expr;
671
672macro_rules! impl_froms { 673macro_rules! impl_froms {
673 ($e:ident { $($v:ident ($t:ty)),* $(,)? }) => { 674 ($e:ident { $($v:ident ($t:ty)),* $(,)? }) => {
674 $( 675 $(