@@ -44,6 +44,7 @@ use syntax::attr::AttrMetaMethods;
44
44
use syntax:: attr;
45
45
use syntax:: codemap:: Span ;
46
46
use syntax:: visit:: { Visitor , FnKind } ;
47
+ use syntax:: parse:: token:: InternedString ;
47
48
use syntax:: { ast, ast_util, visit} ;
48
49
49
50
/// Information about the registered lints.
@@ -193,6 +194,38 @@ macro_rules! run_lints ( ($cx:expr, $f:ident, $($args:expr),*) => ({
193
194
$cx. lints. passes = Some ( passes) ;
194
195
} ) )
195
196
197
+ /// Parse the lint attributes into a vector, with `Err`s for malformed lint
198
+ /// attributes. Writing this as an iterator is an enormous mess.
199
+ pub fn gather_attrs ( attrs : & [ ast:: Attribute ] )
200
+ -> Vec < Result < ( InternedString , Level , Span ) , Span > > {
201
+ let mut out = vec ! ( ) ;
202
+ for attr in attrs. iter ( ) {
203
+ let level = match Level :: from_str ( attr. name ( ) . get ( ) ) {
204
+ None => continue ,
205
+ Some ( lvl) => lvl,
206
+ } ;
207
+
208
+ attr:: mark_used ( attr) ;
209
+
210
+ let meta = attr. node . value ;
211
+ let metas = match meta. node {
212
+ ast:: MetaList ( _, ref metas) => metas,
213
+ _ => {
214
+ out. push ( Err ( meta. span ) ) ;
215
+ continue ;
216
+ }
217
+ } ;
218
+
219
+ for meta in metas. iter ( ) {
220
+ out. push ( match meta. node {
221
+ ast:: MetaWord ( ref lint_name) => Ok ( ( lint_name. clone ( ) , level, meta. span ) ) ,
222
+ _ => Err ( meta. span ) ,
223
+ } ) ;
224
+ }
225
+ }
226
+ out
227
+ }
228
+
196
229
/// Emit a lint as a warning or an error (or not at all)
197
230
/// according to `level`.
198
231
///
@@ -295,9 +328,27 @@ impl<'a> Context<'a> {
295
328
// current dictionary of lint information. Along the way, keep a history
296
329
// of what we changed so we can roll everything back after invoking the
297
330
// specified closure
298
- let lint_attrs = self . gather_lint_attrs ( attrs) ;
299
331
let mut pushed = 0 u;
300
- for ( lint_id, level, span) in lint_attrs. move_iter ( ) {
332
+
333
+ for result in gather_attrs ( attrs) . move_iter ( ) {
334
+ let ( lint_id, level, span) = match result {
335
+ Err ( span) => {
336
+ self . tcx . sess . span_err ( span, "malformed lint attribute" ) ;
337
+ continue ;
338
+ }
339
+ Ok ( ( lint_name, level, span) ) => {
340
+ match self . lints . by_name . find_equiv ( & lint_name. get ( ) ) {
341
+ Some ( & lint_id) => ( lint_id, level, span) ,
342
+ None => {
343
+ self . span_lint ( builtin:: UNRECOGNIZED_LINT , span,
344
+ format ! ( "unknown `{}` attribute: `{}`" ,
345
+ level. as_str( ) , lint_name) . as_slice ( ) ) ;
346
+ continue ;
347
+ }
348
+ }
349
+ }
350
+ } ;
351
+
301
352
let now = self . lints . get_level_source ( lint_id) . val0 ( ) ;
302
353
if now == Forbid && level != Forbid {
303
354
let lint_name = lint_id. as_str ( ) ;
@@ -331,46 +382,6 @@ impl<'a> Context<'a> {
331
382
} ;
332
383
f ( & mut v) ;
333
384
}
334
-
335
- fn gather_lint_attrs ( & mut self , attrs : & [ ast:: Attribute ] ) -> Vec < ( LintId , Level , Span ) > {
336
- // Doing this as an iterator is messy due to multiple borrowing.
337
- // Allocating and copying these should be quick.
338
- let mut out = vec ! ( ) ;
339
- for attr in attrs. iter ( ) {
340
- let level = match Level :: from_str ( attr. name ( ) . get ( ) ) {
341
- None => continue ,
342
- Some ( lvl) => lvl,
343
- } ;
344
-
345
- attr:: mark_used ( attr) ;
346
-
347
- let meta = attr. node . value ;
348
- let metas = match meta. node {
349
- ast:: MetaList ( _, ref metas) => metas,
350
- _ => {
351
- self . tcx . sess . span_err ( meta. span , "malformed lint attribute" ) ;
352
- continue ;
353
- }
354
- } ;
355
-
356
- for meta in metas. iter ( ) {
357
- match meta. node {
358
- ast:: MetaWord ( ref lint_name) => {
359
- match self . lints . by_name . find_equiv ( & lint_name. get ( ) ) {
360
- Some ( lint_id) => out. push ( ( * lint_id, level, meta. span ) ) ,
361
-
362
- None => self . span_lint ( builtin:: UNRECOGNIZED_LINT ,
363
- meta. span ,
364
- format ! ( "unknown `{}` attribute: `{}`" ,
365
- level. as_str( ) , lint_name) . as_slice ( ) ) ,
366
- }
367
- }
368
- _ => self . tcx . sess . span_err ( meta. span , "malformed lint attribute" ) ,
369
- }
370
- }
371
- }
372
- out
373
- }
374
385
}
375
386
376
387
impl < ' a > AstConv for Context < ' a > {
0 commit comments