2
2
//! requests/replies and notifications back to the client.
3
3
use std:: {
4
4
env, fmt,
5
+ sync:: Arc ,
5
6
time:: { Duration , Instant } ,
6
7
} ;
7
8
@@ -12,14 +13,15 @@ use ide::{Canceled, FileId};
12
13
use ide_db:: base_db:: VfsPath ;
13
14
use lsp_server:: { Connection , Notification , Request , Response } ;
14
15
use lsp_types:: notification:: Notification as _;
16
+ use project_model:: BuildDataCollector ;
15
17
use vfs:: ChangeKind ;
16
18
17
19
use crate :: {
18
20
config:: Config ,
19
21
dispatch:: { NotificationDispatcher , RequestDispatcher } ,
20
22
document:: DocumentData ,
21
23
from_proto,
22
- global_state:: { file_id_to_url, url_to_file_id, GlobalState , Status } ,
24
+ global_state:: { file_id_to_url, url_to_file_id, GlobalState } ,
23
25
handlers, lsp_ext,
24
26
lsp_utils:: { apply_document_changes, is_canceled, notification_is, Progress } ,
25
27
reload:: { BuildDataProgress , ProjectWorkspaceProgress } ,
@@ -187,7 +189,7 @@ impl GlobalState {
187
189
log:: info!( "task queue len: {}" , task_queue_len) ;
188
190
}
189
191
190
- let mut new_status = self . status ;
192
+ let was_quiescent = self . is_quiescent ( ) ;
191
193
match event {
192
194
Event :: Lsp ( msg) => match msg {
193
195
lsp_server:: Message :: Request ( req) => self . on_request ( loop_start, req) ?,
@@ -227,11 +229,24 @@ impl GlobalState {
227
229
( Progress :: Report , Some ( msg) )
228
230
}
229
231
ProjectWorkspaceProgress :: End ( workspaces) => {
230
- self . fetch_workspaces_completed ( ) ;
231
- self . switch_workspaces ( workspaces, None ) ;
232
+ self . fetch_workspaces_completed ( workspaces) ;
233
+
234
+ let old = Arc :: clone ( & self . workspaces ) ;
235
+ self . switch_workspaces ( ) ;
236
+ let workspaces_updated = !Arc :: ptr_eq ( & old, & self . workspaces ) ;
237
+
238
+ if self . config . run_build_scripts ( ) && workspaces_updated {
239
+ let mut collector = BuildDataCollector :: default ( ) ;
240
+ for ws in self . workspaces . iter ( ) {
241
+ ws. collect_build_data_configs ( & mut collector) ;
242
+ }
243
+ self . fetch_build_data_request ( collector)
244
+ }
245
+
232
246
( Progress :: End , None )
233
247
}
234
248
} ;
249
+
235
250
self . report_progress ( "fetching" , state, msg, None ) ;
236
251
}
237
252
Task :: FetchBuildData ( progress) => {
@@ -240,19 +255,21 @@ impl GlobalState {
240
255
BuildDataProgress :: Report ( msg) => {
241
256
( Some ( Progress :: Report ) , Some ( msg) )
242
257
}
243
- BuildDataProgress :: End ( collector ) => {
244
- self . fetch_build_data_completed ( ) ;
245
- let workspaces =
246
- ( * self . workspaces ) . clone ( ) . into_iter ( ) . map ( Ok ) . collect ( ) ;
247
- self . switch_workspaces ( workspaces , Some ( collector ) ) ;
258
+ BuildDataProgress :: End ( build_data_result ) => {
259
+ self . fetch_build_data_completed ( build_data_result ) ;
260
+
261
+ self . switch_workspaces ( ) ;
262
+
248
263
( Some ( Progress :: End ) , None )
249
264
}
250
265
} ;
266
+
251
267
if let Some ( state) = state {
252
268
self . report_progress ( "loading" , state, msg, None ) ;
253
269
}
254
270
}
255
271
}
272
+
256
273
// Coalesce multiple task events into one loop turn
257
274
task = match self . task_pool . receiver . try_recv ( ) {
258
275
Ok ( task) => task,
@@ -298,30 +315,25 @@ impl GlobalState {
298
315
}
299
316
vfs:: loader:: Message :: Progress { n_total, n_done, config_version } => {
300
317
always ! ( config_version <= self . vfs_config_version) ;
301
- if n_total == 0 {
302
- new_status = Status :: Invalid ;
318
+
319
+ self . vfs_progress_config_version = config_version;
320
+ self . vfs_progress_n_total = n_total;
321
+ self . vfs_progress_n_done = n_done;
322
+
323
+ let state = if n_done == 0 {
324
+ Progress :: Begin
325
+ } else if n_done < n_total {
326
+ Progress :: Report
303
327
} else {
304
- let state = if n_done == 0 {
305
- new_status = Status :: Loading ;
306
- Progress :: Begin
307
- } else if n_done < n_total {
308
- Progress :: Report
309
- } else {
310
- assert_eq ! ( n_done, n_total) ;
311
- new_status = Status :: Ready {
312
- partial : self . config . run_build_scripts ( )
313
- && self . workspace_build_data . is_none ( )
314
- || config_version < self . vfs_config_version ,
315
- } ;
316
- Progress :: End
317
- } ;
318
- self . report_progress (
319
- "roots scanned" ,
320
- state,
321
- Some ( format ! ( "{}/{}" , n_done, n_total) ) ,
322
- Some ( Progress :: fraction ( n_done, n_total) ) ,
323
- )
324
- }
328
+ assert_eq ! ( n_done, n_total) ;
329
+ Progress :: End
330
+ } ;
331
+ self . report_progress (
332
+ "roots scanned" ,
333
+ state,
334
+ Some ( format ! ( "{}/{}" , n_done, n_total) ) ,
335
+ Some ( Progress :: fraction ( n_done, n_total) ) ,
336
+ )
325
337
}
326
338
}
327
339
// Coalesce many VFS event into a single loop turn
@@ -397,18 +409,14 @@ impl GlobalState {
397
409
}
398
410
399
411
let state_changed = self . process_changes ( ) ;
400
- let prev_status = self . status ;
401
- if prev_status != new_status {
402
- self . transition ( new_status) ;
403
- }
404
- let is_ready = matches ! ( self . status, Status :: Ready { .. } ) ;
405
- if prev_status == Status :: Loading && is_ready {
412
+
413
+ if self . is_quiescent ( ) && !was_quiescent {
406
414
for flycheck in & self . flycheck {
407
415
flycheck. update ( ) ;
408
416
}
409
417
}
410
418
411
- if is_ready && ( state_changed || prev_status == Status :: Loading ) {
419
+ if self . is_quiescent ( ) && ( !was_quiescent || state_changed ) {
412
420
self . update_file_notifications_on_threadpool ( ) ;
413
421
414
422
// Refresh semantic tokens if the client supports it.
@@ -437,9 +445,13 @@ impl GlobalState {
437
445
}
438
446
}
439
447
440
- self . fetch_workspaces_if_needed ( ) ;
448
+ if self . config . cargo_autoreload ( ) {
449
+ self . fetch_workspaces_if_needed ( ) ;
450
+ }
441
451
self . fetch_build_data_if_needed ( ) ;
442
452
453
+ self . report_new_status_if_needed ( ) ;
454
+
443
455
let loop_duration = loop_start. elapsed ( ) ;
444
456
if loop_duration > Duration :: from_millis ( 100 ) {
445
457
log:: warn!( "overly long loop turn: {:?}" , loop_duration) ;
@@ -466,7 +478,8 @@ impl GlobalState {
466
478
return Ok ( ( ) ) ;
467
479
}
468
480
469
- if self . status == Status :: Loading && req. method != "shutdown" {
481
+ // Avoid flashing a bunch of unresolved references during initial load.
482
+ if self . workspaces . is_empty ( ) && !self . is_quiescent ( ) {
470
483
self . respond ( lsp_server:: Response :: new_err (
471
484
req. id ,
472
485
// FIXME: i32 should impl From<ErrorCode> (from() guarantees lossless conversion)
@@ -477,7 +490,11 @@ impl GlobalState {
477
490
}
478
491
479
492
RequestDispatcher { req : Some ( req) , global_state : self }
480
- . on_sync :: < lsp_ext:: ReloadWorkspace > ( |s, ( ) | Ok ( s. fetch_workspaces_request ( ) ) ) ?
493
+ . on_sync :: < lsp_ext:: ReloadWorkspace > ( |s, ( ) | {
494
+ s. fetch_workspaces_request ( ) ;
495
+ s. fetch_workspaces_if_needed ( ) ;
496
+ Ok ( ( ) )
497
+ } ) ?
481
498
. on_sync :: < lsp_ext:: JoinLines > ( |s, p| handlers:: handle_join_lines ( s. snapshot ( ) , p) ) ?
482
499
. on_sync :: < lsp_ext:: OnEnter > ( |s, p| handlers:: handle_on_enter ( s. snapshot ( ) , p) ) ?
483
500
. on_sync :: < lsp_types:: request:: Shutdown > ( |s, ( ) | {
0 commit comments