@@ -78,9 +78,6 @@ impl Rustfmt {
7878 NewlineStyle :: Native => native,
7979 } ;
8080
81- let lsp_line_length = |line : & str | line. chars ( ) . map ( char:: len_utf16) . sum ( ) ;
82- let line_cols: Vec < usize > = input. lines ( ) . map ( lsp_line_length) . collect ( ) ;
83-
8481 let output = self . format ( input, cfg) ?;
8582 let ModifiedLines { chunks } = output. parse ( ) . map_err ( |_| Error :: Failed ) ?;
8683
@@ -89,23 +86,29 @@ impl Rustfmt {
8986 . map ( |item| {
9087 // Rustfmt's line indices are 1-based
9188 let start_line = u64:: from ( item. line_number_orig ) - 1 ;
92- let end_line = {
93- // Could underflow if we don't remove lines and there's only one
94- let removed = u64:: from ( item. lines_removed ) . saturating_sub ( 1 ) ;
95- start_line + removed
96- } ;
97- let end_col: Option < usize > = line_cols. get ( end_line as usize ) . copied ( ) ;
98- let end_col: u64 = end_col. map ( |col| col as u64 ) . unwrap_or_else ( u64:: max_value) ;
89+ let end_line = start_line + u64:: from ( item. lines_removed ) ;
90+
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+ }
99105
100106 TextEdit {
101107 range : Range {
102108 start : Position :: new ( start_line, 0 ) ,
103- // We don't extend the range past the last line because
104- // sometimes it may not exist, skewing the diff and
105- // making us add an invalid additional trailing newline.
106- end : Position :: new ( end_line, end_col) ,
109+ end : Position :: new ( end_line, 0 ) ,
107110 } ,
108- new_text : item . lines . join ( newline ) ,
111+ new_text,
109112 }
110113 } )
111114 . collect ( ) )
@@ -232,13 +235,13 @@ mod tests {
232235 )
233236 }
234237 // Handle single-line text wrt. added/removed trailing newline
235- test_case ( "fn main() {} " , vec ! [ ( 0 , 0 , 0 , 13 , "fn main() {}\n " ) ] ) ;
236- test_case ( "fn main() {} \n " , vec ! [ ( 0 , 0 , 0 , 13 , "fn main() {}" ) ] ) ;
237- test_case ( "\n fn main() {} \n " , vec ! [ ( 0 , 0 , 1 , 13 , "fn main() {}" ) ] ) ;
238+ test_case ( "fn main() {} " , vec ! [ ( 0 , 0 , 1 , 0 , "fn main() {}\n " ) ] ) ;
239+ test_case ( "fn main() {} \n " , vec ! [ ( 0 , 0 , 1 , 0 , "fn main() {}\n " ) ] ) ;
240+ test_case ( "\n fn main() {} \n " , vec ! [ ( 0 , 0 , 2 , 0 , "fn main() {}\n " ) ] ) ;
238241 // Check that we send two separate edits
239242 test_case (
240243 " struct Upper ;\n \n struct Lower ;" ,
241- vec ! [ ( 0 , 0 , 0 , 16 , "struct Upper;" ) , ( 2 , 0 , 2 , 14 , "struct Lower;\n " ) ] ,
244+ vec ! [ ( 0 , 0 , 1 , 0 , "struct Upper;\n " ) , ( 2 , 0 , 3 , 0 , "struct Lower;\n " ) ] ,
242245 ) ;
243246 }
244247}
0 commit comments