@@ -7,6 +7,7 @@ use syntax::{
77 SyntaxKind :: { self , USE_TREE , WHITESPACE } ,
88 SyntaxNode , SyntaxToken , TextRange , TextSize , T ,
99} ;
10+ use test_utils:: mark;
1011use text_edit:: { TextEdit , TextEditBuilder } ;
1112
1213// Feature: Join Lines
@@ -44,9 +45,9 @@ pub(crate) fn join_lines(file: &SourceFile, range: TextRange) -> TextEdit {
4445 let text = token. text ( ) ;
4546 for ( pos, _) in text[ range] . bytes ( ) . enumerate ( ) . filter ( |& ( _, b) | b == b'\n' ) {
4647 let pos: TextSize = ( pos as u32 ) . into ( ) ;
47- let off = token. text_range ( ) . start ( ) + range. start ( ) + pos;
48- if !edit. invalidates_offset ( off ) {
49- remove_newline ( & mut edit, & token, off ) ;
48+ let offset = token. text_range ( ) . start ( ) + range. start ( ) + pos;
49+ if !edit. invalidates_offset ( offset ) {
50+ remove_newline ( & mut edit, & token, offset ) ;
5051 }
5152 }
5253 }
@@ -56,14 +57,25 @@ pub(crate) fn join_lines(file: &SourceFile, range: TextRange) -> TextEdit {
5657
5758fn remove_newline ( edit : & mut TextEditBuilder , token : & SyntaxToken , offset : TextSize ) {
5859 if token. kind ( ) != WHITESPACE || token. text ( ) . bytes ( ) . filter ( |& b| b == b'\n' ) . count ( ) != 1 {
59- // The node is either the first or the last in the file
60- let suff = & token. text ( ) [ TextRange :: new (
61- offset - token. text_range ( ) . start ( ) + TextSize :: of ( '\n' ) ,
62- TextSize :: of ( token. text ( ) ) ,
63- ) ] ;
64- let spaces = suff. bytes ( ) . take_while ( |& b| b == b' ' ) . count ( ) ;
65-
66- edit. replace ( TextRange :: at ( offset, ( ( spaces + 1 ) as u32 ) . into ( ) ) , " " . to_string ( ) ) ;
60+ let mut string_open_quote = false ;
61+ if let Some ( string) = ast:: String :: cast ( token. clone ( ) ) {
62+ if let Some ( range) = string. open_quote_text_range ( ) {
63+ mark:: hit!( join_string_literal) ;
64+ string_open_quote = range. end ( ) == offset;
65+ }
66+ }
67+
68+ let n_spaces_after_line_break = {
69+ let suff = & token. text ( ) [ TextRange :: new (
70+ offset - token. text_range ( ) . start ( ) + TextSize :: of ( '\n' ) ,
71+ TextSize :: of ( token. text ( ) ) ,
72+ ) ] ;
73+ suff. bytes ( ) . take_while ( |& b| b == b' ' ) . count ( )
74+ } ;
75+
76+ let range = TextRange :: at ( offset, ( ( n_spaces_after_line_break + 1 ) as u32 ) . into ( ) ) ;
77+ let replace_with = if string_open_quote { "" } else { " " } ;
78+ edit. replace ( range, replace_with. to_string ( ) ) ;
6779 return ;
6880 }
6981
@@ -194,7 +206,7 @@ fn compute_ws(left: SyntaxKind, right: SyntaxKind) -> &'static str {
194206#[ cfg( test) ]
195207mod tests {
196208 use syntax:: SourceFile ;
197- use test_utils:: { add_cursor, assert_eq_text, extract_offset, extract_range} ;
209+ use test_utils:: { add_cursor, assert_eq_text, extract_offset, extract_range, mark } ;
198210
199211 use super :: * ;
200212
@@ -771,4 +783,42 @@ fn foo() {
771783 " ,
772784 ) ;
773785 }
786+
787+ #[ test]
788+ fn join_string_literal ( ) {
789+ mark:: check!( join_string_literal) ;
790+ check_join_lines (
791+ r#"
792+ fn main() {
793+ $0"
794+ hello
795+ ";
796+ }
797+ "# ,
798+ r#"
799+ fn main() {
800+ $0"hello
801+ ";
802+ }
803+ "# ,
804+ ) ;
805+
806+ check_join_lines (
807+ r#"
808+ fn main() {
809+ "
810+ $0hello
811+ world
812+ ";
813+ }
814+ "# ,
815+ r#"
816+ fn main() {
817+ "
818+ $0hello world
819+ ";
820+ }
821+ "# ,
822+ ) ;
823+ }
774824}
0 commit comments