Skip to content

Commit 5191fb7

Browse files
bors[bot]Crauzer
andauthored
Merge #10480
10480: fix: Change `stdx::to_snake_case` to match rustc implementation r=Veykril a=Crauzer Fixes #10473 Co-authored-by: crauzer <[email protected]>
2 parents fd3f4c5 + ba62a8a commit 5191fb7

File tree

3 files changed

+40
-14
lines changed

3 files changed

+40
-14
lines changed

crates/hir_ty/src/diagnostics/decl_check/case_conv.rs

+3
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ mod tests {
161161
check(to_lower_snake_case, "lowerCamelCase", expect![["lower_camel_case"]]);
162162
check(to_lower_snake_case, "a", expect![[""]]);
163163
check(to_lower_snake_case, "abc", expect![[""]]);
164+
check(to_lower_snake_case, "foo__bar", expect![["foo_bar"]]);
164165
}
165166

166167
#[test]
@@ -192,5 +193,7 @@ mod tests {
192193
check(to_upper_snake_case, "A", expect![[""]]);
193194
check(to_upper_snake_case, "ABC", expect![[""]]);
194195
check(to_upper_snake_case, "X86_64", expect![[""]]);
196+
check(to_upper_snake_case, "FOO_BAr", expect![["FOO_BAR"]]);
197+
check(to_upper_snake_case, "FOO__BAR", expect![["FOO_BAR"]]);
195198
}
196199
}

crates/ide_diagnostics/src/handlers/incorrect_case.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ fn some_fn() {
102102
"#,
103103
r#"
104104
fn some_fn() {
105-
let what_a_weird_formatting = 10;
106-
another_func(what_a_weird_formatting);
105+
let what_aweird_formatting = 10;
106+
another_func(what_aweird_formatting);
107107
}
108108
"#,
109109
);

crates/stdx/src/lib.rs

+35-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! Missing batteries for standard libraries.
2+
use std::iter;
23
use std::{cmp::Ordering, ops, time::Instant};
34

45
mod macros;
@@ -37,22 +38,44 @@ pub fn to_lower_snake_case(s: &str) -> String {
3738
pub fn to_upper_snake_case(s: &str) -> String {
3839
to_snake_case(s, char::to_ascii_uppercase)
3940
}
40-
fn to_snake_case<F: Fn(&char) -> char>(s: &str, change_case: F) -> String {
41-
let mut buf = String::with_capacity(s.len());
42-
let mut prev = false;
43-
for c in s.chars() {
44-
// `&& prev` is required to not insert `_` before the first symbol.
45-
if c.is_ascii_uppercase() && prev {
46-
// This check is required to not translate `Weird_Case` into `weird__case`.
47-
if !buf.ends_with('_') {
48-
buf.push('_');
41+
42+
// Code partially taken from rust/compiler/rustc_lint/src/nonstandard_style.rs
43+
// commit: 9626f2b
44+
fn to_snake_case<F: Fn(&char) -> char>(mut s: &str, change_case: F) -> String {
45+
let mut words = vec![];
46+
47+
// Preserve leading underscores
48+
s = s.trim_start_matches(|c: char| {
49+
if c == '_' {
50+
words.push(String::new());
51+
true
52+
} else {
53+
false
54+
}
55+
});
56+
57+
for s in s.split('_') {
58+
let mut last_upper = false;
59+
let mut buf = String::new();
60+
61+
if s.is_empty() {
62+
continue;
63+
}
64+
65+
for ch in s.chars() {
66+
if !buf.is_empty() && buf != "'" && ch.is_uppercase() && !last_upper {
67+
words.push(buf);
68+
buf = String::new();
4969
}
70+
71+
last_upper = ch.is_uppercase();
72+
buf.extend(iter::once(change_case(&ch)));
5073
}
51-
prev = true;
5274

53-
buf.push(change_case(&c));
75+
words.push(buf);
5476
}
55-
buf
77+
78+
words.join("_")
5679
}
5780

5881
pub fn replace(buf: &mut String, from: char, to: &str) {

0 commit comments

Comments
 (0)