@@ -56,6 +56,8 @@ pub use crate::{
5656} ;
5757pub use paths:: { AbsPath , AbsPathBuf } ;
5858
59+ use rustc_hash:: FxHasher ;
60+ use stdx:: hash_once;
5961use tracing:: { span, Level } ;
6062
6163/// Handle to a file in [`Vfs`]
@@ -106,7 +108,7 @@ pub enum FileState {
106108 /// The file has been created this cycle.
107109 Created ,
108110 /// The file exists.
109- Exists ,
111+ Exists ( u64 ) ,
110112 /// The file is deleted.
111113 Deleted ,
112114}
@@ -139,13 +141,13 @@ impl ChangedFile {
139141
140142 /// Returns `true` if the change is [`Modify`](ChangeKind::Modify).
141143 pub fn is_modified ( & self ) -> bool {
142- matches ! ( self . change, Change :: Modify ( _) )
144+ matches ! ( self . change, Change :: Modify ( _, _ ) )
143145 }
144146
145147 pub fn kind ( & self ) -> ChangeKind {
146148 match self . change {
147149 Change :: Create ( _) => ChangeKind :: Create ,
148- Change :: Modify ( _) => ChangeKind :: Modify ,
150+ Change :: Modify ( _, _ ) => ChangeKind :: Modify ,
149151 Change :: Delete => ChangeKind :: Delete ,
150152 }
151153 }
@@ -157,7 +159,7 @@ pub enum Change {
157159 /// The file was (re-)created
158160 Create ( Vec < u8 > ) ,
159161 /// The file was modified
160- Modify ( Vec < u8 > ) ,
162+ Modify ( Vec < u8 > , u64 ) ,
161163 /// The file was deleted
162164 Delete ,
163165}
@@ -178,7 +180,7 @@ impl Vfs {
178180 pub fn file_id ( & self , path : & VfsPath ) -> Option < FileId > {
179181 self . interner
180182 . get ( path)
181- . filter ( |& it| matches ! ( self . get( it) , FileState :: Exists | FileState :: Created ) )
183+ . filter ( |& it| matches ! ( self . get( it) , FileState :: Exists ( _ ) | FileState :: Created ) )
182184 }
183185
184186 /// File path corresponding to the given `file_id`.
@@ -197,7 +199,7 @@ impl Vfs {
197199 ( 0 ..self . data . len ( ) )
198200 . map ( |it| FileId ( it as u32 ) )
199201 . filter ( move |& file_id| {
200- matches ! ( self . get( file_id) , FileState :: Exists | FileState :: Created )
202+ matches ! ( self . get( file_id) , FileState :: Exists ( _ ) | FileState :: Created )
201203 } )
202204 . map ( move |file_id| {
203205 let path = self . interner . lookup ( file_id) ;
@@ -218,8 +220,18 @@ impl Vfs {
218220 let change_kind = match ( state, contents) {
219221 ( FileState :: Deleted , None ) => return false ,
220222 ( FileState :: Deleted , Some ( v) ) => Change :: Create ( v) ,
221- ( FileState :: Exists | FileState :: Created , None ) => Change :: Delete ,
222- ( FileState :: Exists | FileState :: Created , Some ( v) ) => Change :: Modify ( v) ,
223+ ( FileState :: Exists ( _) | FileState :: Created , None ) => Change :: Delete ,
224+ ( FileState :: Created , Some ( v) ) => {
225+ let hash = hash_once :: < FxHasher > ( & * v) ;
226+ Change :: Modify ( v, hash)
227+ }
228+ ( FileState :: Exists ( hash) , Some ( v) ) => {
229+ let new_hash = hash_once :: < FxHasher > ( & * v) ;
230+ if new_hash == hash {
231+ return false ;
232+ }
233+ Change :: Modify ( v, new_hash)
234+ }
223235 } ;
224236 self . data [ file_id. 0 as usize ] = match change_kind {
225237 Change :: Create ( _) => {
@@ -228,8 +240,8 @@ impl Vfs {
228240 }
229241 // If the file got created this cycle, make sure we keep it that way even
230242 // if a modify comes in
231- Change :: Modify ( _) if matches ! ( state, FileState :: Created ) => FileState :: Created ,
232- Change :: Modify ( _) => FileState :: Exists ,
243+ Change :: Modify ( _, _ ) if matches ! ( state, FileState :: Created ) => FileState :: Created ,
244+ Change :: Modify ( _, hash ) => FileState :: Exists ( hash ) ,
233245 Change :: Delete => FileState :: Deleted ,
234246 } ;
235247 let changed_file = ChangedFile { file_id, change : change_kind } ;
@@ -243,15 +255,15 @@ impl Vfs {
243255 for file_id in self . created_this_cycle . drain ( ..) {
244256 if self . data [ file_id. 0 as usize ] == FileState :: Created {
245257 // downgrade the file from `Created` to `Exists` as the cycle is done
246- self . data [ file_id. 0 as usize ] = FileState :: Exists ;
258+ self . data [ file_id. 0 as usize ] = FileState :: Exists ( todo ! ( ) ) ;
247259 }
248260 }
249261 mem:: take ( & mut self . changes )
250262 }
251263
252264 /// Provides a panic-less way to verify file_id validity.
253265 pub fn exists ( & self , file_id : FileId ) -> bool {
254- matches ! ( self . get( file_id) , FileState :: Exists | FileState :: Created )
266+ matches ! ( self . get( file_id) , FileState :: Exists ( _ ) | FileState :: Created )
255267 }
256268
257269 /// Returns the id associated with `path`
0 commit comments