@@ -15,7 +15,12 @@ use rustc_hash::FxHashSet;
15
15
use syntax:: { algo, ast, AstNode , TextRange , TextSize } ;
16
16
use test_utils:: extract_annotations;
17
17
18
- use crate :: { db:: DefDatabase , nameres:: DefMap , src:: HasSource , Lookup , ModuleDefId , ModuleId } ;
18
+ use crate :: {
19
+ db:: DefDatabase ,
20
+ nameres:: { DefMap , ModuleSource } ,
21
+ src:: HasSource ,
22
+ LocalModuleId , Lookup , ModuleDefId , ModuleId ,
23
+ } ;
19
24
20
25
#[ salsa:: database(
21
26
base_db:: SourceDatabaseExtStorage ,
@@ -87,10 +92,11 @@ impl TestDB {
87
92
pub ( crate ) fn module_at_position ( & self , position : FilePosition ) -> ModuleId {
88
93
let file_module = self . module_for_file ( position. file_id ) ;
89
94
let mut def_map = file_module. def_map ( self ) ;
95
+ let module = self . mod_at_position ( & def_map, position) ;
90
96
91
97
def_map = match self . block_at_position ( & def_map, position) {
92
98
Some ( it) => it,
93
- None => return file_module ,
99
+ None => return def_map . module_id ( module ) ,
94
100
} ;
95
101
loop {
96
102
let new_map = self . block_at_position ( & def_map, position) ;
@@ -106,6 +112,47 @@ impl TestDB {
106
112
}
107
113
}
108
114
115
+ /// Finds the smallest/innermost module in `def_map` containing `position`.
116
+ fn mod_at_position ( & self , def_map : & DefMap , position : FilePosition ) -> LocalModuleId {
117
+ let mut size = None ;
118
+ let mut res = def_map. root ( ) ;
119
+ for ( module, data) in def_map. modules ( ) {
120
+ let src = data. definition_source ( self ) ;
121
+ if src. file_id != position. file_id . into ( ) {
122
+ continue ;
123
+ }
124
+
125
+ let range = match src. value {
126
+ ModuleSource :: SourceFile ( it) => it. syntax ( ) . text_range ( ) ,
127
+ ModuleSource :: Module ( it) => it. syntax ( ) . text_range ( ) ,
128
+ ModuleSource :: BlockExpr ( it) => it. syntax ( ) . text_range ( ) ,
129
+ } ;
130
+
131
+ if !range. contains ( position. offset ) {
132
+ continue ;
133
+ }
134
+
135
+ let new_size = match size {
136
+ None => range. len ( ) ,
137
+ Some ( size) => {
138
+ if range. len ( ) < size {
139
+ range. len ( )
140
+ } else {
141
+ size
142
+ }
143
+ }
144
+ } ;
145
+
146
+ if size != Some ( new_size) {
147
+ cov_mark:: hit!( submodule_in_testdb) ;
148
+ size = Some ( new_size) ;
149
+ res = module;
150
+ }
151
+ }
152
+
153
+ res
154
+ }
155
+
109
156
fn block_at_position ( & self , def_map : & DefMap , position : FilePosition ) -> Option < Arc < DefMap > > {
110
157
// Find the smallest (innermost) function in `def_map` containing the cursor.
111
158
let mut size = None ;
0 commit comments