Skip to content

Commit a813a37

Browse files
author
Keegan McAllister
committed
Rework lint attr parsing and use it in middle::dead
1 parent b5542f7 commit a813a37

File tree

3 files changed

+59
-53
lines changed

3 files changed

+59
-53
lines changed

src/librustc/lint/context.rs

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ use syntax::attr::AttrMetaMethods;
4444
use syntax::attr;
4545
use syntax::codemap::Span;
4646
use syntax::visit::{Visitor, FnKind};
47+
use syntax::parse::token::InternedString;
4748
use 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 = 0u;
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

376387
impl<'a> AstConv for Context<'a>{

src/librustc/lint/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use syntax::codemap::Span;
3636
use syntax::visit::FnKind;
3737
use syntax::ast;
3838

39-
pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate};
39+
pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate, gather_attrs};
4040

4141
/// Specification of a single lint.
4242
pub struct Lint {

src/librustc/middle/dead.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -269,16 +269,11 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
269269
return true;
270270
}
271271

272-
// FIXME: use the lint attr parsing already in rustc::lint
273-
for attr in attrs.iter().filter(|a| a.check_name("allow")) {
274-
match attr.node.value.node {
275-
ast::MetaList(_, ref metas) => for meta in metas.iter() {
276-
match meta.node {
277-
ast::MetaWord(ref name) if name.get() == "dead_code"
278-
=> return true,
279-
_ => (),
280-
}
281-
},
272+
let dead_code = lint::builtin::DEAD_CODE.name_lower();
273+
for attr in lint::gather_attrs(attrs).move_iter() {
274+
match attr {
275+
Ok((ref name, lint::Allow, _))
276+
if name.get() == dead_code.as_slice() => return true,
282277
_ => (),
283278
}
284279
}

0 commit comments

Comments
 (0)