aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/nameres.rs')
-rw-r--r--crates/hir_def/src/nameres.rs95
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};
61use la_arena::Arena; 61use la_arena::Arena;
62use rustc_hash::FxHashMap; 62use rustc_hash::FxHashMap;
63use stdx::format_to; 63use stdx::format_to;
64use syntax::ast; 64use syntax::{ast, AstNode};
65 65
66use crate::{ 66use 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)]
77pub struct DefMap { 77pub 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) = &current_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
338fn 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)]
307pub enum ModuleSource { 368pub enum ModuleSource {
308 SourceFile(ast::SourceFile), 369 SourceFile(ast::SourceFile),