aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorAlexander Andreev <[email protected]>2019-07-29 07:54:40 +0100
committerAlexander Andreev <[email protected]>2019-07-29 07:54:40 +0100
commit538ec1122baeccd85ab672fd0a9f1186d2171058 (patch)
treebd678af17b28232a43ac8c563d019d8a736641b5 /crates/ra_hir
parentde278d164906d6d29974790c5a4db28303692484 (diff)
Added resolve modules inside inline module
#1510
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/nameres/collector.rs148
-rw-r--r--crates/ra_hir/src/nameres/tests/mods.rs53
2 files changed, 147 insertions, 54 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 7f765caf3..80b71e2d9 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;
@@ -106,7 +106,7 @@ where
106 file_id: file_id.into(), 106 file_id: file_id.into(),
107 raw_items: &raw_items, 107 raw_items: &raw_items,
108 } 108 }
109 .collect(raw_items.items()); 109 .collect(None, raw_items.items());
110 110
111 // main name resolution fixed-point loop. 111 // main name resolution fixed-point loop.
112 let mut i = 0; 112 let mut i = 0;
@@ -456,7 +456,7 @@ where
456 let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items); 456 let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items);
457 let raw_items = self.db.raw_items(file_id); 457 let raw_items = self.db.raw_items(file_id);
458 ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items } 458 ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items }
459 .collect(raw_items.items()); 459 .collect(None, raw_items.items());
460 } else { 460 } else {
461 log::error!("Too deep macro expansion: {:?}", macro_call_id); 461 log::error!("Too deep macro expansion: {:?}", macro_call_id);
462 self.def_map.poison_macros.insert(macro_def_id); 462 self.def_map.poison_macros.insert(macro_def_id);
@@ -482,10 +482,10 @@ impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>>
482where 482where
483 DB: DefDatabase, 483 DB: DefDatabase,
484{ 484{
485 fn collect(&mut self, items: &[raw::RawItem]) { 485 fn collect(&mut self, parent_module: Option<&Name>, items: &[raw::RawItem]) {
486 for item in items { 486 for item in items {
487 match *item { 487 match *item {
488 raw::RawItem::Module(m) => self.collect_module(&self.raw_items[m]), 488 raw::RawItem::Module(m) => self.collect_module(parent_module, &self.raw_items[m]),
489 raw::RawItem::Import(import) => self.def_collector.unresolved_imports.push(( 489 raw::RawItem::Import(import) => self.def_collector.unresolved_imports.push((
490 self.module_id, 490 self.module_id,
491 import, 491 import,
@@ -497,7 +497,7 @@ where
497 } 497 }
498 } 498 }
499 499
500 fn collect_module(&mut self, module: &raw::ModuleData) { 500 fn collect_module(&mut self, _module: Option<&Name>, module: &raw::ModuleData) {
501 match module { 501 match module {
502 // inline module, just recurse 502 // inline module, just recurse
503 raw::ModuleData::Definition { name, items, ast_id } => { 503 raw::ModuleData::Definition { name, items, ast_id } => {
@@ -509,7 +509,7 @@ where
509 file_id: self.file_id, 509 file_id: self.file_id,
510 raw_items: self.raw_items, 510 raw_items: self.raw_items,
511 } 511 }
512 .collect(&*items); 512 .collect(Some(name), &*items);
513 } 513 }
514 // out of line module, resolve, parse and recurse 514 // out of line module, resolve, parse and recurse
515 raw::ModuleData::Declaration { name, ast_id, attr_path } => { 515 raw::ModuleData::Declaration { name, ast_id, attr_path } => {
@@ -521,6 +521,7 @@ where
521 name, 521 name,
522 is_root, 522 is_root,
523 attr_path.as_ref(), 523 attr_path.as_ref(),
524 _module,
524 ) { 525 ) {
525 Ok(file_id) => { 526 Ok(file_id) => {
526 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); 527 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
@@ -531,7 +532,7 @@ where
531 file_id: file_id.into(), 532 file_id: file_id.into(),
532 raw_items: &raw_items, 533 raw_items: &raw_items,
533 } 534 }
534 .collect(raw_items.items()) 535 .collect(None, raw_items.items())
535 } 536 }
536 Err(candidate) => self.def_collector.def_map.diagnostics.push( 537 Err(candidate) => self.def_collector.def_map.diagnostics.push(
537 DefDiagnostic::UnresolvedModule { 538 DefDiagnostic::UnresolvedModule {
@@ -636,46 +637,47 @@ fn resolve_submodule(
636 name: &Name, 637 name: &Name,
637 is_root: bool, 638 is_root: bool,
638 attr_path: Option<&SmolStr>, 639 attr_path: Option<&SmolStr>,
640 parent_module: Option<&Name>,
639) -> Result<FileId, RelativePathBuf> { 641) -> Result<FileId, RelativePathBuf> {
640 // FIXME: handle submodules of inline modules properly
641 let file_id = file_id.original_file(db); 642 let file_id = file_id.original_file(db);
642 let source_root_id = db.file_source_root(file_id); 643 let source_root_id = db.file_source_root(file_id);
643 let path = db.file_relative_path(file_id); 644 let path = db.file_relative_path(file_id);
644 let root = RelativePathBuf::default(); 645 let root = RelativePathBuf::default();
645 let dir_path = path.parent().unwrap_or(&root); 646 let dir_path = path.parent().unwrap_or(&root);
646 let mod_name = path.file_stem().unwrap_or("unknown"); 647 let mod_name = path.file_stem().unwrap_or("unknown");
647 let is_dir_owner = is_root || mod_name == "mod"; 648
648 649 let resolve_mode = match (attr_path.filter(|p| !p.is_empty()), parent_module) {
649 let file_mod = dir_path.join(format!("{}.rs", name)); 650 (Some(file_path), Some(parent_name)) => {
650 let dir_mod = dir_path.join(format!("{}/mod.rs", name)); 651 let file_path = normalize_attribute_path(file_path);
651 let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name)); 652 let path = dir_path.join(format!("{}/{}", parent_name, file_path)).normalize();
652 let mut candidates = ArrayVec::<[_; 3]>::new(); 653 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath(path))
653 let file_attr_mod = attr_path.map(|file_path| { 654 }
654 let file_path = normalize_attribute_path(file_path); 655 (Some(file_path), None) => {
655 let file_attr_mod = dir_path.join(file_path.as_ref()).normalize(); 656 let file_path = normalize_attribute_path(file_path);
656 candidates.push(file_attr_mod.clone()); 657 let path = dir_path.join(file_path.as_ref()).normalize();
657 658 ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path))
658 file_attr_mod 659 }
659 }); 660 (None, Some(parent_name)) => {
660 if is_dir_owner { 661 let path = dir_path.join(format!("{}/{}.rs", parent_name, name));
661 candidates.push(file_mod.clone()); 662 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path))
662 candidates.push(dir_mod); 663 }
663 } else { 664 _ => {
664 candidates.push(file_dir_mod.clone()); 665 let is_dir_owner = is_root || mod_name == "mod";
665 }; 666 if is_dir_owner {
666 let sr = db.source_root(source_root_id); 667 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(); 668 let dir_mod = dir_path.join(format!("{}/mod.rs", name));
668 // FIXME: handle ambiguity 669 ResolutionMode::OutOfLine(OutOfLineMode::RootOrModRs {
669 match points_to.next() { 670 file: file_mod,
670 Some(file_id) => Ok(file_id), 671 directory: dir_mod,
671 None => { 672 })
672 if let Some(file_attr_mod) = file_attr_mod {
673 Err(file_attr_mod)
674 } else { 673 } else {
675 Err(if is_dir_owner { file_mod } else { file_dir_mod }) 674 let path = dir_path.join(format!("{}/{}.rs", mod_name, name));
675 ResolutionMode::OutOfLine(OutOfLineMode::FileInDirectory(path))
676 } 676 }
677 } 677 }
678 } 678 };
679
680 resolve_mode.resolve(db.source_root(source_root_id))
679} 681}
680 682
681fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> { 683fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> {
@@ -693,6 +695,74 @@ fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> {
693 } 695 }
694} 696}
695 697
698enum OutOfLineMode {
699 RootOrModRs { file: RelativePathBuf, directory: RelativePathBuf },
700 FileInDirectory(RelativePathBuf),
701 WithAttributePath(RelativePathBuf),
702}
703
704impl OutOfLineMode {
705 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
706 match self {
707 OutOfLineMode::RootOrModRs { file, directory } => match source_root.files.get(file) {
708 None => resolve_simple_path(source_root, directory).map_err(|_| file.clone()),
709 file_id => resolve_find_result(file_id, file),
710 },
711 OutOfLineMode::FileInDirectory(path) => resolve_simple_path(source_root, path),
712 OutOfLineMode::WithAttributePath(path) => resolve_simple_path(source_root, path),
713 }
714 }
715}
716
717enum InsideInlineModuleMode {
718 File(RelativePathBuf),
719 WithAttributePath(RelativePathBuf),
720}
721
722impl InsideInlineModuleMode {
723 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
724 match self {
725 InsideInlineModuleMode::File(path) => resolve_simple_path(source_root, path),
726 InsideInlineModuleMode::WithAttributePath(path) => {
727 resolve_simple_path(source_root, path)
728 }
729 }
730 }
731}
732
733enum ResolutionMode {
734 OutOfLine(OutOfLineMode),
735 InsideInlineModule(InsideInlineModuleMode),
736}
737
738impl ResolutionMode {
739 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
740 use self::ResolutionMode::*;
741
742 match self {
743 OutOfLine(mode) => mode.resolve(source_root),
744 InsideInlineModule(mode) => mode.resolve(source_root),
745 }
746 }
747}
748
749fn resolve_simple_path(
750 source_root: Arc<SourceRoot>,
751 path: &RelativePathBuf,
752) -> Result<FileId, RelativePathBuf> {
753 resolve_find_result(source_root.files.get(path), path)
754}
755
756fn resolve_find_result(
757 file_id: Option<&FileId>,
758 path: &RelativePathBuf,
759) -> Result<FileId, RelativePathBuf> {
760 match file_id {
761 Some(file_id) => Ok(file_id.clone()),
762 None => Err(path.clone()),
763 }
764}
765
696#[cfg(test)] 766#[cfg(test)]
697mod tests { 767mod tests {
698 use ra_db::SourceDatabase; 768 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() {