From 35a0f04128b1ba84da8f3a107e7eed0b164733ed Mon Sep 17 00:00:00 2001 From: Alexander Andreev Date: Sat, 6 Jul 2019 14:04:56 +0300 Subject: Added extract path attribute for current module #1211 --- crates/ra_hir/src/nameres.rs | 2 +- crates/ra_hir/src/nameres/collector.rs | 4 ++-- crates/ra_hir/src/nameres/raw.rs | 22 +++++++++++++++++++--- 3 files changed, 22 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 53ef8d58a..cf9ff0636 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -76,7 +76,7 @@ pub use self::{ raw::ImportId, }; -/// Contans all top-level defs from a macro-expanded crate +/// Contains all top-level defs from a macro-expanded crate #[derive(Debug, PartialEq, Eq)] pub struct CrateDefMap { krate: Crate, diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index d66be34db..951468a98 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -508,8 +508,8 @@ where } .collect(&*items); } - // out of line module, resovle, parse and recurse - raw::ModuleData::Declaration { name, ast_id } => { + // out of line module, resolve, parse and recurse + raw::ModuleData::Declaration { name, ast_id, .. } => { let ast_id = ast_id.with_file_id(self.file_id); let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); match resolve_submodule(self.def_collector.db, self.file_id, name, is_root) { diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs index 7ea59cb75..46b2bef5b 100644 --- a/crates/ra_hir/src/nameres/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs @@ -3,7 +3,7 @@ use std::{ops::Index, sync::Arc}; use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; use ra_syntax::{ ast::{self, AttrsOwner, NameOwner}, - AstNode, AstPtr, SourceFile, TreeArc, + AstNode, AstPtr, SmolStr, SourceFile, TreeArc, }; use test_utils::tested_by; @@ -130,7 +130,7 @@ impl_arena_id!(Module); #[derive(Debug, PartialEq, Eq)] pub(super) enum ModuleData { - Declaration { name: Name, ast_id: FileAstId }, + Declaration { name: Name, ast_id: FileAstId, attr_path: Option }, Definition { name: Name, ast_id: FileAstId, items: Vec }, } @@ -255,9 +255,12 @@ impl RawItemsCollector { Some(it) => it.as_name(), 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 item = self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id }); + let item = + self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id, attr_path }); self.push_item(current_module, RawItem::Module(item)); return; } @@ -339,3 +342,16 @@ impl RawItemsCollector { .push(item) } } + +fn extract_mod_path_attribute(module: &ast::Module) -> Option { + module.attrs().into_iter().find_map(|attr| { + attr.as_key_value().and_then(|(name, value)| { + let is_path = name == "path"; + if is_path { + Some(value) + } else { + None + } + }) + }) +} -- cgit v1.2.3 From 8579a9b834555339e400f3161280305a99189a5f Mon Sep 17 00:00:00 2001 From: Alexander Andreev Date: Sat, 6 Jul 2019 21:54:21 +0300 Subject: Added support attribute path in resolusion module fn --- crates/ra_hir/src/nameres/collector.rs | 29 +++++++++-- crates/ra_hir/src/nameres/tests.rs | 95 ++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 5 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 951468a98..9f197bb58 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -1,6 +1,6 @@ use arrayvec::ArrayVec; use ra_db::FileId; -use ra_syntax::ast; +use ra_syntax::{ast, SmolStr}; use relative_path::RelativePathBuf; use rustc_hash::FxHashMap; use test_utils::tested_by; @@ -509,10 +509,16 @@ where .collect(&*items); } // out of line module, resolve, parse and recurse - raw::ModuleData::Declaration { name, ast_id, .. } => { + raw::ModuleData::Declaration { name, ast_id, attr_path } => { let ast_id = ast_id.with_file_id(self.file_id); let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); - match resolve_submodule(self.def_collector.db, self.file_id, name, is_root) { + match resolve_submodule( + self.def_collector.db, + self.file_id, + name, + is_root, + attr_path.as_ref(), + ) { Ok(file_id) => { let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); let raw_items = self.def_collector.db.raw_items(file_id.into()); @@ -626,6 +632,7 @@ fn resolve_submodule( file_id: HirFileId, name: &Name, is_root: bool, + attr_path: Option<&SmolStr>, ) -> Result { // FIXME: handle submodules of inline modules properly let file_id = file_id.original_file(db); @@ -639,7 +646,13 @@ fn resolve_submodule( let file_mod = dir_path.join(format!("{}.rs", name)); let dir_mod = dir_path.join(format!("{}/mod.rs", name)); let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name)); - let mut candidates = ArrayVec::<[_; 2]>::new(); + let mut candidates = ArrayVec::<[_; 3]>::new(); + let file_attr_mod = attr_path.map(|file_path| { + let file_attr_mod = dir_path.join(file_path.to_string()); + candidates.push(file_attr_mod.clone()); + + file_attr_mod + }); if is_dir_owner { candidates.push(file_mod.clone()); candidates.push(dir_mod); @@ -651,7 +664,13 @@ fn resolve_submodule( // FIXME: handle ambiguity match points_to.next() { Some(file_id) => Ok(file_id), - None => Err(if is_dir_owner { file_mod } else { file_dir_mod }), + None => { + if let Some(file_attr_mod) = file_attr_mod { + Err(file_attr_mod) + } else { + Err(if is_dir_owner { file_mod } else { file_dir_mod }) + } + } } } diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index bd2d855cf..5e8ea6780 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs @@ -364,6 +364,101 @@ fn module_resolution_works_for_raw_modules() { "###); } +#[test] +fn module_resolution_decl_path() { + let map = def_map_with_crate_graph( + " + //- /library.rs + #[path = \"bar/baz/foo.rs\"] + mod foo; + use self::foo::Bar; + + //- /bar/baz/foo.rs + pub struct Bar; + ", + crate_graph! { + "library": ("/library.rs", []), + }, + ); + + assert_snapshot_matches!(map, @r###" + ⋮crate + ⋮Bar: t v + ⋮foo: t + ⋮ + ⋮crate::foo + ⋮Bar: t v + "###); +} + +#[test] +fn module_resolution_module_with_path_in_mod_rs() { + let map = def_map_with_crate_graph( + " + //- /main.rs + mod foo; + + //- /foo/mod.rs + #[path = \"baz.rs\"] + pub mod bar; + + use self::bar::Baz; + + //- /foo/baz.rs + pub struct Baz; + ", + crate_graph! { + "main": ("/main.rs", []), + }, + ); + + assert_snapshot_matches!(map, @r###" + ⋮crate + ⋮foo: t + ⋮ + ⋮crate::foo + ⋮Baz: t v + ⋮bar: t + ⋮ + ⋮crate::foo::bar + ⋮Baz: t v + "###); +} + +#[test] +fn module_resolution_module_with_path_non_crate_root() { + let map = def_map_with_crate_graph( + " + //- /main.rs + mod foo; + + //- /foo.rs + #[path = \"baz.rs\"] + pub mod bar; + + use self::bar::Baz; + + //- /baz.rs + pub struct Baz; + ", + crate_graph! { + "main": ("/main.rs", []), + }, + ); + + assert_snapshot_matches!(map, @r###" + ⋮crate + ⋮foo: t + ⋮ + ⋮crate::foo + ⋮Baz: t v + ⋮bar: t + ⋮ + ⋮crate::foo::bar + ⋮Baz: t v + "###); +} + #[test] fn name_res_works_for_broken_modules() { covers!(name_res_works_for_broken_modules); -- cgit v1.2.3 From 1c582be63b35c6602638023d4bd0bc426b0ca744 Mon Sep 17 00:00:00 2001 From: Alexander Andreev Date: Sun, 7 Jul 2019 16:06:54 +0300 Subject: Moved module resolution test in mods.rs --- crates/ra_hir/src/nameres.rs | 2 +- crates/ra_hir/src/nameres/tests.rs | 192 +----------------------------- crates/ra_hir/src/nameres/tests/mods.rs | 192 ++++++++++++++++++++++++++++++ crates/ra_hir/src/ty/method_resolution.rs | 2 +- 4 files changed, 195 insertions(+), 193 deletions(-) create mode 100644 crates/ra_hir/src/nameres/tests/mods.rs (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index cf9ff0636..c84d2eada 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -1,6 +1,6 @@ /// This module implements import-resolution/macro expansion algorithm. /// -/// The result of this module is `CrateDefMap`: a datastructure which contains: +/// The result of this module is `CrateDefMap`: a data structure which contains: /// /// * a tree of modules for the crate /// * for each module, a set of items visible in the module (directly declared diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index 5e8ea6780..8b0887fb5 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs @@ -2,6 +2,7 @@ mod macros; mod globs; mod incremental; mod primitives; +mod mods; use std::sync::Arc; @@ -312,178 +313,6 @@ fn edition_2015_imports() { "###); } -#[test] -fn module_resolution_works_for_non_standard_filenames() { - let map = def_map_with_crate_graph( - " - //- /my_library.rs - mod foo; - use self::foo::Bar; - - //- /foo/mod.rs - pub struct Bar; - ", - crate_graph! { - "my_library": ("/my_library.rs", []), - }, - ); - - assert_snapshot_matches!(map, @r###" - ⋮crate - ⋮Bar: t v - ⋮foo: t - ⋮ - ⋮crate::foo - ⋮Bar: t v - "###); -} - -#[test] -fn module_resolution_works_for_raw_modules() { - let map = def_map_with_crate_graph( - " - //- /library.rs - mod r#async; - use self::r#async::Bar; - - //- /async.rs - pub struct Bar; - ", - crate_graph! { - "library": ("/library.rs", []), - }, - ); - - assert_snapshot_matches!(map, @r###" - ⋮crate - ⋮Bar: t v - ⋮async: t - ⋮ - ⋮crate::async - ⋮Bar: t v - "###); -} - -#[test] -fn module_resolution_decl_path() { - let map = def_map_with_crate_graph( - " - //- /library.rs - #[path = \"bar/baz/foo.rs\"] - mod foo; - use self::foo::Bar; - - //- /bar/baz/foo.rs - pub struct Bar; - ", - crate_graph! { - "library": ("/library.rs", []), - }, - ); - - assert_snapshot_matches!(map, @r###" - ⋮crate - ⋮Bar: t v - ⋮foo: t - ⋮ - ⋮crate::foo - ⋮Bar: t v - "###); -} - -#[test] -fn module_resolution_module_with_path_in_mod_rs() { - let map = def_map_with_crate_graph( - " - //- /main.rs - mod foo; - - //- /foo/mod.rs - #[path = \"baz.rs\"] - pub mod bar; - - use self::bar::Baz; - - //- /foo/baz.rs - pub struct Baz; - ", - crate_graph! { - "main": ("/main.rs", []), - }, - ); - - assert_snapshot_matches!(map, @r###" - ⋮crate - ⋮foo: t - ⋮ - ⋮crate::foo - ⋮Baz: t v - ⋮bar: t - ⋮ - ⋮crate::foo::bar - ⋮Baz: t v - "###); -} - -#[test] -fn module_resolution_module_with_path_non_crate_root() { - let map = def_map_with_crate_graph( - " - //- /main.rs - mod foo; - - //- /foo.rs - #[path = \"baz.rs\"] - pub mod bar; - - use self::bar::Baz; - - //- /baz.rs - pub struct Baz; - ", - crate_graph! { - "main": ("/main.rs", []), - }, - ); - - assert_snapshot_matches!(map, @r###" - ⋮crate - ⋮foo: t - ⋮ - ⋮crate::foo - ⋮Baz: t v - ⋮bar: t - ⋮ - ⋮crate::foo::bar - ⋮Baz: t v - "###); -} - -#[test] -fn name_res_works_for_broken_modules() { - covers!(name_res_works_for_broken_modules); - let map = def_map( - " - //- /lib.rs - mod foo // no `;`, no body - - use self::foo::Baz; - - //- /foo/mod.rs - pub mod bar; - - pub use self::bar::Baz; - - //- /foo/bar.rs - pub struct Baz; - ", - ); - assert_snapshot_matches!(map, @r###" - ⋮crate - ⋮Baz: _ - "###); -} - #[test] fn item_map_using_self() { let map = def_map( @@ -676,22 +505,3 @@ fn values_dont_shadow_extern_crates() { ⋮foo: v "###); } - -#[test] -fn unresolved_module_diagnostics() { - let diagnostics = MockDatabase::with_files( - r" - //- /lib.rs - mod foo; - mod bar; - mod baz {} - //- /foo.rs - ", - ) - .diagnostics(); - - assert_snapshot_matches!(diagnostics, @r###" -"mod bar;": unresolved module -"### - ); -} diff --git a/crates/ra_hir/src/nameres/tests/mods.rs b/crates/ra_hir/src/nameres/tests/mods.rs new file mode 100644 index 000000000..7c8c832fc --- /dev/null +++ b/crates/ra_hir/src/nameres/tests/mods.rs @@ -0,0 +1,192 @@ +use super::*; + +#[test] +fn name_res_works_for_broken_modules() { + covers!(name_res_works_for_broken_modules); + let map = def_map( + " + //- /lib.rs + mod foo // no `;`, no body + + use self::foo::Baz; + + //- /foo/mod.rs + pub mod bar; + + pub use self::bar::Baz; + + //- /foo/bar.rs + pub struct Baz; + ", + ); + assert_snapshot_matches!(map, @r###" + ⋮crate + ⋮Baz: _ + "###); +} + +#[test] +fn module_resolution_works_for_non_standard_filenames() { + let map = def_map_with_crate_graph( + " + //- /my_library.rs + mod foo; + use self::foo::Bar; + + //- /foo/mod.rs + pub struct Bar; + ", + crate_graph! { + "my_library": ("/my_library.rs", []), + }, + ); + + assert_snapshot_matches!(map, @r###" + ⋮crate + ⋮Bar: t v + ⋮foo: t + ⋮ + ⋮crate::foo + ⋮Bar: t v + "###); +} + +#[test] +fn module_resolution_works_for_raw_modules() { + let map = def_map_with_crate_graph( + " + //- /library.rs + mod r#async; + use self::r#async::Bar; + + //- /async.rs + pub struct Bar; + ", + crate_graph! { + "library": ("/library.rs", []), + }, + ); + + assert_snapshot_matches!(map, @r###" + ⋮crate + ⋮Bar: t v + ⋮async: t + ⋮ + ⋮crate::async + ⋮Bar: t v + "###); +} + +#[test] +fn module_resolution_decl_path() { + let map = def_map_with_crate_graph( + " + //- /library.rs + #[path = \"bar/baz/foo.rs\"] + mod foo; + use self::foo::Bar; + + //- /bar/baz/foo.rs + pub struct Bar; + ", + crate_graph! { + "library": ("/library.rs", []), + }, + ); + + assert_snapshot_matches!(map, @r###" + ⋮crate + ⋮Bar: t v + ⋮foo: t + ⋮ + ⋮crate::foo + ⋮Bar: t v + "###); +} + +#[test] +fn module_resolution_module_with_path_in_mod_rs() { + let map = def_map_with_crate_graph( + " + //- /main.rs + mod foo; + + //- /foo/mod.rs + #[path = \"baz.rs\"] + pub mod bar; + + use self::bar::Baz; + + //- /foo/baz.rs + pub struct Baz; + ", + crate_graph! { + "main": ("/main.rs", []), + }, + ); + + assert_snapshot_matches!(map, @r###" + ⋮crate + ⋮foo: t + ⋮ + ⋮crate::foo + ⋮Baz: t v + ⋮bar: t + ⋮ + ⋮crate::foo::bar + ⋮Baz: t v + "###); +} + +#[test] +fn module_resolution_module_with_path_non_crate_root() { + let map = def_map_with_crate_graph( + " + //- /main.rs + mod foo; + + //- /foo.rs + #[path = \"baz.rs\"] + pub mod bar; + + use self::bar::Baz; + + //- /baz.rs + pub struct Baz; + ", + crate_graph! { + "main": ("/main.rs", []), + }, + ); + + assert_snapshot_matches!(map, @r###" + ⋮crate + ⋮foo: t + ⋮ + ⋮crate::foo + ⋮Baz: t v + ⋮bar: t + ⋮ + ⋮crate::foo::bar + ⋮Baz: t v + "###); +} + +#[test] +fn unresolved_module_diagnostics() { + let diagnostics = MockDatabase::with_files( + r" + //- /lib.rs + mod foo; + mod bar; + mod baz {} + //- /foo.rs + ", + ) + .diagnostics(); + + assert_snapshot_matches!(diagnostics, @r###" +"mod bar;": unresolved module +"### + ); +} diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 10a6e0b10..76ace66ea 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -116,7 +116,7 @@ impl CrateImplBlocks { fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option> { // Types like slice can have inherent impls in several crates, (core and alloc). - // The correspoinding impls are marked with lang items, so we can use them to find the required crates. + // The corresponding impls are marked with lang items, so we can use them to find the required crates. macro_rules! lang_item_crate { ($db:expr, $cur_crate:expr, $($name:expr),+ $(,)?) => {{ let mut v = ArrayVec::<[Crate; 2]>::new(); -- cgit v1.2.3