diff options
author | Igor Aleksanov <[email protected]> | 2020-10-03 12:35:26 +0100 |
---|---|---|
committer | Igor Aleksanov <[email protected]> | 2020-10-12 08:59:54 +0100 |
commit | 1773c6d154abe5da00b31bb16139addcaa443bbb (patch) | |
tree | 1b6f0c6b6a031bcc74d3a46004553fcdaf6d0d16 /crates/hir_ty/src/diagnostics/decl_check | |
parent | f5cea35986a0c8182ca427f10e20bc97ec564315 (diff) |
Extract helper functions into a separate module
Diffstat (limited to 'crates/hir_ty/src/diagnostics/decl_check')
-rw-r--r-- | crates/hir_ty/src/diagnostics/decl_check/str_helpers.rs | 92 |
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 @@ | |||
1 | pub 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 | |||
33 | pub 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 | |||
49 | fn 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 | |||
58 | fn is_upper_snake_case(ident: &str) -> bool { | ||
59 | ident.chars().all(|c| c.is_ascii_uppercase() || c == '_') | ||
60 | } | ||
61 | |||
62 | fn 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)] | ||
68 | mod 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 | } | ||