]> git.lizzy.rs Git - rust.git/commitdiff
Make the naming lints only warn on names with upper/lowercase equivalents
authorP1start <rewi-github@whanau.org>
Sat, 6 Dec 2014 00:17:30 +0000 (13:17 +1300)
committerP1start <rewi-github@whanau.org>
Fri, 30 Jan 2015 01:18:04 +0000 (14:18 +1300)
Closes #21735.

src/librustc/lint/builtin.rs
src/test/compile-fail/issue-17718-const-naming.rs
src/test/compile-fail/lint-group-style.rs
src/test/compile-fail/lint-non-uppercase-statics.rs
src/test/compile-fail/match-static-const-lc.rs
src/test/run-pass/snake-case-no-lowercase-equivalent.rs [new file with mode: 0644]

index f13814527cdfd3a6ddb58b691839c85753a34814..74a389d353c9740154ad8a6d0541059c5d76153d 100644 (file)
@@ -937,6 +937,34 @@ fn method_context(cx: &Context, m: &ast::Method) -> MethodContext {
 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 @@ fn is_snake_case(ident: ast::Ident) -> bool {
             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 @@ fn check_struct_def(&mut self, cx: &Context, s: &ast::StructDef,
 #[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 @@ fn get_lints(&self) -> LintArray {
     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 @@ fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
         // 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);
             }
             _ => {}
         }
index 15f66493f88429a5745e7ab6bd17f9dbb3dc3f0d..06719e2756b19f07fc142c5a9720eb90534c4a25 100644 (file)
@@ -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() {}
index 24d16bcaafc1a49f91a9feeb59c9578e25a2de2a..59ab5be1572a3d43d7bbe74e1aeb3cd367f430f8 100644 (file)
@@ -24,7 +24,7 @@ fn CamelCase() {}
     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 {
index 10475f967d716ca3256e33af4bd1d11e137b0f4b..e1fbc73bbed15ad420d8a21e79ef66ee622e24a4 100644 (file)
@@ -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() { }
index 345c4aa69a720279ca1a72cb656c1fcf765ecd14..04b234d8db7f1fa2ed2eedf6e130c1d067e8beb1 100644 (file)
@@ -19,7 +19,7 @@
 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 (file)
index 0000000..2220761
--- /dev/null
@@ -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() {}