aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/nameres/collector.rs29
-rw-r--r--crates/ra_hir/src/nameres/tests.rs95
2 files changed, 119 insertions, 5 deletions
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 @@
1use arrayvec::ArrayVec; 1use arrayvec::ArrayVec;
2use ra_db::FileId; 2use ra_db::FileId;
3use ra_syntax::ast; 3use ra_syntax::{ast, SmolStr};
4use relative_path::RelativePathBuf; 4use relative_path::RelativePathBuf;
5use rustc_hash::FxHashMap; 5use rustc_hash::FxHashMap;
6use test_utils::tested_by; 6use test_utils::tested_by;
@@ -509,10 +509,16 @@ where
509 .collect(&*items); 509 .collect(&*items);
510 } 510 }
511 // out of line module, resolve, parse and recurse 511 // out of line module, resolve, parse and recurse
512 raw::ModuleData::Declaration { name, ast_id, .. } => { 512 raw::ModuleData::Declaration { name, ast_id, attr_path } => {
513 let ast_id = ast_id.with_file_id(self.file_id); 513 let ast_id = ast_id.with_file_id(self.file_id);
514 let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); 514 let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none();
515 match resolve_submodule(self.def_collector.db, self.file_id, name, is_root) { 515 match resolve_submodule(
516 self.def_collector.db,
517 self.file_id,
518 name,
519 is_root,
520 attr_path.as_ref(),
521 ) {
516 Ok(file_id) => { 522 Ok(file_id) => {
517 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); 523 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
518 let raw_items = self.def_collector.db.raw_items(file_id.into()); 524 let raw_items = self.def_collector.db.raw_items(file_id.into());
@@ -626,6 +632,7 @@ fn resolve_submodule(
626 file_id: HirFileId, 632 file_id: HirFileId,
627 name: &Name, 633 name: &Name,
628 is_root: bool, 634 is_root: bool,
635 attr_path: Option<&SmolStr>,
629) -> Result<FileId, RelativePathBuf> { 636) -> Result<FileId, RelativePathBuf> {
630 // FIXME: handle submodules of inline modules properly 637 // FIXME: handle submodules of inline modules properly
631 let file_id = file_id.original_file(db); 638 let file_id = file_id.original_file(db);
@@ -639,7 +646,13 @@ fn resolve_submodule(
639 let file_mod = dir_path.join(format!("{}.rs", name)); 646 let file_mod = dir_path.join(format!("{}.rs", name));
640 let dir_mod = dir_path.join(format!("{}/mod.rs", name)); 647 let dir_mod = dir_path.join(format!("{}/mod.rs", name));
641 let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name)); 648 let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name));
642 let mut candidates = ArrayVec::<[_; 2]>::new(); 649 let mut candidates = ArrayVec::<[_; 3]>::new();
650 let file_attr_mod = attr_path.map(|file_path| {
651 let file_attr_mod = dir_path.join(file_path.to_string());
652 candidates.push(file_attr_mod.clone());
653
654 file_attr_mod
655 });
643 if is_dir_owner { 656 if is_dir_owner {
644 candidates.push(file_mod.clone()); 657 candidates.push(file_mod.clone());
645 candidates.push(dir_mod); 658 candidates.push(dir_mod);
@@ -651,7 +664,13 @@ fn resolve_submodule(
651 // FIXME: handle ambiguity 664 // FIXME: handle ambiguity
652 match points_to.next() { 665 match points_to.next() {
653 Some(file_id) => Ok(file_id), 666 Some(file_id) => Ok(file_id),
654 None => Err(if is_dir_owner { file_mod } else { file_dir_mod }), 667 None => {
668 if let Some(file_attr_mod) = file_attr_mod {
669 Err(file_attr_mod)
670 } else {
671 Err(if is_dir_owner { file_mod } else { file_dir_mod })
672 }
673 }
655 } 674 }
656} 675}
657 676
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
@@ -365,6 +365,101 @@ fn module_resolution_works_for_raw_modules() {
365} 365}
366 366
367#[test] 367#[test]
368fn module_resolution_decl_path() {
369 let map = def_map_with_crate_graph(
370 "
371 //- /library.rs
372 #[path = \"bar/baz/foo.rs\"]
373 mod foo;
374 use self::foo::Bar;
375
376 //- /bar/baz/foo.rs
377 pub struct Bar;
378 ",
379 crate_graph! {
380 "library": ("/library.rs", []),
381 },
382 );
383
384 assert_snapshot_matches!(map, @r###"
385 ⋮crate
386 ⋮Bar: t v
387 ⋮foo: t
388
389 ⋮crate::foo
390 ⋮Bar: t v
391 "###);
392}
393
394#[test]
395fn module_resolution_module_with_path_in_mod_rs() {
396 let map = def_map_with_crate_graph(
397 "
398 //- /main.rs
399 mod foo;
400
401 //- /foo/mod.rs
402 #[path = \"baz.rs\"]
403 pub mod bar;
404
405 use self::bar::Baz;
406
407 //- /foo/baz.rs
408 pub struct Baz;
409 ",
410 crate_graph! {
411 "main": ("/main.rs", []),
412 },
413 );
414
415 assert_snapshot_matches!(map, @r###"
416 ⋮crate
417 ⋮foo: t
418
419 ⋮crate::foo
420 ⋮Baz: t v
421 ⋮bar: t
422
423 ⋮crate::foo::bar
424 ⋮Baz: t v
425 "###);
426}
427
428#[test]
429fn module_resolution_module_with_path_non_crate_root() {
430 let map = def_map_with_crate_graph(
431 "
432 //- /main.rs
433 mod foo;
434
435 //- /foo.rs
436 #[path = \"baz.rs\"]
437 pub mod bar;
438
439 use self::bar::Baz;
440
441 //- /baz.rs
442 pub struct Baz;
443 ",
444 crate_graph! {
445 "main": ("/main.rs", []),
446 },
447 );
448
449 assert_snapshot_matches!(map, @r###"
450 ⋮crate
451 ⋮foo: t
452
453 ⋮crate::foo
454 ⋮Baz: t v
455 ⋮bar: t
456
457 ⋮crate::foo::bar
458 ⋮Baz: t v
459 "###);
460}
461
462#[test]
368fn name_res_works_for_broken_modules() { 463fn name_res_works_for_broken_modules() {
369 covers!(name_res_works_for_broken_modules); 464 covers!(name_res_works_for_broken_modules);
370 let map = def_map( 465 let map = def_map(