@@ -16,7 +16,10 @@ use std::{
16
16
17
17
use crossbeam_channel:: { select, unbounded, RecvError , Sender } ;
18
18
use lsp_server:: { Connection , ErrorCode , Message , Notification , Request , RequestId , Response } ;
19
- use lsp_types:: { ClientCapabilities , NumberOrString } ;
19
+ use lsp_types:: {
20
+ ClientCapabilities , NumberOrString , WorkDoneProgress , WorkDoneProgressBegin ,
21
+ WorkDoneProgressCreateParams , WorkDoneProgressEnd , WorkDoneProgressReport ,
22
+ } ;
20
23
use ra_cargo_watch:: { url_from_path_with_drive_lowercasing, CheckOptions , CheckTask } ;
21
24
use ra_ide:: { Canceled , FileId , InlayHintsOptions , LibraryData , SourceRootId } ;
22
25
use ra_prof:: profile;
@@ -330,6 +333,7 @@ struct LoopState {
330
333
in_flight_libraries : usize ,
331
334
pending_libraries : Vec < ( SourceRootId , Vec < ( FileId , RelativePathBuf , Arc < String > ) > ) > ,
332
335
workspace_loaded : bool ,
336
+ roots_scanned_progress : Option < usize > ,
333
337
}
334
338
335
339
impl LoopState {
@@ -429,17 +433,15 @@ fn loop_turn(
429
433
&& loop_state. in_flight_libraries == 0
430
434
{
431
435
loop_state. workspace_loaded = true ;
432
- let n_packages: usize = world_state. workspaces . iter ( ) . map ( |it| it. n_packages ( ) ) . sum ( ) ;
433
- if world_state. feature_flags . get ( "notifications.workspace-loaded" ) {
434
- let msg = format ! ( "workspace loaded, {} rust packages" , n_packages) ;
435
- show_message ( req:: MessageType :: Info , msg, & connection. sender ) ;
436
- }
437
436
world_state. check_watcher . update ( ) ;
438
437
pool. execute ( {
439
438
let subs = loop_state. subscriptions . subscriptions ( ) ;
440
439
let snap = world_state. snapshot ( ) ;
441
440
move || snap. analysis ( ) . prime_caches ( subs) . unwrap_or_else ( |_: Canceled | ( ) )
442
441
} ) ;
442
+ send_startup_progress ( & connection. sender , loop_state, world_state) ;
443
+ } else if !loop_state. workspace_loaded {
444
+ send_startup_progress ( & connection. sender , loop_state, world_state) ;
443
445
}
444
446
445
447
if state_changed {
@@ -704,6 +706,65 @@ fn on_diagnostic_task(task: DiagnosticTask, msg_sender: &Sender<Message>, state:
704
706
}
705
707
}
706
708
709
+ fn send_startup_progress (
710
+ sender : & Sender < Message > ,
711
+ loop_state : & mut LoopState ,
712
+ world_state : & WorldState ,
713
+ ) {
714
+ if !world_state. feature_flags . get ( "notifications.workspace-loaded" ) {
715
+ return ;
716
+ }
717
+
718
+ let total: usize = world_state. workspaces . iter ( ) . map ( |it| it. n_packages ( ) ) . sum ( ) ;
719
+ let prev_progress = loop_state. roots_scanned_progress ;
720
+ let progress = total - world_state. roots_to_scan ;
721
+ loop_state. roots_scanned_progress = Some ( progress) ;
722
+
723
+ match ( prev_progress, loop_state. workspace_loaded ) {
724
+ ( None , false ) => {
725
+ let work_done_progress_create = request_new :: < req:: WorkDoneProgressCreate > (
726
+ loop_state. next_request_id ( ) ,
727
+ WorkDoneProgressCreateParams {
728
+ token : req:: ProgressToken :: String ( "rustAnalyzer/startup" . into ( ) ) ,
729
+ } ,
730
+ ) ;
731
+ sender. send ( work_done_progress_create. into ( ) ) . unwrap ( ) ;
732
+ send_startup_progress_notif (
733
+ sender,
734
+ WorkDoneProgress :: Begin ( WorkDoneProgressBegin {
735
+ title : "rust-analyzer" . into ( ) ,
736
+ cancellable : None ,
737
+ message : Some ( format ! ( "{}/{} packages" , progress, total) ) ,
738
+ percentage : Some ( 100.0 * progress as f64 / total as f64 ) ,
739
+ } ) ,
740
+ ) ;
741
+ }
742
+ ( Some ( prev) , false ) if progress != prev => send_startup_progress_notif (
743
+ sender,
744
+ WorkDoneProgress :: Report ( WorkDoneProgressReport {
745
+ cancellable : None ,
746
+ message : Some ( format ! ( "{}/{} packages" , progress, total) ) ,
747
+ percentage : Some ( 100.0 * progress as f64 / total as f64 ) ,
748
+ } ) ,
749
+ ) ,
750
+ ( _, true ) => send_startup_progress_notif (
751
+ sender,
752
+ WorkDoneProgress :: End ( WorkDoneProgressEnd {
753
+ message : Some ( format ! ( "rust-analyzer loaded, {} packages" , progress) ) ,
754
+ } ) ,
755
+ ) ,
756
+ _ => { }
757
+ }
758
+ }
759
+
760
+ fn send_startup_progress_notif ( sender : & Sender < Message > , work_done_progress : WorkDoneProgress ) {
761
+ let notif = notification_new :: < req:: Progress > ( req:: ProgressParams {
762
+ token : req:: ProgressToken :: String ( "rustAnalyzer/startup" . into ( ) ) ,
763
+ value : req:: ProgressParamsValue :: WorkDone ( work_done_progress) ,
764
+ } ) ;
765
+ sender. send ( notif. into ( ) ) . unwrap ( ) ;
766
+ }
767
+
707
768
struct PoolDispatcher < ' a > {
708
769
req : Option < Request > ,
709
770
pool : & ' a ThreadPool ,
0 commit comments