aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map.rs118
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map/collector.rs166
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map/raw.rs51
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map/tests.rs2
-rw-r--r--crates/ra_hir/src/nameres/tests.rs3
5 files changed, 234 insertions, 106 deletions
diff --git a/crates/ra_hir/src/nameres/crate_def_map.rs b/crates/ra_hir/src/nameres/crate_def_map.rs
index 483878c78..d7ccb6584 100644
--- a/crates/ra_hir/src/nameres/crate_def_map.rs
+++ b/crates/ra_hir/src/nameres/crate_def_map.rs
@@ -48,25 +48,40 @@ mod tests;
48 48
49use rustc_hash::FxHashMap; 49use rustc_hash::FxHashMap;
50use test_utils::tested_by; 50use test_utils::tested_by;
51use ra_arena::Arena; 51use ra_arena::{Arena, RawId, impl_arena_id};
52use ra_db::FileId;
53
54use std::sync::Arc;
52 55
53use crate::{ 56use crate::{
54 Name, Module, Path, PathKind, ModuleDef, Crate, 57 Name, Module, Path, PathKind, ModuleDef, Crate, Problem, HirFileId,
55 PersistentHirDatabase, 58 PersistentHirDatabase,
56 module_tree::ModuleId,
57 nameres::{ModuleScope, ResolveMode, ResolvePathResult, PerNs, Edition, ReachedFixedPoint}, 59 nameres::{ModuleScope, ResolveMode, ResolvePathResult, PerNs, Edition, ReachedFixedPoint},
60 ids::{SourceItemId, SourceFileItemId},
58}; 61};
59 62
60#[derive(Default, Debug)] 63pub(crate) use self::raw::RawItems;
61struct ModuleData { 64
62 parent: Option<ModuleId>, 65#[derive(Default, Debug, PartialEq, Eq)]
63 children: FxHashMap<Name, ModuleId>, 66pub(crate) struct ModuleData {
64 scope: ModuleScope, 67 pub(crate) parent: Option<ModuleId>,
68 pub(crate) children: FxHashMap<Name, ModuleId>,
69 pub(crate) scope: ModuleScope,
70 /// None for root
71 pub(crate) declaration: Option<SourceItemId>,
72 /// None for inline modules.
73 ///
74 /// Note that non-inline modules, by definition, live inside non-macro file.
75 pub(crate) definition: Option<FileId>,
65} 76}
66 77
78#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
79pub(crate) struct ModuleId(RawId);
80impl_arena_id!(ModuleId);
81
67/// Contans all top-level defs from a macro-expanded crate 82/// Contans all top-level defs from a macro-expanded crate
68#[derive(Debug)] 83#[derive(Debug, PartialEq, Eq)]
69pub(crate) struct CrateDefMap { 84pub struct CrateDefMap {
70 krate: Crate, 85 krate: Crate,
71 edition: Edition, 86 edition: Edition,
72 /// The prelude module for this crate. This either comes from an import 87 /// The prelude module for this crate. This either comes from an import
@@ -77,19 +92,85 @@ pub(crate) struct CrateDefMap {
77 root: ModuleId, 92 root: ModuleId,
78 modules: Arena<ModuleId, ModuleData>, 93 modules: Arena<ModuleId, ModuleData>,
79 public_macros: FxHashMap<Name, mbe::MacroRules>, 94 public_macros: FxHashMap<Name, mbe::MacroRules>,
95 problems: CrateDefMapProblems,
96}
97
98#[derive(Default, Debug, PartialEq, Eq)]
99pub(crate) struct CrateDefMapProblems {
100 problems: Vec<(SourceItemId, Problem)>,
101}
102
103impl CrateDefMapProblems {
104 fn add(&mut self, source_item_id: SourceItemId, problem: Problem) {
105 self.problems.push((source_item_id, problem))
106 }
107
108 pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a SourceItemId, &'a Problem)> + 'a {
109 self.problems.iter().map(|(s, p)| (s, p))
110 }
80} 111}
81 112
82impl std::ops::Index<ModuleId> for CrateDefMap { 113impl std::ops::Index<ModuleId> for CrateDefMap {
83 type Output = ModuleScope; 114 type Output = ModuleData;
84 fn index(&self, id: ModuleId) -> &ModuleScope { 115 fn index(&self, id: ModuleId) -> &ModuleData {
85 &self.modules[id].scope 116 &self.modules[id]
86 } 117 }
87} 118}
88 119
89impl CrateDefMap { 120impl CrateDefMap {
121 pub(crate) fn crate_def_map_query(
122 db: &impl PersistentHirDatabase,
123 krate: Crate,
124 ) -> Arc<CrateDefMap> {
125 let def_map = {
126 let edition = krate.edition(db);
127 let mut modules: Arena<ModuleId, ModuleData> = Arena::default();
128 let root = modules.alloc(ModuleData::default());
129 CrateDefMap {
130 krate,
131 edition,
132 extern_prelude: FxHashMap::default(),
133 prelude: None,
134 root,
135 modules,
136 public_macros: FxHashMap::default(),
137 problems: CrateDefMapProblems::default(),
138 }
139 };
140 let def_map = collector::collect_defs(db, def_map);
141 Arc::new(def_map)
142 }
143
144 pub(crate) fn root(&self) -> ModuleId {
145 self.root
146 }
147
148 pub(crate) fn problems(&self) -> &CrateDefMapProblems {
149 &self.problems
150 }
151
152 pub(crate) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a {
153 self.modules.iter().map(|(id, _data)| id)
154 }
155
156 pub(crate) fn find_module_by_source(
157 &self,
158 file_id: HirFileId,
159 decl_id: Option<SourceFileItemId>,
160 ) -> Option<ModuleId> {
161 let decl_id = decl_id.map(|it| it.with_file_id(file_id));
162 let (module_id, _module_data) = self.modules.iter().find(|(_module_id, module_data)| {
163 if decl_id.is_some() {
164 module_data.declaration == decl_id
165 } else {
166 module_data.definition.map(|it| it.into()) == Some(file_id)
167 }
168 })?;
169 Some(module_id)
170 }
171
90 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change 172 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
91 // the result. 173 // the result.
92 #[allow(unused)]
93 fn resolve_path_fp( 174 fn resolve_path_fp(
94 &self, 175 &self,
95 db: &impl PersistentHirDatabase, 176 db: &impl PersistentHirDatabase,
@@ -182,7 +263,7 @@ impl CrateDefMap {
182 ); 263 );
183 } 264 }
184 265
185 match self[module.module_id].items.get(&segment.name) { 266 match self[module.module_id].scope.items.get(&segment.name) {
186 Some(res) if !res.def.is_none() => res.def, 267 Some(res) if !res.def.is_none() => res.def,
187 _ => { 268 _ => {
188 log::debug!("path segment {:?} not found", segment.name); 269 log::debug!("path segment {:?} not found", segment.name);
@@ -225,7 +306,8 @@ impl CrateDefMap {
225 } 306 }
226 307
227 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> { 308 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> {
228 let from_crate_root = self[self.root].items.get(name).map_or(PerNs::none(), |it| it.def); 309 let from_crate_root =
310 self[self.root].scope.items.get(name).map_or(PerNs::none(), |it| it.def);
229 let from_extern_prelude = self.resolve_name_in_extern_prelude(name); 311 let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
230 312
231 from_crate_root.or(from_extern_prelude) 313 from_crate_root.or(from_extern_prelude)
@@ -241,7 +323,7 @@ impl CrateDefMap {
241 // - current module / scope 323 // - current module / scope
242 // - extern prelude 324 // - extern prelude
243 // - std prelude 325 // - std prelude
244 let from_scope = self[module].items.get(name).map_or(PerNs::none(), |it| it.def); 326 let from_scope = self[module].scope.items.get(name).map_or(PerNs::none(), |it| it.def);
245 let from_extern_prelude = 327 let from_extern_prelude =
246 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); 328 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
247 let from_prelude = self.resolve_in_prelude(db, name); 329 let from_prelude = self.resolve_in_prelude(db, name);
@@ -256,7 +338,7 @@ impl CrateDefMap {
256 fn resolve_in_prelude(&self, db: &impl PersistentHirDatabase, name: &Name) -> PerNs<ModuleDef> { 338 fn resolve_in_prelude(&self, db: &impl PersistentHirDatabase, name: &Name) -> PerNs<ModuleDef> {
257 if let Some(prelude) = self.prelude { 339 if let Some(prelude) = self.prelude {
258 let resolution = if prelude.krate == self.krate { 340 let resolution = if prelude.krate == self.krate {
259 self[prelude.module_id].items.get(name).cloned() 341 self[prelude.module_id].scope.items.get(name).cloned()
260 } else { 342 } else {
261 db.item_map(prelude.krate)[prelude.module_id].items.get(name).cloned() 343 db.item_map(prelude.krate)[prelude.module_id].items.get(name).cloned()
262 }; 344 };
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}
diff --git a/crates/ra_hir/src/nameres/crate_def_map/raw.rs b/crates/ra_hir/src/nameres/crate_def_map/raw.rs
index fe832b8da..f064f722c 100644
--- a/crates/ra_hir/src/nameres/crate_def_map/raw.rs
+++ b/crates/ra_hir/src/nameres/crate_def_map/raw.rs
@@ -3,6 +3,7 @@ use std::{
3 ops::Index, 3 ops::Index,
4}; 4};
5 5
6use test_utils::tested_by;
6use ra_db::FileId; 7use ra_db::FileId;
7use ra_arena::{Arena, impl_arena_id, RawId}; 8use ra_arena::{Arena, impl_arena_id, RawId};
8use ra_syntax::{ 9use ra_syntax::{
@@ -15,8 +16,8 @@ use crate::{
15 ids::{SourceFileItemId, SourceFileItems}, 16 ids::{SourceFileItemId, SourceFileItems},
16}; 17};
17 18
18#[derive(Default, PartialEq, Eq)] 19#[derive(Debug, Default, PartialEq, Eq)]
19pub(crate) struct RawItems { 20pub struct RawItems {
20 modules: Arena<Module, ModuleData>, 21 modules: Arena<Module, ModuleData>,
21 imports: Arena<ImportId, ImportData>, 22 imports: Arena<ImportId, ImportData>,
22 defs: Arena<Def, DefData>, 23 defs: Arena<Def, DefData>,
@@ -26,18 +27,21 @@ pub(crate) struct RawItems {
26} 27}
27 28
28impl RawItems { 29impl RawItems {
29 pub(crate) fn items(&self) -> &[RawItem] { 30 pub(crate) fn raw_items_query(
30 &self.items 31 db: &impl PersistentHirDatabase,
31 } 32 file_id: FileId,
32 33 ) -> Arc<RawItems> {
33 pub(crate) fn raw_items_query(db: &impl PersistentHirDatabase, file_id: FileId) -> RawItems {
34 let mut collector = RawItemsCollector { 34 let mut collector = RawItemsCollector {
35 raw_items: RawItems::default(), 35 raw_items: RawItems::default(),
36 source_file_items: db.file_items(file_id.into()), 36 source_file_items: db.file_items(file_id.into()),
37 }; 37 };
38 let source_file = db.parse(file_id); 38 let source_file = db.parse(file_id);
39 collector.process_module(None, &*source_file); 39 collector.process_module(None, &*source_file);
40 collector.raw_items 40 Arc::new(collector.raw_items)
41 }
42
43 pub(crate) fn items(&self) -> &[RawItem] {
44 &self.items
41 } 45 }
42 46
43 // We can't use queries during name resolution for fear of cycles, so this 47 // We can't use queries during name resolution for fear of cycles, so this
@@ -81,7 +85,7 @@ impl Index<Macro> for RawItems {
81 } 85 }
82} 86}
83 87
84#[derive(PartialEq, Eq, Clone, Copy)] 88#[derive(Debug, PartialEq, Eq, Clone, Copy)]
85pub(crate) enum RawItem { 89pub(crate) enum RawItem {
86 Module(Module), 90 Module(Module),
87 Import(ImportId), 91 Import(ImportId),
@@ -89,24 +93,24 @@ pub(crate) enum RawItem {
89 Macro(Macro), 93 Macro(Macro),
90} 94}
91 95
92#[derive(Clone, Copy, PartialEq, Eq, Hash)] 96#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
93pub(crate) struct Module(RawId); 97pub(crate) struct Module(RawId);
94impl_arena_id!(Module); 98impl_arena_id!(Module);
95 99
96#[derive(PartialEq, Eq)] 100#[derive(Debug, PartialEq, Eq)]
97pub(crate) enum ModuleData { 101pub(crate) enum ModuleData {
98 Declaration { name: Name }, 102 Declaration { name: Name, source_item_id: SourceFileItemId },
99 Definition { name: Name, items: Vec<RawItem> }, 103 Definition { name: Name, source_item_id: SourceFileItemId, items: Vec<RawItem> },
100} 104}
101 105
102pub(crate) use crate::nameres::lower::ImportId; 106pub(crate) use crate::nameres::lower::ImportId;
103pub(super) use crate::nameres::lower::ImportData; 107pub(super) use crate::nameres::lower::ImportData;
104 108
105#[derive(Clone, Copy, PartialEq, Eq, Hash)] 109#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
106pub(crate) struct Def(RawId); 110pub(crate) struct Def(RawId);
107impl_arena_id!(Def); 111impl_arena_id!(Def);
108 112
109#[derive(PartialEq, Eq)] 113#[derive(Debug, PartialEq, Eq)]
110pub(crate) struct DefData { 114pub(crate) struct DefData {
111 pub(crate) source_item_id: SourceFileItemId, 115 pub(crate) source_item_id: SourceFileItemId,
112 pub(crate) name: Name, 116 pub(crate) name: Name,
@@ -124,11 +128,11 @@ pub(crate) enum DefKind {
124 TypeAlias, 128 TypeAlias,
125} 129}
126 130
127#[derive(Clone, Copy, PartialEq, Eq, Hash)] 131#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
128pub(crate) struct Macro(RawId); 132pub(crate) struct Macro(RawId);
129impl_arena_id!(Macro); 133impl_arena_id!(Macro);
130 134
131#[derive(PartialEq, Eq)] 135#[derive(Debug, PartialEq, Eq)]
132pub(crate) struct MacroData { 136pub(crate) struct MacroData {
133 pub(crate) source_item_id: SourceFileItemId, 137 pub(crate) source_item_id: SourceFileItemId,
134 pub(crate) path: Path, 138 pub(crate) path: Path,
@@ -191,18 +195,25 @@ impl RawItemsCollector {
191 Some(it) => it.as_name(), 195 Some(it) => it.as_name(),
192 None => return, 196 None => return,
193 }; 197 };
198 let source_item_id = self.source_file_items.id_of_unchecked(module.syntax());
194 if module.has_semi() { 199 if module.has_semi() {
195 let item = self.raw_items.modules.alloc(ModuleData::Declaration { name }); 200 let item =
201 self.raw_items.modules.alloc(ModuleData::Declaration { name, source_item_id });
196 self.push_item(current_module, RawItem::Module(item)); 202 self.push_item(current_module, RawItem::Module(item));
197 return; 203 return;
198 } 204 }
199 205
200 if let Some(item_list) = module.item_list() { 206 if let Some(item_list) = module.item_list() {
201 let item = 207 let item = self.raw_items.modules.alloc(ModuleData::Definition {
202 self.raw_items.modules.alloc(ModuleData::Definition { name, items: Vec::new() }); 208 name,
209 source_item_id,
210 items: Vec::new(),
211 });
203 self.process_module(Some(item), item_list); 212 self.process_module(Some(item), item_list);
204 self.push_item(current_module, RawItem::Module(item)); 213 self.push_item(current_module, RawItem::Module(item));
214 return;
205 } 215 }
216 tested_by!(name_res_works_for_broken_modules);
206 } 217 }
207 218
208 fn add_use_item(&mut self, current_module: Option<Module>, use_item: &ast::UseItem) { 219 fn add_use_item(&mut self, current_module: Option<Module>, use_item: &ast::UseItem) {
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests.rs b/crates/ra_hir/src/nameres/crate_def_map/tests.rs
index a56dbaf90..742a19e5c 100644
--- a/crates/ra_hir/src/nameres/crate_def_map/tests.rs
+++ b/crates/ra_hir/src/nameres/crate_def_map/tests.rs
@@ -15,7 +15,7 @@ fn compute_crate_def_map(fixture: &str, graph: Option<CrateGraphFixture>) -> Arc
15 } 15 }
16 let crate_id = db.crate_graph().iter().next().unwrap(); 16 let crate_id = db.crate_graph().iter().next().unwrap();
17 let krate = Crate { crate_id }; 17 let krate = Crate { crate_id };
18 collector::crate_def_map_query(&db, krate) 18 db.crate_def_map(krate)
19} 19}
20 20
21fn render_crate_def_map(map: &CrateDefMap) -> String { 21fn render_crate_def_map(map: &CrateDefMap) -> String {
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index 9b151bb0c..961e442a9 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -7,7 +7,7 @@ use crate::{
7 ItemMap, 7 ItemMap,
8 PersistentHirDatabase, 8 PersistentHirDatabase,
9 mock::MockDatabase, 9 mock::MockDatabase,
10 module_tree::ModuleId, 10 nameres::crate_def_map::ModuleId,
11}; 11};
12use super::Resolution; 12use super::Resolution;
13 13
@@ -359,6 +359,7 @@ fn std_prelude() {
359 let main_id = db.file_id_of("/main.rs"); 359 let main_id = db.file_id_of("/main.rs");
360 360
361 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); 361 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
362 eprintln!("module = {:?}", module);
362 let krate = module.krate(&db).unwrap(); 363 let krate = module.krate(&db).unwrap();
363 let item_map = db.item_map(krate); 364 let item_map = db.item_map(krate);
364 365