@@ -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;
@@ -329,6 +332,7 @@ struct LoopState {
329332 in_flight_libraries : usize ,
330333 pending_libraries : Vec < ( SourceRootId , Vec < ( FileId , RelativePathBuf , Arc < String > ) > ) > ,
331334 workspace_loaded : bool ,
335+ roots_scanned_progress : Option < usize > ,
332336}
333337
334338impl LoopState {
@@ -428,18 +432,14 @@ fn loop_turn(
428432 && loop_state. in_flight_libraries == 0
429433 {
430434 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- }
436435 world_state. check_watcher . update ( ) ;
437436 pool. execute ( {
438437 let subs = loop_state. subscriptions . subscriptions ( ) ;
439438 let snap = world_state. snapshot ( ) ;
440439 move || snap. analysis ( ) . prime_caches ( subs) . unwrap_or_else ( |_: Canceled | ( ) )
441440 } ) ;
442441 }
442+ send_startup_progress ( & connection. sender , loop_state, world_state) ;
443443
444444 if state_changed {
445445 update_file_notifications_on_threadpool (
@@ -703,6 +703,65 @@ fn on_diagnostic_task(task: DiagnosticTask, msg_sender: &Sender<Message>, state:
703703 }
704704}
705705
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+
706765struct PoolDispatcher < ' a > {
707766 req : Option < Request > ,
708767 pool : & ' a ThreadPool ,
0 commit comments