aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/nameres/collector.rs148
-rw-r--r--crates/ra_hir/src/nameres/tests/mods.rs53
2 files changed, 152 insertions, 49 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 7f765caf3..06b732215 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -1,7 +1,7 @@
1use std::borrow::Cow; 1use std::borrow::Cow;
2use std::sync::Arc;
2 3
3use arrayvec::ArrayVec; 4use ra_db::{FileId, SourceRoot};
4use ra_db::FileId;
5use ra_syntax::{ast, SmolStr}; 5use ra_syntax::{ast, SmolStr};
6use relative_path::RelativePathBuf; 6use relative_path::RelativePathBuf;
7use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
@@ -105,6 +105,7 @@ where
105 module_id, 105 module_id,
106 file_id: file_id.into(), 106 file_id: file_id.into(),
107 raw_items: &raw_items, 107 raw_items: &raw_items,
108 parent_module: None,
108 } 109 }
109 .collect(raw_items.items()); 110 .collect(raw_items.items());
110 111
@@ -455,8 +456,14 @@ where
455 if !self.macro_stack_monitor.is_poison(macro_def_id) { 456 if !self.macro_stack_monitor.is_poison(macro_def_id) {
456 let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items); 457 let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items);
457 let raw_items = self.db.raw_items(file_id); 458 let raw_items = self.db.raw_items(file_id);
458 ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items } 459 ModCollector {
459 .collect(raw_items.items()); 460 def_collector: &mut *self,
461 file_id,
462 module_id,
463 raw_items: &raw_items,
464 parent_module: None,
465 }
466 .collect(raw_items.items());
460 } else { 467 } else {
461 log::error!("Too deep macro expansion: {:?}", macro_call_id); 468 log::error!("Too deep macro expansion: {:?}", macro_call_id);
462 self.def_map.poison_macros.insert(macro_def_id); 469 self.def_map.poison_macros.insert(macro_def_id);
@@ -476,6 +483,7 @@ struct ModCollector<'a, D> {
476 module_id: CrateModuleId, 483 module_id: CrateModuleId,
477 file_id: HirFileId, 484 file_id: HirFileId,
478 raw_items: &'a raw::RawItems, 485 raw_items: &'a raw::RawItems,
486 parent_module: Option<&'a Name>,
479} 487}
480 488
481impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>> 489impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>>
@@ -508,6 +516,7 @@ where
508 module_id, 516 module_id,
509 file_id: self.file_id, 517 file_id: self.file_id,
510 raw_items: self.raw_items, 518 raw_items: self.raw_items,
519 parent_module: Some(name),
511 } 520 }
512 .collect(&*items); 521 .collect(&*items);
513 } 522 }
@@ -521,6 +530,7 @@ where
521 name, 530 name,
522 is_root, 531 is_root,
523 attr_path.as_ref(), 532 attr_path.as_ref(),
533 self.parent_module,
524 ) { 534 ) {
525 Ok(file_id) => { 535 Ok(file_id) => {
526 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); 536 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
@@ -530,6 +540,7 @@ where
530 module_id, 540 module_id,
531 file_id: file_id.into(), 541 file_id: file_id.into(),
532 raw_items: &raw_items, 542 raw_items: &raw_items,
543 parent_module: None,
533 } 544 }
534 .collect(raw_items.items()) 545 .collect(raw_items.items())
535 } 546 }
@@ -636,46 +647,47 @@ fn resolve_submodule(
636 name: &Name, 647 name: &Name,
637 is_root: bool, 648 is_root: bool,
638 attr_path: Option<&SmolStr>, 649 attr_path: Option<&SmolStr>,
650 parent_module: Option<&Name>,
639) -> Result<FileId, RelativePathBuf> { 651) -> Result<FileId, RelativePathBuf> {
640 // FIXME: handle submodules of inline modules properly
641 let file_id = file_id.original_file(db); 652 let file_id = file_id.original_file(db);
642 let source_root_id = db.file_source_root(file_id); 653 let source_root_id = db.file_source_root(file_id);
643 let path = db.file_relative_path(file_id); 654 let path = db.file_relative_path(file_id);
644 let root = RelativePathBuf::default(); 655 let root = RelativePathBuf::default();
645 let dir_path = path.parent().unwrap_or(&root); 656 let dir_path = path.parent().unwrap_or(&root);
646 let mod_name = path.file_stem().unwrap_or("unknown"); 657 let mod_name = path.file_stem().unwrap_or("unknown");
647 let is_dir_owner = is_root || mod_name == "mod"; 658
648 659 let resolve_mode = match (attr_path.filter(|p| !p.is_empty()), parent_module) {
649 let file_mod = dir_path.join(format!("{}.rs", name)); 660 (Some(file_path), Some(parent_name)) => {
650 let dir_mod = dir_path.join(format!("{}/mod.rs", name)); 661 let file_path = normalize_attribute_path(file_path);
651 let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name)); 662 let path = dir_path.join(format!("{}/{}", parent_name, file_path)).normalize();
652 let mut candidates = ArrayVec::<[_; 3]>::new(); 663 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath(path))
653 let file_attr_mod = attr_path.map(|file_path| { 664 }
654 let file_path = normalize_attribute_path(file_path); 665 (Some(file_path), None) => {
655 let file_attr_mod = dir_path.join(file_path.as_ref()).normalize(); 666 let file_path = normalize_attribute_path(file_path);
656 candidates.push(file_attr_mod.clone()); 667 let path = dir_path.join(file_path.as_ref()).normalize();
657 668 ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path))
658 file_attr_mod 669 }
659 }); 670 (None, Some(parent_name)) => {
660 if is_dir_owner { 671 let path = dir_path.join(format!("{}/{}.rs", parent_name, name));
661 candidates.push(file_mod.clone()); 672 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path))
662 candidates.push(dir_mod); 673 }
663 } else { 674 _ => {
664 candidates.push(file_dir_mod.clone()); 675 let is_dir_owner = is_root || mod_name == "mod";
665 }; 676 if is_dir_owner {
666 let sr = db.source_root(source_root_id); 677 let file_mod = dir_path.join(format!("{}.rs", name));
667 let mut points_to = candidates.into_iter().filter_map(|path| sr.files.get(&path)).copied(); 678 let dir_mod = dir_path.join(format!("{}/mod.rs", name));
668 // FIXME: handle ambiguity 679 ResolutionMode::OutOfLine(OutOfLineMode::RootOrModRs {
669 match points_to.next() { 680 file: file_mod,
670 Some(file_id) => Ok(file_id), 681 directory: dir_mod,
671 None => { 682 })
672 if let Some(file_attr_mod) = file_attr_mod {
673 Err(file_attr_mod)
674 } else { 683 } else {
675 Err(if is_dir_owner { file_mod } else { file_dir_mod }) 684 let path = dir_path.join(format!("{}/{}.rs", mod_name, name));
685 ResolutionMode::OutOfLine(OutOfLineMode::FileInDirectory(path))
676 } 686 }
677 } 687 }
678 } 688 };
689
690 resolve_mode.resolve(db.source_root(source_root_id))
679} 691}
680 692
681fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> { 693fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> {
@@ -693,6 +705,74 @@ fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> {
693 } 705 }
694} 706}
695 707
708enum OutOfLineMode {
709 RootOrModRs { file: RelativePathBuf, directory: RelativePathBuf },
710 FileInDirectory(RelativePathBuf),
711 WithAttributePath(RelativePathBuf),
712}
713
714impl OutOfLineMode {
715 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
716 match self {
717 OutOfLineMode::RootOrModRs { file, directory } => match source_root.files.get(file) {
718 None => resolve_simple_path(source_root, directory).map_err(|_| file.clone()),
719 file_id => resolve_find_result(file_id, file),
720 },
721 OutOfLineMode::FileInDirectory(path) => resolve_simple_path(source_root, path),
722 OutOfLineMode::WithAttributePath(path) => resolve_simple_path(source_root, path),
723 }
724 }
725}
726
727enum InsideInlineModuleMode {
728 File(RelativePathBuf),
729 WithAttributePath(RelativePathBuf),
730}
731
732impl InsideInlineModuleMode {
733 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
734 match self {
735 InsideInlineModuleMode::File(path) => resolve_simple_path(source_root, path),
736 InsideInlineModuleMode::WithAttributePath(path) => {
737 resolve_simple_path(source_root, path)
738 }
739 }
740 }
741}
742
743enum ResolutionMode {
744 OutOfLine(OutOfLineMode),
745 InsideInlineModule(InsideInlineModuleMode),
746}
747
748impl ResolutionMode {
749 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
750 use self::ResolutionMode::*;
751
752 match self {
753 OutOfLine(mode) => mode.resolve(source_root),
754 InsideInlineModule(mode) => mode.resolve(source_root),
755 }
756 }
757}
758
759fn resolve_simple_path(
760 source_root: Arc<SourceRoot>,
761 path: &RelativePathBuf,
762) -> Result<FileId, RelativePathBuf> {
763 resolve_find_result(source_root.files.get(path), path)
764}
765
766fn resolve_find_result(
767 file_id: Option<&FileId>,
768 path: &RelativePathBuf,
769) -> Result<FileId, RelativePathBuf> {
770 match file_id {
771 Some(file_id) => Ok(file_id.clone()),
772 None => Err(path.clone()),
773 }
774}
775
696#[cfg(test)] 776#[cfg(test)]
697mod tests { 777mod tests {
698 use ra_db::SourceDatabase; 778 use ra_db::SourceDatabase;
diff --git a/crates/ra_hir/src/nameres/tests/mods.rs b/crates/ra_hir/src/nameres/tests/mods.rs
index d714a3276..382728149 100644
--- a/crates/ra_hir/src/nameres/tests/mods.rs
+++ b/crates/ra_hir/src/nameres/tests/mods.rs
@@ -336,10 +336,10 @@ fn module_resolution_explicit_path_mod_rs_with_win_separator() {
336 "###); 336 "###);
337} 337}
338 338
339// FIXME: issue #1510. not support out-of-line modules inside inline. 339// FIXME: issue #1529. not support out-of-line modules inside inline.
340#[test] 340#[test]
341#[ignore] 341#[ignore]
342fn module_resolution_decl_inside_inline_module() { 342fn module_resolution_decl_inside_inline_module_with_path_attribute() {
343 let map = def_map_with_crate_graph( 343 let map = def_map_with_crate_graph(
344 r###" 344 r###"
345 //- /main.rs 345 //- /main.rs
@@ -368,10 +368,39 @@ fn module_resolution_decl_inside_inline_module() {
368 "###); 368 "###);
369} 369}
370 370
371// FIXME: issue #1510. not support out-of-line modules inside inline. 371#[test]
372fn module_resolution_decl_inside_inline_module() {
373 let map = def_map_with_crate_graph(
374 r###"
375 //- /main.rs
376 mod foo {
377 mod bar;
378 }
379
380 //- /foo/bar.rs
381 pub struct Baz;
382 "###,
383 crate_graph! {
384 "main": ("/main.rs", []),
385 },
386 );
387
388 assert_snapshot_matches!(map, @r###"
389 ⋮crate
390 ⋮foo: t
391
392 ⋮crate::foo
393 ⋮bar: t
394
395 ⋮crate::foo::bar
396 ⋮Baz: t v
397 "###);
398}
399
400// FIXME: issue #1529. not support out-of-line modules inside inline.
372#[test] 401#[test]
373#[ignore] 402#[ignore]
374fn module_resolution_decl_inside_inline_module_2() { 403fn module_resolution_decl_inside_inline_module_2_with_path_attribute() {
375 let map = def_map_with_crate_graph( 404 let map = def_map_with_crate_graph(
376 r###" 405 r###"
377 //- /main.rs 406 //- /main.rs
@@ -400,7 +429,7 @@ fn module_resolution_decl_inside_inline_module_2() {
400 "###); 429 "###);
401} 430}
402 431
403// FIXME: issue #1510. not support out-of-line modules inside inline. 432// FIXME: issue #1529. not support out-of-line modules inside inline.
404#[test] 433#[test]
405#[ignore] 434#[ignore]
406fn module_resolution_decl_inside_inline_module_3() { 435fn module_resolution_decl_inside_inline_module_3() {
@@ -433,7 +462,7 @@ fn module_resolution_decl_inside_inline_module_3() {
433 "###); 462 "###);
434} 463}
435 464
436// FIXME: issue #1510. not support out-of-line modules inside inline. 465// FIXME: issue #1529. not support out-of-line modules inside inline.
437#[test] 466#[test]
438#[ignore] 467#[ignore]
439fn module_resolution_decl_inside_inline_module_empty_path() { 468fn module_resolution_decl_inside_inline_module_empty_path() {
@@ -491,7 +520,7 @@ fn module_resolution_decl_empty_path() {
491 "###); 520 "###);
492} 521}
493 522
494// FIXME: issue #1510. not support out-of-line modules inside inline. 523// FIXME: issue #1529. not support out-of-line modules inside inline.
495#[test] 524#[test]
496#[ignore] 525#[ignore]
497fn module_resolution_decl_inside_inline_module_relative_path() { 526fn module_resolution_decl_inside_inline_module_relative_path() {
@@ -523,9 +552,7 @@ fn module_resolution_decl_inside_inline_module_relative_path() {
523 "###); 552 "###);
524} 553}
525 554
526// FIXME: issue #1510. not support out-of-line modules inside inline.
527#[test] 555#[test]
528#[ignore]
529fn module_resolution_decl_inside_inline_module_in_crate_root() { 556fn module_resolution_decl_inside_inline_module_in_crate_root() {
530 let map = def_map_with_crate_graph( 557 let map = def_map_with_crate_graph(
531 r###" 558 r###"
@@ -557,9 +584,7 @@ fn module_resolution_decl_inside_inline_module_in_crate_root() {
557 "###); 584 "###);
558} 585}
559 586
560// FIXME: issue #1510. not support out-of-line modules inside inline.
561#[test] 587#[test]
562#[ignore]
563fn module_resolution_decl_inside_inline_module_in_mod_rs() { 588fn module_resolution_decl_inside_inline_module_in_mod_rs() {
564 let map = def_map_with_crate_graph( 589 let map = def_map_with_crate_graph(
565 r###" 590 r###"
@@ -597,9 +622,7 @@ fn module_resolution_decl_inside_inline_module_in_mod_rs() {
597 "###); 622 "###);
598} 623}
599 624
600// FIXME: issue #1510. not support out-of-line modules inside inline.
601#[test] 625#[test]
602#[ignore]
603fn module_resolution_decl_inside_inline_module_in_non_crate_root() { 626fn module_resolution_decl_inside_inline_module_in_non_crate_root() {
604 let map = def_map_with_crate_graph( 627 let map = def_map_with_crate_graph(
605 r###" 628 r###"
@@ -613,7 +636,7 @@ fn module_resolution_decl_inside_inline_module_in_non_crate_root() {
613 } 636 }
614 use self::bar::baz::Baz; 637 use self::bar::baz::Baz;
615 638
616 //- /foo/bar/qwe.rs 639 //- /bar/qwe.rs
617 pub struct Baz; 640 pub struct Baz;
618 "###, 641 "###,
619 crate_graph! { 642 crate_graph! {
@@ -637,7 +660,7 @@ fn module_resolution_decl_inside_inline_module_in_non_crate_root() {
637 "###); 660 "###);
638} 661}
639 662
640// FIXME: issue #1510. not support out-of-line modules inside inline. 663// FIXME: issue #1529. not support out-of-line modules inside inline.
641#[test] 664#[test]
642#[ignore] 665#[ignore]
643fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() { 666fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() {