about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndy Russell <arussell123@gmail.com>2019-02-12 12:35:38 -0500
committerAndy Russell <arussell123@gmail.com>2019-02-13 13:41:32 -0500
commit2f95299f6bf87a7b23381cda954570e72c80c159 (patch)
treef5857f770f16e280e59802a03802aa407c7704e1
parent57d7cfc3cf50f0c427ad3043ff09eaef20671320 (diff)
downloadrust-2f95299f6bf87a7b23381cda954570e72c80c159.tar.gz
rust-2f95299f6bf87a7b23381cda954570e72c80c159.zip
specify "upper camel case" in style lint
Also, fix an issue where internal upper case letters were converted to
lower case.
-rw-r--r--src/librustc_lint/Cargo.toml1
-rw-r--r--src/librustc_lint/nonstandard_style.rs148
-rw-r--r--src/test/ui/lint/lint-group-nonstandard-style.rs2
-rw-r--r--src/test/ui/lint/lint-group-nonstandard-style.stderr6
-rw-r--r--src/test/ui/lint/lint-non-camel-case-types.rs24
-rw-r--r--src/test/ui/lint/lint-non-camel-case-types.stderr66
-rw-r--r--src/test/ui/utf8_idents.rs4
-rw-r--r--src/test/ui/utf8_idents.stderr14
8 files changed, 139 insertions, 126 deletions
diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml
index 82f7118df2d..fd2b635faef 100644
--- a/src/librustc_lint/Cargo.toml
+++ b/src/librustc_lint/Cargo.toml
@@ -8,7 +8,6 @@ edition = "2018"
 name = "rustc_lint"
 path = "lib.rs"
 crate-type = ["dylib"]
-test = false
 
 [dependencies]
 log = "0.4"
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
index 2dbafc7ede2..c2dd9a3d1b8 100644
--- a/src/librustc_lint/nonstandard_style.rs
+++ b/src/librustc_lint/nonstandard_style.rs
@@ -38,66 +38,87 @@ declare_lint! {
     "types, variants, traits and type parameters should have camel case names"
 }
 
-#[derive(Copy, Clone)]
-pub struct NonCamelCaseTypes;
+fn char_has_case(c: char) -> bool {
+    c.is_lowercase() || c.is_uppercase()
+}
 
-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;
+    }
 
-        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;
             }
 
-            // 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] == '_'
-                })
-        }
+            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
+}
 
-        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
-        }
+#[derive(Copy, Clone)]
+pub struct NonCamelCaseTypes;
 
+impl NonCamelCaseTypes {
+    fn check_case(&self, cx: &EarlyContext<'_>, sort: &str, ident: &Ident) {
         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 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
         }
     }
 }
+
+#[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");
+    }
+}
diff --git a/src/test/ui/lint/lint-group-nonstandard-style.rs b/src/test/ui/lint/lint-group-nonstandard-style.rs
index 0386daaa59b..bd7f327bc0f 100644
--- a/src/test/ui/lint/lint-group-nonstandard-style.rs
+++ b/src/test/ui/lint/lint-group-nonstandard-style.rs
@@ -19,7 +19,7 @@ mod test {
 
         fn CamelCase() {} //~ WARN should have a snake
 
-        struct snake_case; //~ WARN should have a camel
+        struct snake_case; //~ WARN should have an upper camel
     }
 }
 
diff --git a/src/test/ui/lint/lint-group-nonstandard-style.stderr b/src/test/ui/lint/lint-group-nonstandard-style.stderr
index f3c7d70054b..ab36cda57ec 100644
--- a/src/test/ui/lint/lint-group-nonstandard-style.stderr
+++ b/src/test/ui/lint/lint-group-nonstandard-style.stderr
@@ -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
diff --git a/src/test/ui/lint/lint-non-camel-case-types.rs b/src/test/ui/lint/lint-non-camel-case-types.rs
index bca1992605b..d3b119a9441 100644
--- a/src/test/ui/lint/lint-non-camel-case-types.rs
+++ b/src/test/ui/lint/lint-non-camel-case-types.rs
@@ -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() { }
diff --git a/src/test/ui/lint/lint-non-camel-case-types.stderr b/src/test/ui/lint/lint-non-camel-case-types.stderr
index 74f9a5993b8..7afacf64d87 100644
--- a/src/test/ui/lint/lint-non-camel-case-types.stderr
+++ b/src/test/ui/lint/lint-non-camel-case-types.stderr
@@ -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
 
diff --git a/src/test/ui/utf8_idents.rs b/src/test/ui/utf8_idents.rs
index e601c6e4555..f59d5502aae 100644
--- a/src/test/ui/utf8_idents.rs
+++ b/src/test/ui/utf8_idents.rs
@@ -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 {
diff --git a/src/test/ui/utf8_idents.stderr b/src/test/ui/utf8_idents.stderr
index 268dd99d060..52fb607af5b 100644
--- a/src/test/ui/utf8_idents.stderr
+++ b/src/test/ui/utf8_idents.stderr
@@ -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