about summary refs log tree commit diff
diff options
context:
space:
mode:
authorKeegan McAllister <kmcallister@mozilla.com>2014-06-13 15:03:26 -0700
committerKeegan McAllister <kmcallister@mozilla.com>2014-06-24 11:36:27 -0700
commita813a3779be2266cf936ee87907595c356f3afbc (patch)
tree90fb5c354ec8936fb24bf620b9569f2348d88ef9
parentb5542f7f5b1eb11430960687f69b5766857efaa0 (diff)
Rework lint attr parsing and use it in middle::dead
-rw-r--r--src/librustc/lint/context.rs95
-rw-r--r--src/librustc/lint/mod.rs2
-rw-r--r--src/librustc/middle/dead.rs15
3 files changed, 59 insertions, 53 deletions
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 31e6f3907dc..877bf6f52a4 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -44,6 +44,7 @@ use syntax::attr::AttrMetaMethods;
 use syntax::attr;
 use syntax::codemap::Span;
 use syntax::visit::{Visitor, FnKind};
+use syntax::parse::token::InternedString;
 use syntax::{ast, ast_util, visit};
 
 /// Information about the registered lints.
@@ -193,6 +194,38 @@ macro_rules! run_lints ( ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.lints.passes = Some(passes);
 }))
 
+/// Parse the lint attributes into a vector, with `Err`s for malformed lint
+/// attributes. Writing this as an iterator is an enormous mess.
+pub fn gather_attrs(attrs: &[ast::Attribute])
+                    -> Vec<Result<(InternedString, Level, Span), Span>> {
+    let mut out = vec!();
+    for attr in attrs.iter() {
+        let level = match Level::from_str(attr.name().get()) {
+            None => continue,
+            Some(lvl) => lvl,
+        };
+
+        attr::mark_used(attr);
+
+        let meta = attr.node.value;
+        let metas = match meta.node {
+            ast::MetaList(_, ref metas) => metas,
+            _ => {
+                out.push(Err(meta.span));
+                continue;
+            }
+        };
+
+        for meta in metas.iter() {
+            out.push(match meta.node {
+                ast::MetaWord(ref lint_name) => Ok((lint_name.clone(), level, meta.span)),
+                _ => Err(meta.span),
+            });
+        }
+    }
+    out
+}
+
 /// Emit a lint as a warning or an error (or not at all)
 /// according to `level`.
 ///
@@ -295,9 +328,27 @@ impl<'a> Context<'a> {
         // current dictionary of lint information. Along the way, keep a history
         // of what we changed so we can roll everything back after invoking the
         // specified closure
-        let lint_attrs = self.gather_lint_attrs(attrs);
         let mut pushed = 0u;
-        for (lint_id, level, span) in lint_attrs.move_iter() {
+
+        for result in gather_attrs(attrs).move_iter() {
+            let (lint_id, level, span) = match result {
+                Err(span) => {
+                    self.tcx.sess.span_err(span, "malformed lint attribute");
+                    continue;
+                }
+                Ok((lint_name, level, span)) => {
+                    match self.lints.by_name.find_equiv(&lint_name.get()) {
+                        Some(&lint_id) => (lint_id, level, span),
+                        None => {
+                            self.span_lint(builtin::UNRECOGNIZED_LINT, span,
+                                           format!("unknown `{}` attribute: `{}`",
+                                                   level.as_str(), lint_name).as_slice());
+                            continue;
+                        }
+                    }
+                }
+            };
+
             let now = self.lints.get_level_source(lint_id).val0();
             if now == Forbid && level != Forbid {
                 let lint_name = lint_id.as_str();
@@ -331,46 +382,6 @@ impl<'a> Context<'a> {
         };
         f(&mut v);
     }
-
-    fn gather_lint_attrs(&mut self, attrs: &[ast::Attribute]) -> Vec<(LintId, Level, Span)> {
-        // Doing this as an iterator is messy due to multiple borrowing.
-        // Allocating and copying these should be quick.
-        let mut out = vec!();
-        for attr in attrs.iter() {
-            let level = match Level::from_str(attr.name().get()) {
-                None => continue,
-                Some(lvl) => lvl,
-            };
-
-            attr::mark_used(attr);
-
-            let meta = attr.node.value;
-            let metas = match meta.node {
-                ast::MetaList(_, ref metas) => metas,
-                _ => {
-                    self.tcx.sess.span_err(meta.span, "malformed lint attribute");
-                    continue;
-                }
-            };
-
-            for meta in metas.iter() {
-                match meta.node {
-                    ast::MetaWord(ref lint_name) => {
-                        match self.lints.by_name.find_equiv(&lint_name.get()) {
-                            Some(lint_id) => out.push((*lint_id, level, meta.span)),
-
-                            None => self.span_lint(builtin::UNRECOGNIZED_LINT,
-                                meta.span,
-                                format!("unknown `{}` attribute: `{}`",
-                                    level.as_str(), lint_name).as_slice()),
-                        }
-                    }
-                    _ => self.tcx.sess.span_err(meta.span, "malformed lint attribute"),
-                }
-            }
-        }
-        out
-    }
 }
 
 impl<'a> AstConv for Context<'a>{
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 598c5dd3002..33facce2997 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -36,7 +36,7 @@ use syntax::codemap::Span;
 use syntax::visit::FnKind;
 use syntax::ast;
 
-pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate};
+pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate, gather_attrs};
 
 /// Specification of a single lint.
 pub struct Lint {
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 50ba073aafc..156b8840067 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -269,16 +269,11 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
         return true;
     }
 
-    // FIXME: use the lint attr parsing already in rustc::lint
-    for attr in attrs.iter().filter(|a| a.check_name("allow")) {
-        match attr.node.value.node {
-            ast::MetaList(_, ref metas) => for meta in metas.iter() {
-                match meta.node {
-                    ast::MetaWord(ref name) if name.get() == "dead_code"
-                        => return true,
-                    _ => (),
-                }
-            },
+    let dead_code = lint::builtin::DEAD_CODE.name_lower();
+    for attr in lint::gather_attrs(attrs).move_iter() {
+        match attr {
+            Ok((ref name, lint::Allow, _))
+                if name.get() == dead_code.as_slice() => return true,
             _ => (),
         }
     }