mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-11 23:33:00 +00:00
Auto merge of #46907 - varkor:contrib-8, r=nagisa
Allow non-alphabetic underscores in camel case Certain identifiers, such as `X86_64`, cannot currently be unambiguously represented in camel case (`X8664`, `X86_64`, `X8_664`, etc. are all transformed to the same identifier). This change relaxes the rules so that underscores are permitted between two non-alphabetic characters under `#[forbid(non_camel_case_types)]`. Fixes #34633 and fixes #41621.
This commit is contained in:
commit
8a11b8cdd7
@ -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::<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.split('_')
|
||||
.flat_map(|word| {
|
||||
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::<Vec<_>>()
|
||||
.concat()
|
||||
})
|
||||
.filter(|x| !x.is_empty())
|
||||
.collect::<Vec<_>>()
|
||||
.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) {
|
||||
|
@ -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() { }
|
||||
|
Loading…
Reference in New Issue
Block a user