@@ -100,19 +100,83 @@ impl std::ops::Index<LocalModuleId> for CrateDefMap {
100100 }
101101}
102102
103+ #[ derive( Debug , PartialEq , Eq , Clone , Copy , Hash ) ]
104+ pub enum ModuleOrigin {
105+ /// It should not be `None` after collecting definitions.
106+ Root ( Option < FileId > ) ,
107+ /// Note that non-inline modules, by definition, live inside non-macro file.
108+ File ( AstId < ast:: Module > , FileId ) ,
109+ Inline ( AstId < ast:: Module > ) ,
110+ Block ( AstId < ast:: Block > ) ,
111+ }
112+
113+ impl Default for ModuleOrigin {
114+ fn default ( ) -> Self {
115+ ModuleOrigin :: Root ( None )
116+ }
117+ }
118+
119+ impl ModuleOrigin {
120+ pub fn root ( file_id : FileId ) -> Self {
121+ ModuleOrigin :: Root ( Some ( file_id) )
122+ }
123+
124+ pub fn not_sure_file ( file : Option < FileId > , module : AstId < ast:: Module > ) -> Self {
125+ match file {
126+ None => ModuleOrigin :: Inline ( module) ,
127+ Some ( file) => ModuleOrigin :: File ( module, file) ,
128+ }
129+ }
130+
131+ pub fn not_sure_mod ( file : FileId , module : Option < AstId < ast:: Module > > ) -> Self {
132+ match module {
133+ None => ModuleOrigin :: root ( file) ,
134+ Some ( module) => ModuleOrigin :: File ( module, file) ,
135+ }
136+ }
137+
138+ pub fn declaration ( & self ) -> Option < AstId < ast:: Module > > {
139+ match self {
140+ ModuleOrigin :: File ( m, _) | ModuleOrigin :: Inline ( m) => Some ( * m) ,
141+ ModuleOrigin :: Root ( _) | ModuleOrigin :: Block ( _) => None ,
142+ }
143+ }
144+
145+ pub fn file_id ( & self ) -> Option < FileId > {
146+ match self {
147+ ModuleOrigin :: File ( _, file_id) | ModuleOrigin :: Root ( Some ( file_id) ) => Some ( * file_id) ,
148+ _ => None ,
149+ }
150+ }
151+
152+ /// Returns a node which defines this module.
153+ /// That is, a file or a `mod foo {}` with items.
154+ pub fn definition_source (
155+ & self ,
156+ db : & impl DefDatabase ,
157+ ) -> InFile < Either < ast:: SourceFile , ast:: Module > > {
158+ match self {
159+ ModuleOrigin :: File ( _, file_id) | ModuleOrigin :: Root ( Some ( file_id) ) => {
160+ let file_id = * file_id;
161+ let sf = db. parse ( file_id) . tree ( ) ;
162+ return InFile :: new ( file_id. into ( ) , Either :: Left ( sf) ) ;
163+ }
164+ ModuleOrigin :: Root ( None ) => unreachable ! ( ) ,
165+ ModuleOrigin :: Inline ( m) => InFile :: new ( m. file_id , Either :: Right ( m. to_node ( db) ) ) ,
166+ // FIXME: right now it's never constructed, so it's fine to omit
167+ ModuleOrigin :: Block ( b) => unimplemented ! ( ) ,
168+ }
169+ }
170+ }
171+
103172#[ derive( Default , Debug , PartialEq , Eq ) ]
104173pub struct ModuleData {
105174 pub parent : Option < LocalModuleId > ,
106175 pub children : FxHashMap < Name , LocalModuleId > ,
107176 pub scope : ModuleScope ,
108177
109- // FIXME: these can't be both null, we need a three-state enum here.
110- /// None for root
111- pub declaration : Option < AstId < ast:: Module > > ,
112- /// None for inline modules.
113- ///
114- /// Note that non-inline modules, by definition, live inside non-macro file.
115- pub definition : Option < FileId > ,
178+ /// Where does this module come from?
179+ pub origin : ModuleOrigin ,
116180
117181 pub impls : Vec < ImplId > ,
118182}
@@ -262,7 +326,7 @@ impl CrateDefMap {
262326 pub fn modules_for_file ( & self , file_id : FileId ) -> impl Iterator < Item = LocalModuleId > + ' _ {
263327 self . modules
264328 . iter ( )
265- . filter ( move |( _id, data) | data. definition == Some ( file_id) )
329+ . filter ( move |( _id, data) | data. origin . file_id ( ) == Some ( file_id) )
266330 . map ( |( id, _data) | id)
267331 }
268332
@@ -285,18 +349,13 @@ impl ModuleData {
285349 & self ,
286350 db : & impl DefDatabase ,
287351 ) -> InFile < Either < ast:: SourceFile , ast:: Module > > {
288- if let Some ( file_id) = self . definition {
289- let sf = db. parse ( file_id) . tree ( ) ;
290- return InFile :: new ( file_id. into ( ) , Either :: Left ( sf) ) ;
291- }
292- let decl = self . declaration . unwrap ( ) ;
293- InFile :: new ( decl. file_id , Either :: Right ( decl. to_node ( db) ) )
352+ self . origin . definition_source ( db)
294353 }
295354
296355 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
297- /// `None` for the crate root.
356+ /// `None` for the crate root or block .
298357 pub fn declaration_source ( & self , db : & impl DefDatabase ) -> Option < InFile < ast:: Module > > {
299- let decl = self . declaration ?;
358+ let decl = self . origin . declaration ( ) ?;
300359 let value = decl. to_node ( db) ;
301360 Some ( InFile { file_id : decl. file_id , value } )
302361 }
0 commit comments