@@ -100,19 +100,83 @@ impl std::ops::Index<LocalModuleId> for CrateDefMap {
100
100
}
101
101
}
102
102
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
+
103
172
#[ derive( Default , Debug , PartialEq , Eq ) ]
104
173
pub struct ModuleData {
105
174
pub parent : Option < LocalModuleId > ,
106
175
pub children : FxHashMap < Name , LocalModuleId > ,
107
176
pub scope : ModuleScope ,
108
177
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 ,
116
180
117
181
pub impls : Vec < ImplId > ,
118
182
}
@@ -262,7 +326,7 @@ impl CrateDefMap {
262
326
pub fn modules_for_file ( & self , file_id : FileId ) -> impl Iterator < Item = LocalModuleId > + ' _ {
263
327
self . modules
264
328
. iter ( )
265
- . filter ( move |( _id, data) | data. definition == Some ( file_id) )
329
+ . filter ( move |( _id, data) | data. origin . file_id ( ) == Some ( file_id) )
266
330
. map ( |( id, _data) | id)
267
331
}
268
332
@@ -285,18 +349,13 @@ impl ModuleData {
285
349
& self ,
286
350
db : & impl DefDatabase ,
287
351
) -> 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)
294
353
}
295
354
296
355
/// 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 .
298
357
pub fn declaration_source ( & self , db : & impl DefDatabase ) -> Option < InFile < ast:: Module > > {
299
- let decl = self . declaration ?;
358
+ let decl = self . origin . declaration ( ) ?;
300
359
let value = decl. to_node ( db) ;
301
360
Some ( InFile { file_id : decl. file_id , value } )
302
361
}
0 commit comments