@@ -16,7 +16,10 @@ use std::{
1616
1717use crossbeam_channel:: { select, unbounded, RecvError , Sender } ;
1818use 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+ } ;
2023use ra_cargo_watch:: { url_from_path_with_drive_lowercasing, CheckOptions , CheckTask } ;
2124use ra_ide:: { Canceled , FileId , InlayHintsOptions , LibraryData , SourceRootId } ;
2225use ra_prof:: profile;
@@ -330,6 +333,7 @@ struct LoopState {
330333 in_flight_libraries : usize ,
331334 pending_libraries : Vec < ( SourceRootId , Vec < ( FileId , RelativePathBuf , Arc < String > ) > ) > ,
332335 workspace_loaded : bool ,
336+ roots_scanned_progress : Option < usize > ,
333337}
334338
335339impl LoopState {
@@ -429,17 +433,15 @@ fn loop_turn(
429433 && loop_state. in_flight_libraries == 0
430434 {
431435 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- }
437436 world_state. check_watcher . update ( ) ;
438437 pool. execute ( {
439438 let subs = loop_state. subscriptions . subscriptions ( ) ;
440439 let snap = world_state. snapshot ( ) ;
441440 move || snap. analysis ( ) . prime_caches ( subs) . unwrap_or_else ( |_: Canceled | ( ) )
442441 } ) ;
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) ;
443445 }
444446
445447 if state_changed {
@@ -704,6 +706,65 @@ fn on_diagnostic_task(task: DiagnosticTask, msg_sender: &Sender<Message>, state:
704706 }
705707}
706708
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+
707768struct PoolDispatcher < ' a > {
708769 req : Option < Request > ,
709770 pool : & ' a ThreadPool ,
0 commit comments