@@ -78,6 +78,9 @@ 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+
8184 let output = self . format ( input, cfg) ?;
8285 let ModifiedLines { chunks } = output. parse ( ) . map_err ( |_| Error :: Failed ) ?;
8386
@@ -86,15 +89,21 @@ impl Rustfmt {
8689 . map ( |item| {
8790 // Rustfmt's line indices are 1-based
8891 let start_line = u64:: from ( item. line_number_orig ) - 1 ;
89- // Could underflow if we don't remove lines and there's only one
90- let removed = u64:: from ( item. lines_removed ) . saturating_sub ( 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) ;
99+
91100 TextEdit {
92101 range : Range {
93102 start : Position :: new ( start_line, 0 ) ,
94103 // We don't extend the range past the last line because
95104 // sometimes it may not exist, skewing the diff and
96105 // making us add an invalid additional trailing newline.
97- end : Position :: new ( start_line + removed , u64 :: max_value ( ) ) ,
106+ end : Position :: new ( end_line , end_col ) ,
98107 } ,
99108 new_text : item. lines . join ( newline) ,
100109 }
@@ -202,34 +211,34 @@ mod tests {
202211
203212 #[ test]
204213 fn calc_text_edits ( ) {
205- let config = || FmtConfig :: default ( ) . get_rustfmt_config ( ) . clone ( ) ;
206- let format = |x : & str | Rustfmt :: Internal . calc_text_edits ( x. to_string ( ) , config ( ) ) . unwrap ( ) ;
207- let line_range = |start, end| Range {
208- start : Position { line : start, character : 0 } ,
209- end : Position { line : end, character : u64:: max_value ( ) } ,
210- } ;
211- // Handle single-line text wrt. added/removed trailing newline
212- assert_eq ! (
213- format( "fn main() {} " ) ,
214- vec![ TextEdit { range: line_range( 0 , 0 ) , new_text: "fn main() {}\n " . to_owned( ) } ]
215- ) ;
216-
217- assert_eq ! (
218- format( "fn main() {} \n " ) ,
219- vec![ TextEdit { range: line_range( 0 , 0 ) , new_text: "fn main() {}" . to_owned( ) } ]
220- ) ;
214+ fn format ( input : & str ) -> Vec < TextEdit > {
215+ let config = || FmtConfig :: default ( ) . get_rustfmt_config ( ) . clone ( ) ;
216+ Rustfmt :: Internal . calc_text_edits ( input. to_string ( ) , config ( ) ) . unwrap ( )
217+ }
221218
222- assert_eq ! (
223- format( "\n fn main() {} \n " ) ,
224- vec![ TextEdit { range: line_range( 0 , 1 ) , new_text: "fn main() {}" . to_owned( ) } ]
225- ) ;
219+ fn test_case ( input : & str , output : Vec < ( u64 , u64 , u64 , u64 , & str ) > ) {
220+ assert_eq ! (
221+ format( input) ,
222+ output
223+ . into_iter( )
224+ . map( |( start_l, start_c, end_l, end_c, out) | TextEdit {
225+ range: Range {
226+ start: Position { line: start_l, character: start_c } ,
227+ end: Position { line: end_l, character: end_c } ,
228+ } ,
229+ new_text: out. to_owned( ) ,
230+ } )
231+ . collect:: <Vec <_>>( )
232+ )
233+ }
234+ // 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() {}" ) ] ) ;
226238 // Check that we send two separate edits
227- assert_eq ! (
228- format( " struct Upper ;\n \n struct Lower ;" ) ,
229- vec![
230- TextEdit { range: line_range( 0 , 0 ) , new_text: "struct Upper;" . to_owned( ) } ,
231- TextEdit { range: line_range( 2 , 2 ) , new_text: "struct Lower;\n " . to_owned( ) }
232- ]
239+ test_case (
240+ " struct Upper ;\n \n struct Lower ;" ,
241+ vec ! [ ( 0 , 0 , 0 , 16 , "struct Upper;" ) , ( 2 , 0 , 2 , 14 , "struct Lower;\n " ) ] ,
233242 ) ;
234243 }
235244}
0 commit comments