aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres/collector.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/nameres/collector.rs')
-rw-r--r--crates/ra_hir/src/nameres/collector.rs190
1 files changed, 7 insertions, 183 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 5d1c42926..d6c7c083d 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -1,9 +1,5 @@
1use std::borrow::Cow; 1use ra_db::FileId;
2use std::sync::Arc; 2use ra_syntax::ast;
3
4use ra_db::{FileId, SourceRoot};
5use ra_syntax::{ast, SmolStr};
6use relative_path::RelativePathBuf;
7use rustc_hash::FxHashMap; 3use rustc_hash::FxHashMap;
8use test_utils::tested_by; 4use test_utils::tested_by;
9 5
@@ -12,8 +8,10 @@ use crate::{
12 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind}, 8 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind},
13 name::MACRO_RULES, 9 name::MACRO_RULES,
14 nameres::{ 10 nameres::{
15 diagnostics::DefDiagnostic, raw, CrateDefMap, CrateModuleId, ItemOrMacro, ModuleData, 11 diagnostics::DefDiagnostic,
16 ModuleDef, PerNs, ReachedFixedPoint, Resolution, ResolveMode, 12 mod_resolution::{resolve_submodule, ParentModule},
13 raw, CrateDefMap, CrateModuleId, ItemOrMacro, ModuleData, ModuleDef, PerNs,
14 ReachedFixedPoint, Resolution, ResolveMode,
17 }, 15 },
18 AstId, Const, DefDatabase, Enum, Function, HirFileId, MacroDef, Module, Name, Path, Static, 16 AstId, Const, DefDatabase, Enum, Function, HirFileId, MacroDef, Module, Name, Path, Static,
19 Struct, Trait, TypeAlias, Union, 17 Struct, Trait, TypeAlias, Union,
@@ -568,7 +566,7 @@ where
568 name, 566 name,
569 is_root, 567 is_root,
570 attr_path.as_ref(), 568 attr_path.as_ref(),
571 self.parent_module.as_ref(), 569 self.parent_module,
572 ) { 570 ) {
573 Ok(file_id) => { 571 Ok(file_id) => {
574 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); 572 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
@@ -679,180 +677,6 @@ fn is_macro_rules(path: &Path) -> bool {
679 path.as_ident() == Some(&MACRO_RULES) 677 path.as_ident() == Some(&MACRO_RULES)
680} 678}
681 679
682fn resolve_submodule(
683 db: &impl DefDatabase,
684 file_id: HirFileId,
685 name: &Name,
686 is_root: bool,
687 attr_path: Option<&SmolStr>,
688 parent_module: Option<&ParentModule>,
689) -> Result<FileId, RelativePathBuf> {
690 let file_id = file_id.original_file(db);
691 let source_root_id = db.file_source_root(file_id);
692 let path = db.file_relative_path(file_id);
693 let root = RelativePathBuf::default();
694 let dir_path = path.parent().unwrap_or(&root);
695 let mod_name = path.file_stem().unwrap_or("unknown");
696
697 let resolve_mode = match (attr_path.filter(|p| !p.is_empty()), parent_module) {
698 (Some(file_path), Some(parent_module)) => {
699 let file_path = normalize_attribute_path(file_path);
700 match parent_module.attribute_path() {
701 Some(parent_module_attr_path) => {
702 let path = dir_path
703 .join(format!(
704 "{}/{}",
705 normalize_attribute_path(parent_module_attr_path),
706 file_path
707 ))
708 .normalize();
709 ResolutionMode::InlineModuleWithAttributePath(
710 InsideInlineModuleMode::WithAttributePath(path),
711 )
712 }
713 None => {
714 let path =
715 dir_path.join(format!("{}/{}", parent_module.name, file_path)).normalize();
716 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath(
717 path,
718 ))
719 }
720 }
721 }
722 (None, Some(parent_module)) => match parent_module.attribute_path() {
723 Some(parent_module_attr_path) => {
724 let path = dir_path.join(format!(
725 "{}/{}.rs",
726 normalize_attribute_path(parent_module_attr_path),
727 name
728 ));
729 ResolutionMode::InlineModuleWithAttributePath(InsideInlineModuleMode::File(path))
730 }
731 None => {
732 let path = dir_path.join(format!("{}/{}.rs", parent_module.name, name));
733 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path))
734 }
735 },
736 (Some(file_path), None) => {
737 let file_path = normalize_attribute_path(file_path);
738 let path = dir_path.join(file_path.as_ref()).normalize();
739 ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path))
740 }
741 _ => {
742 let is_dir_owner = is_root || mod_name == "mod";
743 if is_dir_owner {
744 let file_mod = dir_path.join(format!("{}.rs", name));
745 let dir_mod = dir_path.join(format!("{}/mod.rs", name));
746 ResolutionMode::OutOfLine(OutOfLineMode::RootOrModRs {
747 file: file_mod,
748 directory: dir_mod,
749 })
750 } else {
751 let path = dir_path.join(format!("{}/{}.rs", mod_name, name));
752 ResolutionMode::OutOfLine(OutOfLineMode::FileInDirectory(path))
753 }
754 }
755 };
756
757 resolve_mode.resolve(db.source_root(source_root_id))
758}
759
760fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> {
761 let current_dir = "./";
762 let windows_path_separator = r#"\"#;
763 let current_dir_normalize = if file_path.starts_with(current_dir) {
764 &file_path[current_dir.len()..]
765 } else {
766 file_path.as_str()
767 };
768 if current_dir_normalize.contains(windows_path_separator) {
769 Cow::Owned(current_dir_normalize.replace(windows_path_separator, "/"))
770 } else {
771 Cow::Borrowed(current_dir_normalize)
772 }
773}
774
775enum OutOfLineMode {
776 RootOrModRs { file: RelativePathBuf, directory: RelativePathBuf },
777 FileInDirectory(RelativePathBuf),
778 WithAttributePath(RelativePathBuf),
779}
780
781impl OutOfLineMode {
782 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
783 match self {
784 OutOfLineMode::RootOrModRs { file, directory } => match source_root.files.get(file) {
785 None => resolve_simple_path(source_root, directory).map_err(|_| file.clone()),
786 file_id => resolve_find_result(file_id, file),
787 },
788 OutOfLineMode::FileInDirectory(path) => resolve_simple_path(source_root, path),
789 OutOfLineMode::WithAttributePath(path) => resolve_simple_path(source_root, path),
790 }
791 }
792}
793
794enum InsideInlineModuleMode {
795 File(RelativePathBuf),
796 WithAttributePath(RelativePathBuf),
797}
798
799impl InsideInlineModuleMode {
800 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
801 match self {
802 InsideInlineModuleMode::File(path) => resolve_simple_path(source_root, path),
803 InsideInlineModuleMode::WithAttributePath(path) => {
804 resolve_simple_path(source_root, path)
805 }
806 }
807 }
808}
809
810enum ResolutionMode {
811 OutOfLine(OutOfLineMode),
812 InsideInlineModule(InsideInlineModuleMode),
813 InlineModuleWithAttributePath(InsideInlineModuleMode),
814}
815
816impl ResolutionMode {
817 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
818 use self::ResolutionMode::*;
819
820 match self {
821 OutOfLine(mode) => mode.resolve(source_root),
822 InsideInlineModule(mode) => mode.resolve(source_root),
823 InlineModuleWithAttributePath(mode) => mode.resolve(source_root),
824 }
825 }
826}
827
828fn resolve_simple_path(
829 source_root: Arc<SourceRoot>,
830 path: &RelativePathBuf,
831) -> Result<FileId, RelativePathBuf> {
832 resolve_find_result(source_root.files.get(path), path)
833}
834
835fn resolve_find_result(
836 file_id: Option<&FileId>,
837 path: &RelativePathBuf,
838) -> Result<FileId, RelativePathBuf> {
839 match file_id {
840 Some(file_id) => Ok(file_id.clone()),
841 None => Err(path.clone()),
842 }
843}
844
845struct ParentModule<'a> {
846 name: &'a Name,
847 attr_path: Option<&'a SmolStr>,
848}
849
850impl<'a> ParentModule<'a> {
851 pub fn attribute_path(&self) -> Option<&SmolStr> {
852 self.attr_path.filter(|p| !p.is_empty())
853 }
854}
855
856#[cfg(test)] 680#[cfg(test)]
857mod tests { 681mod tests {
858 use ra_db::SourceDatabase; 682 use ra_db::SourceDatabase;