aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/item_tree.rs28
-rw-r--r--crates/hir_def/src/item_tree/lower.rs33
2 files changed, 35 insertions, 26 deletions
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index ff62928df..6494cebd3 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -69,13 +69,12 @@ impl GenericParamsId {
69pub struct ItemTree { 69pub struct ItemTree {
70 top_level: SmallVec<[ModItem; 1]>, 70 top_level: SmallVec<[ModItem; 1]>,
71 attrs: FxHashMap<AttrOwner, RawAttrs>, 71 attrs: FxHashMap<AttrOwner, RawAttrs>,
72 inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>,
73 72
74 data: Option<Box<ItemTreeData>>, 73 data: Option<Box<ItemTreeData>>,
75} 74}
76 75
77impl ItemTree { 76impl ItemTree {
78 pub fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { 77 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)); 78 let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id));
80 let syntax = if let Some(node) = db.parse_or_expand(file_id) { 79 let syntax = if let Some(node) = db.parse_or_expand(file_id) {
81 node 80 node
@@ -117,12 +116,7 @@ impl ItemTree {
117 } 116 }
118 117
119 fn empty() -> Self { 118 fn empty() -> Self {
120 Self { 119 Self { top_level: Default::default(), attrs: Default::default(), data: Default::default() }
121 top_level: Default::default(),
122 attrs: Default::default(),
123 inner_items: Default::default(),
124 data: Default::default(),
125 }
126 } 120 }
127 121
128 fn shrink_to_fit(&mut self) { 122 fn shrink_to_fit(&mut self) {
@@ -147,6 +141,7 @@ impl ItemTree {
147 macro_defs, 141 macro_defs,
148 vis, 142 vis,
149 generics, 143 generics,
144 inner_items,
150 } = &mut **data; 145 } = &mut **data;
151 146
152 imports.shrink_to_fit(); 147 imports.shrink_to_fit();
@@ -169,6 +164,8 @@ impl ItemTree {
169 164
170 vis.arena.shrink_to_fit(); 165 vis.arena.shrink_to_fit();
171 generics.arena.shrink_to_fit(); 166 generics.arena.shrink_to_fit();
167
168 inner_items.shrink_to_fit();
172 } 169 }
173 } 170 }
174 171
@@ -191,16 +188,11 @@ impl ItemTree {
191 self.raw_attrs(of).clone().filter(db, krate) 188 self.raw_attrs(of).clone().filter(db, krate)
192 } 189 }
193 190
194 /// Returns the lowered inner items that `ast` corresponds to.
195 ///
196 /// Most AST items are lowered to a single `ModItem`, but some (eg. `use` items) may be lowered
197 /// to multiple items in the `ItemTree`.
198 pub fn inner_items(&self, ast: FileAstId<ast::Item>) -> &[ModItem] {
199 &self.inner_items[&ast]
200 }
201
202 pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ { 191 pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ {
203 self.inner_items.values().flatten().copied() 192 match &self.data {
193 Some(data) => Some(data.inner_items.values().flatten().copied()).into_iter().flatten(),
194 None => None.into_iter().flatten(),
195 }
204 } 196 }
205 197
206 pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source { 198 pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source {
@@ -297,6 +289,8 @@ struct ItemTreeData {
297 289
298 vis: ItemVisibilities, 290 vis: ItemVisibilities,
299 generics: GenericParamsStorage, 291 generics: GenericParamsStorage,
292
293 inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>,
300} 294}
301 295
302#[derive(Debug, Eq, PartialEq, Hash)] 296#[derive(Debug, Eq, PartialEq, Hash)]
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 5e71ca42c..56fe569ff 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -6,7 +6,7 @@ use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId}
6use smallvec::SmallVec; 6use smallvec::SmallVec;
7use syntax::{ 7use syntax::{
8 ast::{self, ModuleItemOwner}, 8 ast::{self, ModuleItemOwner},
9 SyntaxNode, 9 SyntaxNode, WalkEvent,
10}; 10};
11 11
12use crate::{ 12use crate::{
@@ -150,14 +150,29 @@ impl Ctx {
150 150
151 fn collect_inner_items(&mut self, container: &SyntaxNode) { 151 fn collect_inner_items(&mut self, container: &SyntaxNode) {
152 let forced_vis = self.forced_visibility.take(); 152 let forced_vis = self.forced_visibility.take();
153 let mut inner_items = mem::take(&mut self.tree.inner_items); 153
154 inner_items.extend(container.descendants().skip(1).filter_map(ast::Item::cast).filter_map( 154 let mut current_block = None;
155 |item| { 155 for event in container.preorder().skip(1) {
156 let ast_id = self.source_ast_id_map.ast_id(&item); 156 if let WalkEvent::Enter(node) = event {
157 Some((ast_id, self.lower_mod_item(&item, true)?.0)) 157 match_ast! {
158 }, 158 match node {
159 )); 159 ast::BlockExpr(block) => {
160 self.tree.inner_items = inner_items; 160 current_block = Some(self.source_ast_id_map.ast_id(&block));
161 },
162 ast::Item(item) => {
163 let mod_items = self.lower_mod_item(&item, true);
164 if let (Some(mod_items), Some(block)) = (mod_items, current_block) {
165 if !mod_items.0.is_empty() {
166 self.data().inner_items.entry(block).or_default().extend(mod_items.0.iter().copied());
167 }
168 }
169 },
170 _ => {}
171 }
172 }
173 }
174 }
175
161 self.forced_visibility = forced_vis; 176 self.forced_visibility = forced_vis;
162 } 177 }
163 178