From 13bdfab6b59cd3fcbe36329bc1ff285b0a249b98 Mon Sep 17 00:00:00 2001 From: A4-Tacks Date: Sat, 19 Apr 2025 19:16:44 +0800 Subject: [PATCH] Fix replace_string_with_char escaped char quote --- .../src/handlers/replace_string_with_char.rs | 150 +++++++++++++++++- 1 file changed, 145 insertions(+), 5 deletions(-) diff --git a/crates/ide-assists/src/handlers/replace_string_with_char.rs b/crates/ide-assists/src/handlers/replace_string_with_char.rs index 0eab70424a..fb5b234d55 100644 --- a/crates/ide-assists/src/handlers/replace_string_with_char.rs +++ b/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), '"'); } }, ) @@ -105,6 +109,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( @@ -287,6 +308,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( @@ -300,6 +355,91 @@ fn f() { fn f() { find('\''); } +"#, + ) + } + + #[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'); +} "#, ) }