@@ -78,9 +78,6 @@ impl Rustfmt {
78
78
NewlineStyle :: Native => native,
79
79
} ;
80
80
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
-
84
81
let output = self . format ( input, cfg) ?;
85
82
let ModifiedLines { chunks } = output. parse ( ) . map_err ( |_| Error :: Failed ) ?;
86
83
@@ -89,23 +86,29 @@ impl Rustfmt {
89
86
. map ( |item| {
90
87
// Rustfmt's line indices are 1-based
91
88
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
+ }
99
105
100
106
TextEdit {
101
107
range : Range {
102
108
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 ) ,
107
110
} ,
108
- new_text : item . lines . join ( newline ) ,
111
+ new_text,
109
112
}
110
113
} )
111
114
. collect ( ) )
@@ -232,13 +235,13 @@ mod tests {
232
235
)
233
236
}
234
237
// 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 " ) ] ) ;
238
241
// Check that we send two separate edits
239
242
test_case (
240
243
" 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 " ) ] ,
242
245
) ;
243
246
}
244
247
}
0 commit comments