@@ -53,6 +53,14 @@ private struct OpaqueQueuedIndexTask: Equatable {
5353}
5454
5555private enum InProgressIndexStore {
56+ /// We know that we need to index the file but and are currently gathering all information to create the `indexTask`
57+ /// that will index it.
58+ ///
59+ /// This is needed to avoid the following race: We request indexing of file A. Getting the canonical target for A
60+ /// takes a bit and before that finishes, we request another index of A. In this case, we don't want to kick off
61+ /// two tasks to update the index store.
62+ case creatingIndexTask
63+
5664 /// We are waiting for preparation of the file's target to be scheduled. The next step is that we wait for
5765 /// preparation to finish before we can update the index store for this file.
5866 ///
@@ -223,7 +231,7 @@ package final actor SemanticIndexManager {
223231 }
224232 let indexTasks = inProgressIndexTasks. mapValues { status in
225233 switch status {
226- case . waitingForPreparation, . preparing:
234+ case . creatingIndexTask , . waitingForPreparation, . preparing:
227235 return IndexTaskStatus . scheduled
228236 case . updatingIndexStore( updateIndexStoreTask: let updateIndexStoreTask, indexTask: _) :
229237 return updateIndexStoreTask. isExecuting ? IndexTaskStatus . executing : IndexTaskStatus . scheduled
@@ -327,6 +335,8 @@ package final actor SemanticIndexManager {
327335
328336 await inProgressIndexTasks. concurrentForEach { ( _, status) in
329337 switch status {
338+ case . creatingIndexTask:
339+ break
330340 case . waitingForPreparation( preparationTaskID: _, indexTask: let indexTask) ,
331341 . preparing( preparationTaskID: _, indexTask: let indexTask) ,
332342 . updatingIndexStore( updateIndexStoreTask: _, indexTask: let indexTask) :
@@ -448,7 +458,7 @@ package final actor SemanticIndexManager {
448458 }
449459 . filter {
450460 switch inProgressIndexTasks [ $0] {
451- case . waitingForPreparation:
461+ case . waitingForPreparation, . creatingIndexTask :
452462 return false
453463 default :
454464 return true
@@ -639,7 +649,7 @@ package final actor SemanticIndexManager {
639649 if registeredTask == preparationTaskID {
640650 self . inProgressIndexTasks [ fileAndTarget. file] = nil
641651 }
642- case nil :
652+ case . creatingIndexTask , nil :
643653 break
644654 }
645655 }
@@ -687,6 +697,19 @@ package final actor SemanticIndexManager {
687697 // Sort the targets in topological order so that low-level targets get built before high-level targets, allowing us
688698 // to index the low-level targets ASAP.
689699 var filesByTarget : [ BuildTargetIdentifier : [ FileToIndex ] ] = [ : ]
700+
701+ // The number of index tasks that don't currently have an in-progress task associated with it.
702+ // The denominator in the index progress should get incremented by this amount.
703+ // We don't want to increment the denominator for tasks that already have an index in progress.
704+ var newIndexTasks = 0
705+ for file in outOfDateFiles {
706+ if inProgressIndexTasks [ file] == nil {
707+ newIndexTasks += 1
708+ }
709+ inProgressIndexTasks [ file] = . creatingIndexTask
710+ }
711+ indexTasksWereScheduled ( newIndexTasks)
712+
690713 for fileToIndex in outOfDateFiles {
691714 guard let target = await buildSystemManager. canonicalTarget ( for: fileToIndex. mainFile) else {
692715 logger. error (
@@ -767,10 +790,6 @@ package final actor SemanticIndexManager {
767790 }
768791 indexTasks. append ( indexTask)
769792
770- // The number of index tasks that don't currently have an in-progress task associated with it.
771- // The denominator in the index progress should get incremented by this amount.
772- // We don't want to increment the denominator for tasks that already have an index in progress.
773- let newIndexTasks = filesToIndex. filter { inProgressIndexTasks [ $0] == nil } . count
774793 for file in filesToIndex {
775794 // The state of `inProgressIndexTasks` will get pushed on from `updateIndexStore`.
776795 // The updates to `inProgressIndexTasks` from `updateIndexStore` cannot race with setting it to
@@ -782,7 +801,6 @@ package final actor SemanticIndexManager {
782801 indexTask: indexTask
783802 )
784803 }
785- indexTasksWereScheduled ( newIndexTasks)
786804 }
787805
788806 return Task ( priority: priority) {
0 commit comments