10
10
11
11
use attr:: HasAttrs ;
12
12
use feature_gate:: { emit_feature_err, EXPLAIN_STMT_ATTR_SYNTAX , Features , get_features, GateIssue } ;
13
- use fold:: Folder ;
14
13
use { fold, attr} ;
15
14
use ast;
16
15
use codemap:: { Spanned , respan} ;
17
- use parse:: { ParseSess , token } ;
16
+ use parse:: ParseSess ;
18
17
use ptr:: P ;
19
18
20
19
use util:: small_vector:: SmallVector ;
@@ -27,8 +26,51 @@ pub struct StripUnconfigured<'a> {
27
26
pub features : Option < & ' a Features > ,
28
27
}
29
28
29
+ // `cfg_attr`-process the crate's attributes and compute the crate's features.
30
+ pub fn features ( mut krate : ast:: Crate , sess : & ParseSess , should_test : bool )
31
+ -> ( ast:: Crate , Features ) {
32
+ let features;
33
+ {
34
+ let mut strip_unconfigured = StripUnconfigured {
35
+ config : & krate. config . clone ( ) ,
36
+ should_test : should_test,
37
+ sess : sess,
38
+ features : None ,
39
+ } ;
40
+
41
+ let unconfigured_attrs = krate. attrs . clone ( ) ;
42
+ let err_count = sess. span_diagnostic . err_count ( ) ;
43
+ if let Some ( attrs) = strip_unconfigured. configure ( krate. attrs ) {
44
+ krate. attrs = attrs;
45
+ } else { // the entire crate is unconfigured
46
+ krate. attrs = Vec :: new ( ) ;
47
+ krate. module . items = Vec :: new ( ) ;
48
+ return ( krate, Features :: new ( ) ) ;
49
+ }
50
+
51
+ features = get_features ( & sess. span_diagnostic , & krate. attrs ) ;
52
+
53
+ // Avoid reconfiguring malformed `cfg_attr`s
54
+ if err_count == sess. span_diagnostic . err_count ( ) {
55
+ strip_unconfigured. features = Some ( & features) ;
56
+ strip_unconfigured. configure ( unconfigured_attrs) ;
57
+ }
58
+ }
59
+
60
+ ( krate, features)
61
+ }
62
+
63
+ macro_rules! configure {
64
+ ( $this: ident, $node: ident) => {
65
+ match $this. configure( $node) {
66
+ Some ( node) => node,
67
+ None => return Default :: default ( ) ,
68
+ }
69
+ }
70
+ }
71
+
30
72
impl < ' a > StripUnconfigured < ' a > {
31
- fn configure < T : HasAttrs > ( & mut self , node : T ) -> Option < T > {
73
+ pub fn configure < T : HasAttrs > ( & mut self , node : T ) -> Option < T > {
32
74
let node = self . process_cfg_attrs ( node) ;
33
75
if self . in_cfg ( node. attrs ( ) ) { Some ( node) } else { None }
34
76
}
@@ -123,65 +165,35 @@ impl<'a> StripUnconfigured<'a> {
123
165
}
124
166
}
125
167
}
126
- }
127
-
128
- // Support conditional compilation by transforming the AST, stripping out
129
- // any items that do not belong in the current configuration
130
- pub fn strip_unconfigured_items ( mut krate : ast:: Crate , sess : & ParseSess , should_test : bool )
131
- -> ( ast:: Crate , Features ) {
132
- let features;
133
- {
134
- let mut strip_unconfigured = StripUnconfigured {
135
- config : & krate. config . clone ( ) ,
136
- should_test : should_test,
137
- sess : sess,
138
- features : None ,
139
- } ;
140
-
141
- let err_count = sess. span_diagnostic . err_count ( ) ;
142
- let krate_attrs = strip_unconfigured. configure ( krate. attrs . clone ( ) ) . unwrap_or_default ( ) ;
143
- features = get_features ( & sess. span_diagnostic , & krate_attrs) ;
144
- if err_count < sess. span_diagnostic . err_count ( ) {
145
- krate. attrs = krate_attrs. clone ( ) ; // Avoid reconfiguring malformed `cfg_attr`s
146
- }
147
-
148
- strip_unconfigured. features = Some ( & features) ;
149
- krate = strip_unconfigured. fold_crate ( krate) ;
150
- krate. attrs = krate_attrs;
151
- }
152
168
153
- ( krate, features)
154
- }
155
-
156
- impl < ' a > fold:: Folder for StripUnconfigured < ' a > {
157
- fn fold_foreign_mod ( & mut self , foreign_mod : ast:: ForeignMod ) -> ast:: ForeignMod {
169
+ pub fn configure_foreign_mod ( & mut self , foreign_mod : ast:: ForeignMod ) -> ast:: ForeignMod {
158
170
ast:: ForeignMod {
159
171
abi : foreign_mod. abi ,
160
- items : foreign_mod. items . into_iter ( ) . filter_map ( |item| {
161
- self . configure ( item) . map ( |item| fold:: noop_fold_foreign_item ( item, self ) )
162
- } ) . collect ( ) ,
172
+ items : foreign_mod. items . into_iter ( ) . filter_map ( |item| self . configure ( item) ) . collect ( ) ,
163
173
}
164
174
}
165
175
166
- fn fold_item_kind ( & mut self , item : ast:: ItemKind ) -> ast:: ItemKind {
167
- let fold_struct = | this : & mut Self , vdata| match vdata {
176
+ fn configure_variant_data ( & mut self , vdata : ast:: VariantData ) -> ast:: VariantData {
177
+ match vdata {
168
178
ast:: VariantData :: Struct ( fields, id) => {
169
- let fields = fields. into_iter ( ) . filter_map ( |field| this . configure ( field) ) ;
179
+ let fields = fields. into_iter ( ) . filter_map ( |field| self . configure ( field) ) ;
170
180
ast:: VariantData :: Struct ( fields. collect ( ) , id)
171
181
}
172
182
ast:: VariantData :: Tuple ( fields, id) => {
173
- let fields = fields. into_iter ( ) . filter_map ( |field| this . configure ( field) ) ;
183
+ let fields = fields. into_iter ( ) . filter_map ( |field| self . configure ( field) ) ;
174
184
ast:: VariantData :: Tuple ( fields. collect ( ) , id)
175
185
}
176
186
ast:: VariantData :: Unit ( id) => ast:: VariantData :: Unit ( id)
177
- } ;
187
+ }
188
+ }
178
189
179
- let item = match item {
190
+ pub fn configure_item_kind ( & mut self , item : ast:: ItemKind ) -> ast:: ItemKind {
191
+ match item {
180
192
ast:: ItemKind :: Struct ( def, generics) => {
181
- ast:: ItemKind :: Struct ( fold_struct ( self , def) , generics)
193
+ ast:: ItemKind :: Struct ( self . configure_variant_data ( def) , generics)
182
194
}
183
195
ast:: ItemKind :: Union ( def, generics) => {
184
- ast:: ItemKind :: Union ( fold_struct ( self , def) , generics)
196
+ ast:: ItemKind :: Union ( self . configure_variant_data ( def) , generics)
185
197
}
186
198
ast:: ItemKind :: Enum ( def, generics) => {
187
199
let variants = def. variants . into_iter ( ) . filter_map ( |v| {
@@ -190,7 +202,7 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
190
202
node : ast:: Variant_ {
191
203
name : v. node . name ,
192
204
attrs : v. node . attrs ,
193
- data : fold_struct ( self , v. node . data ) ,
205
+ data : self . configure_variant_data ( v. node . data ) ,
194
206
disr_expr : v. node . disr_expr ,
195
207
} ,
196
208
span : v. span
@@ -202,12 +214,19 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
202
214
} , generics)
203
215
}
204
216
item => item,
205
- } ;
217
+ }
218
+ }
206
219
207
- fold:: noop_fold_item_kind ( item, self )
220
+ pub fn configure_expr_kind ( & mut self , expr_kind : ast:: ExprKind ) -> ast:: ExprKind {
221
+ if let ast:: ExprKind :: Match ( m, arms) = expr_kind {
222
+ let arms = arms. into_iter ( ) . filter_map ( |a| self . configure ( a) ) . collect ( ) ;
223
+ ast:: ExprKind :: Match ( m, arms)
224
+ } else {
225
+ expr_kind
226
+ }
208
227
}
209
228
210
- fn fold_expr ( & mut self , expr : P < ast:: Expr > ) -> P < ast:: Expr > {
229
+ pub fn configure_expr ( & mut self , expr : P < ast:: Expr > ) -> P < ast:: Expr > {
211
230
self . visit_stmt_or_expr_attrs ( expr. attrs ( ) ) ;
212
231
213
232
// If an expr is valid to cfg away it will have been removed by the
@@ -222,64 +241,64 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
222
241
self . sess . span_diagnostic . span_err ( attr. span , msg) ;
223
242
}
224
243
225
- let expr = self . process_cfg_attrs ( expr) ;
226
- fold_expr ( self , expr)
244
+ self . process_cfg_attrs ( expr)
227
245
}
228
246
229
- fn fold_opt_expr ( & mut self , expr : P < ast:: Expr > ) -> Option < P < ast:: Expr > > {
230
- self . configure ( expr) . map ( |expr| fold_expr ( self , expr) )
247
+ pub fn configure_stmt ( & mut self , stmt : ast:: Stmt ) -> Option < ast:: Stmt > {
248
+ self . visit_stmt_or_expr_attrs ( stmt. attrs ( ) ) ;
249
+ self . configure ( stmt)
231
250
}
251
+ }
232
252
233
- fn fold_stmt ( & mut self , stmt : ast :: Stmt ) -> SmallVector < ast :: Stmt > {
234
- self . visit_stmt_or_expr_attrs ( stmt . attrs ( ) ) ;
235
- self . configure ( stmt ) . map ( |stmt| fold :: noop_fold_stmt ( stmt , self ) )
236
- . unwrap_or ( SmallVector :: zero ( ) )
253
+ impl < ' a > fold :: Folder for StripUnconfigured < ' a > {
254
+ fn fold_foreign_mod ( & mut self , foreign_mod : ast :: ForeignMod ) -> ast :: ForeignMod {
255
+ let foreign_mod = self . configure_foreign_mod ( foreign_mod ) ;
256
+ fold :: noop_fold_foreign_mod ( foreign_mod , self )
237
257
}
238
258
239
- fn fold_mac ( & mut self , mac : ast:: Mac ) -> ast:: Mac {
240
- fold:: noop_fold_mac ( mac, self )
259
+ fn fold_item_kind ( & mut self , item : ast:: ItemKind ) -> ast:: ItemKind {
260
+ let item = self . configure_item_kind ( item) ;
261
+ fold:: noop_fold_item_kind ( item, self )
262
+ }
263
+
264
+ fn fold_expr ( & mut self , expr : P < ast:: Expr > ) -> P < ast:: Expr > {
265
+ let mut expr = self . configure_expr ( expr) . unwrap ( ) ;
266
+ expr. node = self . configure_expr_kind ( expr. node ) ;
267
+ P ( fold:: noop_fold_expr ( expr, self ) )
268
+ }
269
+
270
+ fn fold_opt_expr ( & mut self , expr : P < ast:: Expr > ) -> Option < P < ast:: Expr > > {
271
+ let mut expr = configure ! ( self , expr) . unwrap ( ) ;
272
+ expr. node = self . configure_expr_kind ( expr. node ) ;
273
+ Some ( P ( fold:: noop_fold_expr ( expr, self ) ) )
274
+ }
275
+
276
+ fn fold_stmt ( & mut self , stmt : ast:: Stmt ) -> SmallVector < ast:: Stmt > {
277
+ match self . configure_stmt ( stmt) {
278
+ Some ( stmt) => fold:: noop_fold_stmt ( stmt, self ) ,
279
+ None => return SmallVector :: zero ( ) ,
280
+ }
241
281
}
242
282
243
283
fn fold_item ( & mut self , item : P < ast:: Item > ) -> SmallVector < P < ast:: Item > > {
244
- self . configure ( item) . map ( |item| fold:: noop_fold_item ( item, self ) )
245
- . unwrap_or ( SmallVector :: zero ( ) )
284
+ fold:: noop_fold_item ( configure ! ( self , item) , self )
246
285
}
247
286
248
287
fn fold_impl_item ( & mut self , item : ast:: ImplItem ) -> SmallVector < ast:: ImplItem > {
249
- self . configure ( item) . map ( |item| fold:: noop_fold_impl_item ( item, self ) )
250
- . unwrap_or ( SmallVector :: zero ( ) )
288
+ fold:: noop_fold_impl_item ( configure ! ( self , item) , self )
251
289
}
252
290
253
291
fn fold_trait_item ( & mut self , item : ast:: TraitItem ) -> SmallVector < ast:: TraitItem > {
254
- self . configure ( item) . map ( |item| fold:: noop_fold_trait_item ( item, self ) )
255
- . unwrap_or ( SmallVector :: zero ( ) )
292
+ fold:: noop_fold_trait_item ( configure ! ( self , item) , self )
256
293
}
257
294
258
- fn fold_interpolated ( & mut self , nt : token :: Nonterminal ) -> token :: Nonterminal {
295
+ fn fold_mac ( & mut self , mac : ast :: Mac ) -> ast :: Mac {
259
296
// Don't configure interpolated AST (c.f. #34171).
260
297
// Interpolated AST will get configured once the surrounding tokens are parsed.
261
- nt
298
+ mac
262
299
}
263
300
}
264
301
265
- fn fold_expr ( folder : & mut StripUnconfigured , expr : P < ast:: Expr > ) -> P < ast:: Expr > {
266
- expr. map ( |ast:: Expr { id, span, node, attrs} | {
267
- fold:: noop_fold_expr ( ast:: Expr {
268
- id : id,
269
- node : match node {
270
- ast:: ExprKind :: Match ( m, arms) => {
271
- ast:: ExprKind :: Match ( m, arms. into_iter ( )
272
- . filter_map ( |a| folder. configure ( a) )
273
- . collect ( ) )
274
- }
275
- _ => node
276
- } ,
277
- span : span,
278
- attrs : attrs,
279
- } , folder)
280
- } )
281
- }
282
-
283
302
fn is_cfg ( attr : & ast:: Attribute ) -> bool {
284
303
attr. check_name ( "cfg" )
285
304
}
0 commit comments