about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_string_with_char.rs150
1 files changed, 145 insertions, 5 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_string_with_char.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_string_with_char.rs
index 0eab70424a1..fb5b234d559 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_string_with_char.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_string_with_char.rs
@@ -5,7 +5,7 @@ use syntax::{
     ast::IsString,
 };
 
-use crate::{AssistContext, AssistId, Assists};
+use crate::{AssistContext, AssistId, Assists, utils::string_suffix};
 
 // Assist: replace_string_with_char
 //
@@ -38,9 +38,11 @@ pub(crate) fn replace_string_with_char(acc: &mut Assists, ctx: &AssistContext<'_
         target,
         |edit| {
             let (left, right) = quote_offsets.quotes;
+            let suffix = TextSize::of(string_suffix(token.text()).unwrap_or_default());
+            let right = TextRange::new(right.start(), right.end() - suffix);
             edit.replace(left, '\'');
             edit.replace(right, '\'');
-            if value == "'" {
+            if token.text_without_quotes() == "'" {
                 edit.insert(left.end(), '\\');
             }
         },
@@ -71,12 +73,14 @@ pub(crate) fn replace_char_with_string(acc: &mut Assists, ctx: &AssistContext<'_
         "Replace char with string",
         target,
         |edit| {
-            if token.text() == "'\"'" {
-                edit.replace(token.text_range(), r#""\"""#);
+            let suffix = string_suffix(token.text()).unwrap_or_default();
+            if token.text().starts_with("'\"'") {
+                edit.replace(token.text_range(), format!(r#""\""{suffix}"#));
             } else {
                 let len = TextSize::of('\'');
+                let suffix = TextSize::of(suffix);
                 edit.replace(TextRange::at(target.start(), len), '"');
-                edit.replace(TextRange::at(target.end() - len, len), '"');
+                edit.replace(TextRange::at(target.end() - suffix - len, len), '"');
             }
         },
     )
@@ -106,6 +110,23 @@ fn f() {
     }
 
     #[test]
+    fn replace_string_with_char_has_suffix() {
+        check_assist(
+            replace_string_with_char,
+            r#"
+fn f() {
+    let s = "$0c"i32;
+}
+"#,
+            r##"
+fn f() {
+    let s = 'c'i32;
+}
+"##,
+        )
+    }
+
+    #[test]
     fn replace_string_with_char_assist_with_multi_byte_char() {
         check_assist(
             replace_string_with_char,
@@ -288,6 +309,40 @@ fn f() {
     }
 
     #[test]
+    fn replace_char_with_string_quote_has_suffix() {
+        check_assist(
+            replace_char_with_string,
+            r#"
+fn f() {
+    find($0'"'i32);
+}
+"#,
+            r#"
+fn f() {
+    find("\""i32);
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn replace_char_with_string_escaped_quote_has_suffix() {
+        check_assist(
+            replace_char_with_string,
+            r#"
+fn f() {
+    find($0'\"'i32);
+}
+"#,
+            r#"
+fn f() {
+    find("\""i32);
+}
+"#,
+        )
+    }
+
+    #[test]
     fn replace_string_with_char_quote() {
         check_assist(
             replace_string_with_char,
@@ -303,4 +358,89 @@ fn f() {
 "#,
         )
     }
+
+    #[test]
+    fn replace_string_with_escaped_char_quote() {
+        check_assist(
+            replace_string_with_char,
+            r#"
+fn f() {
+    find($0"\'");
+}
+"#,
+            r#"
+fn f() {
+    find('\'');
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn replace_string_with_char_quote_has_suffix() {
+        check_assist(
+            replace_string_with_char,
+            r#"
+fn f() {
+    find($0"'"i32);
+}
+"#,
+            r#"
+fn f() {
+    find('\''i32);
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn replace_string_with_escaped_char_quote_has_suffix() {
+        check_assist(
+            replace_string_with_char,
+            r#"
+fn f() {
+    find($0"\'"i32);
+}
+"#,
+            r#"
+fn f() {
+    find('\''i32);
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn replace_raw_string_with_char_quote() {
+        check_assist(
+            replace_string_with_char,
+            r#"
+fn f() {
+    find($0r"'");
+}
+"#,
+            r#"
+fn f() {
+    find('\'');
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn replace_string_with_code_escaped_char_quote() {
+        check_assist(
+            replace_string_with_char,
+            r#"
+fn f() {
+    find($0"\x27");
+}
+"#,
+            r#"
+fn f() {
+    find('\x27');
+}
+"#,
+        )
+    }
 }