Resolve out of line modules inside inline module with attribute path

Fixed #1510
Fixed #1529
This commit is contained in:
Alexander Andreev 2019-08-03 19:44:59 +03:00
parent 0ca30b6c4b
commit 83fe7b5fcb
3 changed files with 70 additions and 28 deletions

View File

@ -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<ParentModule<'a>>,
}
impl<DB> 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<FileId, RelativePathBuf> {
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;

View File

@ -130,8 +130,17 @@ impl_arena_id!(Module);
#[derive(Debug, PartialEq, Eq)]
pub(super) enum ModuleData {
Declaration { name: Name, ast_id: FileAstId<ast::Module>, attr_path: Option<SmolStr> },
Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> },
Declaration {
name: Name,
ast_id: FileAstId<ast::Module>,
attr_path: Option<SmolStr>,
},
Definition {
name: Name,
ast_id: FileAstId<ast::Module>,
items: Vec<RawItem>,
attr_path: Option<SmolStr>,
},
}
#[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));

View File

@ -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###"