@@ -51,7 +51,8 @@ private struct OpaqueQueuedIndexTask: Equatable {
51
51
}
52
52
53
53
private enum InProgressIndexStore {
54
- /// We are waiting for preparation of the file's target to finish before we can index it.
54
+ /// We are waiting for preparation of the file's target to be scheduled. The next step is that we wait for
55
+ /// prepration to finish before we can update the index store for this file.
55
56
///
56
57
/// `preparationTaskID` identifies the preparation task so that we can transition a file's index state to
57
58
/// `updatingIndexStore` when its preparation task has finished.
@@ -60,6 +61,16 @@ private enum InProgressIndexStore {
60
61
/// task is still the sole owner of it and responsible for its cancellation.
61
62
case waitingForPreparation( preparationTaskID: UUID , indexTask: Task < Void , Never > )
62
63
64
+ /// We have started preparing this file and are waiting for preparation to finish before we can update the index
65
+ /// store for this file.
66
+ ///
67
+ /// `preparationTaskID` identifies the preparation task so that we can transition a file's index state to
68
+ /// `updatingIndexStore` when its preparation task has finished.
69
+ ///
70
+ /// `indexTask` is a task that finishes after both preparation and index store update are done. Whoever owns the index
71
+ /// task is still the sole owner of it and responsible for its cancellation.
72
+ case preparing( preparationTaskID: UUID , indexTask: Task < Void , Never > )
73
+
63
74
/// The file's target has been prepared and we are updating the file's index store.
64
75
///
65
76
/// `updateIndexStoreTask` is the task that updates the index store itself.
@@ -210,7 +221,7 @@ package final actor SemanticIndexManager {
210
221
}
211
222
let indexTasks = inProgressIndexTasks. mapValues { status in
212
223
switch status {
213
- case . waitingForPreparation:
224
+ case . waitingForPreparation, . preparing :
214
225
return IndexTaskStatus . scheduled
215
226
case . updatingIndexStore( updateIndexStoreTask: let updateIndexStoreTask, indexTask: _) :
216
227
return updateIndexStoreTask. isExecuting ? IndexTaskStatus . executing : IndexTaskStatus . scheduled
@@ -284,7 +295,17 @@ package final actor SemanticIndexManager {
284
295
}
285
296
if !indexFilesWithUpToDateUnit {
286
297
let index = index. checked ( for: . modifiedFiles)
287
- filesToIndex = filesToIndex. filter { !index. hasUpToDateUnit ( for: $0) }
298
+ filesToIndex = filesToIndex. filter {
299
+ if index. hasUpToDateUnit ( for: $0) {
300
+ return false
301
+ }
302
+ if case . waitingForPreparation = inProgressIndexTasks [ $0] {
303
+ // We haven't started preparing the file yet. Scheduling a new index operation for it won't produce any
304
+ // more recent results.
305
+ return false
306
+ }
307
+ return true
308
+ }
288
309
}
289
310
await scheduleBackgroundIndex ( files: filesToIndex, indexFilesWithUpToDateUnit: indexFilesWithUpToDateUnit)
290
311
generateBuildGraphTask = nil
@@ -312,11 +333,11 @@ package final actor SemanticIndexManager {
312
333
for (_, status) in inProgressIndexTasks {
313
334
switch status {
314
335
case . waitingForPreparation( preparationTaskID: _, indexTask: let indexTask) ,
336
+ . preparing( preparationTaskID: _, indexTask: let indexTask) ,
315
337
. updatingIndexStore( updateIndexStoreTask: _, indexTask: let indexTask) :
316
338
taskGroup. addTask {
317
339
await indexTask. value
318
340
}
319
-
320
341
}
321
342
}
322
343
await taskGroup. waitForAll ( )
@@ -462,7 +483,9 @@ package final actor SemanticIndexManager {
462
483
private func prepare(
463
484
targets: [ BuildTargetIdentifier ] ,
464
485
purpose: TargetPreparationPurpose ,
465
- priority: TaskPriority ?
486
+ priority: TaskPriority ? ,
487
+ executionStatusChangedCallback: @escaping ( QueuedTask < AnyIndexTaskDescription > , TaskExecutionState ) async -> Void =
488
+ { _, _ in }
466
489
) async {
467
490
// Perform a quick initial check whether the target is up-to-date, in which case we don't need to schedule a
468
491
// preparation operation at all.
@@ -490,6 +513,7 @@ package final actor SemanticIndexManager {
490
513
return
491
514
}
492
515
let preparationTask = await indexTaskScheduler. schedule ( priority: priority, taskDescription) { task, newState in
516
+ await executionStatusChangedCallback ( task, newState)
493
517
guard case . finished = newState else {
494
518
self . indexProgressStatusDidChange ( )
495
519
return
@@ -547,28 +571,36 @@ package final actor SemanticIndexManager {
547
571
testHooks: testHooks
548
572
)
549
573
)
574
+
550
575
let updateIndexTask = await indexTaskScheduler. schedule ( priority: priority, taskDescription) { task, newState in
551
576
guard case . finished = newState else {
552
577
self . indexProgressStatusDidChange ( )
553
578
return
554
579
}
555
580
for fileAndTarget in filesAndTargets {
556
- if case . updatingIndexStore( OpaqueQueuedIndexTask ( task) , _) = self . inProgressIndexTasks [
557
- fileAndTarget. file. sourceFile
558
- ] {
559
- self . inProgressIndexTasks [ fileAndTarget. file. sourceFile] = nil
581
+ switch self . inProgressIndexTasks [ fileAndTarget. file. sourceFile] {
582
+ case . updatingIndexStore( let registeredTask, _) :
583
+ if registeredTask == OpaqueQueuedIndexTask ( task) {
584
+ self . inProgressIndexTasks [ fileAndTarget. file. sourceFile] = nil
585
+ }
586
+ case . waitingForPreparation( let registeredTask, _) , . preparing( let registeredTask, _) :
587
+ if registeredTask == preparationTaskID {
588
+ self . inProgressIndexTasks [ fileAndTarget. file. sourceFile] = nil
589
+ }
590
+ case nil :
591
+ break
560
592
}
561
593
}
562
594
self . indexProgressStatusDidChange ( )
563
595
}
564
596
for fileAndTarget in filesAndTargets {
565
- if case . waitingForPreparation( preparationTaskID, let indexTask) = inProgressIndexTasks [
566
- fileAndTarget. file. sourceFile
567
- ] {
597
+ switch inProgressIndexTasks [ fileAndTarget. file. sourceFile] {
598
+ case . waitingForPreparation( preparationTaskID, let indexTask) , . preparing( preparationTaskID, let indexTask) :
568
599
inProgressIndexTasks [ fileAndTarget. file. sourceFile] = . updatingIndexStore(
569
600
updateIndexStoreTask: OpaqueQueuedIndexTask ( updateIndexTask) ,
570
601
indexTask: indexTask
571
602
)
603
+ default : break
572
604
}
573
605
}
574
606
return await updateIndexTask. waitToFinishPropagatingCancellation ( )
@@ -639,9 +671,24 @@ package final actor SemanticIndexManager {
639
671
// (https://github.com/swiftlang/sourcekit-lsp/issues/1262)
640
672
for targetsBatch in sortedTargets. partition ( intoBatchesOfSize: 1 ) {
641
673
let preparationTaskID = UUID ( )
674
+ let filesToIndex = targetsBatch. flatMap ( { filesByTarget [ $0] ! } )
675
+
642
676
let indexTask = Task ( priority: priority) {
643
677
// First prepare the targets.
644
- await prepare ( targets: targetsBatch, purpose: . forIndexing, priority: priority)
678
+ await prepare ( targets: targetsBatch, purpose: . forIndexing, priority: priority) { task, newState in
679
+ if case . executing = newState {
680
+ for file in filesToIndex {
681
+ if case . waitingForPreparation( preparationTaskID: preparationTaskID, indexTask: let indexTask) =
682
+ self . inProgressIndexTasks [ file. sourceFile]
683
+ {
684
+ self . inProgressIndexTasks [ file. sourceFile] = . preparing(
685
+ preparationTaskID: preparationTaskID,
686
+ indexTask: indexTask
687
+ )
688
+ }
689
+ }
690
+ }
691
+ }
645
692
646
693
// And after preparation is done, index the files in the targets.
647
694
await withTaskGroup ( of: Void . self) { taskGroup in
@@ -665,7 +712,6 @@ package final actor SemanticIndexManager {
665
712
}
666
713
indexTasks. append ( indexTask)
667
714
668
- let filesToIndex = targetsBatch. flatMap ( { filesByTarget [ $0] ! } )
669
715
// The number of index tasks that don't currently have an in-progress task associated with it.
670
716
// The denominator in the index progress should get incremented by this amount.
671
717
// We don't want to increment the denominator for tasks that already have an index in progress.
0 commit comments