@@ -96,6 +96,26 @@ public enum IndexProgressStatus {
96
96
}
97
97
}
98
98
99
+ /// See `SemanticIndexManager.inProgressPrepareForEditorTask`.
100
+ fileprivate struct InProgressPrepareForEditorTask {
101
+ fileprivate enum State {
102
+ case determiningCanonicalConfiguredTarget
103
+ case preparingTarget
104
+ }
105
+ /// A unique ID that identifies the preparation task and is used to set
106
+ /// `SemanticIndexManager.inProgressPrepareForEditorTask` to `nil` when the current in progress task finishes.
107
+ let id : UUID
108
+
109
+ /// The document that is being prepared.
110
+ let document : DocumentURI
111
+
112
+ /// The task that prepares the document. Should never be awaited and only be used to cancel the task.
113
+ let task : Task < Void , Never >
114
+
115
+ /// Whether the task is currently determining the file's target or actually preparing the document.
116
+ var state : State
117
+ }
118
+
99
119
/// Schedules index tasks and keeps track of the index status of files.
100
120
public final actor SemanticIndexManager {
101
121
/// The underlying index. This is used to check if the index of a file is already up-to-date, in which case it doesn't
@@ -133,10 +153,7 @@ public final actor SemanticIndexManager {
133
153
/// avoid the following scenario: The user browses through documents from targets A, B, and C in quick succession. We
134
154
/// don't want stack preparation of A, B, and C. Instead we want to only prepare target C - and also finish
135
155
/// preparation of A if it has already started when the user opens C.
136
- ///
137
- /// `id` is a unique ID that identifies the preparation task and is used to set `inProgressPrepareForEditorTask` to
138
- /// `nil` when the current in progress task finishes.
139
- private var inProgressPrepareForEditorTask : ( id: UUID , document: DocumentURI , task: Task < Void , Never > ) ? = nil
156
+ private var inProgressPrepareForEditorTask : InProgressPrepareForEditorTask ? = nil
140
157
141
158
/// The `TaskScheduler` that manages the scheduling of index tasks. This is shared among all `SemanticIndexManager`s
142
159
/// in the process, to ensure that we don't schedule more index operations than processor cores from multiple
@@ -161,7 +178,7 @@ public final actor SemanticIndexManager {
161
178
162
179
/// A summary of the tasks that this `SemanticIndexManager` has currently scheduled or is currently indexing.
163
180
public var progressStatus : IndexProgressStatus {
164
- if inProgressPrepareForEditorTask != nil {
181
+ if let inProgressPrepareForEditorTask, inProgressPrepareForEditorTask . state == . preparingTarget {
165
182
return . preparingFileForEditorFunctionality
166
183
}
167
184
if generateBuildGraphTask != nil {
@@ -370,15 +387,33 @@ public final actor SemanticIndexManager {
370
387
let id = UUID ( )
371
388
let task = Task ( priority: priority) {
372
389
await withLoggingScope ( " preparation " ) {
373
- await self . prepareFileForEditorFunctionality ( uri)
390
+ // Should be kept in sync with `prepareFileForEditorFunctionality`
391
+ guard let target = await buildSystemManager. canonicalConfiguredTarget ( for: uri) else {
392
+ return
393
+ }
394
+ if Task . isCancelled {
395
+ return
396
+ }
397
+ if inProgressPrepareForEditorTask? . id == id {
398
+ if inProgressPrepareForEditorTask? . state != . determiningCanonicalConfiguredTarget {
399
+ logger. fault ( " inProgressPrepareForEditorTask is in unexpected state " )
400
+ }
401
+ inProgressPrepareForEditorTask? . state = . preparingTarget
402
+ }
403
+ await self . prepare ( targets: [ target] , priority: nil )
374
404
if inProgressPrepareForEditorTask? . id == id {
375
405
inProgressPrepareForEditorTask = nil
376
406
self . indexProgressStatusDidChange ( )
377
407
}
378
408
}
379
409
}
380
410
inProgressPrepareForEditorTask? . task. cancel ( )
381
- inProgressPrepareForEditorTask = ( id, uri, task)
411
+ inProgressPrepareForEditorTask = InProgressPrepareForEditorTask (
412
+ id: id,
413
+ document: uri,
414
+ task: task,
415
+ state: . determiningCanonicalConfiguredTarget
416
+ )
382
417
self . indexProgressStatusDidChange ( )
383
418
}
384
419
@@ -387,6 +422,7 @@ public final actor SemanticIndexManager {
387
422
///
388
423
/// If file's target is known to be up-to-date, this returns almost immediately.
389
424
public func prepareFileForEditorFunctionality( _ uri: DocumentURI ) async {
425
+ // Should be kept in sync with `schedulePreparationForEditorFunctionality`.
390
426
guard let target = await buildSystemManager. canonicalConfiguredTarget ( for: uri) else {
391
427
return
392
428
}
0 commit comments