@@ -88,16 +88,27 @@ impl Rustfmt {
8888 let start_line = u64:: from ( item. line_number_orig ) - 1 ;
8989 let end_line = start_line + u64:: from ( item. lines_removed ) ;
9090
91+ let mut new_text = item. lines . join ( newline) ;
92+
93+ // Rustfmt represents an added line as start_line == end_line, new_text == "",
94+ // which is a no-op, so we need to add a terminating newline.
95+ if start_line == end_line && new_text. len ( ) == 0 {
96+ new_text. push_str ( newline) ;
97+ }
98+
99+ // Line deletions are represented as start_line != end_line, new_text == "".
100+ // If we're not deleting a line, there should always be a terminating newline.
101+ let delete_only = start_line != end_line && new_text. len ( ) == 0 ;
102+ if !delete_only && !new_text. ends_with ( newline) {
103+ new_text. push_str ( newline) ;
104+ }
105+
91106 TextEdit {
92107 range : Range {
93108 start : Position :: new ( start_line, 0 ) ,
94109 end : Position :: new ( end_line, 0 ) ,
95110 } ,
96- new_text : item. lines . iter ( ) . fold ( String :: new ( ) , |mut acc, s| {
97- acc. push_str ( s) ;
98- acc. push_str ( newline) ;
99- acc
100- } ) ,
111+ new_text,
101112 }
102113 } )
103114 . collect ( ) )
@@ -224,13 +235,13 @@ mod tests {
224235 )
225236 }
226237 // Handle single-line text wrt. added/removed trailing newline
227- test_case ( "fn main() {} " , vec ! [ ( 0 , 0 , 1 , 0 , "fn main() {}\n \n " ) ] ) ;
238+ test_case ( "fn main() {} " , vec ! [ ( 0 , 0 , 1 , 0 , "fn main() {}\n " ) ] ) ;
228239 test_case ( "fn main() {} \n " , vec ! [ ( 0 , 0 , 1 , 0 , "fn main() {}\n " ) ] ) ;
229240 test_case ( "\n fn main() {} \n " , vec ! [ ( 0 , 0 , 2 , 0 , "fn main() {}\n " ) ] ) ;
230241 // Check that we send two separate edits
231242 test_case (
232243 " struct Upper ;\n \n struct Lower ;" ,
233- vec ! [ ( 0 , 0 , 1 , 0 , "struct Upper;\n " ) , ( 2 , 0 , 3 , 0 , "struct Lower;\n \n " ) ] ,
244+ vec ! [ ( 0 , 0 , 1 , 0 , "struct Upper;\n " ) , ( 2 , 0 , 3 , 0 , "struct Lower;\n " ) ] ,
234245 ) ;
235246 }
236247}
0 commit comments