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,38 @@ 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
+ for changed_file in & changed_files {
202
197
use vfs:: ChangeKind :: * ;
203
198
204
- let has_collapsed_create_delete = mem:: replace ( & mut collapsed_create_delete, false ) ;
205
-
206
- if a. file_id != b. file_id {
207
- return false ;
208
- }
209
-
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
199
+ match ( file_changes. get_mut ( & changed_file. file_id ) , changed_file. change_kind ) {
200
+ ( None , new_change @ _) => {
201
+ file_changes. insert ( changed_file. file_id , new_change) ;
226
202
}
203
+ // duplicates can be merged
204
+ ( Some ( Create ) , Create ) | ( Some ( Modify ) , Modify ) | ( Some ( Delete ) , Delete ) => { }
205
+ // keep the deletion
206
+ ( Some ( change) , Delete ) => * change = Delete ,
207
+ // just leave the create, modify is irrelevant
208
+ ( Some ( Create ) , Modify ) => { }
227
209
// 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
- }
210
+ ( Some ( change @ Delete ) , new_change @ ( Create | Modify ) ) => * change = new_change,
237
211
// can't really occur
238
- ( Modify , Create ) => false ,
239
- ( Delete , Modify ) => false ,
212
+ ( Some ( change @ Modify ) , new_change @ Create ) => * change = new_change,
240
213
}
241
- } ) ;
242
- if collapsed_create_delete {
243
- changed_files. pop ( ) ;
244
214
}
215
+
216
+ changed_files. clear ( ) ;
217
+ changed_files. extend (
218
+ file_changes
219
+ . into_iter ( )
220
+ . map ( |( file_id, change_kind) | vfs:: ChangedFile { file_id, change_kind } ) ,
221
+ ) ;
222
+
223
+ // A file was added or deleted
224
+ let mut has_structure_changes = false ;
245
225
for file in & changed_files {
246
226
if let Some ( path) = vfs. file_path ( file. file_id ) . as_path ( ) {
247
227
let path = path. to_path_buf ( ) ;
0 commit comments