Unnamed repository; edit this file 'description' to name the repository.
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]>
bors[bot] 2021-10-07
parent fd3f4c5 · parent ba62a8a · commit 5191fb7
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check/case_conv.rs3
-rw-r--r--crates/ide_diagnostics/src/handlers/incorrect_case.rs4
-rw-r--r--crates/stdx/src/lib.rs47
3 files changed, 40 insertions, 14 deletions
diff --git a/crates/hir_ty/src/diagnostics/decl_check/case_conv.rs b/crates/hir_ty/src/diagnostics/decl_check/case_conv.rs
index 7c477d4945..88d607194f 100644
--- a/crates/hir_ty/src/diagnostics/decl_check/case_conv.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check/case_conv.rs
@@ -161,6 +161,7 @@ mod tests {
check(to_lower_snake_case, "lowerCamelCase", expect![["lower_camel_case"]]);
check(to_lower_snake_case, "a", expect![[""]]);
check(to_lower_snake_case, "abc", expect![[""]]);
+ check(to_lower_snake_case, "foo__bar", expect![["foo_bar"]]);
}
#[test]
@@ -192,5 +193,7 @@ mod tests {
check(to_upper_snake_case, "A", expect![[""]]);
check(to_upper_snake_case, "ABC", expect![[""]]);
check(to_upper_snake_case, "X86_64", expect![[""]]);
+ check(to_upper_snake_case, "FOO_BAr", expect![["FOO_BAR"]]);
+ check(to_upper_snake_case, "FOO__BAR", expect![["FOO_BAR"]]);
}
}
diff --git a/crates/ide_diagnostics/src/handlers/incorrect_case.rs b/crates/ide_diagnostics/src/handlers/incorrect_case.rs
index e2bbabd53c..6990b19cf3 100644
--- a/crates/ide_diagnostics/src/handlers/incorrect_case.rs
+++ b/crates/ide_diagnostics/src/handlers/incorrect_case.rs
@@ -102,8 +102,8 @@ fn some_fn() {
"#,
r#"
fn some_fn() {
- let what_a_weird_formatting = 10;
- another_func(what_a_weird_formatting);
+ let what_aweird_formatting = 10;
+ another_func(what_aweird_formatting);
}
"#,
);
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index bfa6024679..ee23f57934 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -1,4 +1,5 @@
//! Missing batteries for standard libraries.
+use std::iter;
use std::{cmp::Ordering, ops, time::Instant};
mod macros;
@@ -37,22 +38,44 @@ pub fn to_lower_snake_case(s: &str) -> String {
pub fn to_upper_snake_case(s: &str) -> String {
to_snake_case(s, char::to_ascii_uppercase)
}
-fn to_snake_case<F: Fn(&char) -> char>(s: &str, change_case: F) -> String {
- let mut buf = String::with_capacity(s.len());
- let mut prev = false;
- for c in s.chars() {
- // `&& prev` is required to not insert `_` before the first symbol.
- if c.is_ascii_uppercase() && prev {
- // This check is required to not translate `Weird_Case` into `weird__case`.
- if !buf.ends_with('_') {
- buf.push('_');
+
+// Code partially taken from rust/compiler/rustc_lint/src/nonstandard_style.rs
+// commit: 9626f2b
+fn to_snake_case<F: Fn(&char) -> char>(mut s: &str, change_case: F) -> String {
+ let mut words = vec![];
+
+ // Preserve leading underscores
+ s = s.trim_start_matches(|c: char| {
+ if c == '_' {
+ words.push(String::new());
+ true
+ } else {
+ false
+ }
+ });
+
+ for s in s.split('_') {
+ let mut last_upper = false;
+ let mut buf = String::new();
+
+ if s.is_empty() {
+ continue;
+ }
+
+ for ch in s.chars() {
+ if !buf.is_empty() && buf != "'" && ch.is_uppercase() && !last_upper {
+ words.push(buf);
+ buf = String::new();
}
+
+ last_upper = ch.is_uppercase();
+ buf.extend(iter::once(change_case(&ch)));
}
- prev = true;
- buf.push(change_case(&c));
+ words.push(buf);
}
- buf
+
+ words.join("_")
}
pub fn replace(buf: &mut String, from: char, to: &str) {