8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use attr:: HasAttrs ;
11
+ use attr:: { self , HasAttrs } ;
12
12
use feature_gate:: { emit_feature_err, EXPLAIN_STMT_ATTR_SYNTAX , Features , get_features, GateIssue } ;
13
- use fold:: Folder ;
14
- use { fold, attr} ;
15
13
use ast;
16
14
use codemap:: { Spanned , respan} ;
17
- use parse:: { ParseSess , token } ;
15
+ use parse:: ParseSess ;
18
16
use ptr:: P ;
19
17
20
- use util:: small_vector:: SmallVector ;
21
-
22
18
/// A folder that strips out items that do not belong in the current configuration.
23
19
pub struct StripUnconfigured < ' a > {
24
20
pub config : & ' a ast:: CrateConfig ,
@@ -27,8 +23,42 @@ pub struct StripUnconfigured<'a> {
27
23
pub features : Option < & ' a Features > ,
28
24
}
29
25
26
+ // `cfg_attr`-process the crate's attributes and compute the crate's features.
27
+ pub fn features ( mut krate : ast:: Crate , sess : & ParseSess , should_test : bool )
28
+ -> ( ast:: Crate , Features ) {
29
+ let features;
30
+ {
31
+ let mut strip_unconfigured = StripUnconfigured {
32
+ config : & krate. config . clone ( ) ,
33
+ should_test : should_test,
34
+ sess : sess,
35
+ features : None ,
36
+ } ;
37
+
38
+ let unconfigured_attrs = krate. attrs . clone ( ) ;
39
+ let err_count = sess. span_diagnostic . err_count ( ) ;
40
+ if let Some ( attrs) = strip_unconfigured. configure ( krate. attrs ) {
41
+ krate. attrs = attrs;
42
+ } else { // the entire crate is unconfigured
43
+ krate. attrs = Vec :: new ( ) ;
44
+ krate. module . items = Vec :: new ( ) ;
45
+ return ( krate, Features :: new ( ) ) ;
46
+ }
47
+
48
+ features = get_features ( & sess. span_diagnostic , & krate. attrs ) ;
49
+
50
+ // Avoid reconfiguring malformed `cfg_attr`s
51
+ if err_count == sess. span_diagnostic . err_count ( ) {
52
+ strip_unconfigured. features = Some ( & features) ;
53
+ strip_unconfigured. configure ( unconfigured_attrs) ;
54
+ }
55
+ }
56
+
57
+ ( krate, features)
58
+ }
59
+
30
60
impl < ' a > StripUnconfigured < ' a > {
31
- fn configure < T : HasAttrs > ( & mut self , node : T ) -> Option < T > {
61
+ pub fn configure < T : HasAttrs > ( & mut self , node : T ) -> Option < T > {
32
62
let node = self . process_cfg_attrs ( node) ;
33
63
if self . in_cfg ( node. attrs ( ) ) { Some ( node) } else { None }
34
64
}
@@ -123,65 +153,35 @@ impl<'a> StripUnconfigured<'a> {
123
153
}
124
154
}
125
155
}
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
156
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
-
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 {
157
+ pub fn configure_foreign_mod ( & mut self , foreign_mod : ast:: ForeignMod ) -> ast:: ForeignMod {
158
158
ast:: ForeignMod {
159
159
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 ( ) ,
160
+ items : foreign_mod. items . into_iter ( ) . filter_map ( |item| self . configure ( item) ) . collect ( ) ,
163
161
}
164
162
}
165
163
166
- fn fold_item_kind ( & mut self , item : ast:: ItemKind ) -> ast:: ItemKind {
167
- let fold_struct = | this : & mut Self , vdata| match vdata {
164
+ fn configure_variant_data ( & mut self , vdata : ast:: VariantData ) -> ast:: VariantData {
165
+ match vdata {
168
166
ast:: VariantData :: Struct ( fields, id) => {
169
- let fields = fields. into_iter ( ) . filter_map ( |field| this . configure ( field) ) ;
167
+ let fields = fields. into_iter ( ) . filter_map ( |field| self . configure ( field) ) ;
170
168
ast:: VariantData :: Struct ( fields. collect ( ) , id)
171
169
}
172
170
ast:: VariantData :: Tuple ( fields, id) => {
173
- let fields = fields. into_iter ( ) . filter_map ( |field| this . configure ( field) ) ;
171
+ let fields = fields. into_iter ( ) . filter_map ( |field| self . configure ( field) ) ;
174
172
ast:: VariantData :: Tuple ( fields. collect ( ) , id)
175
173
}
176
174
ast:: VariantData :: Unit ( id) => ast:: VariantData :: Unit ( id)
177
- } ;
175
+ }
176
+ }
178
177
179
- let item = match item {
178
+ pub fn configure_item_kind ( & mut self , item : ast:: ItemKind ) -> ast:: ItemKind {
179
+ match item {
180
180
ast:: ItemKind :: Struct ( def, generics) => {
181
- ast:: ItemKind :: Struct ( fold_struct ( self , def) , generics)
181
+ ast:: ItemKind :: Struct ( self . configure_variant_data ( def) , generics)
182
182
}
183
183
ast:: ItemKind :: Union ( def, generics) => {
184
- ast:: ItemKind :: Union ( fold_struct ( self , def) , generics)
184
+ ast:: ItemKind :: Union ( self . configure_variant_data ( def) , generics)
185
185
}
186
186
ast:: ItemKind :: Enum ( def, generics) => {
187
187
let variants = def. variants . into_iter ( ) . filter_map ( |v| {
@@ -190,7 +190,7 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
190
190
node : ast:: Variant_ {
191
191
name : v. node . name ,
192
192
attrs : v. node . attrs ,
193
- data : fold_struct ( self , v. node . data ) ,
193
+ data : self . configure_variant_data ( v. node . data ) ,
194
194
disr_expr : v. node . disr_expr ,
195
195
} ,
196
196
span : v. span
@@ -202,12 +202,19 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
202
202
} , generics)
203
203
}
204
204
item => item,
205
- } ;
205
+ }
206
+ }
206
207
207
- fold:: noop_fold_item_kind ( item, self )
208
+ pub fn configure_expr_kind ( & mut self , expr_kind : ast:: ExprKind ) -> ast:: ExprKind {
209
+ if let ast:: ExprKind :: Match ( m, arms) = expr_kind {
210
+ let arms = arms. into_iter ( ) . filter_map ( |a| self . configure ( a) ) . collect ( ) ;
211
+ ast:: ExprKind :: Match ( m, arms)
212
+ } else {
213
+ expr_kind
214
+ }
208
215
}
209
216
210
- fn fold_expr ( & mut self , expr : P < ast:: Expr > ) -> P < ast:: Expr > {
217
+ pub fn configure_expr ( & mut self , expr : P < ast:: Expr > ) -> P < ast:: Expr > {
211
218
self . visit_stmt_or_expr_attrs ( expr. attrs ( ) ) ;
212
219
213
220
// If an expr is valid to cfg away it will have been removed by the
@@ -222,62 +229,13 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
222
229
self . sess . span_diagnostic . span_err ( attr. span , msg) ;
223
230
}
224
231
225
- let expr = self . process_cfg_attrs ( expr) ;
226
- fold_expr ( self , expr)
232
+ self . process_cfg_attrs ( expr)
227
233
}
228
234
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) )
231
- }
232
-
233
- fn fold_stmt ( & mut self , stmt : ast:: Stmt ) -> SmallVector < ast:: Stmt > {
235
+ pub fn configure_stmt ( & mut self , stmt : ast:: Stmt ) -> Option < ast:: Stmt > {
234
236
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 ( ) )
237
- }
238
-
239
- fn fold_mac ( & mut self , mac : ast:: Mac ) -> ast:: Mac {
240
- fold:: noop_fold_mac ( mac, self )
241
- }
242
-
243
- 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 ( ) )
246
- }
247
-
248
- 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 ( ) )
251
- }
252
-
253
- 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 ( ) )
237
+ self . configure ( stmt)
256
238
}
257
-
258
- fn fold_interpolated ( & mut self , nt : token:: Nonterminal ) -> token:: Nonterminal {
259
- // Don't configure interpolated AST (c.f. #34171).
260
- // Interpolated AST will get configured once the surrounding tokens are parsed.
261
- nt
262
- }
263
- }
264
-
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
239
}
282
240
283
241
fn is_cfg ( attr : & ast:: Attribute ) -> bool {
0 commit comments