let mut lints: Vec<_> = lints.move_iter().map(|(x, _)| x).collect();
lints.sort_by(|x: &&Lint, y: &&Lint| {
match x.default_level.cmp(&y.default_level) {
+ // The sort doesn't case-fold but it's doubtful we care.
Equal => x.name.cmp(&y.name),
r => r,
}
let print_lints = |lints: Vec<&Lint>| {
for lint in lints.move_iter() {
- let name = lint.name.replace("_", "-");
+ let name = lint.name_lower().replace("_", "-");
println!(" {} {:7.7s} {}",
padded(name.as_slice()), lint.default_level.as_str(), lint.desc);
}
passes: Option<Vec<LintPassObject>>,
/// Lints indexed by name.
- by_name: HashMap<&'static str, LintId>,
+ by_name: HashMap<String, LintId>,
/// Current levels of each lint, and where they were set.
levels: HashMap<LintId, LevelSource>,
self.lints.push((lint, from_plugin));
let id = LintId::of(lint);
- if !self.by_name.insert(lint.name, id) {
- let msg = format!("duplicate specification of lint {}", lint.name);
+ if !self.by_name.insert(lint.name_lower(), id) {
+ let msg = format!("duplicate specification of lint {}", lint.name_lower());
match (sess, from_plugin) {
// We load builtin lints first, so a duplicate is a compiler bug.
// Use early_error when handling -W help with no crate.
let (mut level, source) = lvlsrc;
if level == Allow { return }
+ let name = lint.name_lower();
let mut note = None;
let msg = match source {
Default => {
format!("{}, #[{}({})] on by default", msg,
- level.as_str(), lint.name)
+ level.as_str(), name)
},
CommandLine => {
format!("{} [-{} {}]", msg,
match level {
Warn => 'W', Deny => 'D', Forbid => 'F',
Allow => fail!()
- }, lint.name.replace("_", "-"))
+ }, name.replace("_", "-"))
},
Node(src) => {
note = Some(src);
for meta in metas.iter() {
match meta.node {
ast::MetaWord(ref lint_name) => {
- match self.lints.by_name.find_equiv(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,
use middle::privacy::ExportedItems;
use std::hash;
+use std::ascii::StrAsciiExt;
use syntax::codemap::Span;
use syntax::visit::FnKind;
use syntax::ast;
pub struct Lint {
/// A string identifier for the lint.
///
- /// Written with underscores, e.g. "unused_imports".
- /// This identifies the lint in attributes and in
- /// command-line arguments. On the command line,
- /// underscores become dashes.
+ /// This identifies the lint in attributes and in command-line arguments.
+ /// In those contexts it is always lowercase, but this field is compared
+ /// in a way which is case-insensitive for ASCII characters. This allows
+ /// `declare_lint!()` invocations to follow the convention of upper-case
+ /// statics without repeating the name.
+ ///
+ /// The name is written with underscores, e.g. "unused_imports".
+ /// On the command line, underscores become dashes.
pub name: &'static str,
/// Default level for the lint.
pub desc: &'static str,
}
+impl Lint {
+ /// Get the lint's name, with ASCII letters converted to lowercase.
+ pub fn name_lower(&self) -> String {
+ self.name.to_ascii_lower()
+ }
+}
+
/// Build a `Lint` initializer.
#[macro_export]
macro_rules! lint_initializer (
}
/// Get the name of the lint.
- pub fn as_str(&self) -> &'static str {
- self.lint.name
+ pub fn as_str(&self) -> String {
+ self.lint.name_lower()
}
}