diff options
Diffstat (limited to 'crates/hir_def/src/nameres.rs')
-rw-r--r-- | crates/hir_def/src/nameres.rs | 95 |
1 files changed, 78 insertions, 17 deletions
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index a3200c710..93931a21a 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -61,7 +61,7 @@ use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; | |||
61 | use la_arena::Arena; | 61 | use la_arena::Arena; |
62 | use rustc_hash::FxHashMap; | 62 | use rustc_hash::FxHashMap; |
63 | use stdx::format_to; | 63 | use stdx::format_to; |
64 | use syntax::ast; | 64 | use syntax::{ast, AstNode}; |
65 | 65 | ||
66 | use crate::{ | 66 | use crate::{ |
67 | db::DefDatabase, | 67 | db::DefDatabase, |
@@ -75,6 +75,7 @@ use crate::{ | |||
75 | /// Contains all top-level defs from a macro-expanded crate | 75 | /// Contains all top-level defs from a macro-expanded crate |
76 | #[derive(Debug, PartialEq, Eq)] | 76 | #[derive(Debug, PartialEq, Eq)] |
77 | pub struct DefMap { | 77 | pub struct DefMap { |
78 | parent: Option<Arc<DefMap>>, | ||
78 | root: LocalModuleId, | 79 | root: LocalModuleId, |
79 | modules: Arena<ModuleData>, | 80 | modules: Arena<ModuleData>, |
80 | krate: CrateId, | 81 | krate: CrateId, |
@@ -181,24 +182,50 @@ impl DefMap { | |||
181 | let _p = profile::span("crate_def_map_query").detail(|| { | 182 | let _p = profile::span("crate_def_map_query").detail(|| { |
182 | db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string() | 183 | db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string() |
183 | }); | 184 | }); |
184 | let def_map = { | 185 | let edition = db.crate_graph()[krate].edition; |
185 | let edition = db.crate_graph()[krate].edition; | 186 | let def_map = DefMap::empty(krate, edition); |
186 | let mut modules: Arena<ModuleData> = Arena::default(); | 187 | let def_map = collector::collect_defs(db, def_map, None); |
187 | let root = modules.alloc(ModuleData::default()); | 188 | Arc::new(def_map) |
188 | DefMap { | 189 | } |
189 | krate, | 190 | |
190 | edition, | 191 | pub(crate) fn block_def_map_query( |
191 | extern_prelude: FxHashMap::default(), | 192 | db: &dyn DefDatabase, |
192 | prelude: None, | 193 | krate: CrateId, |
193 | root, | 194 | block: AstId<ast::BlockExpr>, |
194 | modules, | 195 | ) -> Arc<DefMap> { |
195 | diagnostics: Vec::new(), | 196 | let item_tree = db.item_tree(block.file_id); |
196 | } | 197 | let block_items = item_tree.inner_items_of_block(block.value); |
197 | }; | 198 | |
198 | let def_map = collector::collect_defs(db, def_map); | 199 | let parent = parent_def_map(db, krate, block); |
200 | |||
201 | if block_items.is_empty() { | ||
202 | // If there are no inner items, nothing new is brought into scope, so we can just return | ||
203 | // the parent DefMap. This keeps DefMap parent chains short. | ||
204 | return parent; | ||
205 | } | ||
206 | |||
207 | let mut def_map = DefMap::empty(krate, parent.edition); | ||
208 | def_map.parent = Some(parent); | ||
209 | |||
210 | let def_map = collector::collect_defs(db, def_map, Some(block.value)); | ||
199 | Arc::new(def_map) | 211 | Arc::new(def_map) |
200 | } | 212 | } |
201 | 213 | ||
214 | fn empty(krate: CrateId, edition: Edition) -> DefMap { | ||
215 | let mut modules: Arena<ModuleData> = Arena::default(); | ||
216 | let root = modules.alloc(ModuleData::default()); | ||
217 | DefMap { | ||
218 | parent: None, | ||
219 | krate, | ||
220 | edition, | ||
221 | extern_prelude: FxHashMap::default(), | ||
222 | prelude: None, | ||
223 | root, | ||
224 | modules, | ||
225 | diagnostics: Vec::new(), | ||
226 | } | ||
227 | } | ||
228 | |||
202 | pub fn add_diagnostics( | 229 | pub fn add_diagnostics( |
203 | &self, | 230 | &self, |
204 | db: &dyn DefDatabase, | 231 | db: &dyn DefDatabase, |
@@ -251,7 +278,12 @@ impl DefMap { | |||
251 | // even), as this should be a great debugging aid. | 278 | // even), as this should be a great debugging aid. |
252 | pub fn dump(&self) -> String { | 279 | pub fn dump(&self) -> String { |
253 | let mut buf = String::new(); | 280 | let mut buf = String::new(); |
254 | go(&mut buf, self, "crate", self.root); | 281 | let mut current_map = self; |
282 | while let Some(parent) = ¤t_map.parent { | ||
283 | go(&mut buf, current_map, "block scope", current_map.root); | ||
284 | current_map = &**parent; | ||
285 | } | ||
286 | go(&mut buf, current_map, "crate", current_map.root); | ||
255 | return buf; | 287 | return buf; |
256 | 288 | ||
257 | fn go(buf: &mut String, map: &DefMap, path: &str, module: LocalModuleId) { | 289 | fn go(buf: &mut String, map: &DefMap, path: &str, module: LocalModuleId) { |
@@ -303,6 +335,35 @@ impl ModuleData { | |||
303 | } | 335 | } |
304 | } | 336 | } |
305 | 337 | ||
338 | fn parent_def_map( | ||
339 | db: &dyn DefDatabase, | ||
340 | krate: CrateId, | ||
341 | block: AstId<ast::BlockExpr>, | ||
342 | ) -> Arc<DefMap> { | ||
343 | // FIXME: store this info in the item tree instead of reparsing here | ||
344 | let ast_id_map = db.ast_id_map(block.file_id); | ||
345 | let block_ptr = ast_id_map.get(block.value); | ||
346 | let root = match db.parse_or_expand(block.file_id) { | ||
347 | Some(it) => it, | ||
348 | None => { | ||
349 | return Arc::new(DefMap::empty(krate, Edition::Edition2018)); | ||
350 | } | ||
351 | }; | ||
352 | let ast = block_ptr.to_node(&root); | ||
353 | |||
354 | for ancestor in ast.syntax().ancestors().skip(1) { | ||
355 | if let Some(block_expr) = ast::BlockExpr::cast(ancestor) { | ||
356 | let ancestor_id = ast_id_map.ast_id(&block_expr); | ||
357 | let ast_id = InFile::new(block.file_id, ancestor_id); | ||
358 | let parent_map = db.block_def_map(krate, ast_id); | ||
359 | return parent_map; | ||
360 | } | ||
361 | } | ||
362 | |||
363 | // No enclosing block scope, so the parent is the crate-level DefMap. | ||
364 | db.crate_def_map(krate) | ||
365 | } | ||
366 | |||
306 | #[derive(Debug, Clone, PartialEq, Eq)] | 367 | #[derive(Debug, Clone, PartialEq, Eq)] |
307 | pub enum ModuleSource { | 368 | pub enum ModuleSource { |
308 | SourceFile(ast::SourceFile), | 369 | SourceFile(ast::SourceFile), |