@@ -10,7 +10,7 @@ use std::{
10
10
use always_assert:: always;
11
11
use crossbeam_channel:: { select, Receiver } ;
12
12
use flycheck:: FlycheckHandle ;
13
- use ide_db:: base_db:: { SourceDatabase , SourceDatabaseExt , VfsPath } ;
13
+ use ide_db:: base_db:: { SourceDatabaseExt , VfsPath } ;
14
14
use itertools:: Itertools ;
15
15
use lsp_server:: { Connection , Notification , Request } ;
16
16
use lsp_types:: notification:: Notification as _;
@@ -191,7 +191,7 @@ impl GlobalState {
191
191
// NOTE: don't count blocking select! call as a loop-turn time
192
192
let _p = profile:: span ( "GlobalState::handle_event" ) ;
193
193
194
- tracing:: debug!( "handle_event({:?})" , event) ;
194
+ tracing:: debug!( "{:?} handle_event({:?})" , loop_start , event) ;
195
195
let task_queue_len = self . task_pool . handle . len ( ) ;
196
196
if task_queue_len > 0 {
197
197
tracing:: info!( "task queue len: {}" , task_queue_len) ;
@@ -727,7 +727,7 @@ impl GlobalState {
727
727
. insert ( path. clone ( ) , DocumentData :: new ( params. text_document . version ) )
728
728
. is_err ( ) ;
729
729
if already_exists {
730
- tracing:: error!( "duplicate DidOpenTextDocument: {}" , path)
730
+ tracing:: error!( "duplicate DidOpenTextDocument: {}" , path) ;
731
731
}
732
732
this. vfs
733
733
. write ( )
@@ -774,83 +774,98 @@ impl GlobalState {
774
774
Ok ( ( ) )
775
775
} ) ?
776
776
. on :: < lsp_types:: notification:: DidSaveTextDocument > ( |this, params| {
777
- let mut updated = false ;
778
777
if let Ok ( vfs_path) = from_proto:: vfs_path ( & params. text_document . uri ) {
779
- let ( vfs, _) = & * this. vfs . read ( ) ;
780
-
781
- // Trigger flychecks for all workspaces that depend on the saved file
782
- if let Some ( file_id) = vfs. file_id ( & vfs_path) {
783
- let analysis = this. analysis_host . analysis ( ) ;
784
- // Crates containing or depending on the saved file
785
- let crate_ids: Vec < _ > = analysis
786
- . crates_for ( file_id) ?
787
- . into_iter ( )
788
- . flat_map ( |id| {
789
- this. analysis_host
790
- . raw_database ( )
791
- . crate_graph ( )
792
- . transitive_rev_deps ( id)
793
- } )
794
- . sorted ( )
795
- . unique ( )
796
- . collect ( ) ;
797
-
798
- let crate_root_paths: Vec < _ > = crate_ids
799
- . iter ( )
800
- . filter_map ( |& crate_id| {
801
- analysis
802
- . crate_root ( crate_id)
803
- . map ( |file_id| {
804
- vfs. file_path ( file_id) . as_path ( ) . map ( ToOwned :: to_owned)
805
- } )
806
- . transpose ( )
807
- } )
808
- . collect :: < ide:: Cancellable < _ > > ( ) ?;
809
- let crate_root_paths: Vec < _ > =
810
- crate_root_paths. iter ( ) . map ( Deref :: deref) . collect ( ) ;
811
-
812
- // Find all workspaces that have at least one target containing the saved file
813
- let workspace_ids =
814
- this. workspaces . iter ( ) . enumerate ( ) . filter ( |( _, ws) | match ws {
815
- project_model:: ProjectWorkspace :: Cargo { cargo, .. } => {
816
- cargo. packages ( ) . any ( |pkg| {
817
- cargo[ pkg] . targets . iter ( ) . any ( |& it| {
818
- crate_root_paths. contains ( & cargo[ it] . root . as_path ( ) )
819
- } )
820
- } )
821
- }
822
- project_model:: ProjectWorkspace :: Json { project, .. } => project
823
- . crates ( )
824
- . any ( |( c, _) | crate_ids. iter ( ) . any ( |& crate_id| crate_id == c) ) ,
825
- project_model:: ProjectWorkspace :: DetachedFiles { .. } => false ,
826
- } ) ;
827
-
828
- // Find and trigger corresponding flychecks
829
- for flycheck in & this. flycheck {
830
- for ( id, _) in workspace_ids. clone ( ) {
831
- if id == flycheck. id ( ) {
832
- updated = true ;
833
- flycheck. restart ( ) ;
834
- continue ;
835
- }
836
- }
837
- }
838
- }
839
-
840
778
// Re-fetch workspaces if a workspace related file has changed
841
779
if let Some ( abs_path) = vfs_path. as_path ( ) {
842
780
if reload:: should_refresh_for_change ( & abs_path, ChangeKind :: Modify ) {
843
781
this. fetch_workspaces_queue
844
782
. request_op ( format ! ( "DidSaveTextDocument {}" , abs_path. display( ) ) ) ;
845
783
}
846
784
}
785
+
786
+ let file_id = this. vfs . read ( ) . 0 . file_id ( & vfs_path) ;
787
+ if let Some ( file_id) = file_id {
788
+ let world = this. snapshot ( ) ;
789
+ let mut updated = false ;
790
+ let task = move || -> std:: result:: Result < ( ) , ide:: Cancelled > {
791
+ // Trigger flychecks for all workspaces that depend on the saved file
792
+ // Crates containing or depending on the saved file
793
+ let crate_ids: Vec < _ > = world
794
+ . analysis
795
+ . crates_for ( file_id) ?
796
+ . into_iter ( )
797
+ . flat_map ( |id| world. analysis . transitive_rev_deps ( id) )
798
+ . flatten ( )
799
+ . sorted ( )
800
+ . unique ( )
801
+ . collect ( ) ;
802
+
803
+ let crate_root_paths: Vec < _ > = crate_ids
804
+ . iter ( )
805
+ . filter_map ( |& crate_id| {
806
+ world
807
+ . analysis
808
+ . crate_root ( crate_id)
809
+ . map ( |file_id| {
810
+ world
811
+ . file_id_to_file_path ( file_id)
812
+ . as_path ( )
813
+ . map ( ToOwned :: to_owned)
814
+ } )
815
+ . transpose ( )
816
+ } )
817
+ . collect :: < ide:: Cancellable < _ > > ( ) ?;
818
+ let crate_root_paths: Vec < _ > =
819
+ crate_root_paths. iter ( ) . map ( Deref :: deref) . collect ( ) ;
820
+
821
+ // Find all workspaces that have at least one target containing the saved file
822
+ let workspace_ids =
823
+ world. workspaces . iter ( ) . enumerate ( ) . filter ( |( _, ws) | match ws {
824
+ project_model:: ProjectWorkspace :: Cargo { cargo, .. } => {
825
+ cargo. packages ( ) . any ( |pkg| {
826
+ cargo[ pkg] . targets . iter ( ) . any ( |& it| {
827
+ crate_root_paths. contains ( & cargo[ it] . root . as_path ( ) )
828
+ } )
829
+ } )
830
+ }
831
+ project_model:: ProjectWorkspace :: Json { project, .. } => {
832
+ project. crates ( ) . any ( |( c, _) | {
833
+ crate_ids. iter ( ) . any ( |& crate_id| crate_id == c)
834
+ } )
835
+ }
836
+ project_model:: ProjectWorkspace :: DetachedFiles { .. } => false ,
837
+ } ) ;
838
+
839
+ // Find and trigger corresponding flychecks
840
+ for flycheck in world. flycheck . iter ( ) {
841
+ for ( id, _) in workspace_ids. clone ( ) {
842
+ if id == flycheck. id ( ) {
843
+ updated = true ;
844
+ flycheck. restart ( ) ;
845
+ continue ;
846
+ }
847
+ }
848
+ }
849
+ // No specific flycheck was triggered, so let's trigger all of them.
850
+ if !updated {
851
+ for flycheck in world. flycheck . iter ( ) {
852
+ flycheck. restart ( ) ;
853
+ }
854
+ }
855
+ Ok ( ( ) )
856
+ } ;
857
+ this. task_pool . handle . spawn_with_sender ( move |_| {
858
+ if let Err ( e) = std:: panic:: catch_unwind ( task) {
859
+ tracing:: error!( "DidSaveTextDocument flycheck task panicked: {e:?}" )
860
+ }
861
+ } ) ;
862
+ return Ok ( ( ) ) ;
863
+ }
847
864
}
848
865
849
866
// No specific flycheck was triggered, so let's trigger all of them.
850
- if !updated {
851
- for flycheck in & this. flycheck {
852
- flycheck. restart ( ) ;
853
- }
867
+ for flycheck in this. flycheck . iter ( ) {
868
+ flycheck. restart ( ) ;
854
869
}
855
870
Ok ( ( ) )
856
871
} ) ?
0 commit comments