diff options
author | Sergey Parilin <[email protected]> | 2019-04-02 15:55:14 +0100 |
---|---|---|
committer | Sergey Parilin <[email protected]> | 2019-04-02 15:55:14 +0100 |
commit | b74449e9952846a8ea66c3507e52c24348d6dbc9 (patch) | |
tree | 00bb1101334b0bf1b189a2e6451cb28e0af959a1 /crates/ra_hir/src/nameres | |
parent | 9b73f809596e955216dde24fcf921d6985a1a767 (diff) | |
parent | 849d7428aa6b733d452b2ebc55ec322d96345f49 (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.rs | 198 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/raw.rs | 143 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 19 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests/incremental.rs | 46 |
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; | |||
3 | use relative_path::RelativePathBuf; | 3 | use relative_path::RelativePathBuf; |
4 | use test_utils::tested_by; | 4 | use test_utils::tested_by; |
5 | use ra_db::FileId; | 5 | use ra_db::FileId; |
6 | use ra_syntax::ast; | ||
6 | 7 | ||
7 | use crate::{ | 8 | use 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 | ||
15 | use super::{CrateDefMap, CrateModuleId, ModuleData, CrateMacroId}; | ||
16 | |||
17 | pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { | 22 | pub(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 | ||
55 | impl<'a, DB> DefCollector<&'a DB> | 60 | impl<'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(¯o_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(¯o_id) = | 469 | if let Some(¯o_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 | ||
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
7 | use ra_db::FileId; | ||
8 | use ra_arena::{Arena, impl_arena_id, RawId, map::ArenaMap}; | 7 | use ra_arena::{Arena, impl_arena_id, RawId, map::ArenaMap}; |
9 | use ra_syntax::{ | 8 | use ra_syntax::{ |
10 | AstNode, SourceFile, AstPtr, TreeArc, | 9 | AstNode, SourceFile, AstPtr, TreeArc, |
@@ -13,9 +12,13 @@ use ra_syntax::{ | |||
13 | 12 | ||
14 | use crate::{ | 13 | use 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)] |
20 | pub struct RawItems { | 23 | pub struct RawItems { |
21 | modules: Arena<Module, ModuleData>, | 24 | modules: Arena<Module, ModuleData>, |
@@ -32,11 +35,11 @@ pub struct ImportSourceMap { | |||
32 | } | 35 | } |
33 | 36 | ||
34 | impl ImportSourceMap { | 37 | impl 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 | ||
49 | impl RawItems { | 52 | impl 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 | ||
86 | impl Index<Module> for RawItems { | 76 | impl 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)] |
115 | pub(crate) enum RawItem { | 105 | pub(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)] |
123 | pub(crate) struct Module(RawId); | 113 | pub(super) struct Module(RawId); |
124 | impl_arena_id!(Module); | 114 | impl_arena_id!(Module); |
125 | 115 | ||
126 | #[derive(Debug, PartialEq, Eq)] | 116 | #[derive(Debug, PartialEq, Eq)] |
127 | pub(crate) enum ModuleData { | 117 | pub(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)] |
137 | pub struct ImportData { | 127 | pub 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)] |
146 | pub(crate) struct Def(RawId); | 136 | pub(super) struct Def(RawId); |
147 | impl_arena_id!(Def); | 137 | impl_arena_id!(Def); |
148 | 138 | ||
149 | #[derive(Debug, PartialEq, Eq)] | 139 | #[derive(Debug, PartialEq, Eq)] |
150 | pub(crate) struct DefData { | 140 | pub(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)] |
157 | pub(crate) enum DefKind { | 146 | pub(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)] |
168 | pub(crate) struct Macro(RawId); | 157 | pub(super) struct Macro(RawId); |
169 | impl_arena_id!(Macro); | 158 | impl_arena_id!(Macro); |
170 | 159 | ||
171 | #[derive(Debug, PartialEq, Eq)] | 160 | #[derive(Debug, PartialEq, Eq)] |
172 | pub(crate) struct MacroData { | 161 | pub(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 | ||
180 | struct RawItemsCollector { | 168 | struct 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] | ||
557 | fn 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] | 94 | fn typing_inside_a_macro_should_not_invalidate_def_map() { |
96 | fn 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 | } |