aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres/crate_def_map/collector.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/nameres/crate_def_map/collector.rs')
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map/collector.rs166
1 files changed, 100 insertions, 66 deletions
diff --git a/crates/ra_hir/src/nameres/crate_def_map/collector.rs b/crates/ra_hir/src/nameres/crate_def_map/collector.rs
index cd328b755..2fbfa9e34 100644
--- a/crates/ra_hir/src/nameres/crate_def_map/collector.rs
+++ b/crates/ra_hir/src/nameres/crate_def_map/collector.rs
@@ -1,42 +1,25 @@
1use std::sync::Arc; 1use arrayvec::ArrayVec;
2
3use rustc_hash::FxHashMap; 2use rustc_hash::FxHashMap;
4use ra_arena::Arena; 3use relative_path::RelativePathBuf;
5use test_utils::tested_by; 4use test_utils::tested_by;
5use ra_db::FileId;
6 6
7use crate::{ 7use crate::{
8 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, 8 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias,
9 Crate, PersistentHirDatabase, HirFileId, Name, Path, 9 PersistentHirDatabase, HirFileId, Name, Path, Problem,
10 KnownName, 10 KnownName,
11 nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode}, 11 nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode},
12 ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, 12 ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId},
13 module_tree::resolve_module_declaration,
14}; 13};
15 14
16use super::{CrateDefMap, ModuleId, ModuleData, raw}; 15use super::{CrateDefMap, ModuleId, ModuleData, raw};
17 16
18#[allow(unused)] 17pub(super) fn collect_defs(
19pub(crate) fn crate_def_map_query(
20 db: &impl PersistentHirDatabase, 18 db: &impl PersistentHirDatabase,
21 krate: Crate, 19 mut def_map: CrateDefMap,
22) -> Arc<CrateDefMap> { 20) -> CrateDefMap {
23 let mut def_map = {
24 let edition = krate.edition(db);
25 let mut modules: Arena<ModuleId, ModuleData> = Arena::default();
26 let root = modules.alloc(ModuleData::default());
27 CrateDefMap {
28 krate,
29 edition,
30 extern_prelude: FxHashMap::default(),
31 prelude: None,
32 root,
33 modules,
34 public_macros: FxHashMap::default(),
35 }
36 };
37
38 // populate external prelude 21 // populate external prelude
39 for dep in krate.dependencies(db) { 22 for dep in def_map.krate.dependencies(db) {
40 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate); 23 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate);
41 if let Some(module) = dep.krate.root_module(db) { 24 if let Some(module) = dep.krate.root_module(db) {
42 def_map.extern_prelude.insert(dep.name.clone(), module.into()); 25 def_map.extern_prelude.insert(dep.name.clone(), module.into());
@@ -52,7 +35,6 @@ pub(crate) fn crate_def_map_query(
52 35
53 let mut collector = DefCollector { 36 let mut collector = DefCollector {
54 db, 37 db,
55 krate,
56 def_map, 38 def_map,
57 glob_imports: FxHashMap::default(), 39 glob_imports: FxHashMap::default(),
58 unresolved_imports: Vec::new(), 40 unresolved_imports: Vec::new(),
@@ -60,14 +42,12 @@ pub(crate) fn crate_def_map_query(
60 global_macro_scope: FxHashMap::default(), 42 global_macro_scope: FxHashMap::default(),
61 }; 43 };
62 collector.collect(); 44 collector.collect();
63 let def_map = collector.finish(); 45 collector.finish()
64 Arc::new(def_map)
65} 46}
66 47
67/// Walks the tree of module recursively 48/// Walks the tree of module recursively
68struct DefCollector<DB> { 49struct DefCollector<DB> {
69 db: DB, 50 db: DB,
70 krate: Crate,
71 def_map: CrateDefMap, 51 def_map: CrateDefMap,
72 glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, raw::ImportId)>>, 52 glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, raw::ImportId)>>,
73 unresolved_imports: Vec<(ModuleId, raw::ImportId, raw::ImportData)>, 53 unresolved_imports: Vec<(ModuleId, raw::ImportId, raw::ImportData)>,
@@ -75,23 +55,16 @@ struct DefCollector<DB> {
75 global_macro_scope: FxHashMap<Name, mbe::MacroRules>, 55 global_macro_scope: FxHashMap<Name, mbe::MacroRules>,
76} 56}
77 57
78/// Walks a single module, populating defs, imports and macros
79struct ModCollector<'a, D> {
80 def_collector: D,
81 module_id: ModuleId,
82 file_id: HirFileId,
83 raw_items: &'a raw::RawItems,
84}
85
86impl<'a, DB> DefCollector<&'a DB> 58impl<'a, DB> DefCollector<&'a DB>
87where 59where
88 DB: PersistentHirDatabase, 60 DB: PersistentHirDatabase,
89{ 61{
90 fn collect(&mut self) { 62 fn collect(&mut self) {
91 let crate_graph = self.db.crate_graph(); 63 let crate_graph = self.db.crate_graph();
92 let file_id = crate_graph.crate_root(self.krate.crate_id()); 64 let file_id = crate_graph.crate_root(self.def_map.krate.crate_id());
93 let raw_items = raw::RawItems::raw_items_query(self.db, file_id); 65 let raw_items = self.db.raw_items(file_id);
94 let module_id = self.def_map.root; 66 let module_id = self.def_map.root;
67 self.def_map.modules[module_id].definition = Some(file_id);
95 ModCollector { 68 ModCollector {
96 def_collector: &mut *self, 69 def_collector: &mut *self,
97 module_id, 70 module_id,
@@ -123,10 +96,6 @@ where
123 } 96 }
124 } 97 }
125 98
126 fn alloc_module(&mut self) -> ModuleId {
127 self.def_map.modules.alloc(ModuleData::default())
128 }
129
130 fn resolve_imports(&mut self) -> ReachedFixedPoint { 99 fn resolve_imports(&mut self) -> ReachedFixedPoint {
131 let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); 100 let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
132 let mut resolved = Vec::new(); 101 let mut resolved = Vec::new();
@@ -184,7 +153,7 @@ where
184 if import.is_prelude { 153 if import.is_prelude {
185 tested_by!(std_prelude); 154 tested_by!(std_prelude);
186 self.def_map.prelude = Some(m); 155 self.def_map.prelude = Some(m);
187 } else if m.krate != self.krate { 156 } else if m.krate != self.def_map.krate {
188 tested_by!(glob_across_crates); 157 tested_by!(glob_across_crates);
189 // glob import from other crate => we can just import everything once 158 // glob import from other crate => we can just import everything once
190 let item_map = self.db.item_map(m.krate); 159 let item_map = self.db.item_map(m.krate);
@@ -199,7 +168,7 @@ where
199 // glob import from same crate => we do an initial 168 // glob import from same crate => we do an initial
200 // import, and then need to propagate any further 169 // import, and then need to propagate any further
201 // additions 170 // additions
202 let scope = &self.def_map[m.module_id]; 171 let scope = &self.def_map[m.module_id].scope;
203 let items = scope 172 let items = scope
204 .items 173 .items
205 .iter() 174 .iter()
@@ -243,11 +212,9 @@ where
243 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); 212 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
244 213
245 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 214 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
246 if let Some(root_module) = self.krate.root_module(self.db) { 215 if import.is_extern_crate && module_id == self.def_map.root {
247 if import.is_extern_crate && module_id == root_module.module_id { 216 if let Some(def) = def.take_types() {
248 if let Some(def) = def.take_types() { 217 self.def_map.extern_prelude.insert(name.clone(), def);
249 self.def_map.extern_prelude.insert(name.clone(), def);
250 }
251 } 218 }
252 } 219 }
253 let resolution = Resolution { def, import: Some(import_id) }; 220 let resolution = Resolution { def, import: Some(import_id) };
@@ -324,8 +291,7 @@ where
324 Some(it) => it, 291 Some(it) => it,
325 _ => return true, 292 _ => return true,
326 }; 293 };
327 // FIXME: this should be a proper query 294 let def_map = self.db.crate_def_map(krate);
328 let def_map = crate_def_map_query(self.db, krate);
329 let rules = def_map.public_macros.get(&path.segments[1].name).cloned(); 295 let rules = def_map.public_macros.get(&path.segments[1].name).cloned();
330 resolved.push((*module_id, *call_id, rules, tt.clone())); 296 resolved.push((*module_id, *call_id, rules, tt.clone()));
331 false 297 false
@@ -367,6 +333,14 @@ where
367 } 333 }
368} 334}
369 335
336/// Walks a single module, populating defs, imports and macros
337struct ModCollector<'a, D> {
338 def_collector: D,
339 module_id: ModuleId,
340 file_id: HirFileId,
341 raw_items: &'a raw::RawItems,
342}
343
370impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>> 344impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>>
371where 345where
372 DB: PersistentHirDatabase, 346 DB: PersistentHirDatabase,
@@ -389,8 +363,12 @@ where
389 fn collect_module(&mut self, module: &raw::ModuleData) { 363 fn collect_module(&mut self, module: &raw::ModuleData) {
390 match module { 364 match module {
391 // inline module, just recurse 365 // inline module, just recurse
392 raw::ModuleData::Definition { name, items } => { 366 raw::ModuleData::Definition { name, items, source_item_id } => {
393 let module_id = self.push_child_module(name.clone()); 367 let module_id = self.push_child_module(
368 name.clone(),
369 source_item_id.with_file_id(self.file_id),
370 None,
371 );
394 ModCollector { 372 ModCollector {
395 def_collector: &mut *self.def_collector, 373 def_collector: &mut *self.def_collector,
396 module_id, 374 module_id,
@@ -400,13 +378,20 @@ where
400 .collect(&*items); 378 .collect(&*items);
401 } 379 }
402 // out of line module, resovle, parse and recurse 380 // out of line module, resovle, parse and recurse
403 raw::ModuleData::Declaration { name } => { 381 raw::ModuleData::Declaration { name, source_item_id } => {
404 let module_id = self.push_child_module(name.clone()); 382 let source_item_id = source_item_id.with_file_id(self.file_id);
405 let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); 383 let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none();
406 if let Some(file_id) = 384 let (file_ids, problem) =
407 resolve_module_declaration(self.def_collector.db, self.file_id, name, is_root) 385 resolve_submodule(self.def_collector.db, self.file_id, name, is_root);
408 { 386
409 let raw_items = raw::RawItems::raw_items_query(self.def_collector.db, file_id); 387 if let Some(problem) = problem {
388 self.def_collector.def_map.problems.add(source_item_id, problem)
389 }
390
391 if let Some(&file_id) = file_ids.first() {
392 let module_id =
393 self.push_child_module(name.clone(), source_item_id, Some(file_id));
394 let raw_items = self.def_collector.db.raw_items(file_id);
410 ModCollector { 395 ModCollector {
411 def_collector: &mut *self.def_collector, 396 def_collector: &mut *self.def_collector,
412 module_id, 397 module_id,
@@ -419,15 +404,23 @@ where
419 } 404 }
420 } 405 }
421 406
422 fn push_child_module(&mut self, name: Name) -> ModuleId { 407 fn push_child_module(
423 let res = self.def_collector.alloc_module(); 408 &mut self,
424 self.def_collector.def_map.modules[res].parent = Some(self.module_id); 409 name: Name,
425 self.def_collector.def_map.modules[self.module_id].children.insert(name, res); 410 declaration: SourceItemId,
411 definition: Option<FileId>,
412 ) -> ModuleId {
413 let modules = &mut self.def_collector.def_map.modules;
414 let res = modules.alloc(ModuleData::default());
415 modules[res].parent = Some(self.module_id);
416 modules[res].declaration = Some(declaration);
417 modules[res].definition = definition;
418 modules[self.module_id].children.insert(name, res);
426 res 419 res
427 } 420 }
428 421
429 fn define_def(&mut self, def: &raw::DefData) { 422 fn define_def(&mut self, def: &raw::DefData) {
430 let module = Module { krate: self.def_collector.krate, module_id: self.module_id }; 423 let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id };
431 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into()); 424 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into());
432 macro_rules! id { 425 macro_rules! id {
433 () => { 426 () => {
@@ -462,7 +455,7 @@ where
462 455
463 let source_item_id = SourceItemId { file_id: self.file_id, item_id: mac.source_item_id }; 456 let source_item_id = SourceItemId { file_id: self.file_id, item_id: mac.source_item_id };
464 let macro_call_id = MacroCallLoc { 457 let macro_call_id = MacroCallLoc {
465 module: Module { krate: self.def_collector.krate, module_id: self.module_id }, 458 module: Module { krate: self.def_collector.def_map.krate, module_id: self.module_id },
466 source_item_id, 459 source_item_id,
467 } 460 }
468 .id(self.def_collector.db); 461 .id(self.def_collector.db);
@@ -491,3 +484,44 @@ where
491fn is_macro_rules(path: &Path) -> bool { 484fn is_macro_rules(path: &Path) -> bool {
492 path.as_ident().and_then(Name::as_known_name) == Some(KnownName::MacroRules) 485 path.as_ident().and_then(Name::as_known_name) == Some(KnownName::MacroRules)
493} 486}
487
488fn resolve_submodule(
489 db: &impl PersistentHirDatabase,
490 file_id: HirFileId,
491 name: &Name,
492 is_root: bool,
493) -> (Vec<FileId>, Option<Problem>) {
494 // FIXME: handle submodules of inline modules properly
495 let file_id = file_id.original_file(db);
496 let source_root_id = db.file_source_root(file_id);
497 let path = db.file_relative_path(file_id);
498 let root = RelativePathBuf::default();
499 let dir_path = path.parent().unwrap_or(&root);
500 let mod_name = path.file_stem().unwrap_or("unknown");
501 let is_dir_owner = is_root || mod_name == "mod";
502
503 let file_mod = dir_path.join(format!("{}.rs", name));
504 let dir_mod = dir_path.join(format!("{}/mod.rs", name));
505 let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name));
506 let mut candidates = ArrayVec::<[_; 2]>::new();
507 if is_dir_owner {
508 candidates.push(file_mod.clone());
509 candidates.push(dir_mod);
510 } else {
511 candidates.push(file_dir_mod.clone());
512 };
513 let sr = db.source_root(source_root_id);
514 let points_to = candidates
515 .into_iter()
516 .filter_map(|path| sr.files.get(&path))
517 .map(|&it| it)
518 .collect::<Vec<_>>();
519 let problem = if points_to.is_empty() {
520 Some(Problem::UnresolvedModule {
521 candidate: if is_dir_owner { file_mod } else { file_dir_mod },
522 })
523 } else {
524 None
525 };
526 (points_to, problem)
527}