aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/module_tree.rs6
-rw-r--r--crates/ra_hir/src/nameres/tests.rs36
-rw-r--r--crates/ra_ide_api/tests/test/main.rs12
-rw-r--r--crates/ra_syntax/src/algo.rs4
4 files changed, 48 insertions, 10 deletions
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs
index d1dc3fa4b..893c375b5 100644
--- a/crates/ra_hir/src/module_tree.rs
+++ b/crates/ra_hir/src/module_tree.rs
@@ -172,6 +172,7 @@ impl ModuleTree {
172 file_id: HirFileId, 172 file_id: HirFileId,
173 decl_id: Option<SourceFileItemId>, 173 decl_id: Option<SourceFileItemId>,
174 ) -> ModuleId { 174 ) -> ModuleId {
175 let is_root = parent.is_none();
175 let id = self.alloc_mod(ModuleData { 176 let id = self.alloc_mod(ModuleData {
176 file_id, 177 file_id,
177 decl_id, 178 decl_id,
@@ -191,7 +192,7 @@ impl ModuleTree {
191 }); 192 });
192 193
193 let (points_to, problem) = if sub.is_declaration { 194 let (points_to, problem) = if sub.is_declaration {
194 let (points_to, problem) = resolve_submodule(db, file_id, &sub.name); 195 let (points_to, problem) = resolve_submodule(db, file_id, &sub.name, is_root);
195 let points_to = points_to 196 let points_to = points_to
196 .into_iter() 197 .into_iter()
197 .map(|file_id| { 198 .map(|file_id| {
@@ -295,6 +296,7 @@ fn resolve_submodule(
295 db: &impl HirDatabase, 296 db: &impl HirDatabase,
296 file_id: HirFileId, 297 file_id: HirFileId,
297 name: &Name, 298 name: &Name,
299 is_root: bool,
298) -> (Vec<FileId>, Option<Problem>) { 300) -> (Vec<FileId>, Option<Problem>) {
299 // FIXME: handle submodules of inline modules properly 301 // FIXME: handle submodules of inline modules properly
300 let file_id = file_id.original_file(db); 302 let file_id = file_id.original_file(db);
@@ -303,7 +305,7 @@ fn resolve_submodule(
303 let root = RelativePathBuf::default(); 305 let root = RelativePathBuf::default();
304 let dir_path = path.parent().unwrap_or(&root); 306 let dir_path = path.parent().unwrap_or(&root);
305 let mod_name = path.file_stem().unwrap_or("unknown"); 307 let mod_name = path.file_stem().unwrap_or("unknown");
306 let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; 308 let is_dir_owner = is_root || mod_name == "mod";
307 309
308 let file_mod = dir_path.join(format!("{}.rs", name)); 310 let file_mod = dir_path.join(format!("{}.rs", name));
309 let dir_mod = dir_path.join(format!("{}/mod.rs", name)); 311 let dir_mod = dir_path.join(format!("{}/mod.rs", name));
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index e72781f51..3d420467c 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -19,6 +19,20 @@ fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
19 (db.item_map(krate.crate_id), module_id) 19 (db.item_map(krate.crate_id), module_id)
20} 20}
21 21
22/// Sets the crate root to the file of the cursor marker
23fn item_map_custom_crate_root(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
24 let (mut db, pos) = MockDatabase::with_position(fixture);
25
26 let mut crate_graph = CrateGraph::default();
27 crate_graph.add_crate_root(pos.file_id);
28 db.set_crate_graph(Arc::new(crate_graph));
29
30 let module = crate::source_binder::module_from_position(&db, pos).unwrap();
31 let krate = module.krate(&db).unwrap();
32 let module_id = module.module_id;
33 (db.item_map(krate.crate_id), module_id)
34}
35
22fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { 36fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) {
23 let mut lines = map[module_id] 37 let mut lines = map[module_id]
24 .items 38 .items
@@ -134,6 +148,28 @@ fn re_exports() {
134} 148}
135 149
136#[test] 150#[test]
151fn module_resolution_works_for_non_standard_filenames() {
152 let (item_map, module_id) = item_map_custom_crate_root(
153 "
154 //- /my_library.rs
155 mod foo;
156 use self::foo::Bar;
157 <|>
158 //- /foo/mod.rs
159 pub struct Bar;
160 ",
161 );
162 check_module_item_map(
163 &item_map,
164 module_id,
165 "
166 Bar: t v
167 foo: t
168 ",
169 );
170}
171
172#[test]
137fn name_res_works_for_broken_modules() { 173fn name_res_works_for_broken_modules() {
138 covers!(name_res_works_for_broken_modules); 174 covers!(name_res_works_for_broken_modules);
139 let (item_map, module_id) = item_map( 175 let (item_map, module_id) = item_map(
diff --git a/crates/ra_ide_api/tests/test/main.rs b/crates/ra_ide_api/tests/test/main.rs
index 756075190..c2cb38f7e 100644
--- a/crates/ra_ide_api/tests/test/main.rs
+++ b/crates/ra_ide_api/tests/test/main.rs
@@ -1,9 +1,9 @@
1use insta::assert_debug_snapshot_matches;
1use ra_ide_api::{ 2use ra_ide_api::{
2 AnalysisChange, 3 mock_analysis::{single_file, single_file_with_position, MockAnalysis},
3 CrateGraph, FileId, mock_analysis::{MockAnalysis, single_file, single_file_with_position}, Query, 4 AnalysisChange, CrateGraph, FileId, Query,
4}; 5};
5use ra_syntax::TextRange; 6use ra_syntax::TextRange;
6use insta::assert_debug_snapshot_matches;
7 7
8#[test] 8#[test]
9fn test_unresolved_module_diagnostic() { 9fn test_unresolved_module_diagnostic() {
@@ -26,12 +26,12 @@ fn test_resolve_crate_root() {
26 " 26 "
27 //- /bar.rs 27 //- /bar.rs
28 mod foo; 28 mod foo;
29 //- /bar/foo.rs 29 //- /foo.rs
30 // emtpy <|> 30 // empty <|>
31 ", 31 ",
32 ); 32 );
33 let root_file = mock.id_of("/bar.rs"); 33 let root_file = mock.id_of("/bar.rs");
34 let mod_file = mock.id_of("/bar/foo.rs"); 34 let mod_file = mock.id_of("/foo.rs");
35 let mut host = mock.analysis_host(); 35 let mut host = mock.analysis_host();
36 assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); 36 assert!(host.analysis().crate_for(mod_file).unwrap().is_empty());
37 37
diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs
index 45747e21d..99b0983b0 100644
--- a/crates/ra_syntax/src/algo.rs
+++ b/crates/ra_syntax/src/algo.rs
@@ -17,14 +17,14 @@ pub fn find_leaf_at_offset(node: &SyntaxNode, offset: TextUnit) -> LeafAtOffset<
17} 17}
18 18
19/// Finds a node of specific Ast type at offset. Note that this is slightly 19/// Finds a node of specific Ast type at offset. Note that this is slightly
20/// impercise: if the cursor is strictly betwen two nodes of the desired type, 20/// imprecise: if the cursor is strictly between two nodes of the desired type,
21/// as in 21/// as in
22/// 22///
23/// ```no-run 23/// ```no-run
24/// struct Foo {}|struct Bar; 24/// struct Foo {}|struct Bar;
25/// ``` 25/// ```
26/// 26///
27/// then the left node will be silently prefered. 27/// then the left node will be silently preferred.
28pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextUnit) -> Option<&N> { 28pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextUnit) -> Option<&N> {
29 find_leaf_at_offset(syntax, offset).find_map(|leaf| leaf.ancestors().find_map(N::cast)) 29 find_leaf_at_offset(syntax, offset).find_map(|leaf| leaf.ancestors().find_map(N::cast))
30} 30}