@@ -6,6 +6,7 @@ use ra_syntax::{
6
6
algo:: find_node_at_offset,
7
7
ast:: { self , AstNode } ,
8
8
} ;
9
+ use test_utils:: tested_by;
9
10
10
11
use crate :: NavigationTarget ;
11
12
@@ -14,7 +15,21 @@ use crate::NavigationTarget;
14
15
pub ( crate ) fn parent_module ( db : & RootDatabase , position : FilePosition ) -> Vec < NavigationTarget > {
15
16
let mut sb = hir:: SourceBinder :: new ( db) ;
16
17
let parse = db. parse ( position. file_id ) ;
17
- let module = match find_node_at_offset :: < ast:: Module > ( parse. tree ( ) . syntax ( ) , position. offset ) {
18
+
19
+ let mut module = find_node_at_offset :: < ast:: Module > ( parse. tree ( ) . syntax ( ) , position. offset ) ;
20
+
21
+ // If cursor is literally on `mod foo`, go to the grandpa.
22
+ if let Some ( m) = & module {
23
+ if !m
24
+ . item_list ( )
25
+ . map_or ( false , |it| it. syntax ( ) . text_range ( ) . contains_inclusive ( position. offset ) )
26
+ {
27
+ tested_by ! ( test_resolve_parent_module_on_module_decl) ;
28
+ module = m. syntax ( ) . ancestors ( ) . skip ( 1 ) . find_map ( ast:: Module :: cast) ;
29
+ }
30
+ }
31
+
32
+ let module = match module {
18
33
Some ( module) => sb. to_def ( hir:: InFile :: new ( position. file_id . into ( ) , module) ) ,
19
34
None => sb. to_module_def ( position. file_id ) ,
20
35
} ;
@@ -41,6 +56,7 @@ pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
41
56
mod tests {
42
57
use ra_cfg:: CfgOptions ;
43
58
use ra_db:: Env ;
59
+ use test_utils:: covers;
44
60
45
61
use crate :: {
46
62
mock_analysis:: { analysis_and_position, MockAnalysis } ,
@@ -62,6 +78,25 @@ mod tests {
62
78
nav. assert_match ( "foo MODULE FileId(1) [0; 8)" ) ;
63
79
}
64
80
81
+ #[ test]
82
+ fn test_resolve_parent_module_on_module_decl ( ) {
83
+ covers ! ( test_resolve_parent_module_on_module_decl) ;
84
+ let ( analysis, pos) = analysis_and_position (
85
+ "
86
+ //- /lib.rs
87
+ mod foo;
88
+
89
+ //- /foo.rs
90
+ mod <|>bar;
91
+
92
+ //- /foo/bar.rs
93
+ // empty
94
+ " ,
95
+ ) ;
96
+ let nav = analysis. parent_module ( pos) . unwrap ( ) . pop ( ) . unwrap ( ) ;
97
+ nav. assert_match ( "foo MODULE FileId(1) [0; 8)" ) ;
98
+ }
99
+
65
100
#[ test]
66
101
fn test_resolve_parent_module_for_inline ( ) {
67
102
let ( analysis, pos) = analysis_and_position (
0 commit comments