diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index 494bbfa297e..ac0bf9f4a99 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -53,6 +53,10 @@ pub struct NonCamelCaseTypes; impl NonCamelCaseTypes { fn check_case(&self, cx: &LateContext, sort: &str, name: ast::Name, span: Span) { + fn char_has_case(c: char) -> bool { + c.is_lowercase() || c.is_uppercase() + } + fn is_camel_case(name: ast::Name) -> bool { let name = name.as_str(); if name.is_empty() { @@ -62,20 +66,38 @@ impl NonCamelCaseTypes { // 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.is_empty() && !name.chars().next().unwrap().is_lowercase() && + !name.contains("__") && !name.chars().collect::>().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.split('_') - .flat_map(|word| { + s.trim_matches('_') + .split('_') + .map(|word| { word.chars().enumerate().map(|(i, c)| if i == 0 { c.to_uppercase().collect::() } else { c.to_lowercase().collect() }) + .collect::>() + .concat() }) + .filter(|x| !x.is_empty()) .collect::>() - .concat() + .iter().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 } if !is_camel_case(name) { diff --git a/src/test/compile-fail/lint-non-camel-case-types.rs b/src/test/compile-fail/lint-non-camel-case-types.rs index f6d3d62d0bf..5dcdf3a863f 100644 --- a/src/test/compile-fail/lint-non-camel-case-types.rs +++ b/src/test/compile-fail/lint-non-camel-case-types.rs @@ -45,4 +45,12 @@ struct foo7 { type __ = isize; //~ ERROR type `__` should have a camel case name such as `CamelCase` +struct X86_64; + +struct X86__64; //~ ERROR type `X86__64` should have a camel case name such as `X86_64` + +struct Abc_123; //~ ERROR type `Abc_123` should have a camel case name such as `Abc123` + +struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have a camel case name such as `A1B2C3` + fn main() { }