hir_ty/diagnostics/decl_check/
case_conv.rspub(crate) fn to_camel_case(ident: &str) -> Option<String> {
if is_camel_case(ident) {
return None;
}
Some(stdx::to_camel_case(ident))
}
pub(crate) fn to_lower_snake_case(ident: &str) -> Option<String> {
if is_lower_snake_case(ident) {
return None;
} else if is_upper_snake_case(ident) {
return Some(ident.to_lowercase());
}
Some(stdx::to_lower_snake_case(ident))
}
pub(crate) fn to_upper_snake_case(ident: &str) -> Option<String> {
if is_upper_snake_case(ident) {
return None;
} else if is_lower_snake_case(ident) {
return Some(ident.to_uppercase());
}
Some(stdx::to_upper_snake_case(ident))
}
fn is_camel_case(name: &str) -> bool {
let name = name.trim_matches('_');
if name.is_empty() {
return true;
}
let mut fst = None;
name.chars().next().map_or(true, |c| !c.is_lowercase())
&& !name.contains("__")
&& !name.chars().any(|snd| {
let ret = match fst {
None => false,
Some(fst) => {
stdx::char_has_case(fst) && snd == '_' || stdx::char_has_case(snd) && fst == '_'
}
};
fst = Some(snd);
ret
})
}
fn is_lower_snake_case(ident: &str) -> bool {
is_snake_case(ident, char::is_uppercase)
}
fn is_upper_snake_case(ident: &str) -> bool {
is_snake_case(ident, char::is_lowercase)
}
fn is_snake_case<F: Fn(char) -> bool>(ident: &str, wrong_case: F) -> bool {
if ident.is_empty() {
return true;
}
let ident = ident.trim_matches('_');
let mut allow_underscore = true;
ident.chars().all(|c| {
allow_underscore = match c {
'_' if !allow_underscore => return false,
'_' => false,
c if !wrong_case(c) => true,
_ => return false,
};
true
})
}
#[cfg(test)]
mod tests {
use super::*;
use expect_test::{expect, Expect};
fn check<F: Fn(&str) -> Option<String>>(fun: F, input: &str, expect: Expect) {
let output = fun(input).unwrap_or_default();
expect.assert_eq(&output);
}
#[test]
fn test_to_lower_snake_case() {
check(to_lower_snake_case, "lower_snake_case", expect![[""]]);
check(to_lower_snake_case, "UPPER_SNAKE_CASE", expect![["upper_snake_case"]]);
check(to_lower_snake_case, "Weird_Case", expect![["weird_case"]]);
check(to_lower_snake_case, "UpperCamelCase", expect![["upper_camel_case"]]);
check(to_lower_snake_case, "lowerCamelCase", expect![["lower_camel_case"]]);
check(to_lower_snake_case, "a", expect![[""]]);
check(to_lower_snake_case, "abc", expect![[""]]);
check(to_lower_snake_case, "foo__bar", expect![["foo_bar"]]);
check(to_lower_snake_case, "Δ", expect!["δ"]);
}
#[test]
fn test_to_camel_case() {
check(to_camel_case, "UpperCamelCase", expect![[""]]);
check(to_camel_case, "UpperCamelCase_", expect![[""]]);
check(to_camel_case, "_CamelCase", expect![[""]]);
check(to_camel_case, "lowerCamelCase", expect![["LowerCamelCase"]]);
check(to_camel_case, "lower_snake_case", expect![["LowerSnakeCase"]]);
check(to_camel_case, "UPPER_SNAKE_CASE", expect![["UpperSnakeCase"]]);
check(to_camel_case, "Weird_Case", expect![["WeirdCase"]]);
check(to_camel_case, "name", expect![["Name"]]);
check(to_camel_case, "A", expect![[""]]);
check(to_camel_case, "AABB", expect![[""]]);
check(to_camel_case, "X86_64", expect![[""]]);
check(to_camel_case, "x86__64", expect![["X86_64"]]);
check(to_camel_case, "Abc_123", expect![["Abc123"]]);
check(to_camel_case, "A1_b2_c3", expect![["A1B2C3"]]);
}
#[test]
fn test_to_upper_snake_case() {
check(to_upper_snake_case, "UPPER_SNAKE_CASE", expect![[""]]);
check(to_upper_snake_case, "lower_snake_case", expect![["LOWER_SNAKE_CASE"]]);
check(to_upper_snake_case, "Weird_Case", expect![["WEIRD_CASE"]]);
check(to_upper_snake_case, "UpperCamelCase", expect![["UPPER_CAMEL_CASE"]]);
check(to_upper_snake_case, "lowerCamelCase", expect![["LOWER_CAMEL_CASE"]]);
check(to_upper_snake_case, "A", expect![[""]]);
check(to_upper_snake_case, "ABC", expect![[""]]);
check(to_upper_snake_case, "X86_64", expect![[""]]);
check(to_upper_snake_case, "FOO_BAr", expect![["FOO_BAR"]]);
check(to_upper_snake_case, "FOO__BAR", expect![["FOO_BAR"]]);
check(to_upper_snake_case, "ß", expect!["SS"]);
}
}