diff options
Diffstat (limited to 'crates/hir_def/src/item_tree')
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 45 |
1 files changed, 32 insertions, 13 deletions
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 5e71ca42c..ce470fc3b 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} | |||
6 | use smallvec::SmallVec; | 6 | use smallvec::SmallVec; |
7 | use syntax::{ | 7 | use syntax::{ |
8 | ast::{self, ModuleItemOwner}, | 8 | ast::{self, ModuleItemOwner}, |
9 | SyntaxNode, | 9 | SyntaxNode, WalkEvent, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
@@ -37,7 +37,6 @@ pub(super) struct Ctx { | |||
37 | file: HirFileId, | 37 | file: HirFileId, |
38 | source_ast_id_map: Arc<AstIdMap>, | 38 | source_ast_id_map: Arc<AstIdMap>, |
39 | body_ctx: crate::body::LowerCtx, | 39 | body_ctx: crate::body::LowerCtx, |
40 | inner_items: Vec<ModItem>, | ||
41 | forced_visibility: Option<RawVisibilityId>, | 40 | forced_visibility: Option<RawVisibilityId>, |
42 | } | 41 | } |
43 | 42 | ||
@@ -49,7 +48,6 @@ impl Ctx { | |||
49 | file, | 48 | file, |
50 | source_ast_id_map: db.ast_id_map(file), | 49 | source_ast_id_map: db.ast_id_map(file), |
51 | body_ctx: crate::body::LowerCtx::new(db, file), | 50 | body_ctx: crate::body::LowerCtx::new(db, file), |
52 | inner_items: Vec::new(), | ||
53 | forced_visibility: None, | 51 | forced_visibility: None, |
54 | } | 52 | } |
55 | } | 53 | } |
@@ -73,8 +71,6 @@ impl Ctx { | |||
73 | } | 71 | } |
74 | 72 | ||
75 | fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems> { | 73 | fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems> { |
76 | assert!(inner || self.inner_items.is_empty()); | ||
77 | |||
78 | // Collect inner items for 1-to-1-lowered items. | 74 | // Collect inner items for 1-to-1-lowered items. |
79 | match item { | 75 | match item { |
80 | ast::Item::Struct(_) | 76 | ast::Item::Struct(_) |
@@ -150,14 +146,37 @@ impl Ctx { | |||
150 | 146 | ||
151 | fn collect_inner_items(&mut self, container: &SyntaxNode) { | 147 | fn collect_inner_items(&mut self, container: &SyntaxNode) { |
152 | let forced_vis = self.forced_visibility.take(); | 148 | let forced_vis = self.forced_visibility.take(); |
153 | let mut inner_items = mem::take(&mut self.tree.inner_items); | 149 | |
154 | inner_items.extend(container.descendants().skip(1).filter_map(ast::Item::cast).filter_map( | 150 | let mut block_stack = Vec::new(); |
155 | |item| { | 151 | for event in container.preorder().skip(1) { |
156 | let ast_id = self.source_ast_id_map.ast_id(&item); | 152 | match event { |
157 | Some((ast_id, self.lower_mod_item(&item, true)?.0)) | 153 | WalkEvent::Enter(node) => { |
158 | }, | 154 | match_ast! { |
159 | )); | 155 | match node { |
160 | self.tree.inner_items = inner_items; | 156 | ast::BlockExpr(block) => { |
157 | block_stack.push(self.source_ast_id_map.ast_id(&block)); | ||
158 | }, | ||
159 | ast::Item(item) => { | ||
160 | let mod_items = self.lower_mod_item(&item, true); | ||
161 | let current_block = block_stack.last(); | ||
162 | if let (Some(mod_items), Some(block)) = (mod_items, current_block) { | ||
163 | if !mod_items.0.is_empty() { | ||
164 | self.data().inner_items.entry(*block).or_default().extend(mod_items.0.iter().copied()); | ||
165 | } | ||
166 | } | ||
167 | }, | ||
168 | _ => {} | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | WalkEvent::Leave(node) => { | ||
173 | if ast::BlockExpr::cast(node).is_some() { | ||
174 | block_stack.pop(); | ||
175 | } | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | |||
161 | self.forced_visibility = forced_vis; | 180 | self.forced_visibility = forced_vis; |
162 | } | 181 | } |
163 | 182 | ||