@@ -98,10 +98,9 @@ impl Workspace {
9898 document : TextDocument ,
9999 ) -> Option < WorkspaceFileEvent > {
100100 self . buffers . open ( url. clone ( ) , document) ;
101- self . ensure_file_for_url ( db, url) . inspect ( |event| {
102- if let WorkspaceFileEvent :: Updated { file, .. } = event {
103- db. touch_file ( * file) ;
104- }
101+ self . ensure_file_for_url ( db, url) . map ( |event| {
102+ db. touch_file ( event. file ( ) ) ;
103+ event
105104 } )
106105 }
107106
@@ -128,8 +127,9 @@ impl Workspace {
128127 }
129128 }
130129
131- self . ensure_file_for_url ( db, url) . inspect ( |event| {
130+ self . ensure_file_for_url ( db, url) . map ( |event| {
132131 db. touch_file ( event. file ( ) ) ;
132+ event
133133 } )
134134 }
135135
@@ -153,20 +153,23 @@ impl Workspace {
153153 /// Touch the tracked file when the client saves the document.
154154 pub fn save_document ( & self , db : & mut dyn Db , url : & Url ) -> Option < WorkspaceFileEvent > {
155155 let path = paths:: url_to_path ( url) ?;
156+
156157 let event = self . track_file ( db, path. as_path ( ) ) ;
157158 db. touch_file ( event. file ( ) ) ;
158159 Some ( event)
159160 }
160161
161162 /// Close a document, removing it from buffers and touching the tracked file.
162163 pub fn close_document ( & mut self , db : & mut dyn Db , url : & Url ) -> Option < TextDocument > {
164+ let closed = self . buffers . close ( url) ;
165+
163166 if let Some ( path) = paths:: url_to_path ( url) {
164167 if let Some ( file) = self . files . get ( & path) {
165168 db. touch_file ( * file) ;
166169 }
167170 }
168171
169- self . buffers . close ( url )
172+ closed
170173 }
171174
172175 /// Get a document from the buffer if it's open.
@@ -202,12 +205,12 @@ mod tests {
202205 use std:: sync:: Arc ;
203206
204207 use camino:: Utf8Path ;
208+ use camino:: Utf8PathBuf ;
205209 use tempfile:: tempdir;
206210 use url:: Url ;
207211
208212 use super :: * ;
209213 use crate :: encoding:: PositionEncoding ;
210- use crate :: InMemoryFileSystem ;
211214 use crate :: LanguageId ;
212215
213216 #[ salsa:: db]
@@ -218,10 +221,10 @@ mod tests {
218221 }
219222
220223 impl TestDb {
221- fn new ( ) -> Self {
224+ fn new ( fs : Arc < dyn FileSystem > ) -> Self {
222225 Self {
223226 storage : salsa:: Storage :: default ( ) ,
224- fs : Arc :: new ( InMemoryFileSystem :: new ( ) ) ,
227+ fs,
225228 }
226229 }
227230 }
@@ -231,8 +234,8 @@ mod tests {
231234
232235 #[ salsa:: db]
233236 impl djls_source:: Db for TestDb {
234- fn read_file_source ( & self , _path : & Utf8Path ) -> std:: io:: Result < String > {
235- Ok ( String :: new ( ) )
237+ fn read_file_source ( & self , path : & Utf8Path ) -> std:: io:: Result < String > {
238+ self . fs . read_to_string ( path )
236239 }
237240 }
238241
@@ -246,7 +249,7 @@ mod tests {
246249 #[ test]
247250 fn test_open_document ( ) {
248251 let mut workspace = Workspace :: new ( ) ;
249- let mut db = TestDb :: new ( ) ;
252+ let mut db = TestDb :: new ( workspace . file_system ( ) ) ;
250253 let url = Url :: parse ( "file:///test.py" ) . unwrap ( ) ;
251254
252255 let document = TextDocument :: new ( "print('hello')" . to_string ( ) , 1 , LanguageId :: Python ) ;
@@ -264,7 +267,7 @@ mod tests {
264267 #[ test]
265268 fn test_update_document ( ) {
266269 let mut workspace = Workspace :: new ( ) ;
267- let mut db = TestDb :: new ( ) ;
270+ let mut db = TestDb :: new ( workspace . file_system ( ) ) ;
268271 let url = Url :: parse ( "file:///test.py" ) . unwrap ( ) ;
269272
270273 let document = TextDocument :: new ( "initial" . to_string ( ) , 1 , LanguageId :: Python ) ;
@@ -288,7 +291,7 @@ mod tests {
288291 #[ test]
289292 fn test_close_document ( ) {
290293 let mut workspace = Workspace :: new ( ) ;
291- let mut db = TestDb :: new ( ) ;
294+ let mut db = TestDb :: new ( workspace . file_system ( ) ) ;
292295 let url = Url :: parse ( "file:///test.py" ) . unwrap ( ) ;
293296
294297 let document = TextDocument :: new ( "content" . to_string ( ) , 1 , LanguageId :: Python ) ;
@@ -306,7 +309,7 @@ mod tests {
306309 std:: fs:: write ( & file_path, "disk content" ) . unwrap ( ) ;
307310
308311 let mut workspace = Workspace :: new ( ) ;
309- let mut db = TestDb :: new ( ) ;
312+ let mut db = TestDb :: new ( workspace . file_system ( ) ) ;
310313 let url = Url :: from_file_path ( & file_path) . unwrap ( ) ;
311314
312315 let document = TextDocument :: new ( "buffer content" . to_string ( ) , 1 , LanguageId :: Python ) ;
@@ -318,4 +321,77 @@ mod tests {
318321 . unwrap ( ) ;
319322 assert_eq ! ( content, "buffer content" ) ;
320323 }
324+
325+ #[ test]
326+ fn test_file_source_reads_from_buffer ( ) {
327+ let mut workspace = Workspace :: new ( ) ;
328+ let mut db = TestDb :: new ( workspace. file_system ( ) ) ;
329+
330+ let temp_dir = tempdir ( ) . unwrap ( ) ;
331+ let file_path = Utf8PathBuf :: from_path_buf ( temp_dir. path ( ) . join ( "template.html" ) ) . unwrap ( ) ;
332+ std:: fs:: write ( file_path. as_std_path ( ) , "disk template" ) . unwrap ( ) ;
333+ let url = Url :: from_file_path ( file_path. as_std_path ( ) ) . unwrap ( ) ;
334+
335+ let document = TextDocument :: new ( "line1\n line2" . to_string ( ) , 1 , LanguageId :: HtmlDjango ) ;
336+ let event = workspace
337+ . open_document ( & mut db, & url, document. clone ( ) )
338+ . unwrap ( ) ;
339+ let file = event. file ( ) ;
340+
341+ let source = file. source ( & db) ;
342+ assert_eq ! ( source. as_str( ) , document. content( ) ) ;
343+
344+ let line_index = file. line_index ( & db) ;
345+ assert_eq ! ( line_index. to_line_col( 0 ) , ( 0 , 0 ) ) ;
346+ assert_eq ! ( line_index. to_line_col( 6 ) , ( 1 , 0 ) ) ;
347+ }
348+
349+ #[ test]
350+ fn test_update_document_updates_source ( ) {
351+ let mut workspace = Workspace :: new ( ) ;
352+ let mut db = TestDb :: new ( workspace. file_system ( ) ) ;
353+
354+ let temp_dir = tempdir ( ) . unwrap ( ) ;
355+ let file_path = Utf8PathBuf :: from_path_buf ( temp_dir. path ( ) . join ( "buffer.py" ) ) . unwrap ( ) ;
356+ std:: fs:: write ( file_path. as_std_path ( ) , "disk" ) . unwrap ( ) ;
357+ let url = Url :: from_file_path ( file_path. as_std_path ( ) ) . unwrap ( ) ;
358+
359+ let document = TextDocument :: new ( "initial" . to_string ( ) , 1 , LanguageId :: Python ) ;
360+ let event = workspace. open_document ( & mut db, & url, document) . unwrap ( ) ;
361+ let file = event. file ( ) ;
362+
363+ let changes = vec ! [ TextDocumentContentChangeEvent {
364+ range: None ,
365+ range_length: None ,
366+ text: "updated" . to_string( ) ,
367+ } ] ;
368+ workspace
369+ . update_document ( & mut db, & url, changes, 2 , PositionEncoding :: Utf16 )
370+ . unwrap ( ) ;
371+
372+ let source = file. source ( & db) ;
373+ assert_eq ! ( source. as_str( ) , "updated" ) ;
374+ }
375+
376+ #[ test]
377+ fn test_close_document_reverts_to_disk ( ) {
378+ let mut workspace = Workspace :: new ( ) ;
379+ let mut db = TestDb :: new ( workspace. file_system ( ) ) ;
380+
381+ let temp_dir = tempdir ( ) . unwrap ( ) ;
382+ let file_path = Utf8PathBuf :: from_path_buf ( temp_dir. path ( ) . join ( "close.py" ) ) . unwrap ( ) ;
383+ std:: fs:: write ( file_path. as_std_path ( ) , "disk content" ) . unwrap ( ) ;
384+ let url = Url :: from_file_path ( file_path. as_std_path ( ) ) . unwrap ( ) ;
385+
386+ let document = TextDocument :: new ( "buffer content" . to_string ( ) , 1 , LanguageId :: Python ) ;
387+ let event = workspace. open_document ( & mut db, & url, document) . unwrap ( ) ;
388+ let file = event. file ( ) ;
389+
390+ assert_eq ! ( file. source( & db) . as_str( ) , "buffer content" ) ;
391+
392+ workspace. close_document ( & mut db, & url) ;
393+
394+ let source_after = file. source ( & db) ;
395+ assert_eq ! ( source_after. as_str( ) , "disk content" ) ;
396+ }
321397}
0 commit comments