@@ -15,7 +15,12 @@ use rustc_hash::FxHashSet;
1515use syntax:: { algo, ast, AstNode , TextRange , TextSize } ;
1616use test_utils:: extract_annotations;
1717
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+ } ;
1924
2025#[ salsa:: database(
2126 base_db:: SourceDatabaseExtStorage ,
@@ -87,10 +92,11 @@ impl TestDB {
8792 pub ( crate ) fn module_at_position ( & self , position : FilePosition ) -> ModuleId {
8893 let file_module = self . module_for_file ( position. file_id ) ;
8994 let mut def_map = file_module. def_map ( self ) ;
95+ let module = self . mod_at_position ( & def_map, position) ;
9096
9197 def_map = match self . block_at_position ( & def_map, position) {
9298 Some ( it) => it,
93- None => return file_module ,
99+ None => return def_map . module_id ( module ) ,
94100 } ;
95101 loop {
96102 let new_map = self . block_at_position ( & def_map, position) ;
@@ -106,6 +112,47 @@ impl TestDB {
106112 }
107113 }
108114
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+
109156 fn block_at_position ( & self , def_map : & DefMap , position : FilePosition ) -> Option < Arc < DefMap > > {
110157 // Find the smallest (innermost) function in `def_map` containing the cursor.
111158 let mut size = None ;
0 commit comments