@@ -703,6 +703,88 @@ impl GlobalState {
703703
704704 /// Handles an incoming notification.
705705 fn on_notification ( & mut self , not : Notification ) -> Result < ( ) > {
706+ // FIXME: Move these implementations out into a module similar to on_request
707+ fn run_flycheck ( this : & mut GlobalState , vfs_path : VfsPath ) -> bool {
708+ let file_id = this. vfs . read ( ) . 0 . file_id ( & vfs_path) ;
709+ if let Some ( file_id) = file_id {
710+ let world = this. snapshot ( ) ;
711+ let mut updated = false ;
712+ let task = move || -> std:: result:: Result < ( ) , ide:: Cancelled > {
713+ // Trigger flychecks for all workspaces that depend on the saved file
714+ // Crates containing or depending on the saved file
715+ let crate_ids: Vec < _ > = world
716+ . analysis
717+ . crates_for ( file_id) ?
718+ . into_iter ( )
719+ . flat_map ( |id| world. analysis . transitive_rev_deps ( id) )
720+ . flatten ( )
721+ . sorted ( )
722+ . unique ( )
723+ . collect ( ) ;
724+
725+ let crate_root_paths: Vec < _ > = crate_ids
726+ . iter ( )
727+ . filter_map ( |& crate_id| {
728+ world
729+ . analysis
730+ . crate_root ( crate_id)
731+ . map ( |file_id| {
732+ world
733+ . file_id_to_file_path ( file_id)
734+ . as_path ( )
735+ . map ( ToOwned :: to_owned)
736+ } )
737+ . transpose ( )
738+ } )
739+ . collect :: < ide:: Cancellable < _ > > ( ) ?;
740+ let crate_root_paths: Vec < _ > =
741+ crate_root_paths. iter ( ) . map ( Deref :: deref) . collect ( ) ;
742+
743+ // Find all workspaces that have at least one target containing the saved file
744+ let workspace_ids =
745+ world. workspaces . iter ( ) . enumerate ( ) . filter ( |( _, ws) | match ws {
746+ project_model:: ProjectWorkspace :: Cargo { cargo, .. } => {
747+ cargo. packages ( ) . any ( |pkg| {
748+ cargo[ pkg] . targets . iter ( ) . any ( |& it| {
749+ crate_root_paths. contains ( & cargo[ it] . root . as_path ( ) )
750+ } )
751+ } )
752+ }
753+ project_model:: ProjectWorkspace :: Json { project, .. } => project
754+ . crates ( )
755+ . any ( |( c, _) | crate_ids. iter ( ) . any ( |& crate_id| crate_id == c) ) ,
756+ project_model:: ProjectWorkspace :: DetachedFiles { .. } => false ,
757+ } ) ;
758+
759+ // Find and trigger corresponding flychecks
760+ for flycheck in world. flycheck . iter ( ) {
761+ for ( id, _) in workspace_ids. clone ( ) {
762+ if id == flycheck. id ( ) {
763+ updated = true ;
764+ flycheck. restart ( ) ;
765+ continue ;
766+ }
767+ }
768+ }
769+ // No specific flycheck was triggered, so let's trigger all of them.
770+ if !updated {
771+ for flycheck in world. flycheck . iter ( ) {
772+ flycheck. restart ( ) ;
773+ }
774+ }
775+ Ok ( ( ) )
776+ } ;
777+ this. task_pool . handle . spawn_with_sender ( move |_| {
778+ if let Err ( e) = std:: panic:: catch_unwind ( task) {
779+ tracing:: error!( "flycheck task panicked: {e:?}" )
780+ }
781+ } ) ;
782+ true
783+ } else {
784+ false
785+ }
786+ }
787+
706788 NotificationDispatcher { not : Some ( not) , global_state : self }
707789 . on :: < lsp_types:: notification:: Cancel > ( |this, params| {
708790 let id: lsp_server:: RequestId = match params. id {
@@ -782,6 +864,20 @@ impl GlobalState {
782864 }
783865 Ok ( ( ) )
784866 } ) ?
867+ . on :: < lsp_ext:: RunFlycheck > ( |this, params| {
868+ if let Some ( text_document) = params. text_document {
869+ if let Ok ( vfs_path) = from_proto:: vfs_path ( & text_document. uri ) {
870+ if run_flycheck ( this, vfs_path) {
871+ return Ok ( ( ) ) ;
872+ }
873+ }
874+ }
875+ // No specific flycheck was triggered, so let's trigger all of them.
876+ for flycheck in this. flycheck . iter ( ) {
877+ flycheck. restart ( ) ;
878+ }
879+ Ok ( ( ) )
880+ } ) ?
785881 . on :: < lsp_types:: notification:: DidSaveTextDocument > ( |this, params| {
786882 if let Ok ( vfs_path) = from_proto:: vfs_path ( & params. text_document . uri ) {
787883 // Re-fetch workspaces if a workspace related file has changed
@@ -792,82 +888,7 @@ impl GlobalState {
792888 }
793889 }
794890
795- let file_id = this. vfs . read ( ) . 0 . file_id ( & vfs_path) ;
796- if let Some ( file_id) = file_id {
797- let world = this. snapshot ( ) ;
798- let mut updated = false ;
799- let task = move || -> std:: result:: Result < ( ) , ide:: Cancelled > {
800- // Trigger flychecks for all workspaces that depend on the saved file
801- // Crates containing or depending on the saved file
802- let crate_ids: Vec < _ > = world
803- . analysis
804- . crates_for ( file_id) ?
805- . into_iter ( )
806- . flat_map ( |id| world. analysis . transitive_rev_deps ( id) )
807- . flatten ( )
808- . sorted ( )
809- . unique ( )
810- . collect ( ) ;
811-
812- let crate_root_paths: Vec < _ > = crate_ids
813- . iter ( )
814- . filter_map ( |& crate_id| {
815- world
816- . analysis
817- . crate_root ( crate_id)
818- . map ( |file_id| {
819- world
820- . file_id_to_file_path ( file_id)
821- . as_path ( )
822- . map ( ToOwned :: to_owned)
823- } )
824- . transpose ( )
825- } )
826- . collect :: < ide:: Cancellable < _ > > ( ) ?;
827- let crate_root_paths: Vec < _ > =
828- crate_root_paths. iter ( ) . map ( Deref :: deref) . collect ( ) ;
829-
830- // Find all workspaces that have at least one target containing the saved file
831- let workspace_ids =
832- world. workspaces . iter ( ) . enumerate ( ) . filter ( |( _, ws) | match ws {
833- project_model:: ProjectWorkspace :: Cargo { cargo, .. } => {
834- cargo. packages ( ) . any ( |pkg| {
835- cargo[ pkg] . targets . iter ( ) . any ( |& it| {
836- crate_root_paths. contains ( & cargo[ it] . root . as_path ( ) )
837- } )
838- } )
839- }
840- project_model:: ProjectWorkspace :: Json { project, .. } => {
841- project. crates ( ) . any ( |( c, _) | {
842- crate_ids. iter ( ) . any ( |& crate_id| crate_id == c)
843- } )
844- }
845- project_model:: ProjectWorkspace :: DetachedFiles { .. } => false ,
846- } ) ;
847-
848- // Find and trigger corresponding flychecks
849- for flycheck in world. flycheck . iter ( ) {
850- for ( id, _) in workspace_ids. clone ( ) {
851- if id == flycheck. id ( ) {
852- updated = true ;
853- flycheck. restart ( ) ;
854- continue ;
855- }
856- }
857- }
858- // No specific flycheck was triggered, so let's trigger all of them.
859- if !updated {
860- for flycheck in world. flycheck . iter ( ) {
861- flycheck. restart ( ) ;
862- }
863- }
864- Ok ( ( ) )
865- } ;
866- this. task_pool . handle . spawn_with_sender ( move |_| {
867- if let Err ( e) = std:: panic:: catch_unwind ( task) {
868- tracing:: error!( "DidSaveTextDocument flycheck task panicked: {e:?}" )
869- }
870- } ) ;
891+ if run_flycheck ( this, vfs_path) {
871892 return Ok ( ( ) ) ;
872893 }
873894 }
0 commit comments