@@ -3,6 +3,7 @@ use std::collections::BTreeMap;
3
3
use std:: path:: { Path , PathBuf } ;
4
4
5
5
use rustc_ast:: ast;
6
+ use rustc_ast:: attr:: HasAttrs ;
6
7
use rustc_ast:: visit:: Visitor ;
7
8
use rustc_span:: symbol:: { self , sym, Symbol } ;
8
9
use thiserror:: Error ;
@@ -18,12 +19,48 @@ use crate::formatting::{
18
19
19
20
mod visitor;
20
21
21
- type FileModMap < ' ast > = BTreeMap < FileName , Cow < ' ast , ast :: Mod > > ;
22
+ type FileModMap < ' ast > = BTreeMap < FileName , Module < ' ast > > ;
22
23
23
24
lazy_static ! {
24
25
static ref CFG_IF : Symbol = Symbol :: intern( "cfg_if" ) ;
25
26
}
26
27
28
+ /// Represents module with its inner attributes.
29
+ #[ derive( Debug , Clone ) ]
30
+ pub ( crate ) struct Module < ' a > {
31
+ ast_mod : Cow < ' a , ast:: Mod > ,
32
+ inner_attr : Vec < ast:: Attribute > ,
33
+ }
34
+
35
+ impl < ' a > Module < ' a > {
36
+ pub ( crate ) fn new ( ast_mod : Cow < ' a , ast:: Mod > , attrs : & [ ast:: Attribute ] ) -> Self {
37
+ let inner_attr = attrs
38
+ . iter ( )
39
+ . filter ( |attr| attr. style == ast:: AttrStyle :: Inner )
40
+ . cloned ( )
41
+ . collect ( ) ;
42
+ Module {
43
+ ast_mod,
44
+ inner_attr,
45
+ }
46
+ }
47
+ }
48
+
49
+ impl < ' a > HasAttrs for Module < ' a > {
50
+ fn attrs ( & self ) -> & [ ast:: Attribute ] {
51
+ & self . inner_attr
52
+ }
53
+ fn visit_attrs ( & mut self , f : impl FnOnce ( & mut Vec < ast:: Attribute > ) ) {
54
+ f ( & mut self . inner_attr )
55
+ }
56
+ }
57
+
58
+ impl < ' a > AsRef < ast:: Mod > for Module < ' a > {
59
+ fn as_ref ( & self ) -> & ast:: Mod {
60
+ & self . ast_mod
61
+ }
62
+ }
63
+
27
64
/// Maps each module to the corresponding file.
28
65
pub ( crate ) struct ModResolver < ' ast , ' sess > {
29
66
parse_sess : & ' sess ParseSess ,
@@ -53,9 +90,9 @@ pub(crate) enum ModuleResolutionErrorKind {
53
90
#[ derive( Clone ) ]
54
91
enum SubModKind < ' a , ' ast > {
55
92
/// `mod foo;`
56
- External ( PathBuf , DirectoryOwnership , Cow < ' ast , ast :: Mod > ) ,
93
+ External ( PathBuf , DirectoryOwnership , Module < ' ast > ) ,
57
94
/// `mod foo;` with multiple sources.
58
- MultiExternal ( Vec < ( PathBuf , DirectoryOwnership , Cow < ' ast , ast :: Mod > ) > ) ,
95
+ MultiExternal ( Vec < ( PathBuf , DirectoryOwnership , Module < ' ast > ) > ) ,
59
96
/// `mod foo {}`
60
97
Internal ( & ' a ast:: Item ) ,
61
98
}
@@ -94,8 +131,10 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
94
131
self . visit_mod_from_ast ( & krate. module ) ?;
95
132
}
96
133
97
- self . file_map
98
- . insert ( root_filename, Cow :: Borrowed ( & krate. module ) ) ;
134
+ self . file_map . insert (
135
+ root_filename,
136
+ Module :: new ( Cow :: Borrowed ( & krate. module ) , & krate. attrs ) ,
137
+ ) ;
99
138
Ok ( self . file_map )
100
139
}
101
140
@@ -105,7 +144,10 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
105
144
visitor. visit_item ( & item) ;
106
145
for module_item in visitor. mods ( ) {
107
146
if let ast:: ItemKind :: Mod ( ref sub_mod) = module_item. item . kind {
108
- self . visit_sub_mod ( & module_item. item , Cow :: Owned ( sub_mod. clone ( ) ) ) ?;
147
+ self . visit_sub_mod (
148
+ & module_item. item ,
149
+ Module :: new ( Cow :: Owned ( sub_mod. clone ( ) ) , & module_item. item . attrs ) ,
150
+ ) ?;
109
151
}
110
152
}
111
153
Ok ( ( ) )
@@ -120,7 +162,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
120
162
}
121
163
122
164
if let ast:: ItemKind :: Mod ( ref sub_mod) = item. kind {
123
- self . visit_sub_mod ( & item, Cow :: Owned ( sub_mod. clone ( ) ) ) ?;
165
+ self . visit_sub_mod ( & item, Module :: new ( Cow :: Owned ( sub_mod. clone ( ) ) , & item . attrs ) ) ?;
124
166
}
125
167
}
126
168
Ok ( ( ) )
@@ -134,7 +176,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
134
176
}
135
177
136
178
if let ast:: ItemKind :: Mod ( ref sub_mod) = item. kind {
137
- self . visit_sub_mod ( item, Cow :: Borrowed ( sub_mod) ) ?;
179
+ self . visit_sub_mod ( item, Module :: new ( Cow :: Borrowed ( sub_mod) , & item . attrs ) ) ?;
138
180
}
139
181
}
140
182
Ok ( ( ) )
@@ -143,12 +185,12 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
143
185
fn visit_sub_mod (
144
186
& mut self ,
145
187
item : & ' c ast:: Item ,
146
- sub_mod : Cow < ' ast , ast :: Mod > ,
188
+ sub_mod : Module < ' ast > ,
147
189
) -> Result < ( ) , ModuleResolutionError > {
148
190
let old_directory = self . directory . clone ( ) ;
149
191
let sub_mod_kind = self . peek_sub_mod ( item, & sub_mod) ?;
150
192
if let Some ( sub_mod_kind) = sub_mod_kind {
151
- self . insert_sub_mod ( sub_mod_kind. clone ( ) , sub_mod . clone ( ) ) ?;
193
+ self . insert_sub_mod ( sub_mod_kind. clone ( ) ) ?;
152
194
self . visit_sub_mod_inner ( sub_mod, sub_mod_kind) ?;
153
195
}
154
196
self . directory = old_directory;
@@ -159,7 +201,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
159
201
fn peek_sub_mod (
160
202
& self ,
161
203
item : & ' c ast:: Item ,
162
- sub_mod : & Cow < ' ast , ast :: Mod > ,
204
+ sub_mod : & Module < ' ast > ,
163
205
) -> Result < Option < SubModKind < ' c , ' ast > > , ModuleResolutionError > {
164
206
if contains_skip ( & item. attrs ) {
165
207
return Ok ( None ) ;
@@ -178,7 +220,6 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
178
220
fn insert_sub_mod (
179
221
& mut self ,
180
222
sub_mod_kind : SubModKind < ' c , ' ast > ,
181
- _sub_mod : Cow < ' ast , ast:: Mod > ,
182
223
) -> Result < ( ) , ModuleResolutionError > {
183
224
match sub_mod_kind {
184
225
SubModKind :: External ( mod_path, _, sub_mod) => {
@@ -200,7 +241,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
200
241
201
242
fn visit_sub_mod_inner (
202
243
& mut self ,
203
- sub_mod : Cow < ' ast , ast :: Mod > ,
244
+ sub_mod : Module < ' ast > ,
204
245
sub_mod_kind : SubModKind < ' c , ' ast > ,
205
246
) -> Result < ( ) , ModuleResolutionError > {
206
247
match sub_mod_kind {
@@ -230,13 +271,13 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
230
271
231
272
fn visit_sub_mod_after_directory_update (
232
273
& mut self ,
233
- sub_mod : Cow < ' ast , ast :: Mod > ,
274
+ sub_mod : Module < ' ast > ,
234
275
directory : Option < Directory > ,
235
276
) -> Result < ( ) , ModuleResolutionError > {
236
277
if let Some ( directory) = directory {
237
278
self . directory = directory;
238
279
}
239
- match sub_mod {
280
+ match sub_mod. ast_mod {
240
281
Cow :: Borrowed ( sub_mod) => self . visit_mod_from_ast ( sub_mod) ,
241
282
Cow :: Owned ( sub_mod) => self . visit_mod_outside_ast ( sub_mod) ,
242
283
}
@@ -247,7 +288,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
247
288
& self ,
248
289
mod_name : symbol:: Ident ,
249
290
attrs : & [ ast:: Attribute ] ,
250
- sub_mod : & Cow < ' ast , ast :: Mod > ,
291
+ sub_mod : & Module < ' ast > ,
251
292
) -> Result < Option < SubModKind < ' c , ' ast > > , ModuleResolutionError > {
252
293
let relative = match self . directory . ownership {
253
294
DirectoryOwnership :: Owned { relative } => relative,
@@ -257,11 +298,12 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
257
298
if self . parse_sess . is_file_parsed ( & path) {
258
299
return Ok ( None ) ;
259
300
}
260
- return match Parser :: parse_file_as_module ( self . parse_sess , & path, sub_mod. inner ) {
301
+ return match Parser :: parse_file_as_module ( self . parse_sess , & path, sub_mod. ast_mod . inner )
302
+ {
261
303
Ok ( m) => Ok ( Some ( SubModKind :: External (
262
304
path,
263
305
DirectoryOwnership :: Owned { relative : None } ,
264
- Cow :: Owned ( m) ,
306
+ Module :: new ( Cow :: Owned ( m. 0 ) , & m . 1 ) ,
265
307
) ) ) ,
266
308
Err ( ParserError :: ParseError ) => Err ( ModuleResolutionError {
267
309
module : mod_name. to_string ( ) ,
@@ -299,12 +341,18 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
299
341
return Ok ( Some ( SubModKind :: MultiExternal ( mods_outside_ast) ) ) ;
300
342
}
301
343
}
302
- match Parser :: parse_file_as_module ( self . parse_sess , & path, sub_mod. inner ) {
303
- Ok ( m) if outside_mods_empty => {
304
- Ok ( Some ( SubModKind :: External ( path, ownership, Cow :: Owned ( m) ) ) )
305
- }
344
+ match Parser :: parse_file_as_module ( self . parse_sess , & path, sub_mod. ast_mod . inner ) {
345
+ Ok ( m) if outside_mods_empty => Ok ( Some ( SubModKind :: External (
346
+ path,
347
+ ownership,
348
+ Module :: new ( Cow :: Owned ( m. 0 ) , & m. 1 ) ,
349
+ ) ) ) ,
306
350
Ok ( m) => {
307
- mods_outside_ast. push ( ( path. clone ( ) , ownership, Cow :: Owned ( m) ) ) ;
351
+ mods_outside_ast. push ( (
352
+ path. clone ( ) ,
353
+ ownership,
354
+ Module :: new ( Cow :: Owned ( m. 0 ) , & m. 1 ) ,
355
+ ) ) ;
308
356
if should_insert {
309
357
mods_outside_ast. push ( ( path, ownership, sub_mod. clone ( ) ) ) ;
310
358
}
@@ -366,8 +414,8 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
366
414
fn find_mods_outside_of_ast (
367
415
& self ,
368
416
attrs : & [ ast:: Attribute ] ,
369
- sub_mod : & Cow < ' ast , ast :: Mod > ,
370
- ) -> Vec < ( PathBuf , DirectoryOwnership , Cow < ' ast , ast :: Mod > ) > {
417
+ sub_mod : & Module < ' ast > ,
418
+ ) -> Vec < ( PathBuf , DirectoryOwnership , Module < ' ast > ) > {
371
419
// Filter nested path, like `#[cfg_attr(feature = "foo", path = "bar.rs")]`.
372
420
let mut path_visitor = visitor:: PathVisitor :: default ( ) ;
373
421
for attr in attrs. iter ( ) {
@@ -394,16 +442,19 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
394
442
continue ;
395
443
}
396
444
397
- let m = match Parser :: parse_file_as_module ( self . parse_sess , & actual_path, sub_mod. inner )
398
- {
445
+ let m = match Parser :: parse_file_as_module (
446
+ self . parse_sess ,
447
+ & actual_path,
448
+ sub_mod. ast_mod . inner ,
449
+ ) {
399
450
Ok ( m) => m,
400
451
Err ( ..) => continue ,
401
452
} ;
402
453
403
454
result. push ( (
404
455
actual_path,
405
456
DirectoryOwnership :: Owned { relative : None } ,
406
- Cow :: Owned ( m) ,
457
+ Module :: new ( Cow :: Owned ( m. 0 ) , & m . 1 ) ,
407
458
) )
408
459
}
409
460
result
0 commit comments