@@ -8,10 +8,87 @@ use lsp_types::{
88 Range , ServerCapabilities , ServerInfo , TextDocumentSyncCapability , TextDocumentSyncKind ,
99 TextEdit , Uri ,
1010} ;
11+ use similar:: { DiffOp , TextDiff } ;
1112use stylua_lib:: { format_code, OutputVerification } ;
1213
1314use crate :: { config:: ConfigResolver , opt} ;
1415
16+ fn diffop_to_textedit ( op : DiffOp , formatted_contents : & str ) -> Option < TextEdit > {
17+ match op {
18+ DiffOp :: Equal {
19+ old_index : _,
20+ new_index : _,
21+ len : _,
22+ } => None ,
23+ DiffOp :: Delete {
24+ old_index,
25+ old_len,
26+ new_index : _,
27+ } => Some ( TextEdit {
28+ range : Range {
29+ start : Position {
30+ line : old_index. try_into ( ) . expect ( "usize fits into u32" ) ,
31+ character : 0 ,
32+ } ,
33+ end : Position {
34+ line : ( old_index + old_len)
35+ . try_into ( )
36+ . expect ( "usize fits into u32" ) ,
37+ character : 0 ,
38+ } ,
39+ } ,
40+ new_text : String :: new ( ) ,
41+ } ) ,
42+ DiffOp :: Insert {
43+ old_index,
44+ new_index,
45+ new_len,
46+ } => {
47+ let insert_position = Position {
48+ line : old_index. try_into ( ) . expect ( "usize fits into u32" ) ,
49+ character : 0 ,
50+ } ;
51+ Some ( TextEdit {
52+ range : Range {
53+ start : insert_position,
54+ end : insert_position,
55+ } ,
56+ new_text : formatted_contents
57+ . lines ( )
58+ . skip ( new_index)
59+ . take ( new_len)
60+ . collect :: < Vec < _ > > ( )
61+ . join ( "\n " ) ,
62+ } )
63+ }
64+ DiffOp :: Replace {
65+ old_index,
66+ old_len,
67+ new_index,
68+ new_len,
69+ } => Some ( TextEdit {
70+ range : Range {
71+ start : Position {
72+ line : old_index. try_into ( ) . expect ( "usize fits into u32" ) ,
73+ character : 0 ,
74+ } ,
75+ end : Position {
76+ line : ( old_index + old_len)
77+ . try_into ( )
78+ . expect ( "usize fits into u32" ) ,
79+ character : 0 ,
80+ } ,
81+ } ,
82+ new_text : formatted_contents
83+ . lines ( )
84+ . skip ( new_index)
85+ . take ( new_len)
86+ . collect :: < Vec < _ > > ( )
87+ . join ( "\n " ) ,
88+ } ) ,
89+ }
90+ }
91+
1592fn handle_formatting (
1693 uri : & Uri ,
1794 document : & FullTextDocument ,
@@ -30,18 +107,16 @@ fn handle_formatting(
30107
31108 let formatted_contents = format_code ( contents, config, range, OutputVerification :: None ) . ok ( ) ?;
32109
33- let last_line_idx = document. line_count ( ) . saturating_sub ( 1 ) ;
34- let last_line_offset = document. offset_at ( Position :: new ( last_line_idx, 0 ) ) ;
35- let last_col = document. content_len ( ) - last_line_offset;
36-
37- // TODO: We can be smarter about this in the future, and update only the parts that changed (using output_diff)
38- Some ( vec ! [ TextEdit {
39- range: Range {
40- start: Position :: new( 0 , 0 ) ,
41- end: Position :: new( last_line_idx, last_col) ,
42- } ,
43- new_text: formatted_contents,
44- } ] )
110+ let operations = TextDiff :: from_lines ( contents, & formatted_contents) . grouped_ops ( 0 ) ;
111+ let edits = operations
112+ . into_iter ( )
113+ . flat_map ( |operations| {
114+ operations
115+ . into_iter ( )
116+ . filter_map ( |op| diffop_to_textedit ( op, & formatted_contents) )
117+ } )
118+ . collect ( ) ;
119+ Some ( edits)
45120}
46121
47122fn handle_request (
0 commit comments