@@ -17,11 +17,11 @@ use vfs::ChangeKind;
1717use crate :: {
1818 config:: Config ,
1919 dispatch:: { NotificationDispatcher , RequestDispatcher } ,
20- document:: DocumentData ,
2120 from_proto,
2221 global_state:: { file_id_to_url, url_to_file_id, GlobalState } ,
2322 handlers, lsp_ext,
2423 lsp_utils:: { apply_document_changes, is_cancelled, notification_is, Progress } ,
24+ mem_docs:: DocumentData ,
2525 reload:: { BuildDataProgress , ProjectWorkspaceProgress } ,
2626 Result ,
2727} ;
@@ -305,7 +305,7 @@ impl GlobalState {
305305 let vfs = & mut self . vfs . write ( ) . 0 ;
306306 for ( path, contents) in files {
307307 let path = VfsPath :: from ( path) ;
308- if !self . mem_docs . contains_key ( & path) {
308+ if !self . mem_docs . contains ( & path) {
309309 vfs. set_file_contents ( path, contents) ;
310310 }
311311 }
@@ -406,25 +406,49 @@ impl GlobalState {
406406 }
407407
408408 let state_changed = self . process_changes ( ) ;
409+ let memdocs_added_or_removed = self . mem_docs . take_changes ( ) ;
409410
410- if self . is_quiescent ( ) && !was_quiescent {
411- for flycheck in & self . flycheck {
412- flycheck. update ( ) ;
411+ if self . is_quiescent ( ) {
412+ if !was_quiescent {
413+ for flycheck in & self . flycheck {
414+ flycheck. update ( ) ;
415+ }
413416 }
414- }
415417
416- if self . is_quiescent ( ) && ( !was_quiescent || state_changed) {
417- self . update_file_notifications_on_threadpool ( ) ;
418+ if !was_quiescent || state_changed {
419+ // Ensure that only one cache priming task can run at a time
420+ self . prime_caches_queue . request_op ( ) ;
421+ if self . prime_caches_queue . should_start_op ( ) {
422+ self . task_pool . handle . spawn_with_sender ( {
423+ let snap = self . snapshot ( ) ;
424+ move |sender| {
425+ let cb = |progress| {
426+ sender. send ( Task :: PrimeCaches ( progress) ) . unwrap ( ) ;
427+ } ;
428+ match snap. analysis . prime_caches ( cb) {
429+ Ok ( ( ) ) => ( ) ,
430+ Err ( _canceled) => ( ) ,
431+ }
432+ }
433+ } ) ;
434+ }
418435
419- // Refresh semantic tokens if the client supports it.
420- if self . config . semantic_tokens_refresh ( ) {
421- self . semantic_tokens_cache . lock ( ) . clear ( ) ;
422- self . send_request :: < lsp_types:: request:: SemanticTokensRefesh > ( ( ) , |_, _| ( ) ) ;
436+ // Refresh semantic tokens if the client supports it.
437+ if self . config . semantic_tokens_refresh ( ) {
438+ self . semantic_tokens_cache . lock ( ) . clear ( ) ;
439+ self . send_request :: < lsp_types:: request:: SemanticTokensRefesh > ( ( ) , |_, _| ( ) ) ;
440+ }
441+
442+ // Refresh code lens if the client supports it.
443+ if self . config . code_lens_refresh ( ) {
444+ self . send_request :: < lsp_types:: request:: CodeLensRefresh > ( ( ) , |_, _| ( ) ) ;
445+ }
423446 }
424447
425- // Refresh code lens if the client supports it.
426- if self . config . code_lens_refresh ( ) {
427- self . send_request :: < lsp_types:: request:: CodeLensRefresh > ( ( ) , |_, _| ( ) ) ;
448+ if !was_quiescent || state_changed || memdocs_added_or_removed {
449+ if self . config . publish_diagnostics ( ) {
450+ self . update_diagnostics ( )
451+ }
428452 }
429453 }
430454
@@ -582,53 +606,43 @@ impl GlobalState {
582606 if this
583607 . mem_docs
584608 . insert ( path. clone ( ) , DocumentData :: new ( params. text_document . version ) )
585- . is_some ( )
609+ . is_err ( )
586610 {
587611 log:: error!( "duplicate DidOpenTextDocument: {}" , path)
588612 }
589- let changed = this
590- . vfs
613+ this. vfs
591614 . write ( )
592615 . 0
593616 . set_file_contents ( path, Some ( params. text_document . text . into_bytes ( ) ) ) ;
594-
595- // If the VFS contents are unchanged, update diagnostics, since `handle_event`
596- // won't see any changes. This avoids missing diagnostics when opening a file.
597- //
598- // If the file *was* changed, `handle_event` will already recompute and send
599- // diagnostics. We can't do it here, since the *current* file contents might be
600- // unset in salsa, since the VFS change hasn't been applied to the database yet.
601- if !changed {
602- this. maybe_update_diagnostics ( ) ;
603- }
604617 }
605618 Ok ( ( ) )
606619 } ) ?
607620 . on :: < lsp_types:: notification:: DidChangeTextDocument > ( |this, params| {
608621 if let Ok ( path) = from_proto:: vfs_path ( & params. text_document . uri ) {
609- let doc = match this. mem_docs . get_mut ( & path) {
610- Some ( doc) => doc,
622+ match this. mem_docs . get_mut ( & path) {
623+ Some ( doc) => {
624+ // The version passed in DidChangeTextDocument is the version after all edits are applied
625+ // so we should apply it before the vfs is notified.
626+ doc. version = params. text_document . version ;
627+ }
611628 None => {
612629 log:: error!( "expected DidChangeTextDocument: {}" , path) ;
613630 return Ok ( ( ) ) ;
614631 }
615632 } ;
633+
616634 let vfs = & mut this. vfs . write ( ) . 0 ;
617635 let file_id = vfs. file_id ( & path) . unwrap ( ) ;
618636 let mut text = String :: from_utf8 ( vfs. file_contents ( file_id) . to_vec ( ) ) . unwrap ( ) ;
619637 apply_document_changes ( & mut text, params. content_changes ) ;
620638
621- // The version passed in DidChangeTextDocument is the version after all edits are applied
622- // so we should apply it before the vfs is notified.
623- doc. version = params. text_document . version ;
624-
625639 vfs. set_file_contents ( path. clone ( ) , Some ( text. into_bytes ( ) ) ) ;
626640 }
627641 Ok ( ( ) )
628642 } ) ?
629643 . on :: < lsp_types:: notification:: DidCloseTextDocument > ( |this, params| {
630644 if let Ok ( path) = from_proto:: vfs_path ( & params. text_document . uri ) {
631- if this. mem_docs . remove ( & path) . is_none ( ) {
645+ if this. mem_docs . remove ( & path) . is_err ( ) {
632646 log:: error!( "orphan DidCloseTextDocument: {}" , path) ;
633647 }
634648
@@ -696,53 +710,33 @@ impl GlobalState {
696710 . finish ( ) ;
697711 Ok ( ( ) )
698712 }
699- fn update_file_notifications_on_threadpool ( & mut self ) {
700- self . maybe_update_diagnostics ( ) ;
701-
702- // Ensure that only one cache priming task can run at a time
703- self . prime_caches_queue . request_op ( ) ;
704- if self . prime_caches_queue . should_start_op ( ) {
705- self . task_pool . handle . spawn_with_sender ( {
706- let snap = self . snapshot ( ) ;
707- move |sender| {
708- let cb = |progress| {
709- sender. send ( Task :: PrimeCaches ( progress) ) . unwrap ( ) ;
710- } ;
711- match snap. analysis . prime_caches ( cb) {
712- Ok ( ( ) ) => ( ) ,
713- Err ( _canceled) => ( ) ,
714- }
715- }
716- } ) ;
717- }
718- }
719- fn maybe_update_diagnostics ( & mut self ) {
713+
714+ fn update_diagnostics ( & mut self ) {
720715 let subscriptions = self
721716 . mem_docs
722- . keys ( )
717+ . iter ( )
723718 . map ( |path| self . vfs . read ( ) . 0 . file_id ( path) . unwrap ( ) )
724719 . collect :: < Vec < _ > > ( ) ;
725720
726721 log:: trace!( "updating notifications for {:?}" , subscriptions) ;
727- if self . config . publish_diagnostics ( ) {
728- let snapshot = self . snapshot ( ) ;
729- self . task_pool . handle . spawn ( move || {
730- let diagnostics = subscriptions
731- . into_iter ( )
732- . filter_map ( |file_id| {
733- handlers:: publish_diagnostics ( & snapshot, file_id)
734- . map_err ( |err| {
735- if !is_cancelled ( & * err) {
736- log:: error!( "failed to compute diagnostics: {:?}" , err) ;
737- }
738- ( )
739- } )
740- . ok ( )
741- . map ( |diags| ( file_id, diags) )
742- } )
743- . collect :: < Vec < _ > > ( ) ;
744- Task :: Diagnostics ( diagnostics)
745- } )
746- }
722+
723+ let snapshot = self . snapshot ( ) ;
724+ self . task_pool . handle . spawn ( move || {
725+ let diagnostics = subscriptions
726+ . into_iter ( )
727+ . filter_map ( |file_id| {
728+ handlers:: publish_diagnostics ( & snapshot, file_id)
729+ . map_err ( |err| {
730+ if !is_cancelled ( & * err) {
731+ log:: error!( "failed to compute diagnostics: {:?}" , err) ;
732+ }
733+ ( )
734+ } )
735+ . ok ( )
736+ . map ( |diags| ( file_id, diags) )
737+ } )
738+ . collect :: < Vec < _ > > ( ) ;
739+ Task :: Diagnostics ( diagnostics)
740+ } )
747741 }
748742}
0 commit comments