]> git.lizzy.rs Git - rust.git/commitdiff
Resolve out of line modules inside inline module with attribute path
authorAlexander Andreev <andreevlex.as@gmail.com>
Sat, 3 Aug 2019 16:44:59 +0000 (19:44 +0300)
committerAlexander Andreev <andreevlex.as@gmail.com>
Sat, 3 Aug 2019 16:44:59 +0000 (19:44 +0300)
Fixed #1510
Fixed #1529

crates/ra_hir/src/nameres/collector.rs
crates/ra_hir/src/nameres/raw.rs
crates/ra_hir/src/nameres/tests/mods.rs

index 06b7322153203bbf8c97e6c2c7e799d662e65a08..7da2dcdff1c5eedc613c2b13937dc301de958f2e 100644 (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 @@ fn collect(&mut self, items: &[raw::RawItem]) {
     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 @@ fn collect_module(&mut self, module: &raw::ModuleData) {
                     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 @@ pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePa
 enum ResolutionMode {
     OutOfLine(OutOfLineMode),
     InsideInlineModule(InsideInlineModuleMode),
+    InlineModuleWithAttributePath(InsideInlineModuleMode),
 }
 
 impl ResolutionMode {
@@ -752,6 +783,7 @@ pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePa
         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;
index 8517f3c430dda9215aab89dbcbef8324453fee4d..584e15e290d652df0b05bafd3ae36ab11439159a 100644 (file)
@@ -130,8 +130,17 @@ pub(super) enum RawItem {
 
 #[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 @@ fn add_module(&mut self, current_module: Option<Module>, module: ast::Module) {
             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 @@ fn add_module(&mut self, current_module: Option<Module>, module: ast::Module) {
         }
 
         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));
index 38272814992c0bf3e6173dc301d362d0d5f0d583..6dd18df1a9ac09601ec336592eb0c8adcb6be67d 100644 (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 @@ mod foo {
     "###);
 }
 
-// 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 @@ mod foo {
     "###);
 }
 
-// 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 @@ mod foo {
     "###);
 }
 
-// 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 @@ mod foo {
             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 @@ mod bar {
     "###);
 }
 
-// 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###"