@@ -44,6 +44,7 @@ use syntax::attr::AttrMetaMethods;
4444use syntax:: attr;
4545use syntax:: codemap:: Span ;
4646use syntax:: visit:: { Visitor , FnKind } ;
47+ use syntax:: parse:: token:: InternedString ;
4748use syntax:: { ast, ast_util, visit} ;
4849
4950/// Information about the registered lints.
@@ -193,6 +194,38 @@ macro_rules! run_lints ( ($cx:expr, $f:ident, $($args:expr),*) => ({
193194 $cx. lints. passes = Some ( passes) ;
194195} ) )
195196
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+
196229/// Emit a lint as a warning or an error (or not at all)
197230/// according to `level`.
198231///
@@ -295,9 +328,27 @@ impl<'a> Context<'a> {
295328 // current dictionary of lint information. Along the way, keep a history
296329 // of what we changed so we can roll everything back after invoking the
297330 // specified closure
298- let lint_attrs = self . gather_lint_attrs ( attrs) ;
299331 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+
301352 let now = self . lints . get_level_source ( lint_id) . val0 ( ) ;
302353 if now == Forbid && level != Forbid {
303354 let lint_name = lint_id. as_str ( ) ;
@@ -331,46 +382,6 @@ impl<'a> Context<'a> {
331382 } ;
332383 f ( & mut v) ;
333384 }
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- }
374385}
375386
376387impl < ' a > AstConv for Context < ' a > {
0 commit comments