3
3
//!
4
4
//! Each tick provides an immutable snapshot of the state as `WorldSnapshot`.
5
5
6
- use std:: { mem , sync:: Arc , time:: Instant } ;
6
+ use std:: { sync:: Arc , time:: Instant } ;
7
7
8
8
use crossbeam_channel:: { unbounded, Receiver , Sender } ;
9
9
use flycheck:: FlycheckHandle ;
@@ -179,10 +179,9 @@ impl GlobalState {
179
179
180
180
pub ( crate ) fn process_changes ( & mut self ) -> bool {
181
181
let _p = profile:: span ( "GlobalState::process_changes" ) ;
182
- // A file was added or deleted
183
- let mut has_structure_changes = false ;
184
182
let mut workspace_structure_change = None ;
185
183
184
+ let mut file_changes = FxHashMap :: default ( ) ;
186
185
let ( change, changed_files) = {
187
186
let mut change = Change :: new ( ) ;
188
187
let ( vfs, line_endings_map) = & mut * self . vfs . write ( ) ;
@@ -191,57 +190,41 @@ impl GlobalState {
191
190
return false ;
192
191
}
193
192
194
- // important: this needs to be a stable sort, the order between changes is relevant
195
- // for the same file ids
196
- changed_files. sort_by_key ( |file| file. file_id ) ;
197
- // We need to fix up the changed events a bit, if we have a create or modify for a file
198
- // id that is followed by a delete we actually no longer observe the file text from the
199
- // create or modify which may cause problems later on
200
- let mut collapsed_create_delete = false ;
201
- changed_files. dedup_by ( |a, b| {
193
+ // We need to fix up the changed events a bit. If we have a create or modify for a file
194
+ // id that is followed by a delete we actually skip observing the file text from the
195
+ // earlier event, to avoid problems later on.
196
+ file_changes. clear ( ) ;
197
+ for changed_file in & changed_files {
202
198
use vfs:: ChangeKind :: * ;
203
199
204
- let has_collapsed_create_delete = mem:: replace ( & mut collapsed_create_delete, false ) ;
200
+ file_changes
201
+ . entry ( changed_file. file_id )
202
+ . and_modify ( |change| match ( change, changed_file. change_kind ) {
203
+ // latter `Delete` wins
204
+ ( change, Delete ) => * change = Delete ,
205
+ // merge `Create` with `Create` or `Modify`
206
+ ( Create , Create | Modify ) => { }
207
+ // collapse identical `Modify`es
208
+ ( Modify , Modify ) => { }
209
+ // equivalent to `Modify`
210
+ ( change @ Delete , Create ) => * change = Modify ,
211
+ // shouldn't occur, but collapse into `Create`
212
+ ( change @ Delete , Modify ) => * change = Create ,
213
+ // shouldn't occur, but collapse into `Modify`
214
+ ( Modify , Create ) => { }
215
+ } )
216
+ . or_insert ( changed_file. change_kind ) ;
217
+ }
205
218
206
- if a. file_id != b. file_id {
207
- return false ;
208
- }
219
+ changed_files. clear ( ) ;
220
+ changed_files. extend (
221
+ file_changes
222
+ . into_iter ( )
223
+ . map ( |( file_id, change_kind) | vfs:: ChangedFile { file_id, change_kind } ) ,
224
+ ) ;
209
225
210
- // true => delete the second element (a), we swap them here as they are inverted by dedup_by
211
- match ( b. change_kind , a. change_kind ) {
212
- // duplicate can be merged
213
- ( Create , Create ) | ( Modify , Modify ) | ( Delete , Delete ) => true ,
214
- // just leave the create, modify is irrelevant
215
- ( Create , Modify ) => true ,
216
- // modify becomes irrelevant if the file is deleted
217
- ( Modify , Delete ) => {
218
- mem:: swap ( a, b) ;
219
- true
220
- }
221
- // Remove the create message, and in the following loop, also remove the delete
222
- ( Create , Delete ) => {
223
- collapsed_create_delete = true ;
224
- b. change_kind = Delete ;
225
- true
226
- }
227
- // trailing delete from earlier
228
- ( Delete , Create | Modify ) if has_collapsed_create_delete => {
229
- b. change_kind = Create ;
230
- true
231
- }
232
- // this is equivalent to a modify
233
- ( Delete , Create ) => {
234
- b. change_kind = Modify ;
235
- true
236
- }
237
- // can't really occur
238
- ( Modify , Create ) => false ,
239
- ( Delete , Modify ) => false ,
240
- }
241
- } ) ;
242
- if collapsed_create_delete {
243
- changed_files. pop ( ) ;
244
- }
226
+ // A file was added or deleted
227
+ let mut has_structure_changes = false ;
245
228
for file in & changed_files {
246
229
if let Some ( path) = vfs. file_path ( file. file_id ) . as_path ( ) {
247
230
let path = path. to_path_buf ( ) ;
0 commit comments