about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-01-30 12:03:34 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-01-30 12:03:34 -0800
commit6ea5fb8a6d3131931dd70d45dc4d4f0b1e26cd01 (patch)
treef01f397c5b39e7169146fa8ab3b920f29c946619
parent62a8462ba48060d9c51765c3ac3f26b03d4fe1ae (diff)
parent39a8c23c0b2aab6fba24a2facc2a565d6b9faa1f (diff)
downloadrust-6ea5fb8a6d3131931dd70d45dc4d4f0b1e26cd01.tar.gz
rust-6ea5fb8a6d3131931dd70d45dc4d4f0b1e26cd01.zip
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.
-rw-r--r--src/librustc/lint/builtin.rs113
-rw-r--r--src/test/compile-fail/issue-17718-const-naming.rs2
-rw-r--r--src/test/compile-fail/lint-group-style.rs2
-rw-r--r--src/test/compile-fail/lint-non-uppercase-statics.rs2
-rw-r--r--src/test/compile-fail/match-static-const-lc.rs6
-rw-r--r--src/test/run-pass/snake-case-no-lowercase-equivalent.rs17
6 files changed, 90 insertions, 52 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 2248562352d..98b6d4bd88e 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -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);
             }
             _ => {}
         }
diff --git a/src/test/compile-fail/issue-17718-const-naming.rs b/src/test/compile-fail/issue-17718-const-naming.rs
index 15f66493f88..06719e2756b 100644
--- a/src/test/compile-fail/issue-17718-const-naming.rs
+++ b/src/test/compile-fail/issue-17718-const-naming.rs
@@ -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() {}
diff --git a/src/test/compile-fail/lint-group-style.rs b/src/test/compile-fail/lint-group-style.rs
index 24d16bcaafc..59ab5be1572 100644
--- a/src/test/compile-fail/lint-group-style.rs
+++ b/src/test/compile-fail/lint-group-style.rs
@@ -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 {
diff --git a/src/test/compile-fail/lint-non-uppercase-statics.rs b/src/test/compile-fail/lint-non-uppercase-statics.rs
index 10475f967d7..e1fbc73bbed 100644
--- a/src/test/compile-fail/lint-non-uppercase-statics.rs
+++ b/src/test/compile-fail/lint-non-uppercase-statics.rs
@@ -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() { }
diff --git a/src/test/compile-fail/match-static-const-lc.rs b/src/test/compile-fail/match-static-const-lc.rs
index 345c4aa69a7..04b234d8db7 100644
--- a/src/test/compile-fail/match-static-const-lc.rs
+++ b/src/test/compile-fail/match-static-const-lc.rs
@@ -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);
diff --git a/src/test/run-pass/snake-case-no-lowercase-equivalent.rs b/src/test/run-pass/snake-case-no-lowercase-equivalent.rs
new file mode 100644
index 00000000000..2220761a026
--- /dev/null
+++ b/src/test/run-pass/snake-case-no-lowercase-equivalent.rs
@@ -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() {}