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