提交 a813a377 编写于 作者: K Keegan McAllister

Rework lint attr parsing and use it in middle::dead

上级 b5542f7f
......@@ -44,6 +44,7 @@
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 @@ pub struct Context<'a> {
$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 @@ fn with_lint_attrs(&mut self,
// 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 @@ fn visit_ids(&self, f: |&mut ast_util::IdVisitor<Context>|) {
};
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>{
......
......@@ -36,7 +36,7 @@
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 {
......
......@@ -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,
_ => (),
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册