Skip to content

Commit 1773c6d

Browse files
committed
Extract helper functions into a separate module
1 parent f5cea35 commit 1773c6d

File tree

2 files changed

+112
-29
lines changed

2 files changed

+112
-29
lines changed

crates/hir_ty/src/diagnostics/decl_check.rs

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
// If you see these lines in the pull request, feel free to call me stupid :P.
1010
#![allow(dead_code, unused_imports, unused_variables)]
1111

12+
mod str_helpers;
13+
1214
use std::sync::Arc;
1315

1416
use hir_def::{
@@ -18,7 +20,7 @@ use hir_def::{
1820
item_tree::ItemTreeNode,
1921
resolver::{resolver_for_expr, ResolveValueResult, ValueNs},
2022
src::HasSource,
21-
AdtId, FunctionId, Lookup, ModuleDefId,
23+
AdtId, EnumId, FunctionId, Lookup, ModuleDefId, StructId,
2224
};
2325
use hir_expand::{diagnostics::DiagnosticSink, name::Name};
2426
use syntax::{
@@ -28,7 +30,7 @@ use syntax::{
2830

2931
use crate::{
3032
db::HirDatabase,
31-
diagnostics::{CaseType, IncorrectCase},
33+
diagnostics::{decl_check::str_helpers::*, CaseType, IncorrectCase},
3234
lower::CallableDefId,
3335
ApplicationTy, InferenceResult, Ty, TypeCtor,
3436
};
@@ -191,41 +193,30 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
191193
}
192194
}
193195

194-
fn validate_adt(&mut self, db: &dyn HirDatabase, adt: AdtId) {}
195-
}
196-
197-
fn pat_equals_to_name(pat: Option<ast::Pat>, name: &Name) -> bool {
198-
if let Some(ast::Pat::IdentPat(ident)) = pat {
199-
ident.to_string() == name.to_string()
200-
} else {
201-
false
196+
fn validate_adt(&mut self, db: &dyn HirDatabase, adt: AdtId) {
197+
match adt {
198+
AdtId::StructId(struct_id) => self.validate_struct(db, struct_id),
199+
AdtId::EnumId(enum_id) => self.validate_enum(db, enum_id),
200+
AdtId::UnionId(_) => {
201+
// Unions aren't yet supported by this validator.
202+
}
203+
}
202204
}
203-
}
204205

205-
fn to_lower_snake_case(ident: &str) -> Option<String> {
206-
// First, assume that it's UPPER_SNAKE_CASE.
207-
if let Some(normalized) = to_lower_snake_case_from_upper_snake_case(ident) {
208-
return Some(normalized);
206+
fn validate_struct(&mut self, db: &dyn HirDatabase, struct_id: StructId) {
207+
let data = db.struct_data(struct_id);
209208
}
210209

211-
// Otherwise, assume that it's CamelCase.
212-
let lower_snake_case = stdx::to_lower_snake_case(ident);
213-
214-
if lower_snake_case == ident {
215-
None
216-
} else {
217-
Some(lower_snake_case)
210+
fn validate_enum(&mut self, db: &dyn HirDatabase, enum_id: EnumId) {
211+
let data = db.enum_data(enum_id);
218212
}
219213
}
220214

221-
fn to_lower_snake_case_from_upper_snake_case(ident: &str) -> Option<String> {
222-
let is_upper_snake_case = ident.chars().all(|c| c.is_ascii_uppercase() || c == '_');
223-
224-
if is_upper_snake_case {
225-
let string = ident.chars().map(|c| c.to_ascii_lowercase()).collect();
226-
Some(string)
215+
fn pat_equals_to_name(pat: Option<ast::Pat>, name: &Name) -> bool {
216+
if let Some(ast::Pat::IdentPat(ident)) = pat {
217+
ident.to_string() == name.to_string()
227218
} else {
228-
None
219+
false
229220
}
230221
}
231222

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

0 commit comments

Comments
 (0)