aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres
diff options
context:
space:
mode:
authorSergey Parilin <[email protected]>2019-04-02 15:55:14 +0100
committerSergey Parilin <[email protected]>2019-04-02 15:55:14 +0100
commitb74449e9952846a8ea66c3507e52c24348d6dbc9 (patch)
tree00bb1101334b0bf1b189a2e6451cb28e0af959a1 /crates/ra_hir/src/nameres
parent9b73f809596e955216dde24fcf921d6985a1a767 (diff)
parent849d7428aa6b733d452b2ebc55ec322d96345f49 (diff)
Merge remote-tracking branch 'upstream/master' into issue961_profiling
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r--crates/ra_hir/src/nameres/collector.rs198
-rw-r--r--crates/ra_hir/src/nameres/raw.rs143
-rw-r--r--crates/ra_hir/src/nameres/tests.rs19
-rw-r--r--crates/ra_hir/src/nameres/tests/incremental.rs46
4 files changed, 195 insertions, 211 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index c5b73cfbe..39cadc94a 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -3,17 +3,22 @@ use rustc_hash::FxHashMap;
3use relative_path::RelativePathBuf; 3use relative_path::RelativePathBuf;
4use test_utils::tested_by; 4use test_utils::tested_by;
5use ra_db::FileId; 5use ra_db::FileId;
6use ra_syntax::ast;
6 7
7use crate::{ 8use crate::{
8 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, 9 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias,
9 DefDatabase, HirFileId, Name, Path, Problem, Crate, 10 DefDatabase, HirFileId, Name, Path,
10 KnownName, 11 KnownName,
11 nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, raw}, 12 nameres::{
12 ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, 13 Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode,
14 CrateDefMap, CrateModuleId, ModuleData,
15 diagnostics::DefDiagnostic,
16 raw,
17 },
18 ids::{AstItemDef, LocationCtx, MacroCallLoc, MacroCallId, MacroDefId},
19 AstId,
13}; 20};
14 21
15use super::{CrateDefMap, CrateModuleId, ModuleData, CrateMacroId};
16
17pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { 22pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
18 // populate external prelude 23 // populate external prelude
19 for dep in def_map.krate.dependencies(db) { 24 for dep in def_map.krate.dependencies(db) {
@@ -48,8 +53,8 @@ struct DefCollector<DB> {
48 def_map: CrateDefMap, 53 def_map: CrateDefMap,
49 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, 54 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>,
50 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, 55 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>,
51 unexpanded_macros: Vec<(CrateModuleId, MacroCallId, Path, tt::Subtree)>, 56 unexpanded_macros: Vec<(CrateModuleId, AstId<ast::MacroCall>, Path)>,
52 global_macro_scope: FxHashMap<Name, CrateMacroId>, 57 global_macro_scope: FxHashMap<Name, MacroDefId>,
53} 58}
54 59
55impl<'a, DB> DefCollector<&'a DB> 60impl<'a, DB> DefCollector<&'a DB>
@@ -59,7 +64,7 @@ where
59 fn collect(&mut self) { 64 fn collect(&mut self) {
60 let crate_graph = self.db.crate_graph(); 65 let crate_graph = self.db.crate_graph();
61 let file_id = crate_graph.crate_root(self.def_map.krate.crate_id()); 66 let file_id = crate_graph.crate_root(self.def_map.krate.crate_id());
62 let raw_items = self.db.raw_items(file_id); 67 let raw_items = self.db.raw_items(file_id.into());
63 let module_id = self.def_map.root; 68 let module_id = self.def_map.root;
64 self.def_map.modules[module_id].definition = Some(file_id); 69 self.def_map.modules[module_id].definition = Some(file_id);
65 ModCollector { 70 ModCollector {
@@ -90,14 +95,11 @@ where
90 } 95 }
91 } 96 }
92 97
93 fn define_macro(&mut self, name: Name, tt: &tt::Subtree, export: bool) { 98 fn define_macro(&mut self, name: Name, macro_id: MacroDefId, export: bool) {
94 if let Ok(rules) = mbe::MacroRules::parse(tt) { 99 if export {
95 let macro_id = self.def_map.macros.alloc(rules); 100 self.def_map.public_macros.insert(name.clone(), macro_id);
96 if export {
97 self.def_map.public_macros.insert(name.clone(), macro_id);
98 }
99 self.global_macro_scope.insert(name, macro_id);
100 } 101 }
102 self.global_macro_scope.insert(name, macro_id);
101 } 103 }
102 104
103 fn resolve_imports(&mut self) -> ReachedFixedPoint { 105 fn resolve_imports(&mut self) -> ReachedFixedPoint {
@@ -293,7 +295,7 @@ where
293 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); 295 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
294 let mut resolved = Vec::new(); 296 let mut resolved = Vec::new();
295 let mut res = ReachedFixedPoint::Yes; 297 let mut res = ReachedFixedPoint::Yes;
296 macros.retain(|(module_id, call_id, path, tt)| { 298 macros.retain(|(module_id, ast_id, path)| {
297 if path.segments.len() != 2 { 299 if path.segments.len() != 2 {
298 return true; 300 return true;
299 } 301 }
@@ -309,47 +311,23 @@ where
309 res = ReachedFixedPoint::No; 311 res = ReachedFixedPoint::No;
310 let def_map = self.db.crate_def_map(krate); 312 let def_map = self.db.crate_def_map(krate);
311 if let Some(macro_id) = def_map.public_macros.get(&path.segments[1].name).cloned() { 313 if let Some(macro_id) = def_map.public_macros.get(&path.segments[1].name).cloned() {
312 resolved.push((*module_id, *call_id, (krate, macro_id), tt.clone())); 314 let call_id = MacroCallLoc { def: macro_id, ast_id: *ast_id }.id(self.db);
315 resolved.push((*module_id, call_id));
313 } 316 }
314 false 317 false
315 }); 318 });
316 319
317 for (module_id, macro_call_id, macro_def_id, arg) in resolved { 320 for (module_id, macro_call_id) in resolved {
318 self.collect_macro_expansion(module_id, macro_call_id, macro_def_id, arg); 321 self.collect_macro_expansion(module_id, macro_call_id);
319 } 322 }
320 res 323 res
321 } 324 }
322 325
323 fn collect_macro_expansion( 326 fn collect_macro_expansion(&mut self, module_id: CrateModuleId, macro_call_id: MacroCallId) {
324 &mut self, 327 let file_id: HirFileId = macro_call_id.into();
325 module_id: CrateModuleId, 328 let raw_items = self.db.raw_items(file_id);
326 macro_call_id: MacroCallId, 329 ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items }
327 macro_def_id: (Crate, CrateMacroId), 330 .collect(raw_items.items())
328 macro_arg: tt::Subtree,
329 ) {
330 let (macro_krate, macro_id) = macro_def_id;
331 let dm;
332 let rules = if macro_krate == self.def_map.krate {
333 &self.def_map[macro_id]
334 } else {
335 dm = self.db.crate_def_map(macro_krate);
336 &dm[macro_id]
337 };
338 if let Ok(expansion) = rules.expand(&macro_arg) {
339 self.def_map.macro_resolutions.insert(macro_call_id, macro_def_id);
340 // XXX: this **does not** go through a database, because we can't
341 // identify macro_call without adding the whole state of name resolution
342 // as a parameter to the query.
343 //
344 // So, we run the queries "manually" and we must ensure that
345 // `db.hir_parse(macro_call_id)` returns the same source_file.
346 let file_id: HirFileId = macro_call_id.into();
347 let source_file = mbe::token_tree_to_ast_item_list(&expansion);
348
349 let raw_items = raw::RawItems::from_source_file(&source_file, file_id);
350 ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items }
351 .collect(raw_items.items())
352 }
353 } 331 }
354 332
355 fn finish(self) -> CrateDefMap { 333 fn finish(self) -> CrateDefMap {
@@ -387,12 +365,9 @@ where
387 fn collect_module(&mut self, module: &raw::ModuleData) { 365 fn collect_module(&mut self, module: &raw::ModuleData) {
388 match module { 366 match module {
389 // inline module, just recurse 367 // inline module, just recurse
390 raw::ModuleData::Definition { name, items, source_item_id } => { 368 raw::ModuleData::Definition { name, items, ast_id } => {
391 let module_id = self.push_child_module( 369 let module_id =
392 name.clone(), 370 self.push_child_module(name.clone(), ast_id.with_file_id(self.file_id), None);
393 source_item_id.with_file_id(self.file_id),
394 None,
395 );
396 ModCollector { 371 ModCollector {
397 def_collector: &mut *self.def_collector, 372 def_collector: &mut *self.def_collector,
398 module_id, 373 module_id,
@@ -402,28 +377,29 @@ where
402 .collect(&*items); 377 .collect(&*items);
403 } 378 }
404 // out of line module, resovle, parse and recurse 379 // out of line module, resovle, parse and recurse
405 raw::ModuleData::Declaration { name, source_item_id } => { 380 raw::ModuleData::Declaration { name, ast_id } => {
406 let source_item_id = source_item_id.with_file_id(self.file_id); 381 let ast_id = ast_id.with_file_id(self.file_id);
407 let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); 382 let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none();
408 let (file_ids, problem) = 383 match resolve_submodule(self.def_collector.db, self.file_id, name, is_root) {
409 resolve_submodule(self.def_collector.db, self.file_id, name, is_root); 384 Ok(file_id) => {
410 385 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
411 if let Some(problem) = problem { 386 let raw_items = self.def_collector.db.raw_items(file_id.into());
412 self.def_collector.def_map.problems.add(source_item_id, problem) 387 ModCollector {
413 } 388 def_collector: &mut *self.def_collector,
414 389 module_id,
415 if let Some(&file_id) = file_ids.first() { 390 file_id: file_id.into(),
416 let module_id = 391 raw_items: &raw_items,
417 self.push_child_module(name.clone(), source_item_id, Some(file_id)); 392 }
418 let raw_items = self.def_collector.db.raw_items(file_id); 393 .collect(raw_items.items())
419 ModCollector {
420 def_collector: &mut *self.def_collector,
421 module_id,
422 file_id: file_id.into(),
423 raw_items: &raw_items,
424 } 394 }
425 .collect(raw_items.items()) 395 Err(candidate) => self.def_collector.def_map.diagnostics.push(
426 } 396 DefDiagnostic::UnresolvedModule {
397 module: self.module_id,
398 declaration: ast_id,
399 candidate,
400 },
401 ),
402 };
427 } 403 }
428 } 404 }
429 } 405 }
@@ -431,7 +407,7 @@ where
431 fn push_child_module( 407 fn push_child_module(
432 &mut self, 408 &mut self,
433 name: Name, 409 name: Name,
434 declaration: SourceItemId, 410 declaration: AstId<ast::Module>,
435 definition: Option<FileId>, 411 definition: Option<FileId>,
436 ) -> CrateModuleId { 412 ) -> CrateModuleId {
437 let modules = &mut self.def_collector.def_map.modules; 413 let modules = &mut self.def_collector.def_map.modules;
@@ -453,23 +429,24 @@ where
453 fn define_def(&mut self, def: &raw::DefData) { 429 fn define_def(&mut self, def: &raw::DefData) {
454 let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id }; 430 let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id };
455 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into()); 431 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into());
456 macro_rules! id { 432
457 () => { 433 macro_rules! def {
458 AstItemDef::from_source_item_id_unchecked(ctx, def.source_item_id) 434 ($kind:ident, $ast_id:ident) => {
435 $kind { id: AstItemDef::from_ast_id(ctx, $ast_id) }.into()
459 }; 436 };
460 } 437 }
461 let name = def.name.clone(); 438 let name = def.name.clone();
462 let def: PerNs<ModuleDef> = match def.kind { 439 let def: PerNs<ModuleDef> = match def.kind {
463 raw::DefKind::Function => PerNs::values(Function { id: id!() }.into()), 440 raw::DefKind::Function(ast_id) => PerNs::values(def!(Function, ast_id)),
464 raw::DefKind::Struct => { 441 raw::DefKind::Struct(ast_id) => {
465 let s = Struct { id: id!() }.into(); 442 let s = def!(Struct, ast_id);
466 PerNs::both(s, s) 443 PerNs::both(s, s)
467 } 444 }
468 raw::DefKind::Enum => PerNs::types(Enum { id: id!() }.into()), 445 raw::DefKind::Enum(ast_id) => PerNs::types(def!(Enum, ast_id)),
469 raw::DefKind::Const => PerNs::values(Const { id: id!() }.into()), 446 raw::DefKind::Const(ast_id) => PerNs::values(def!(Const, ast_id)),
470 raw::DefKind::Static => PerNs::values(Static { id: id!() }.into()), 447 raw::DefKind::Static(ast_id) => PerNs::values(def!(Static, ast_id)),
471 raw::DefKind::Trait => PerNs::types(Trait { id: id!() }.into()), 448 raw::DefKind::Trait(ast_id) => PerNs::types(def!(Trait, ast_id)),
472 raw::DefKind::TypeAlias => PerNs::types(TypeAlias { id: id!() }.into()), 449 raw::DefKind::TypeAlias(ast_id) => PerNs::types(def!(TypeAlias, ast_id)),
473 }; 450 };
474 let resolution = Resolution { def, import: None }; 451 let resolution = Resolution { def, import: None };
475 self.def_collector.update(self.module_id, None, &[(name, resolution)]) 452 self.def_collector.update(self.module_id, None, &[(name, resolution)])
@@ -479,39 +456,27 @@ where
479 // Case 1: macro rules, define a macro in crate-global mutable scope 456 // Case 1: macro rules, define a macro in crate-global mutable scope
480 if is_macro_rules(&mac.path) { 457 if is_macro_rules(&mac.path) {
481 if let Some(name) = &mac.name { 458 if let Some(name) = &mac.name {
482 self.def_collector.define_macro(name.clone(), &mac.arg, mac.export) 459 let macro_id = MacroDefId(mac.ast_id.with_file_id(self.file_id));
460 self.def_collector.define_macro(name.clone(), macro_id, mac.export)
483 } 461 }
484 return; 462 return;
485 } 463 }
486 464
487 let source_item_id = SourceItemId { file_id: self.file_id, item_id: mac.source_item_id }; 465 let ast_id = mac.ast_id.with_file_id(self.file_id);
488 let macro_call_id = MacroCallLoc {
489 module: Module { krate: self.def_collector.def_map.krate, module_id: self.module_id },
490 source_item_id,
491 }
492 .id(self.def_collector.db);
493 466
494 // Case 2: try to expand macro_rules from this crate, triggering 467 // Case 2: try to expand macro_rules from this crate, triggering
495 // recursive item collection. 468 // recursive item collection.
496 if let Some(&macro_id) = 469 if let Some(&macro_id) =
497 mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(name)) 470 mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(name))
498 { 471 {
499 self.def_collector.collect_macro_expansion( 472 let macro_call_id = MacroCallLoc { def: macro_id, ast_id }.id(self.def_collector.db);
500 self.module_id, 473
501 macro_call_id, 474 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id);
502 (self.def_collector.def_map.krate, macro_id),
503 mac.arg.clone(),
504 );
505 return; 475 return;
506 } 476 }
507 477
508 // Case 3: path to a macro from another crate, expand during name resolution 478 // Case 3: path to a macro from another crate, expand during name resolution
509 self.def_collector.unexpanded_macros.push(( 479 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, mac.path.clone()))
510 self.module_id,
511 macro_call_id,
512 mac.path.clone(),
513 mac.arg.clone(),
514 ))
515 } 480 }
516} 481}
517 482
@@ -524,7 +489,7 @@ fn resolve_submodule(
524 file_id: HirFileId, 489 file_id: HirFileId,
525 name: &Name, 490 name: &Name,
526 is_root: bool, 491 is_root: bool,
527) -> (Vec<FileId>, Option<Problem>) { 492) -> Result<FileId, RelativePathBuf> {
528 // FIXME: handle submodules of inline modules properly 493 // FIXME: handle submodules of inline modules properly
529 let file_id = file_id.original_file(db); 494 let file_id = file_id.original_file(db);
530 let source_root_id = db.file_source_root(file_id); 495 let source_root_id = db.file_source_root(file_id);
@@ -545,17 +510,10 @@ fn resolve_submodule(
545 candidates.push(file_dir_mod.clone()); 510 candidates.push(file_dir_mod.clone());
546 }; 511 };
547 let sr = db.source_root(source_root_id); 512 let sr = db.source_root(source_root_id);
548 let points_to = candidates 513 let mut points_to = candidates.into_iter().filter_map(|path| sr.files.get(&path)).map(|&it| it);
549 .into_iter() 514 // FIXME: handle ambiguity
550 .filter_map(|path| sr.files.get(&path)) 515 match points_to.next() {
551 .map(|&it| it) 516 Some(file_id) => Ok(file_id),
552 .collect::<Vec<_>>(); 517 None => Err(if is_dir_owner { file_mod } else { file_dir_mod }),
553 let problem = if points_to.is_empty() { 518 }
554 Some(Problem::UnresolvedModule {
555 candidate: if is_dir_owner { file_mod } else { file_dir_mod },
556 })
557 } else {
558 None
559 };
560 (points_to, problem)
561} 519}
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index f8ba398ec..0936229ac 100644
--- a/crates/ra_hir/src/nameres/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -4,7 +4,6 @@ use std::{
4}; 4};
5 5
6use test_utils::tested_by; 6use test_utils::tested_by;
7use ra_db::FileId;
8use ra_arena::{Arena, impl_arena_id, RawId, map::ArenaMap}; 7use ra_arena::{Arena, impl_arena_id, RawId, map::ArenaMap};
9use ra_syntax::{ 8use ra_syntax::{
10 AstNode, SourceFile, AstPtr, TreeArc, 9 AstNode, SourceFile, AstPtr, TreeArc,
@@ -13,9 +12,13 @@ use ra_syntax::{
13 12
14use crate::{ 13use crate::{
15 DefDatabase, Name, AsName, Path, HirFileId, ModuleSource, 14 DefDatabase, Name, AsName, Path, HirFileId, ModuleSource,
16 ids::{SourceFileItemId, SourceFileItems}, 15 AstIdMap, FileAstId,
17}; 16};
18 17
18/// `RawItems` is a set of top-level items in a file (except for impls).
19///
20/// It is the input to name resolution algorithm. `RawItems` are not invalidated
21/// on most edits.
19#[derive(Debug, Default, PartialEq, Eq)] 22#[derive(Debug, Default, PartialEq, Eq)]
20pub struct RawItems { 23pub struct RawItems {
21 modules: Arena<Module, ModuleData>, 24 modules: Arena<Module, ModuleData>,
@@ -32,11 +35,11 @@ pub struct ImportSourceMap {
32} 35}
33 36
34impl ImportSourceMap { 37impl ImportSourceMap {
35 pub(crate) fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) { 38 fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) {
36 self.map.insert(import, AstPtr::new(segment)) 39 self.map.insert(import, AstPtr::new(segment))
37 } 40 }
38 41
39 pub fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> { 42 pub(crate) fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> {
40 let file = match source { 43 let file = match source {
41 ModuleSource::SourceFile(file) => &*file, 44 ModuleSource::SourceFile(file) => &*file,
42 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(), 45 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
@@ -47,40 +50,27 @@ impl ImportSourceMap {
47} 50}
48 51
49impl RawItems { 52impl RawItems {
50 pub(crate) fn raw_items_query(db: &impl DefDatabase, file_id: FileId) -> Arc<RawItems> { 53 pub(crate) fn raw_items_query(db: &impl DefDatabase, file_id: HirFileId) -> Arc<RawItems> {
51 db.raw_items_with_source_map(file_id).0 54 db.raw_items_with_source_map(file_id).0
52 } 55 }
53 56
54 pub(crate) fn raw_items_with_source_map_query( 57 pub(crate) fn raw_items_with_source_map_query(
55 db: &impl DefDatabase, 58 db: &impl DefDatabase,
56 file_id: FileId, 59 file_id: HirFileId,
57 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) { 60 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) {
58 let mut collector = RawItemsCollector { 61 let mut collector = RawItemsCollector {
59 raw_items: RawItems::default(), 62 raw_items: RawItems::default(),
60 source_file_items: db.file_items(file_id.into()), 63 source_ast_id_map: db.ast_id_map(file_id.into()),
61 source_map: ImportSourceMap::default(), 64 source_map: ImportSourceMap::default(),
62 }; 65 };
63 let source_file = db.parse(file_id); 66 let source_file = db.hir_parse(file_id);
64 collector.process_module(None, &*source_file); 67 collector.process_module(None, &*source_file);
65 (Arc::new(collector.raw_items), Arc::new(collector.source_map)) 68 (Arc::new(collector.raw_items), Arc::new(collector.source_map))
66 } 69 }
67 70
68 pub(crate) fn items(&self) -> &[RawItem] { 71 pub(super) fn items(&self) -> &[RawItem] {
69 &self.items 72 &self.items
70 } 73 }
71
72 // We can't use queries during name resolution for fear of cycles, so this
73 // is a query-less variant of the above function.
74 pub(crate) fn from_source_file(source_file: &SourceFile, file_id: HirFileId) -> RawItems {
75 let source_file_items = SourceFileItems::from_source_file(source_file, file_id);
76 let mut collector = RawItemsCollector {
77 raw_items: RawItems::default(),
78 source_file_items: Arc::new(source_file_items),
79 source_map: ImportSourceMap::default(),
80 };
81 collector.process_module(None, &*source_file);
82 collector.raw_items
83 }
84} 74}
85 75
86impl Index<Module> for RawItems { 76impl Index<Module> for RawItems {
@@ -112,7 +102,7 @@ impl Index<Macro> for RawItems {
112} 102}
113 103
114#[derive(Debug, PartialEq, Eq, Clone, Copy)] 104#[derive(Debug, PartialEq, Eq, Clone, Copy)]
115pub(crate) enum RawItem { 105pub(super) enum RawItem {
116 Module(Module), 106 Module(Module),
117 Import(ImportId), 107 Import(ImportId),
118 Def(Def), 108 Def(Def),
@@ -120,13 +110,13 @@ pub(crate) enum RawItem {
120} 110}
121 111
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 112#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
123pub(crate) struct Module(RawId); 113pub(super) struct Module(RawId);
124impl_arena_id!(Module); 114impl_arena_id!(Module);
125 115
126#[derive(Debug, PartialEq, Eq)] 116#[derive(Debug, PartialEq, Eq)]
127pub(crate) enum ModuleData { 117pub(super) enum ModuleData {
128 Declaration { name: Name, source_item_id: SourceFileItemId }, 118 Declaration { name: Name, ast_id: FileAstId<ast::Module> },
129 Definition { name: Name, source_item_id: SourceFileItemId, items: Vec<RawItem> }, 119 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> },
130} 120}
131 121
132#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -135,51 +125,49 @@ impl_arena_id!(ImportId);
135 125
136#[derive(Debug, Clone, PartialEq, Eq)] 126#[derive(Debug, Clone, PartialEq, Eq)]
137pub struct ImportData { 127pub struct ImportData {
138 pub(crate) path: Path, 128 pub(super) path: Path,
139 pub(crate) alias: Option<Name>, 129 pub(super) alias: Option<Name>,
140 pub(crate) is_glob: bool, 130 pub(super) is_glob: bool,
141 pub(crate) is_prelude: bool, 131 pub(super) is_prelude: bool,
142 pub(crate) is_extern_crate: bool, 132 pub(super) is_extern_crate: bool,
143} 133}
144 134
145#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 135#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
146pub(crate) struct Def(RawId); 136pub(super) struct Def(RawId);
147impl_arena_id!(Def); 137impl_arena_id!(Def);
148 138
149#[derive(Debug, PartialEq, Eq)] 139#[derive(Debug, PartialEq, Eq)]
150pub(crate) struct DefData { 140pub(super) struct DefData {
151 pub(crate) source_item_id: SourceFileItemId, 141 pub(super) name: Name,
152 pub(crate) name: Name, 142 pub(super) kind: DefKind,
153 pub(crate) kind: DefKind,
154} 143}
155 144
156#[derive(Debug, PartialEq, Eq, Clone, Copy)] 145#[derive(Debug, PartialEq, Eq, Clone, Copy)]
157pub(crate) enum DefKind { 146pub(super) enum DefKind {
158 Function, 147 Function(FileAstId<ast::FnDef>),
159 Struct, 148 Struct(FileAstId<ast::StructDef>),
160 Enum, 149 Enum(FileAstId<ast::EnumDef>),
161 Const, 150 Const(FileAstId<ast::ConstDef>),
162 Static, 151 Static(FileAstId<ast::StaticDef>),
163 Trait, 152 Trait(FileAstId<ast::TraitDef>),
164 TypeAlias, 153 TypeAlias(FileAstId<ast::TypeAliasDef>),
165} 154}
166 155
167#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 156#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
168pub(crate) struct Macro(RawId); 157pub(super) struct Macro(RawId);
169impl_arena_id!(Macro); 158impl_arena_id!(Macro);
170 159
171#[derive(Debug, PartialEq, Eq)] 160#[derive(Debug, PartialEq, Eq)]
172pub(crate) struct MacroData { 161pub(super) struct MacroData {
173 pub(crate) source_item_id: SourceFileItemId, 162 pub(super) ast_id: FileAstId<ast::MacroCall>,
174 pub(crate) path: Path, 163 pub(super) path: Path,
175 pub(crate) name: Option<Name>, 164 pub(super) name: Option<Name>,
176 pub(crate) arg: tt::Subtree, 165 pub(super) export: bool,
177 pub(crate) export: bool,
178} 166}
179 167
180struct RawItemsCollector { 168struct RawItemsCollector {
181 raw_items: RawItems, 169 raw_items: RawItems,
182 source_file_items: Arc<SourceFileItems>, 170 source_ast_id_map: Arc<AstIdMap>,
183 source_map: ImportSourceMap, 171 source_map: ImportSourceMap,
184} 172}
185 173
@@ -211,18 +199,31 @@ impl RawItemsCollector {
211 // impls don't participate in name resolution 199 // impls don't participate in name resolution
212 return; 200 return;
213 } 201 }
214 ast::ModuleItemKind::StructDef(it) => (DefKind::Struct, it.name()), 202 ast::ModuleItemKind::StructDef(it) => {
215 ast::ModuleItemKind::EnumDef(it) => (DefKind::Enum, it.name()), 203 (DefKind::Struct(self.source_ast_id_map.ast_id(it)), it.name())
216 ast::ModuleItemKind::FnDef(it) => (DefKind::Function, it.name()), 204 }
217 ast::ModuleItemKind::TraitDef(it) => (DefKind::Trait, it.name()), 205 ast::ModuleItemKind::EnumDef(it) => {
218 ast::ModuleItemKind::TypeAliasDef(it) => (DefKind::TypeAlias, it.name()), 206 (DefKind::Enum(self.source_ast_id_map.ast_id(it)), it.name())
219 ast::ModuleItemKind::ConstDef(it) => (DefKind::Const, it.name()), 207 }
220 ast::ModuleItemKind::StaticDef(it) => (DefKind::Static, it.name()), 208 ast::ModuleItemKind::FnDef(it) => {
209 (DefKind::Function(self.source_ast_id_map.ast_id(it)), it.name())
210 }
211 ast::ModuleItemKind::TraitDef(it) => {
212 (DefKind::Trait(self.source_ast_id_map.ast_id(it)), it.name())
213 }
214 ast::ModuleItemKind::TypeAliasDef(it) => {
215 (DefKind::TypeAlias(self.source_ast_id_map.ast_id(it)), it.name())
216 }
217 ast::ModuleItemKind::ConstDef(it) => {
218 (DefKind::Const(self.source_ast_id_map.ast_id(it)), it.name())
219 }
220 ast::ModuleItemKind::StaticDef(it) => {
221 (DefKind::Static(self.source_ast_id_map.ast_id(it)), it.name())
222 }
221 }; 223 };
222 if let Some(name) = name { 224 if let Some(name) = name {
223 let name = name.as_name(); 225 let name = name.as_name();
224 let source_item_id = self.source_file_items.id_of_unchecked(item.syntax()); 226 let def = self.raw_items.defs.alloc(DefData { name, kind });
225 let def = self.raw_items.defs.alloc(DefData { name, kind, source_item_id });
226 self.push_item(current_module, RawItem::Def(def)) 227 self.push_item(current_module, RawItem::Def(def))
227 } 228 }
228 } 229 }
@@ -232,10 +233,9 @@ impl RawItemsCollector {
232 Some(it) => it.as_name(), 233 Some(it) => it.as_name(),
233 None => return, 234 None => return,
234 }; 235 };
235 let source_item_id = self.source_file_items.id_of_unchecked(module.syntax()); 236 let ast_id = self.source_ast_id_map.ast_id(module);
236 if module.has_semi() { 237 if module.has_semi() {
237 let item = 238 let item = self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id });
238 self.raw_items.modules.alloc(ModuleData::Declaration { name, source_item_id });
239 self.push_item(current_module, RawItem::Module(item)); 239 self.push_item(current_module, RawItem::Module(item));
240 return; 240 return;
241 } 241 }
@@ -243,7 +243,7 @@ impl RawItemsCollector {
243 if let Some(item_list) = module.item_list() { 243 if let Some(item_list) = module.item_list() {
244 let item = self.raw_items.modules.alloc(ModuleData::Definition { 244 let item = self.raw_items.modules.alloc(ModuleData::Definition {
245 name, 245 name,
246 source_item_id, 246 ast_id,
247 items: Vec::new(), 247 items: Vec::new(),
248 }); 248 });
249 self.process_module(Some(item), item_list); 249 self.process_module(Some(item), item_list);
@@ -291,18 +291,15 @@ impl RawItemsCollector {
291 } 291 }
292 292
293 fn add_macro(&mut self, current_module: Option<Module>, m: &ast::MacroCall) { 293 fn add_macro(&mut self, current_module: Option<Module>, m: &ast::MacroCall) {
294 let (path, arg) = match ( 294 let path = match m.path().and_then(Path::from_ast) {
295 m.path().and_then(Path::from_ast), 295 Some(it) => it,
296 m.token_tree().and_then(mbe::ast_to_token_tree),
297 ) {
298 (Some(path), Some((token_tree, _token_map))) => (path, token_tree),
299 _ => return, 296 _ => return,
300 }; 297 };
301 298
302 let name = m.name().map(|it| it.as_name()); 299 let name = m.name().map(|it| it.as_name());
303 let source_item_id = self.source_file_items.id_of_unchecked(m.syntax()); 300 let ast_id = self.source_ast_id_map.ast_id(m);
304 let export = m.has_atom_attr("macro_export"); 301 let export = m.has_atom_attr("macro_export");
305 let m = self.raw_items.macros.alloc(MacroData { source_item_id, path, arg, name, export }); 302 let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export });
306 self.push_item(current_module, RawItem::Macro(m)); 303 self.push_item(current_module, RawItem::Macro(m));
307 } 304 }
308 305
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index ac9b88520..572bd1bf7 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -552,3 +552,22 @@ foo: v
552"### 552"###
553 ); 553 );
554} 554}
555
556#[test]
557fn unresolved_module_diagnostics() {
558 let diagnostics = MockDatabase::with_files(
559 r"
560 //- /lib.rs
561 mod foo;
562 mod bar;
563 mod baz {}
564 //- /foo.rs
565 ",
566 )
567 .diagnostics();
568
569 assert_snapshot_matches!(diagnostics, @r###"
570"mod bar;": unresolved module
571"###
572 );
573}
diff --git a/crates/ra_hir/src/nameres/tests/incremental.rs b/crates/ra_hir/src/nameres/tests/incremental.rs
index 698781923..001f76ac3 100644
--- a/crates/ra_hir/src/nameres/tests/incremental.rs
+++ b/crates/ra_hir/src/nameres/tests/incremental.rs
@@ -90,34 +90,44 @@ fn adding_inner_items_should_not_invalidate_def_map() {
90 ); 90 );
91} 91}
92 92
93// It would be awesome to make this work, but it's unclear how
94#[test] 93#[test]
95#[ignore] 94fn typing_inside_a_macro_should_not_invalidate_def_map() {
96fn typing_inside_a_function_inside_a_macro_should_not_invalidate_def_map() { 95 let (mut db, pos) = MockDatabase::with_position(
97 check_def_map_is_not_recomputed(
98 " 96 "
99 //- /lib.rs 97 //- /lib.rs
98 macro_rules! m {
99 ($ident:ident) => {
100 fn f() {
101 $ident + $ident;
102 };
103 }
104 }
100 mod foo; 105 mod foo;
101 106
102 use crate::foo::bar::Baz;
103
104 //- /foo/mod.rs 107 //- /foo/mod.rs
105 pub mod bar; 108 pub mod bar;
106 109
107 //- /foo/bar.rs 110 //- /foo/bar.rs
108 <|> 111 <|>
109 salsa::query_group! { 112 m!(X);
110 trait Baz {
111 fn foo() -> i32 { 1 + 1 }
112 }
113 }
114 ",
115 "
116 salsa::query_group! {
117 trait Baz {
118 fn foo() -> i32 { 92 }
119 }
120 }
121 ", 113 ",
122 ); 114 );
115 {
116 let events = db.log_executed(|| {
117 let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap();
118 let decls = module.declarations(&db);
119 assert_eq!(decls.len(), 1);
120 });
121 assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
122 }
123 db.set_file_text(pos.file_id, Arc::new("m!(Y);".to_string()));
124
125 {
126 let events = db.log_executed(|| {
127 let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap();
128 let decls = module.declarations(&db);
129 assert_eq!(decls.len(), 1);
130 });
131 assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
132 }
123} 133}