33//!
44//! Each tick provides an immutable snapshot of the state as `WorldSnapshot`.
55
6- use std:: time:: Instant ;
6+ use std:: { collections :: hash_map :: Entry , time:: Instant } ;
77
88use crossbeam_channel:: { unbounded, Receiver , Sender } ;
99use flycheck:: FlycheckHandle ;
@@ -21,7 +21,7 @@ use proc_macro_api::ProcMacroServer;
2121use project_model:: { CargoWorkspace , ProjectWorkspace , Target , WorkspaceBuildScripts } ;
2222use rustc_hash:: { FxHashMap , FxHashSet } ;
2323use triomphe:: Arc ;
24- use vfs:: { AnchoredPathBuf , Vfs } ;
24+ use vfs:: { AnchoredPathBuf , ChangedFile , Vfs } ;
2525
2626use crate :: {
2727 config:: { Config , ConfigError } ,
@@ -217,8 +217,8 @@ impl GlobalState {
217217 pub ( crate ) fn process_changes ( & mut self ) -> bool {
218218 let _p = profile:: span ( "GlobalState::process_changes" ) ;
219219
220- let mut file_changes = FxHashMap :: default ( ) ;
221- let ( change, changed_files , workspace_structure_change) = {
220+ let mut file_changes = FxHashMap :: < _ , ( bool , ChangedFile ) > :: default ( ) ;
221+ let ( change, modified_files , workspace_structure_change) = {
222222 let mut change = Change :: new ( ) ;
223223 let mut guard = self . vfs . write ( ) ;
224224 let changed_files = guard. 0 . take_changes ( ) ;
@@ -233,64 +233,63 @@ impl GlobalState {
233233 // id that is followed by a delete we actually skip observing the file text from the
234234 // earlier event, to avoid problems later on.
235235 for changed_file in changed_files {
236- use vfs:: ChangeKind :: * ;
237-
238- file_changes
239- . entry ( changed_file. file_id )
240- . and_modify ( |( change, just_created) | {
241- // None -> Delete => keep
242- // Create -> Delete => collapse
243- //
244- match ( change, just_created, changed_file. change_kind ) {
236+ use vfs:: Change :: * ;
237+ match file_changes. entry ( changed_file. file_id ) {
238+ Entry :: Occupied ( mut o) => {
239+ let ( just_created, change) = o. get_mut ( ) ;
240+ match ( & mut change. change , just_created, changed_file. change ) {
245241 // latter `Delete` wins
246242 ( change, _, Delete ) => * change = Delete ,
247243 // merge `Create` with `Create` or `Modify`
248- ( Create , _, Create | Modify ) => { }
244+ ( Create ( prev ) , _, Create ( new ) | Modify ( new ) ) => * prev = new ,
249245 // collapse identical `Modify`es
250- ( Modify , _, Modify ) => { }
246+ ( Modify ( prev ) , _, Modify ( new ) ) => * prev = new ,
251247 // equivalent to `Modify`
252- ( change @ Delete , just_created, Create ) => {
253- * change = Modify ;
248+ ( change @ Delete , just_created, Create ( new ) ) => {
249+ * change = Modify ( new ) ;
254250 * just_created = true ;
255251 }
256252 // shouldn't occur, but collapse into `Create`
257- ( change @ Delete , just_created, Modify ) => {
258- * change = Create ;
253+ ( change @ Delete , just_created, Modify ( new ) ) => {
254+ * change = Create ( new ) ;
259255 * just_created = true ;
260256 }
261257 // shouldn't occur, but collapse into `Modify`
262- ( Modify , _, Create ) => { }
258+ ( Modify ( prev ) , _, Create ( new ) ) => * prev = new ,
263259 }
264- } )
265- . or_insert ( (
266- changed_file. change_kind ,
267- matches ! ( changed_file . change_kind , Create ) ,
268- ) ) ;
260+ }
261+ Entry :: Vacant ( v ) => {
262+ _ = v . insert ( ( matches ! ( & changed_file. change , Create ( _ ) ) , changed_file ) )
263+ }
264+ }
269265 }
270266
271267 let changed_files: Vec < _ > = file_changes
272268 . into_iter ( )
273- . filter ( |( _, ( change_kind , just_created ) ) | {
274- !matches ! ( ( change_kind , just_created ) , ( vfs:: ChangeKind :: Delete , true ) )
269+ . filter ( |( _, ( just_created , change ) ) | {
270+ !( * just_created && matches ! ( change . change , vfs:: Change :: Delete ) )
275271 } )
276- . map ( |( file_id, ( change_kind , _ ) ) | vfs:: ChangedFile { file_id, change_kind } )
272+ . map ( |( file_id, ( _ , change ) ) | vfs:: ChangedFile { file_id, ..change } )
277273 . collect ( ) ;
278274
279275 let mut workspace_structure_change = None ;
280276 // A file was added or deleted
281277 let mut has_structure_changes = false ;
282278 let mut bytes = vec ! [ ] ;
283- for file in & changed_files {
279+ let mut modified_files = vec ! [ ] ;
280+ for file in changed_files {
284281 let vfs_path = & vfs. file_path ( file. file_id ) ;
285282 if let Some ( path) = vfs_path. as_path ( ) {
286283 let path = path. to_path_buf ( ) ;
287- if reload:: should_refresh_for_change ( & path, file. change_kind ) {
284+ if reload:: should_refresh_for_change ( & path, file. kind ( ) ) {
288285 workspace_structure_change = Some ( ( path. clone ( ) , false ) ) ;
289286 }
290287 if file. is_created_or_deleted ( ) {
291288 has_structure_changes = true ;
292289 workspace_structure_change =
293290 Some ( ( path, self . crate_graph_file_dependencies . contains ( vfs_path) ) ) ;
291+ } else {
292+ modified_files. push ( file. file_id ) ;
294293 }
295294 }
296295
@@ -299,10 +298,8 @@ impl GlobalState {
299298 self . diagnostics . clear_native_for ( file. file_id ) ;
300299 }
301300
302- let text = if file. exists ( ) {
303- let bytes = vfs. file_contents ( file. file_id ) . to_vec ( ) ;
304-
305- String :: from_utf8 ( bytes) . ok ( ) . and_then ( |text| {
301+ let text = if let vfs:: Change :: Create ( v) | vfs:: Change :: Modify ( v) = file. change {
302+ String :: from_utf8 ( v) . ok ( ) . and_then ( |text| {
306303 // FIXME: Consider doing normalization in the `vfs` instead? That allows
307304 // getting rid of some locking
308305 let ( text, line_endings) = LineEndings :: normalize ( text) ;
@@ -327,11 +324,10 @@ impl GlobalState {
327324 let roots = self . source_root_config . partition ( vfs) ;
328325 change. set_roots ( roots) ;
329326 }
330- ( change, changed_files , workspace_structure_change)
327+ ( change, modified_files , workspace_structure_change)
331328 } ;
332329
333330 self . analysis_host . apply_change ( change) ;
334-
335331 {
336332 let raw_database = self . analysis_host . raw_database ( ) ;
337333 // FIXME: ideally we should only trigger a workspace fetch for non-library changes
@@ -343,13 +339,12 @@ impl GlobalState {
343339 force_crate_graph_reload,
344340 ) ;
345341 }
346- self . proc_macro_changed =
347- changed_files. iter ( ) . filter ( |file| !file. is_created_or_deleted ( ) ) . any ( |file| {
348- let crates = raw_database. relevant_crates ( file. file_id ) ;
349- let crate_graph = raw_database. crate_graph ( ) ;
342+ self . proc_macro_changed = modified_files. into_iter ( ) . any ( |file_id| {
343+ let crates = raw_database. relevant_crates ( file_id) ;
344+ let crate_graph = raw_database. crate_graph ( ) ;
350345
351- crates. iter ( ) . any ( |& krate| crate_graph[ krate] . is_proc_macro )
352- } ) ;
346+ crates. iter ( ) . any ( |& krate| crate_graph[ krate] . is_proc_macro )
347+ } ) ;
353348 }
354349
355350 true
@@ -494,10 +489,6 @@ impl GlobalStateSnapshot {
494489 } )
495490 }
496491
497- pub ( crate ) fn vfs_memory_usage ( & self ) -> usize {
498- self . vfs_read ( ) . memory_usage ( )
499- }
500-
501492 pub ( crate ) fn file_exists ( & self , file_id : FileId ) -> bool {
502493 self . vfs . read ( ) . 0 . exists ( file_id)
503494 }
0 commit comments