Skip to content

Commit 669a308

Browse files
authored
Merge pull request #19622 from A4-Tacks/raw-string-suffix
Fix ide-assists raw_string suffix fail
2 parents 2b4b483 + 13bdfab commit 669a308

File tree

3 files changed

+293
-13
lines changed

3 files changed

+293
-13
lines changed

crates/ide-assists/src/handlers/raw_string.rs

+134-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ use std::borrow::Cow;
22

33
use syntax::{AstToken, TextRange, TextSize, ast, ast::IsString};
44

5-
use crate::{AssistContext, AssistId, Assists, utils::required_hashes};
5+
use crate::{
6+
AssistContext, AssistId, Assists,
7+
utils::{required_hashes, string_suffix},
8+
};
69

710
// Assist: make_raw_string
811
//
@@ -33,12 +36,15 @@ pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
3336
target,
3437
|edit| {
3538
let hashes = "#".repeat(required_hashes(&value).max(1));
39+
let range = token.syntax().text_range();
40+
let suffix = string_suffix(token.text()).unwrap_or_default();
41+
let range = TextRange::new(range.start(), range.end() - TextSize::of(suffix));
3642
if matches!(value, Cow::Borrowed(_)) {
3743
// Avoid replacing the whole string to better position the cursor.
38-
edit.insert(token.syntax().text_range().start(), format!("r{hashes}"));
39-
edit.insert(token.syntax().text_range().end(), hashes);
44+
edit.insert(range.start(), format!("r{hashes}"));
45+
edit.insert(range.end(), hashes);
4046
} else {
41-
edit.replace(token.syntax().text_range(), format!("r{hashes}\"{value}\"{hashes}"));
47+
edit.replace(range, format!("r{hashes}\"{value}\"{hashes}"));
4248
}
4349
},
4450
)
@@ -73,15 +79,19 @@ pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
7379
|edit| {
7480
// parse inside string to escape `"`
7581
let escaped = value.escape_default().to_string();
82+
let suffix = string_suffix(token.text()).unwrap_or_default();
7683
if let Some(offsets) = token.quote_offsets() {
7784
if token.text()[offsets.contents - token.syntax().text_range().start()] == escaped {
85+
let end_quote = offsets.quotes.1;
86+
let end_quote =
87+
TextRange::new(end_quote.start(), end_quote.end() - TextSize::of(suffix));
7888
edit.replace(offsets.quotes.0, "\"");
79-
edit.replace(offsets.quotes.1, "\"");
89+
edit.replace(end_quote, "\"");
8090
return;
8191
}
8292
}
8393

84-
edit.replace(token.syntax().text_range(), format!("\"{escaped}\""));
94+
edit.replace(token.syntax().text_range(), format!("\"{escaped}\"{suffix}"));
8595
},
8696
)
8797
}
@@ -109,8 +119,9 @@ pub(crate) fn add_hash(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()>
109119
let text_range = token.syntax().text_range();
110120
let target = text_range;
111121
acc.add(AssistId::refactor("add_hash"), "Add #", target, |edit| {
122+
let suffix = string_suffix(token.text()).unwrap_or_default();
112123
edit.insert(text_range.start() + TextSize::of('r'), "#");
113-
edit.insert(text_range.end(), "#");
124+
edit.insert(text_range.end() - TextSize::of(suffix), "#");
114125
})
115126
}
116127

@@ -151,8 +162,12 @@ pub(crate) fn remove_hash(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
151162
}
152163

153164
acc.add(AssistId::refactor_rewrite("remove_hash"), "Remove #", text_range, |edit| {
165+
let suffix = string_suffix(text).unwrap_or_default();
154166
edit.delete(TextRange::at(text_range.start() + TextSize::of('r'), TextSize::of('#')));
155-
edit.delete(TextRange::new(text_range.end() - TextSize::of('#'), text_range.end()));
167+
edit.delete(
168+
TextRange::new(text_range.end() - TextSize::of('#'), text_range.end())
169+
- TextSize::of(suffix),
170+
);
156171
})
157172
}
158173

@@ -262,6 +277,23 @@ string"###;
262277
)
263278
}
264279

280+
#[test]
281+
fn make_raw_string_has_suffix() {
282+
check_assist(
283+
make_raw_string,
284+
r#"
285+
fn f() {
286+
let s = $0"random string"i32;
287+
}
288+
"#,
289+
r##"
290+
fn f() {
291+
let s = r#"random string"#i32;
292+
}
293+
"##,
294+
)
295+
}
296+
265297
#[test]
266298
fn make_raw_string_not_works_on_partial_string() {
267299
check_assist_not_applicable(
@@ -316,6 +348,23 @@ string"###;
316348
)
317349
}
318350

351+
#[test]
352+
fn add_hash_has_suffix_works() {
353+
check_assist(
354+
add_hash,
355+
r#"
356+
fn f() {
357+
let s = $0r"random string"i32;
358+
}
359+
"#,
360+
r##"
361+
fn f() {
362+
let s = r#"random string"#i32;
363+
}
364+
"##,
365+
)
366+
}
367+
319368
#[test]
320369
fn add_more_hash_works() {
321370
check_assist(
@@ -333,6 +382,23 @@ string"###;
333382
)
334383
}
335384

385+
#[test]
386+
fn add_more_hash_has_suffix_works() {
387+
check_assist(
388+
add_hash,
389+
r##"
390+
fn f() {
391+
let s = $0r#"random"string"#i32;
392+
}
393+
"##,
394+
r###"
395+
fn f() {
396+
let s = r##"random"string"##i32;
397+
}
398+
"###,
399+
)
400+
}
401+
336402
#[test]
337403
fn add_hash_not_works() {
338404
check_assist_not_applicable(
@@ -367,6 +433,15 @@ string"###;
367433
)
368434
}
369435

436+
#[test]
437+
fn remove_hash_has_suffix_works() {
438+
check_assist(
439+
remove_hash,
440+
r##"fn f() { let s = $0r#"random string"#i32; }"##,
441+
r#"fn f() { let s = r"random string"i32; }"#,
442+
)
443+
}
444+
370445
#[test]
371446
fn cant_remove_required_hash() {
372447
cov_mark::check!(cant_remove_required_hash);
@@ -397,6 +472,23 @@ string"###;
397472
)
398473
}
399474

475+
#[test]
476+
fn remove_more_hash_has_suffix_works() {
477+
check_assist(
478+
remove_hash,
479+
r###"
480+
fn f() {
481+
let s = $0r##"random string"##i32;
482+
}
483+
"###,
484+
r##"
485+
fn f() {
486+
let s = r#"random string"#i32;
487+
}
488+
"##,
489+
)
490+
}
491+
400492
#[test]
401493
fn remove_hash_does_not_work() {
402494
check_assist_not_applicable(remove_hash, r#"fn f() { let s = $0"random string"; }"#);
@@ -437,6 +529,23 @@ string"###;
437529
)
438530
}
439531

532+
#[test]
533+
fn make_usual_string_has_suffix_works() {
534+
check_assist(
535+
make_usual_string,
536+
r##"
537+
fn f() {
538+
let s = $0r#"random string"#i32;
539+
}
540+
"##,
541+
r#"
542+
fn f() {
543+
let s = "random string"i32;
544+
}
545+
"#,
546+
)
547+
}
548+
440549
#[test]
441550
fn make_usual_string_with_quote_works() {
442551
check_assist(
@@ -471,6 +580,23 @@ string"###;
471580
)
472581
}
473582

583+
#[test]
584+
fn make_usual_string_more_hash_has_suffix_works() {
585+
check_assist(
586+
make_usual_string,
587+
r###"
588+
fn f() {
589+
let s = $0r##"random string"##i32;
590+
}
591+
"###,
592+
r##"
593+
fn f() {
594+
let s = "random string"i32;
595+
}
596+
"##,
597+
)
598+
}
599+
474600
#[test]
475601
fn make_usual_string_not_works() {
476602
check_assist_not_applicable(

0 commit comments

Comments
 (0)