Skip to content

Commit 39a8c23

Browse files
committed
Make the naming lints only warn on names with upper/lowercase equivalents
Closes #21735.
1 parent c5961ad commit 39a8c23

6 files changed

+90
-52
lines changed

src/librustc/lint/builtin.rs

Lines changed: 67 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,34 @@ declare_lint! {
937937
pub struct NonSnakeCase;
938938

939939
impl NonSnakeCase {
940+
fn to_snake_case(mut str: &str) -> String {
941+
let mut words = vec![];
942+
// Preserve leading underscores
943+
str = str.trim_left_matches(|&mut: c: char| {
944+
if c == '_' {
945+
words.push(String::new());
946+
true
947+
} else { false }
948+
});
949+
for s in str.split('_') {
950+
let mut last_upper = false;
951+
let mut buf = String::new();
952+
if s.is_empty() { continue; }
953+
for ch in s.chars() {
954+
if !buf.is_empty() && buf != "'"
955+
&& ch.is_uppercase()
956+
&& !last_upper {
957+
words.push(buf);
958+
buf = String::new();
959+
}
960+
last_upper = ch.is_uppercase();
961+
buf.push(ch.to_lowercase());
962+
}
963+
words.push(buf);
964+
}
965+
words.connect("_")
966+
}
967+
940968
fn check_snake_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
941969
fn is_snake_case(ident: ast::Ident) -> bool {
942970
let ident = token::get_ident(ident);
@@ -947,41 +975,28 @@ impl NonSnakeCase {
947975
let mut allow_underscore = true;
948976
ident.chars().all(|c| {
949977
allow_underscore = match c {
950-
c if c.is_lowercase() || c.is_numeric() => true,
951-
'_' if allow_underscore => false,
978+
'_' if !allow_underscore => return false,
979+
'_' => false,
980+
c if !c.is_uppercase() => true,
952981
_ => return false,
953982
};
954983
true
955984
})
956985
}
957986

958-
fn to_snake_case(str: &str) -> String {
959-
let mut words = vec![];
960-
for s in str.split('_') {
961-
let mut last_upper = false;
962-
let mut buf = String::new();
963-
if s.is_empty() { continue; }
964-
for ch in s.chars() {
965-
if !buf.is_empty() && buf != "'"
966-
&& ch.is_uppercase()
967-
&& !last_upper {
968-
words.push(buf);
969-
buf = String::new();
970-
}
971-
last_upper = ch.is_uppercase();
972-
buf.push(ch.to_lowercase());
973-
}
974-
words.push(buf);
975-
}
976-
words.connect("_")
977-
}
978-
979987
let s = token::get_ident(ident);
980988

981989
if !is_snake_case(ident) {
982-
cx.span_lint(NON_SNAKE_CASE, span,
983-
&format!("{} `{}` should have a snake case name such as `{}`",
984-
sort, s, to_snake_case(s.get()))[]);
990+
let sc = NonSnakeCase::to_snake_case(s.get());
991+
if sc != s.get() {
992+
cx.span_lint(NON_SNAKE_CASE, span,
993+
&*format!("{} `{}` should have a snake case name such as `{}`",
994+
sort, s, sc));
995+
} else {
996+
cx.span_lint(NON_SNAKE_CASE, span,
997+
&*format!("{} `{}` should have a snake case name",
998+
sort, s));
999+
}
9851000
}
9861001
}
9871002
}
@@ -1049,6 +1064,26 @@ declare_lint! {
10491064
#[derive(Copy)]
10501065
pub struct NonUpperCaseGlobals;
10511066

1067+
impl NonUpperCaseGlobals {
1068+
fn check_upper_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
1069+
let s = token::get_ident(ident);
1070+
1071+
if s.get().chars().any(|c| c.is_lowercase()) {
1072+
let uc: String = NonSnakeCase::to_snake_case(s.get()).chars()
1073+
.map(|c| c.to_uppercase()).collect();
1074+
if uc != s.get() {
1075+
cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
1076+
format!("{} `{}` should have an upper case name such as `{}`",
1077+
sort, s, uc).as_slice());
1078+
} else {
1079+
cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
1080+
format!("{} `{}` should have an upper case name",
1081+
sort, s).as_slice());
1082+
}
1083+
}
1084+
}
1085+
}
1086+
10521087
impl LintPass for NonUpperCaseGlobals {
10531088
fn get_lints(&self) -> LintArray {
10541089
lint_array!(NON_UPPER_CASE_GLOBALS)
@@ -1057,19 +1092,11 @@ impl LintPass for NonUpperCaseGlobals {
10571092
fn check_item(&mut self, cx: &Context, it: &ast::Item) {
10581093
match it.node {
10591094
// only check static constants
1060-
ast::ItemStatic(_, ast::MutImmutable, _) |
1095+
ast::ItemStatic(_, ast::MutImmutable, _) => {
1096+
NonUpperCaseGlobals::check_upper_case(cx, "static constant", it.ident, it.span);
1097+
}
10611098
ast::ItemConst(..) => {
1062-
let s = token::get_ident(it.ident);
1063-
// check for lowercase letters rather than non-uppercase
1064-
// ones (some scripts don't have a concept of
1065-
// upper/lowercase)
1066-
if s.get().chars().any(|c| c.is_lowercase()) {
1067-
cx.span_lint(NON_UPPER_CASE_GLOBALS, it.span,
1068-
&format!("static constant `{}` should have an uppercase name \
1069-
such as `{}`",
1070-
s.get(), &s.get().chars().map(|c| c.to_uppercase())
1071-
.collect::<String>()[])[]);
1072-
}
1099+
NonUpperCaseGlobals::check_upper_case(cx, "constant", it.ident, it.span);
10731100
}
10741101
_ => {}
10751102
}
@@ -1079,14 +1106,8 @@ impl LintPass for NonUpperCaseGlobals {
10791106
// Lint for constants that look like binding identifiers (#7526)
10801107
match (&p.node, cx.tcx.def_map.borrow().get(&p.id)) {
10811108
(&ast::PatIdent(_, ref path1, _), Some(&def::DefConst(..))) => {
1082-
let s = token::get_ident(path1.node);
1083-
if s.get().chars().any(|c| c.is_lowercase()) {
1084-
cx.span_lint(NON_UPPER_CASE_GLOBALS, path1.span,
1085-
&format!("static constant in pattern `{}` should have an uppercase \
1086-
name such as `{}`",
1087-
s.get(), &s.get().chars().map(|c| c.to_uppercase())
1088-
.collect::<String>()[])[]);
1089-
}
1109+
NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
1110+
path1.node, p.span);
10901111
}
10911112
_ => {}
10921113
}

src/test/compile-fail/issue-17718-const-naming.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#[deny(warnings)]
1212

1313
const foo: isize = 3;
14-
//~^ ERROR: should have an uppercase name such as
14+
//~^ ERROR: should have an upper case name such as
1515
//~^^ ERROR: constant item is never used
1616

1717
fn main() {}

src/test/compile-fail/lint-group-style.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ mod test {
2424
mod bad {
2525
fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name
2626

27-
static bad: isize = 1; //~ ERROR static constant `bad` should have an uppercase name
27+
static bad: isize = 1; //~ ERROR static constant `bad` should have an upper case name
2828
}
2929

3030
mod warn {

src/test/compile-fail/lint-non-uppercase-statics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@
1111
#![forbid(non_upper_case_globals)]
1212
#![allow(dead_code)]
1313

14-
static foo: isize = 1; //~ ERROR static constant `foo` should have an uppercase name such as `FOO`
14+
static foo: isize = 1; //~ ERROR static constant `foo` should have an upper case name such as `FOO`
1515

1616
fn main() { }

src/test/compile-fail/match-static-const-lc.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub const a : isize = 97;
1919
fn f() {
2020
let r = match (0,0) {
2121
(0, a) => 0,
22-
//~^ ERROR static constant in pattern `a` should have an uppercase name such as `A`
22+
//~^ ERROR constant in pattern `a` should have an upper case name such as `A`
2323
(x, y) => 1 + x + y,
2424
};
2525
assert!(r == 1);
@@ -34,7 +34,7 @@ fn g() {
3434
use self::m::aha;
3535
let r = match (0,0) {
3636
(0, aha) => 0,
37-
//~^ ERROR static constant in pattern `aha` should have an uppercase name such as `AHA`
37+
//~^ ERROR constant in pattern `aha` should have an upper case name such as `AHA`
3838
(x, y) => 1 + x + y,
3939
};
4040
assert!(r == 1);
@@ -48,7 +48,7 @@ fn h() {
4848
use self::n::OKAY as not_okay;
4949
let r = match (0,0) {
5050
(0, not_okay) => 0,
51-
//~^ ERROR static constant in pattern `not_okay` should have an uppercase name such as `NOT_OKAY`
51+
//~^ ERROR constant in pattern `not_okay` should have an upper case name such as `NOT_OKAY`
5252
(x, y) => 1 + x + y,
5353
};
5454
assert!(r == 1);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(non_ascii_idents)]
12+
#![deny(non_snake_case)]
13+
14+
// This name is neither upper nor lower case
15+
fn 你好() {}
16+
17+
fn main() {}

0 commit comments

Comments
 (0)