hir_ty/diagnostics/decl_check/
case_conv.rs1pub(crate) fn to_camel_case(ident: &str) -> Option<String> {
10 if is_camel_case(ident) {
11 return None;
12 }
13
14 Some(stdx::to_camel_case(ident))
15}
16
17pub(crate) fn to_lower_snake_case(ident: &str) -> Option<String> {
20 if is_lower_snake_case(ident) {
21 return None;
22 } else if is_upper_snake_case(ident) {
23 return Some(ident.to_lowercase());
24 }
25
26 Some(stdx::to_lower_snake_case(ident))
27}
28
29pub(crate) fn to_upper_snake_case(ident: &str) -> Option<String> {
32 if is_upper_snake_case(ident) {
33 return None;
34 } else if is_lower_snake_case(ident) {
35 return Some(ident.to_uppercase());
36 }
37
38 Some(stdx::to_upper_snake_case(ident))
39}
40
41fn is_camel_case(name: &str) -> bool {
44 let name = name.trim_matches('_');
45 if name.is_empty() {
46 return true;
47 }
48
49 let mut fst = None;
50 name.chars().next().is_none_or(|c| !c.is_lowercase())
53 && !name.contains("__")
54 && !name.chars().any(|snd| {
55 let ret = match fst {
56 None => false,
57 Some(fst) => {
58 stdx::char_has_case(fst) && snd == '_' || stdx::char_has_case(snd) && fst == '_'
59 }
60 };
61 fst = Some(snd);
62
63 ret
64 })
65}
66
67fn is_lower_snake_case(ident: &str) -> bool {
68 is_snake_case(ident, char::is_uppercase)
69}
70
71fn is_upper_snake_case(ident: &str) -> bool {
72 is_snake_case(ident, char::is_lowercase)
73}
74
75fn is_snake_case<F: Fn(char) -> bool>(ident: &str, wrong_case: F) -> bool {
78 if ident.is_empty() {
79 return true;
80 }
81 let ident = ident.trim_matches('_');
82
83 let mut allow_underscore = true;
84 ident.chars().all(|c| {
85 allow_underscore = match c {
86 '_' if !allow_underscore => return false,
87 '_' => false,
88 c if !wrong_case(c) => true,
91 _ => return false,
92 };
93 true
94 })
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100 use expect_test::{Expect, expect};
101
102 fn check<F: Fn(&str) -> Option<String>>(fun: F, input: &str, expect: Expect) {
103 let output = fun(input).unwrap_or_default();
105
106 expect.assert_eq(&output);
107 }
108
109 #[test]
110 fn test_to_lower_snake_case() {
111 check(to_lower_snake_case, "lower_snake_case", expect![[""]]);
112 check(to_lower_snake_case, "UPPER_SNAKE_CASE", expect![["upper_snake_case"]]);
113 check(to_lower_snake_case, "Weird_Case", expect![["weird_case"]]);
114 check(to_lower_snake_case, "UpperCamelCase", expect![["upper_camel_case"]]);
115 check(to_lower_snake_case, "lowerCamelCase", expect![["lower_camel_case"]]);
116 check(to_lower_snake_case, "a", expect![[""]]);
117 check(to_lower_snake_case, "abc", expect![[""]]);
118 check(to_lower_snake_case, "foo__bar", expect![["foo_bar"]]);
119 check(to_lower_snake_case, "Δ", expect!["δ"]);
120 }
121
122 #[test]
123 fn test_to_camel_case() {
124 check(to_camel_case, "UpperCamelCase", expect![[""]]);
125 check(to_camel_case, "UpperCamelCase_", expect![[""]]);
126 check(to_camel_case, "_CamelCase", expect![[""]]);
127 check(to_camel_case, "lowerCamelCase", expect![["LowerCamelCase"]]);
128 check(to_camel_case, "lower_snake_case", expect![["LowerSnakeCase"]]);
129 check(to_camel_case, "UPPER_SNAKE_CASE", expect![["UpperSnakeCase"]]);
130 check(to_camel_case, "Weird_Case", expect![["WeirdCase"]]);
131 check(to_camel_case, "name", expect![["Name"]]);
132 check(to_camel_case, "A", expect![[""]]);
133 check(to_camel_case, "AABB", expect![[""]]);
134 check(to_camel_case, "X86_64", expect![[""]]);
136 check(to_camel_case, "x86__64", expect![["X86_64"]]);
137 check(to_camel_case, "Abc_123", expect![["Abc123"]]);
138 check(to_camel_case, "A1_b2_c3", expect![["A1B2C3"]]);
139 }
140
141 #[test]
142 fn test_to_upper_snake_case() {
143 check(to_upper_snake_case, "UPPER_SNAKE_CASE", expect![[""]]);
144 check(to_upper_snake_case, "lower_snake_case", expect![["LOWER_SNAKE_CASE"]]);
145 check(to_upper_snake_case, "Weird_Case", expect![["WEIRD_CASE"]]);
146 check(to_upper_snake_case, "UpperCamelCase", expect![["UPPER_CAMEL_CASE"]]);
147 check(to_upper_snake_case, "lowerCamelCase", expect![["LOWER_CAMEL_CASE"]]);
148 check(to_upper_snake_case, "A", expect![[""]]);
149 check(to_upper_snake_case, "ABC", expect![[""]]);
150 check(to_upper_snake_case, "X86_64", expect![[""]]);
151 check(to_upper_snake_case, "FOO_BAr", expect![["FOO_BAR"]]);
152 check(to_upper_snake_case, "FOO__BAR", expect![["FOO_BAR"]]);
153 check(to_upper_snake_case, "ß", expect!["SS"]);
154 }
155}