Make the naming lints only warn on names with upper/lowercase equivalents
Closes #21735.
This commit is contained in:
parent
c5961ad06d
commit
39a8c23c0b
6 changed files with 90 additions and 52 deletions
|
@ -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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#[deny(warnings)]
|
||||
|
||||
const foo: isize = 3;
|
||||
//~^ ERROR: should have an uppercase name such as
|
||||
//~^ ERROR: should have an upper case name such as
|
||||
//~^^ ERROR: constant item is never used
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -24,7 +24,7 @@ mod test {
|
|||
mod bad {
|
||||
fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name
|
||||
|
||||
static bad: isize = 1; //~ ERROR static constant `bad` should have an uppercase name
|
||||
static bad: isize = 1; //~ ERROR static constant `bad` should have an upper case name
|
||||
}
|
||||
|
||||
mod warn {
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
#![forbid(non_upper_case_globals)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
static foo: isize = 1; //~ ERROR static constant `foo` should have an uppercase name such as `FOO`
|
||||
static foo: isize = 1; //~ ERROR static constant `foo` should have an upper case name such as `FOO`
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -19,7 +19,7 @@ pub const a : isize = 97;
|
|||
fn f() {
|
||||
let r = match (0,0) {
|
||||
(0, a) => 0,
|
||||
//~^ ERROR static constant in pattern `a` should have an uppercase name such as `A`
|
||||
//~^ ERROR constant in pattern `a` should have an upper case name such as `A`
|
||||
(x, y) => 1 + x + y,
|
||||
};
|
||||
assert!(r == 1);
|
||||
|
@ -34,7 +34,7 @@ fn g() {
|
|||
use self::m::aha;
|
||||
let r = match (0,0) {
|
||||
(0, aha) => 0,
|
||||
//~^ ERROR static constant in pattern `aha` should have an uppercase name such as `AHA`
|
||||
//~^ ERROR constant in pattern `aha` should have an upper case name such as `AHA`
|
||||
(x, y) => 1 + x + y,
|
||||
};
|
||||
assert!(r == 1);
|
||||
|
@ -48,7 +48,7 @@ fn h() {
|
|||
use self::n::OKAY as not_okay;
|
||||
let r = match (0,0) {
|
||||
(0, not_okay) => 0,
|
||||
//~^ ERROR static constant in pattern `not_okay` should have an uppercase name such as `NOT_OKAY`
|
||||
//~^ ERROR constant in pattern `not_okay` should have an upper case name such as `NOT_OKAY`
|
||||
(x, y) => 1 + x + y,
|
||||
};
|
||||
assert!(r == 1);
|
||||
|
|
17
src/test/run-pass/snake-case-no-lowercase-equivalent.rs
Normal file
17
src/test/run-pass/snake-case-no-lowercase-equivalent.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(non_ascii_idents)]
|
||||
#![deny(non_snake_case)]
|
||||
|
||||
// This name is neither upper nor lower case
|
||||
fn 你好() {}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in a new issue