diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-01-20 16:09:22 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2021-01-20 16:09:22 +0000 |
commit | e62533c3ec74358d3488e8e4b7967c78459b238f (patch) | |
tree | cd1fe4ad8f6a19b44678e1389c0c7553a6d11036 /crates | |
parent | 9d10aa09726f38d184d499c0a04f8ba4bc1c2bba (diff) | |
parent | c5ed2284b5733dcaf8b57b1771c441afc39fa5e7 (diff) |
Merge #7359
7359: ItemTree: store a mapping from blocks to inner items r=jonas-schievink a=jonas-schievink
To do name resolution within block expressions, we need to know which inner items are located inside each block expression. This adds such a mapping to `ItemTree`, replacing the previous one, which was seemingly unused other than to access all the inner items.
This also assigns `AstId`s to block expressions, which is needed to store the mapping in salsa.
Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 28 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 33 | ||||
-rw-r--r-- | crates/hir_expand/src/ast_id_map.rs | 20 |
3 files changed, 49 insertions, 32 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 { | |||
69 | pub struct ItemTree { | 69 | pub 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 | ||
77 | impl ItemTree { | 76 | impl 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} | |||
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::{ |
@@ -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 | ||
diff --git a/crates/hir_expand/src/ast_id_map.rs b/crates/hir_expand/src/ast_id_map.rs index 2401b0cc5..0991fffd8 100644 --- a/crates/hir_expand/src/ast_id_map.rs +++ b/crates/hir_expand/src/ast_id_map.rs | |||
@@ -13,7 +13,7 @@ use std::{ | |||
13 | }; | 13 | }; |
14 | 14 | ||
15 | use la_arena::{Arena, Idx}; | 15 | use la_arena::{Arena, Idx}; |
16 | use syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr}; | 16 | use syntax::{ast, match_ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr}; |
17 | 17 | ||
18 | /// `AstId` points to an AST node in a specific file. | 18 | /// `AstId` points to an AST node in a specific file. |
19 | pub struct FileAstId<N: AstNode> { | 19 | pub struct FileAstId<N: AstNode> { |
@@ -72,12 +72,20 @@ impl AstIdMap { | |||
72 | // get lower ids then children. That is, adding a new child does not | 72 | // get lower ids then children. That is, adding a new child does not |
73 | // change parent's id. This means that, say, adding a new function to a | 73 | // change parent's id. This means that, say, adding a new function to a |
74 | // trait does not change ids of top-level items, which helps caching. | 74 | // trait does not change ids of top-level items, which helps caching. |
75 | bdfs(node, |it| match ast::Item::cast(it) { | 75 | bdfs(node, |it| { |
76 | Some(module_item) => { | 76 | match_ast! { |
77 | res.alloc(module_item.syntax()); | 77 | match it { |
78 | true | 78 | ast::Item(module_item) => { |
79 | res.alloc(module_item.syntax()); | ||
80 | true | ||
81 | }, | ||
82 | ast::BlockExpr(block) => { | ||
83 | res.alloc(block.syntax()); | ||
84 | true | ||
85 | }, | ||
86 | _ => false, | ||
87 | } | ||
79 | } | 88 | } |
80 | None => false, | ||
81 | }); | 89 | }); |
82 | res | 90 | res |
83 | } | 91 | } |