rollup merge of #21765: P1start/non-ascii-style-lints

An alternative to #21749.

This also refactors the naming lint code a little bit and slightly rephrases some warnings (`uppercase` → `upper case`).

Closes #21735.
This commit is contained in:
Alex Crichton 2015-01-30 12:03:34 -08:00
commit 6ea5fb8a6d
6 changed files with 90 additions and 52 deletions

View file

@ -937,6 +937,34 @@ declare_lint! {
pub struct NonSnakeCase;
impl NonSnakeCase {
fn to_snake_case(mut str: &str) -> String {
let mut words = vec![];
// Preserve leading underscores
str = str.trim_left_matches(|&mut: c: char| {
if c == '_' {
words.push(String::new());
true
} else { false }
});
for s in str.split('_') {
let mut last_upper = false;
let mut buf = String::new();
if s.is_empty() { continue; }
for ch in s.chars() {
if !buf.is_empty() && buf != "'"
&& ch.is_uppercase()
&& !last_upper {
words.push(buf);
buf = String::new();
}
last_upper = ch.is_uppercase();
buf.push(ch.to_lowercase());
}
words.push(buf);
}
words.connect("_")
}
fn check_snake_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
fn is_snake_case(ident: ast::Ident) -> bool {
let ident = token::get_ident(ident);
@ -947,41 +975,28 @@ impl NonSnakeCase {
let mut allow_underscore = true;
ident.chars().all(|c| {
allow_underscore = match c {
c if c.is_lowercase() || c.is_numeric() => true,
'_' if allow_underscore => false,
'_' if !allow_underscore => return false,
'_' => false,
c if !c.is_uppercase() => true,
_ => return false,
};
true
})
}
fn to_snake_case(str: &str) -> String {
let mut words = vec![];
for s in str.split('_') {
let mut last_upper = false;
let mut buf = String::new();
if s.is_empty() { continue; }
for ch in s.chars() {
if !buf.is_empty() && buf != "'"
&& ch.is_uppercase()
&& !last_upper {
words.push(buf);
buf = String::new();
}
last_upper = ch.is_uppercase();
buf.push(ch.to_lowercase());
}
words.push(buf);
}
words.connect("_")
}
let s = token::get_ident(ident);
if !is_snake_case(ident) {
cx.span_lint(NON_SNAKE_CASE, span,
&format!("{} `{}` should have a snake case name such as `{}`",
sort, s, to_snake_case(s.get()))[]);
let sc = NonSnakeCase::to_snake_case(s.get());
if sc != s.get() {
cx.span_lint(NON_SNAKE_CASE, span,
&*format!("{} `{}` should have a snake case name such as `{}`",
sort, s, sc));
} else {
cx.span_lint(NON_SNAKE_CASE, span,
&*format!("{} `{}` should have a snake case name",
sort, s));
}
}
}
}
@ -1049,6 +1064,26 @@ declare_lint! {
#[derive(Copy)]
pub struct NonUpperCaseGlobals;
impl NonUpperCaseGlobals {
fn check_upper_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
let s = token::get_ident(ident);
if s.get().chars().any(|c| c.is_lowercase()) {
let uc: String = NonSnakeCase::to_snake_case(s.get()).chars()
.map(|c| c.to_uppercase()).collect();
if uc != s.get() {
cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
format!("{} `{}` should have an upper case name such as `{}`",
sort, s, uc).as_slice());
} else {
cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
format!("{} `{}` should have an upper case name",
sort, s).as_slice());
}
}
}
}
impl LintPass for NonUpperCaseGlobals {
fn get_lints(&self) -> LintArray {
lint_array!(NON_UPPER_CASE_GLOBALS)
@ -1057,19 +1092,11 @@ impl LintPass for NonUpperCaseGlobals {
fn check_item(&mut self, cx: &Context, it: &ast::Item) {
match it.node {
// only check static constants
ast::ItemStatic(_, ast::MutImmutable, _) |
ast::ItemStatic(_, ast::MutImmutable, _) => {
NonUpperCaseGlobals::check_upper_case(cx, "static constant", it.ident, it.span);
}
ast::ItemConst(..) => {
let s = token::get_ident(it.ident);
// check for lowercase letters rather than non-uppercase
// ones (some scripts don't have a concept of
// upper/lowercase)
if s.get().chars().any(|c| c.is_lowercase()) {
cx.span_lint(NON_UPPER_CASE_GLOBALS, it.span,
&format!("static constant `{}` should have an uppercase name \
such as `{}`",
s.get(), &s.get().chars().map(|c| c.to_uppercase())
.collect::<String>()[])[]);
}
NonUpperCaseGlobals::check_upper_case(cx, "constant", it.ident, it.span);
}
_ => {}
}
@ -1079,14 +1106,8 @@ impl LintPass for NonUpperCaseGlobals {
// Lint for constants that look like binding identifiers (#7526)
match (&p.node, cx.tcx.def_map.borrow().get(&p.id)) {
(&ast::PatIdent(_, ref path1, _), Some(&def::DefConst(..))) => {
let s = token::get_ident(path1.node);
if s.get().chars().any(|c| c.is_lowercase()) {
cx.span_lint(NON_UPPER_CASE_GLOBALS, path1.span,
&format!("static constant in pattern `{}` should have an uppercase \
name such as `{}`",
s.get(), &s.get().chars().map(|c| c.to_uppercase())
.collect::<String>()[])[]);
}
NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
path1.node, p.span);
}
_ => {}
}