From 83fe7b5fcb6c60b53f9ee3126b6b7995709840d3 Mon Sep 17 00:00:00 2001 From: Alexander Andreev Date: Sat, 3 Aug 2019 19:44:59 +0300 Subject: Resolve out of line modules inside inline module with attribute path Fixed #1510 Fixed #1529 --- crates/ra_hir/src/nameres/collector.rs | 67 +++++++++++++++++++++++++++------ crates/ra_hir/src/nameres/raw.rs | 17 +++++++-- crates/ra_hir/src/nameres/tests/mods.rs | 14 +------ 3 files changed, 70 insertions(+), 28 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index 06b732215..7da2dcdff 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -483,7 +483,7 @@ struct ModCollector<'a, D> { module_id: CrateModuleId, file_id: HirFileId, raw_items: &'a raw::RawItems, - parent_module: Option<&'a Name>, + parent_module: Option>, } impl ModCollector<'_, &'_ mut DefCollector<&'_ DB>> @@ -508,15 +508,16 @@ where fn collect_module(&mut self, module: &raw::ModuleData) { match module { // inline module, just recurse - raw::ModuleData::Definition { name, items, ast_id } => { + raw::ModuleData::Definition { name, items, ast_id, attr_path } => { let module_id = self.push_child_module(name.clone(), ast_id.with_file_id(self.file_id), None); + let parent_module = ParentModule { name, attr_path: attr_path.as_ref() }; ModCollector { def_collector: &mut *self.def_collector, module_id, file_id: self.file_id, raw_items: self.raw_items, - parent_module: Some(name), + parent_module: Some(parent_module), } .collect(&*items); } @@ -530,7 +531,7 @@ where name, is_root, attr_path.as_ref(), - self.parent_module, + self.parent_module.as_ref(), ) { Ok(file_id) => { let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); @@ -647,7 +648,7 @@ fn resolve_submodule( name: &Name, is_root: bool, attr_path: Option<&SmolStr>, - parent_module: Option<&Name>, + parent_module: Option<&ParentModule>, ) -> Result { let file_id = file_id.original_file(db); let source_root_id = db.file_source_root(file_id); @@ -657,20 +658,49 @@ fn resolve_submodule( let mod_name = path.file_stem().unwrap_or("unknown"); let resolve_mode = match (attr_path.filter(|p| !p.is_empty()), parent_module) { - (Some(file_path), Some(parent_name)) => { + (Some(file_path), Some(parent_module)) => { let file_path = normalize_attribute_path(file_path); - let path = dir_path.join(format!("{}/{}", parent_name, file_path)).normalize(); - ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath(path)) + match parent_module.attribute_path() { + Some(parent_module_attr_path) => { + let path = dir_path + .join(format!( + "{}/{}", + normalize_attribute_path(parent_module_attr_path), + file_path + )) + .normalize(); + ResolutionMode::InlineModuleWithAttributePath( + InsideInlineModuleMode::WithAttributePath(path), + ) + } + None => { + let path = + dir_path.join(format!("{}/{}", parent_module.name, file_path)).normalize(); + ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath( + path, + )) + } + } } + (None, Some(parent_module)) => match parent_module.attribute_path() { + Some(parent_module_attr_path) => { + let path = dir_path.join(format!( + "{}/{}.rs", + normalize_attribute_path(parent_module_attr_path), + name + )); + ResolutionMode::InlineModuleWithAttributePath(InsideInlineModuleMode::File(path)) + } + None => { + let path = dir_path.join(format!("{}/{}.rs", parent_module.name, name)); + ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path)) + } + }, (Some(file_path), None) => { let file_path = normalize_attribute_path(file_path); let path = dir_path.join(file_path.as_ref()).normalize(); ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path)) } - (None, Some(parent_name)) => { - let path = dir_path.join(format!("{}/{}.rs", parent_name, name)); - ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path)) - } _ => { let is_dir_owner = is_root || mod_name == "mod"; if is_dir_owner { @@ -743,6 +773,7 @@ impl InsideInlineModuleMode { enum ResolutionMode { OutOfLine(OutOfLineMode), InsideInlineModule(InsideInlineModuleMode), + InlineModuleWithAttributePath(InsideInlineModuleMode), } impl ResolutionMode { @@ -752,6 +783,7 @@ impl ResolutionMode { match self { OutOfLine(mode) => mode.resolve(source_root), InsideInlineModule(mode) => mode.resolve(source_root), + InlineModuleWithAttributePath(mode) => mode.resolve(source_root), } } } @@ -773,6 +805,17 @@ fn resolve_find_result( } } +struct ParentModule<'a> { + name: &'a Name, + attr_path: Option<&'a SmolStr>, +} + +impl<'a> ParentModule<'a> { + pub fn attribute_path(&self) -> Option<&SmolStr> { + self.attr_path.filter(|p| !p.is_empty()) + } +} + #[cfg(test)] mod tests { use ra_db::SourceDatabase; diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs index 8517f3c43..584e15e29 100644 --- a/crates/ra_hir/src/nameres/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs @@ -130,8 +130,17 @@ impl_arena_id!(Module); #[derive(Debug, PartialEq, Eq)] pub(super) enum ModuleData { - Declaration { name: Name, ast_id: FileAstId, attr_path: Option }, - Definition { name: Name, ast_id: FileAstId, items: Vec }, + Declaration { + name: Name, + ast_id: FileAstId, + attr_path: Option, + }, + Definition { + name: Name, + ast_id: FileAstId, + items: Vec, + attr_path: Option, + }, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -256,9 +265,9 @@ impl RawItemsCollector { None => return, }; - let attr_path = extract_mod_path_attribute(&module); let ast_id = self.source_ast_id_map.ast_id(&module); if module.has_semi() { + let attr_path = extract_mod_path_attribute(&module); let item = self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id, attr_path }); self.push_item(current_module, RawItem::Module(item)); @@ -266,10 +275,12 @@ impl RawItemsCollector { } if let Some(item_list) = module.item_list() { + let attr_path = extract_mod_path_attribute(&module); let item = self.raw_items.modules.alloc(ModuleData::Definition { name, ast_id, items: Vec::new(), + attr_path, }); self.process_module(Some(item), item_list); self.push_item(current_module, RawItem::Module(item)); diff --git a/crates/ra_hir/src/nameres/tests/mods.rs b/crates/ra_hir/src/nameres/tests/mods.rs index 382728149..6dd18df1a 100644 --- a/crates/ra_hir/src/nameres/tests/mods.rs +++ b/crates/ra_hir/src/nameres/tests/mods.rs @@ -336,9 +336,7 @@ fn module_resolution_explicit_path_mod_rs_with_win_separator() { "###); } -// FIXME: issue #1529. not support out-of-line modules inside inline. #[test] -#[ignore] fn module_resolution_decl_inside_inline_module_with_path_attribute() { let map = def_map_with_crate_graph( r###" @@ -397,9 +395,7 @@ fn module_resolution_decl_inside_inline_module() { "###); } -// FIXME: issue #1529. not support out-of-line modules inside inline. #[test] -#[ignore] fn module_resolution_decl_inside_inline_module_2_with_path_attribute() { let map = def_map_with_crate_graph( r###" @@ -429,9 +425,7 @@ fn module_resolution_decl_inside_inline_module_2_with_path_attribute() { "###); } -// FIXME: issue #1529. not support out-of-line modules inside inline. #[test] -#[ignore] fn module_resolution_decl_inside_inline_module_3() { let map = def_map_with_crate_graph( r###" @@ -462,9 +456,7 @@ fn module_resolution_decl_inside_inline_module_3() { "###); } -// FIXME: issue #1529. not support out-of-line modules inside inline. #[test] -#[ignore] fn module_resolution_decl_inside_inline_module_empty_path() { let map = def_map_with_crate_graph( r###" @@ -475,7 +467,7 @@ fn module_resolution_decl_inside_inline_module_empty_path() { mod bar; } - //- /users.rs + //- /foo/users.rs pub struct Baz; "###, crate_graph! { @@ -520,9 +512,7 @@ fn module_resolution_decl_empty_path() { "###); } -// FIXME: issue #1529. not support out-of-line modules inside inline. #[test] -#[ignore] fn module_resolution_decl_inside_inline_module_relative_path() { let map = def_map_with_crate_graph( r###" @@ -660,9 +650,7 @@ fn module_resolution_decl_inside_inline_module_in_non_crate_root() { "###); } -// FIXME: issue #1529. not support out-of-line modules inside inline. #[test] -#[ignore] fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() { let map = def_map_with_crate_graph( r###" -- cgit v1.2.3