Skip to content

Commit e2d5aa7

Browse files
committed
Don't increment in-progress task counter for files that cannot be indexed
We had a bug where we would add an entry to `inProgressIndexTasks` for files that we couldn’t actually index, so we never actually scheduled an index task for them, which means that the files were never removed from `inProgressIndexTasks` and thus caused the indexing progress to never finish.
1 parent 71dfc73 commit e2d5aa7

File tree

2 files changed

+69
-14
lines changed

2 files changed

+69
-14
lines changed

Sources/SemanticIndex/SemanticIndexManager.swift

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -711,18 +711,13 @@ package final actor SemanticIndexManager {
711711
// sort files to get deterministic indexing order
712712
.sorted(by: { $0.file.sourceFile.stringValue < $1.file.sourceFile.stringValue })
713713

714-
// The number of index tasks that don't currently have an in-progress task associated with it.
715-
// The denominator in the index progress should get incremented by this amount.
716-
// We don't want to increment the denominator for tasks that already have an index in progress.
717-
var newIndexTasks = 0
718714
var alreadyScheduledTasks: Set<FileToIndex> = []
719715
for file in filesToIndex {
720716
let inProgress = inProgressIndexTasks[file.file]
721717

722718
let shouldScheduleIndexing: Bool
723719
switch inProgress?.state {
724720
case nil:
725-
newIndexTasks += 1
726721
shouldScheduleIndexing = true
727722
case .creatingIndexTask, .waitingForPreparation:
728723
// We already have a task that indexes the file but hasn't started preparation yet. Indexing the file again
@@ -739,18 +734,11 @@ package final actor SemanticIndexManager {
739734
}
740735
}
741736
if shouldScheduleIndexing {
742-
inProgressIndexTasks[file.file] = InProgressIndexStore(
743-
state: .creatingIndexTask,
744-
fileModificationDate: file.fileModificationDate
745-
)
737+
746738
} else {
747739
alreadyScheduledTasks.insert(file.file)
748-
749740
}
750741
}
751-
if newIndexTasks > 0 {
752-
indexTasksWereScheduled(newIndexTasks)
753-
}
754742
filesToIndex = filesToIndex.filter { !alreadyScheduledTasks.contains($0.file) }
755743

756744
if filesToIndex.isEmpty {
@@ -764,7 +752,12 @@ package final actor SemanticIndexManager {
764752
// to index the low-level targets ASAP.
765753
var filesByTarget: [BuildTargetIdentifier: [(FileToIndex)]] = [:]
766754

767-
for fileToIndex in filesToIndex.map(\.file) {
755+
// The number of index tasks that don't currently have an in-progress task associated with it.
756+
// The denominator in the index progress should get incremented by this amount.
757+
// We don't want to increment the denominator for tasks that already have an index in progress.
758+
var newIndexTasks = 0
759+
760+
for (fileToIndex, fileModificationDate) in filesToIndex {
768761
guard let target = await buildSystemManager.canonicalTarget(for: fileToIndex.mainFile) else {
769762
logger.error(
770763
"Not indexing \(fileToIndex.forLogging) because the target could not be determined"
@@ -777,8 +770,21 @@ package final actor SemanticIndexManager {
777770
continue
778771
}
779772

773+
if inProgressIndexTasks[fileToIndex] == nil {
774+
// If `inProgressIndexTasks[fileToIndex]` is not `nil`, this new index task is replacing another index task.
775+
// We are thus not indexing a new file and thus shouldn't increment the denominator of the indexing status.
776+
newIndexTasks += 1
777+
}
778+
inProgressIndexTasks[fileToIndex] = InProgressIndexStore(
779+
state: .creatingIndexTask,
780+
fileModificationDate: fileModificationDate
781+
)
782+
780783
filesByTarget[target, default: []].append(fileToIndex)
781784
}
785+
if newIndexTasks > 0 {
786+
indexTasksWereScheduled(newIndexTasks)
787+
}
782788

783789
// The targets sorted in reverse topological order, low-level targets before high-level targets. If topological
784790
// sorting fails, sorted in another deterministic way where the actual order doesn't matter.

Tests/SourceKitLSPTests/BackgroundIndexingTests.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,6 +2176,55 @@ final class BackgroundIndexingTests: XCTestCase {
21762176
]
21772177
)
21782178
}
2179+
2180+
func testIndexingProgressIfNonIndexableFileIsInPackage() async throws {
2181+
let receivedReportProgressNotification = AtomicBool(initialValue: false)
2182+
2183+
let project = try await SwiftPMTestProject(
2184+
files: [
2185+
"MyLibrary/include/Test.h": "",
2186+
"MyLibrary/Test.c": "",
2187+
"MyLibrary/Assembly.S": "",
2188+
],
2189+
capabilities: ClientCapabilities(window: WindowClientCapabilities(workDoneProgress: true)),
2190+
hooks: Hooks(
2191+
indexHooks: IndexHooks(updateIndexStoreTaskDidFinish: { _ in
2192+
while !receivedReportProgressNotification.value {
2193+
try? await Task.sleep(for: .milliseconds(10))
2194+
}
2195+
})
2196+
),
2197+
enableBackgroundIndexing: true,
2198+
pollIndex: false,
2199+
preInitialization: { testClient in
2200+
testClient.handleMultipleRequests { (request: CreateWorkDoneProgressRequest) in
2201+
return VoidResponse()
2202+
}
2203+
}
2204+
)
2205+
2206+
let beginNotification = try await project.testClient.nextNotification(
2207+
ofType: WorkDoneProgress.self,
2208+
satisfying: { notification in
2209+
guard case .begin(let data) = notification.value else {
2210+
return false
2211+
}
2212+
return data.title == "Indexing"
2213+
}
2214+
)
2215+
receivedReportProgressNotification.value = true
2216+
2217+
// Check that we receive an `end` notification
2218+
_ = try await project.testClient.nextNotification(
2219+
ofType: WorkDoneProgress.self,
2220+
satisfying: { notification in
2221+
if notification.token == beginNotification.token, case .end = notification.value {
2222+
return true
2223+
}
2224+
return false
2225+
}
2226+
)
2227+
}
21792228
}
21802229

21812230
extension HoverResponseContents {

0 commit comments

Comments
 (0)