@@ -2,7 +2,10 @@ use std::borrow::Cow;
22
33use 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