Rollup merge of #58407 - euclio:upper-camel-case, r=estebank
specify "upper camel case" in style lint Also, fix an issue where internal upper case letters were converted to lower case. Fixes #57319.
This commit is contained in:
commit
a115fea884
@ -8,7 +8,6 @@ edition = "2018"
|
||||
name = "rustc_lint"
|
||||
path = "lib.rs"
|
||||
crate-type = ["dylib"]
|
||||
test = false
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
|
@ -38,66 +38,87 @@ pub fn method_context(cx: &LateContext<'_, '_>, id: ast::NodeId) -> MethodLateCo
|
||||
"types, variants, traits and type parameters should have camel case names"
|
||||
}
|
||||
|
||||
fn char_has_case(c: char) -> bool {
|
||||
c.is_lowercase() || c.is_uppercase()
|
||||
}
|
||||
|
||||
fn is_camel_case(name: &str) -> bool {
|
||||
let name = name.trim_matches('_');
|
||||
if name.is_empty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// start with a non-lowercase letter rather than non-uppercase
|
||||
// ones (some scripts don't have a concept of upper/lowercase)
|
||||
!name.chars().next().unwrap().is_lowercase()
|
||||
&& !name.contains("__")
|
||||
&& !name.chars().collect::<Vec<_>>().windows(2).any(|pair| {
|
||||
// contains a capitalisable character followed by, or preceded by, an underscore
|
||||
char_has_case(pair[0]) && pair[1] == '_' || char_has_case(pair[1]) && pair[0] == '_'
|
||||
})
|
||||
}
|
||||
|
||||
fn to_camel_case(s: &str) -> String {
|
||||
s.trim_matches('_')
|
||||
.split('_')
|
||||
.filter(|component| !component.is_empty())
|
||||
.map(|component| {
|
||||
let mut camel_cased_component = String::new();
|
||||
|
||||
let mut new_word = true;
|
||||
let mut prev_is_lower_case = true;
|
||||
|
||||
for c in component.chars() {
|
||||
// Preserve the case if an uppercase letter follows a lowercase letter, so that
|
||||
// `camelCase` is converted to `CamelCase`.
|
||||
if prev_is_lower_case && c.is_uppercase() {
|
||||
new_word = true;
|
||||
}
|
||||
|
||||
if new_word {
|
||||
camel_cased_component.push_str(&c.to_uppercase().to_string());
|
||||
} else {
|
||||
camel_cased_component.push_str(&c.to_lowercase().to_string());
|
||||
}
|
||||
|
||||
prev_is_lower_case = c.is_lowercase();
|
||||
new_word = false;
|
||||
}
|
||||
|
||||
camel_cased_component
|
||||
})
|
||||
.fold(
|
||||
(String::new(), None),
|
||||
|(acc, prev): (String, Option<String>), next| {
|
||||
// separate two components with an underscore if their boundary cannot
|
||||
// be distinguished using a uppercase/lowercase case distinction
|
||||
let join = if let Some(prev) = prev {
|
||||
let l = prev.chars().last().unwrap();
|
||||
let f = next.chars().next().unwrap();
|
||||
!char_has_case(l) && !char_has_case(f)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
(acc + if join { "_" } else { "" } + &next, Some(next))
|
||||
},
|
||||
)
|
||||
.0
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct NonCamelCaseTypes;
|
||||
|
||||
impl NonCamelCaseTypes {
|
||||
fn check_case(&self, cx: &EarlyContext<'_>, sort: &str, ident: &Ident) {
|
||||
fn char_has_case(c: char) -> bool {
|
||||
c.is_lowercase() || c.is_uppercase()
|
||||
}
|
||||
|
||||
fn is_camel_case(name: &str) -> bool {
|
||||
let name = name.trim_matches('_');
|
||||
if name.is_empty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// start with a non-lowercase letter rather than non-uppercase
|
||||
// ones (some scripts don't have a concept of upper/lowercase)
|
||||
!name.is_empty() && !name.chars().next().unwrap().is_lowercase() &&
|
||||
!name.contains("__") && !name.chars().collect::<Vec<_>>().windows(2).any(|pair| {
|
||||
// contains a capitalisable character followed by, or preceded by, an underscore
|
||||
char_has_case(pair[0]) && pair[1] == '_' ||
|
||||
char_has_case(pair[1]) && pair[0] == '_'
|
||||
})
|
||||
}
|
||||
|
||||
fn to_camel_case(s: &str) -> String {
|
||||
s.trim_matches('_')
|
||||
.split('_')
|
||||
.map(|word| {
|
||||
word.chars().enumerate().map(|(i, c)| if i == 0 {
|
||||
c.to_uppercase().collect::<String>()
|
||||
} else {
|
||||
c.to_lowercase().collect()
|
||||
})
|
||||
.collect::<String>()
|
||||
})
|
||||
.filter(|x| !x.is_empty())
|
||||
.fold((String::new(), None), |(acc, prev): (String, Option<String>), next| {
|
||||
// separate two components with an underscore if their boundary cannot
|
||||
// be distinguished using a uppercase/lowercase case distinction
|
||||
let join = if let Some(prev) = prev {
|
||||
let l = prev.chars().last().unwrap();
|
||||
let f = next.chars().next().unwrap();
|
||||
!char_has_case(l) && !char_has_case(f)
|
||||
} else { false };
|
||||
(acc + if join { "_" } else { "" } + &next, Some(next))
|
||||
}).0
|
||||
}
|
||||
|
||||
let name = &ident.name.as_str();
|
||||
|
||||
if !is_camel_case(name) {
|
||||
let c = to_camel_case(name);
|
||||
|
||||
let msg = format!("{} `{}` should have a camel case name", sort, name);
|
||||
let msg = format!("{} `{}` should have an upper camel case name", sort, name);
|
||||
cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, &msg)
|
||||
.span_suggestion(
|
||||
ident.span,
|
||||
"convert the identifier to camel case",
|
||||
c,
|
||||
"convert the identifier to upper camel case",
|
||||
to_camel_case(name),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
@ -119,11 +140,7 @@ impl EarlyLintPass for NonCamelCaseTypes {
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
|
||||
let has_repr_c = it.attrs
|
||||
.iter()
|
||||
.any(|attr| {
|
||||
attr::find_repr_attrs(&cx.sess.parse_sess, attr)
|
||||
.iter()
|
||||
.any(|r| r == &attr::ReprC)
|
||||
});
|
||||
.any(|attr| attr::find_repr_attrs(&cx.sess.parse_sess, attr).contains(&attr::ReprC));
|
||||
|
||||
if has_repr_c {
|
||||
return;
|
||||
@ -439,3 +456,28 @@ fn check_pat(&mut self, cx: &LateContext<'_, '_>, p: &hir::Pat) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{is_camel_case, to_camel_case};
|
||||
|
||||
#[test]
|
||||
fn camel_case() {
|
||||
assert!(!is_camel_case("userData"));
|
||||
assert_eq!(to_camel_case("userData"), "UserData");
|
||||
|
||||
assert!(is_camel_case("X86_64"));
|
||||
|
||||
assert!(!is_camel_case("X86__64"));
|
||||
assert_eq!(to_camel_case("X86__64"), "X86_64");
|
||||
|
||||
assert!(!is_camel_case("Abc_123"));
|
||||
assert_eq!(to_camel_case("Abc_123"), "Abc123");
|
||||
|
||||
assert!(!is_camel_case("A1_b2_c3"));
|
||||
assert_eq!(to_camel_case("A1_b2_c3"), "A1B2C3");
|
||||
|
||||
assert!(!is_camel_case("ONE_TWO_THREE"));
|
||||
assert_eq!(to_camel_case("ONE_TWO_THREE"), "OneTwoThree");
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ mod warn {
|
||||
|
||||
fn CamelCase() {} //~ WARN should have a snake
|
||||
|
||||
struct snake_case; //~ WARN should have a camel
|
||||
struct snake_case; //~ WARN should have an upper camel
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
warning: type `snake_case` should have a camel case name
|
||||
warning: type `snake_case` should have an upper camel case name
|
||||
--> $DIR/lint-group-nonstandard-style.rs:22:16
|
||||
|
|
||||
LL | struct snake_case; //~ WARN should have a camel
|
||||
| ^^^^^^^^^^ help: convert the identifier to camel case: `SnakeCase`
|
||||
LL | struct snake_case; //~ WARN should have an upper camel
|
||||
| ^^^^^^^^^^ help: convert the identifier to upper camel case: `SnakeCase`
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/lint-group-nonstandard-style.rs:18:17
|
||||
|
@ -2,43 +2,35 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
struct ONE_TWO_THREE;
|
||||
//~^ ERROR type `ONE_TWO_THREE` should have a camel case name
|
||||
//~^ ERROR type `ONE_TWO_THREE` should have an upper camel case name
|
||||
|
||||
struct foo { //~ ERROR type `foo` should have a camel case name
|
||||
struct foo { //~ ERROR type `foo` should have an upper camel case name
|
||||
bar: isize,
|
||||
}
|
||||
|
||||
enum foo2 { //~ ERROR type `foo2` should have a camel case name
|
||||
enum foo2 { //~ ERROR type `foo2` should have an upper camel case name
|
||||
Bar
|
||||
}
|
||||
|
||||
struct foo3 { //~ ERROR type `foo3` should have a camel case name
|
||||
struct foo3 { //~ ERROR type `foo3` should have an upper camel case name
|
||||
bar: isize
|
||||
}
|
||||
|
||||
type foo4 = isize; //~ ERROR type `foo4` should have a camel case name
|
||||
type foo4 = isize; //~ ERROR type `foo4` should have an upper camel case name
|
||||
|
||||
enum Foo5 {
|
||||
bar //~ ERROR variant `bar` should have a camel case name
|
||||
bar //~ ERROR variant `bar` should have an upper camel case name
|
||||
}
|
||||
|
||||
trait foo6 { //~ ERROR trait `foo6` should have a camel case name
|
||||
trait foo6 { //~ ERROR trait `foo6` should have an upper camel case name
|
||||
fn dummy(&self) { }
|
||||
}
|
||||
|
||||
fn f<ty>(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name
|
||||
fn f<ty>(_: ty) {} //~ ERROR type parameter `ty` should have an upper camel case name
|
||||
|
||||
#[repr(C)]
|
||||
struct foo7 {
|
||||
bar: isize,
|
||||
}
|
||||
|
||||
struct X86_64;
|
||||
|
||||
struct X86__64; //~ ERROR type `X86__64` should have a camel case name
|
||||
|
||||
struct Abc_123; //~ ERROR type `Abc_123` should have a camel case name
|
||||
|
||||
struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have a camel case name
|
||||
|
||||
fn main() { }
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: type `ONE_TWO_THREE` should have a camel case name
|
||||
error: type `ONE_TWO_THREE` should have an upper camel case name
|
||||
--> $DIR/lint-non-camel-case-types.rs:4:8
|
||||
|
|
||||
LL | struct ONE_TWO_THREE;
|
||||
| ^^^^^^^^^^^^^ help: convert the identifier to camel case: `OneTwoThree`
|
||||
| ^^^^^^^^^^^^^ help: convert the identifier to upper camel case: `OneTwoThree`
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/lint-non-camel-case-types.rs:1:11
|
||||
@ -10,65 +10,47 @@ note: lint level defined here
|
||||
LL | #![forbid(non_camel_case_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: type `foo` should have a camel case name
|
||||
error: type `foo` should have an upper camel case name
|
||||
--> $DIR/lint-non-camel-case-types.rs:7:8
|
||||
|
|
||||
LL | struct foo { //~ ERROR type `foo` should have a camel case name
|
||||
| ^^^ help: convert the identifier to camel case: `Foo`
|
||||
LL | struct foo { //~ ERROR type `foo` should have an upper camel case name
|
||||
| ^^^ help: convert the identifier to upper camel case: `Foo`
|
||||
|
||||
error: type `foo2` should have a camel case name
|
||||
error: type `foo2` should have an upper camel case name
|
||||
--> $DIR/lint-non-camel-case-types.rs:11:6
|
||||
|
|
||||
LL | enum foo2 { //~ ERROR type `foo2` should have a camel case name
|
||||
| ^^^^ help: convert the identifier to camel case: `Foo2`
|
||||
LL | enum foo2 { //~ ERROR type `foo2` should have an upper camel case name
|
||||
| ^^^^ help: convert the identifier to upper camel case: `Foo2`
|
||||
|
||||
error: type `foo3` should have a camel case name
|
||||
error: type `foo3` should have an upper camel case name
|
||||
--> $DIR/lint-non-camel-case-types.rs:15:8
|
||||
|
|
||||
LL | struct foo3 { //~ ERROR type `foo3` should have a camel case name
|
||||
| ^^^^ help: convert the identifier to camel case: `Foo3`
|
||||
LL | struct foo3 { //~ ERROR type `foo3` should have an upper camel case name
|
||||
| ^^^^ help: convert the identifier to upper camel case: `Foo3`
|
||||
|
||||
error: type `foo4` should have a camel case name
|
||||
error: type `foo4` should have an upper camel case name
|
||||
--> $DIR/lint-non-camel-case-types.rs:19:6
|
||||
|
|
||||
LL | type foo4 = isize; //~ ERROR type `foo4` should have a camel case name
|
||||
| ^^^^ help: convert the identifier to camel case: `Foo4`
|
||||
LL | type foo4 = isize; //~ ERROR type `foo4` should have an upper camel case name
|
||||
| ^^^^ help: convert the identifier to upper camel case: `Foo4`
|
||||
|
||||
error: variant `bar` should have a camel case name
|
||||
error: variant `bar` should have an upper camel case name
|
||||
--> $DIR/lint-non-camel-case-types.rs:22:5
|
||||
|
|
||||
LL | bar //~ ERROR variant `bar` should have a camel case name
|
||||
| ^^^ help: convert the identifier to camel case: `Bar`
|
||||
LL | bar //~ ERROR variant `bar` should have an upper camel case name
|
||||
| ^^^ help: convert the identifier to upper camel case: `Bar`
|
||||
|
||||
error: trait `foo6` should have a camel case name
|
||||
error: trait `foo6` should have an upper camel case name
|
||||
--> $DIR/lint-non-camel-case-types.rs:25:7
|
||||
|
|
||||
LL | trait foo6 { //~ ERROR trait `foo6` should have a camel case name
|
||||
| ^^^^ help: convert the identifier to camel case: `Foo6`
|
||||
LL | trait foo6 { //~ ERROR trait `foo6` should have an upper camel case name
|
||||
| ^^^^ help: convert the identifier to upper camel case: `Foo6`
|
||||
|
||||
error: type parameter `ty` should have a camel case name
|
||||
error: type parameter `ty` should have an upper camel case name
|
||||
--> $DIR/lint-non-camel-case-types.rs:29:6
|
||||
|
|
||||
LL | fn f<ty>(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name
|
||||
| ^^ help: convert the identifier to camel case: `Ty`
|
||||
LL | fn f<ty>(_: ty) {} //~ ERROR type parameter `ty` should have an upper camel case name
|
||||
| ^^ help: convert the identifier to upper camel case: `Ty`
|
||||
|
||||
error: type `X86__64` should have a camel case name
|
||||
--> $DIR/lint-non-camel-case-types.rs:38:8
|
||||
|
|
||||
LL | struct X86__64; //~ ERROR type `X86__64` should have a camel case name
|
||||
| ^^^^^^^ help: convert the identifier to camel case: `X86_64`
|
||||
|
||||
error: type `Abc_123` should have a camel case name
|
||||
--> $DIR/lint-non-camel-case-types.rs:40:8
|
||||
|
|
||||
LL | struct Abc_123; //~ ERROR type `Abc_123` should have a camel case name
|
||||
| ^^^^^^^ help: convert the identifier to camel case: `Abc123`
|
||||
|
||||
error: type `A1_b2_c3` should have a camel case name
|
||||
--> $DIR/lint-non-camel-case-types.rs:42:8
|
||||
|
|
||||
LL | struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have a camel case name
|
||||
| ^^^^^^^^ help: convert the identifier to camel case: `A1B2C3`
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
//
|
||||
|
||||
fn foo<
|
||||
'β, //~ ERROR non-ascii idents are not fully supported
|
||||
γ //~ ERROR non-ascii idents are not fully supported
|
||||
//~^ WARN type parameter `γ` should have a camel case name
|
||||
//~^ WARN type parameter `γ` should have an upper camel case name
|
||||
>() {}
|
||||
|
||||
struct X {
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
|
||||
--> $DIR/utf8_idents.rs:4:5
|
||||
--> $DIR/utf8_idents.rs:2:5
|
||||
|
|
||||
LL | 'β, //~ ERROR non-ascii idents are not fully supported
|
||||
| ^^
|
||||
@ -7,7 +7,7 @@ LL | 'β, //~ ERROR non-ascii idents are not fully supported
|
||||
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
|
||||
|
||||
error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
|
||||
--> $DIR/utf8_idents.rs:5:5
|
||||
--> $DIR/utf8_idents.rs:3:5
|
||||
|
|
||||
LL | γ //~ ERROR non-ascii idents are not fully supported
|
||||
| ^
|
||||
@ -15,7 +15,7 @@ LL | γ //~ ERROR non-ascii idents are not fully supported
|
||||
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
|
||||
|
||||
error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
|
||||
--> $DIR/utf8_idents.rs:10:5
|
||||
--> $DIR/utf8_idents.rs:8:5
|
||||
|
|
||||
LL | δ: usize //~ ERROR non-ascii idents are not fully supported
|
||||
| ^
|
||||
@ -23,18 +23,18 @@ LL | δ: usize //~ ERROR non-ascii idents are not fully supported
|
||||
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
|
||||
|
||||
error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
|
||||
--> $DIR/utf8_idents.rs:14:9
|
||||
--> $DIR/utf8_idents.rs:12:9
|
||||
|
|
||||
LL | let α = 0.00001f64; //~ ERROR non-ascii idents are not fully supported
|
||||
| ^
|
||||
|
|
||||
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
|
||||
|
||||
warning: type parameter `γ` should have a camel case name
|
||||
--> $DIR/utf8_idents.rs:5:5
|
||||
warning: type parameter `γ` should have an upper camel case name
|
||||
--> $DIR/utf8_idents.rs:3:5
|
||||
|
|
||||
LL | γ //~ ERROR non-ascii idents are not fully supported
|
||||
| ^ help: convert the identifier to camel case: `Γ`
|
||||
| ^ help: convert the identifier to upper camel case: `Γ`
|
||||
|
|
||||
= note: #[warn(non_camel_case_types)] on by default
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user