aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/diagnostics/decl_check/str_helpers.rs
diff options
context:
space:
mode:
authorIgor Aleksanov <[email protected]>2020-10-03 12:35:26 +0100
committerIgor Aleksanov <[email protected]>2020-10-12 08:59:54 +0100
commit1773c6d154abe5da00b31bb16139addcaa443bbb (patch)
tree1b6f0c6b6a031bcc74d3a46004553fcdaf6d0d16 /crates/hir_ty/src/diagnostics/decl_check/str_helpers.rs
parentf5cea35986a0c8182ca427f10e20bc97ec564315 (diff)
Extract helper functions into a separate module
Diffstat (limited to 'crates/hir_ty/src/diagnostics/decl_check/str_helpers.rs')
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check/str_helpers.rs92
1 files changed, 92 insertions, 0 deletions
diff --git a/crates/hir_ty/src/diagnostics/decl_check/str_helpers.rs b/crates/hir_ty/src/diagnostics/decl_check/str_helpers.rs
new file mode 100644
index 000000000..3d8f1b5f2
--- /dev/null
+++ b/crates/hir_ty/src/diagnostics/decl_check/str_helpers.rs
@@ -0,0 +1,92 @@
1pub fn to_camel_case(ident: &str) -> Option<String> {
2 let mut output = String::new();
3
4 if is_camel_case(ident) {
5 return None;
6 }
7
8 let mut capital_added = false;
9 for chr in ident.chars() {
10 if chr.is_alphabetic() {
11 if !capital_added {
12 output.push(chr.to_ascii_uppercase());
13 capital_added = true;
14 } else {
15 output.push(chr.to_ascii_lowercase());
16 }
17 } else if chr == '_' {
18 // Skip this character and make the next one capital.
19 capital_added = false;
20 } else {
21 // Put the characted as-is.
22 output.push(chr);
23 }
24 }
25
26 if output == ident {
27 None
28 } else {
29 Some(output)
30 }
31}
32
33pub fn to_lower_snake_case(ident: &str) -> Option<String> {
34 // First, assume that it's UPPER_SNAKE_CASE.
35 if let Some(normalized) = to_lower_snake_case_from_upper_snake_case(ident) {
36 return Some(normalized);
37 }
38
39 // Otherwise, assume that it's CamelCase.
40 let lower_snake_case = stdx::to_lower_snake_case(ident);
41
42 if lower_snake_case == ident {
43 None
44 } else {
45 Some(lower_snake_case)
46 }
47}
48
49fn to_lower_snake_case_from_upper_snake_case(ident: &str) -> Option<String> {
50 if is_upper_snake_case(ident) {
51 let string = ident.chars().map(|c| c.to_ascii_lowercase()).collect();
52 Some(string)
53 } else {
54 None
55 }
56}
57
58fn is_upper_snake_case(ident: &str) -> bool {
59 ident.chars().all(|c| c.is_ascii_uppercase() || c == '_')
60}
61
62fn is_camel_case(ident: &str) -> bool {
63 // We assume that the string is either snake case or camel case.
64 ident.chars().all(|c| c != '_')
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70 use expect_test::{expect, Expect};
71
72 fn check<F: Fn(&str) -> Option<String>>(fun: F, input: &str, expect: Expect) {
73 // `None` is translated to empty string, meaning that there is nothing to fix.
74 let output = fun(input).unwrap_or_default();
75
76 expect.assert_eq(&output);
77 }
78
79 #[test]
80 fn test_to_lower_snake_case() {
81 check(to_lower_snake_case, "lower_snake_case", expect![[""]]);
82 check(to_lower_snake_case, "UPPER_SNAKE_CASE", expect![["upper_snake_case"]]);
83 check(to_lower_snake_case, "CamelCase", expect![["camel_case"]]);
84 }
85
86 #[test]
87 fn test_to_camel_case() {
88 check(to_camel_case, "CamelCase", expect![[""]]);
89 check(to_camel_case, "lower_snake_case", expect![["LowerSnakeCase"]]);
90 check(to_camel_case, "UPPER_SNAKE_CASE", expect![["UpperSnakeCase"]]);
91 }
92}