aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-01-21 15:28:40 +0000
committerGitHub <[email protected]>2021-01-21 15:28:40 +0000
commit47a70aadcedbcf28ad6d1ea59b77bf0e11493de0 (patch)
treee5f494422dacc1a6bcae2b696d06f937b64d9163 /crates/hir_def/src/nameres.rs
parent323138f32ea74cfe9f5381e9e170cf87e7592818 (diff)
parentec4a1dc297eb90dde4c22c682a35606aaa50b4d4 (diff)
Merge #7375
7375: Add support for running name resolution in block expressions r=jonas-schievink a=jonas-schievink This adds a `block_def_map` query that runs the name resolution algorithm on a block expression, and returns a `DefMap` that stores links to the parent `DefMap` (either the containing block or the crate-level `DefMap`). Blocks with no inner items return the parent's `DefMap` as-is, to avoid creating unnecessarily long `DefMap` chains. Path resolution is updated to recurse into the parent `DefMap` after looking up a path in the original `DefMap`. I've added a few new tests for this, but outside of those this isn't used yet. bors r+ Co-authored-by: Jonas Schievink <[email protected]>
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),