Skip to content

Commit 209fb1b

Browse files
authored
Merge pull request #2053 from ahoppen/index-progress
Don't increment in-progress task counter for files that cannot be indexed
2 parents 956742d + 55b514f commit 209fb1b

File tree

3 files changed

+89
-40
lines changed

3 files changed

+89
-40
lines changed

Sources/SemanticIndex/SemanticIndexManager.swift

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -714,47 +714,28 @@ package final actor SemanticIndexManager {
714714
// sort files to get deterministic indexing order
715715
.sorted(by: { $0.file.sourceFile.stringValue < $1.file.sourceFile.stringValue })
716716

717-
// The number of index tasks that don't currently have an in-progress task associated with it.
718-
// The denominator in the index progress should get incremented by this amount.
719-
// We don't want to increment the denominator for tasks that already have an index in progress.
720-
var newIndexTasks = 0
721-
var alreadyScheduledTasks: Set<FileToIndex> = []
722-
for file in filesToIndex {
723-
let inProgress = inProgressIndexTasks[file.file]
724-
725-
let shouldScheduleIndexing: Bool
726-
switch inProgress?.state {
727-
case nil:
728-
newIndexTasks += 1
729-
shouldScheduleIndexing = true
730-
case .creatingIndexTask, .waitingForPreparation:
731-
// We already have a task that indexes the file but hasn't started preparation yet. Indexing the file again
732-
// won't produce any new results.
733-
alreadyScheduledTasks.insert(file.file)
734-
shouldScheduleIndexing = false
735-
case .preparing(_, _), .updatingIndexStore(_, _):
736-
// We have started indexing of the file and are now requesting to index it again. Unless we know that the file
737-
// hasn't been modified since the last request for indexing, we need to schedule it to get re-indexed again.
738-
if let modDate = file.fileModificationDate, inProgress?.fileModificationDate == modDate {
739-
shouldScheduleIndexing = false
740-
} else {
741-
shouldScheduleIndexing = true
717+
filesToIndex =
718+
filesToIndex
719+
.filter { file in
720+
let inProgress = inProgressIndexTasks[file.file]
721+
722+
switch inProgress?.state {
723+
case nil:
724+
return true
725+
case .creatingIndexTask, .waitingForPreparation:
726+
// We already have a task that indexes the file but hasn't started preparation yet. Indexing the file again
727+
// won't produce any new results.
728+
return false
729+
case .preparing(_, _), .updatingIndexStore(_, _):
730+
// We have started indexing of the file and are now requesting to index it again. Unless we know that the file
731+
// hasn't been modified since the last request for indexing, we need to schedule it to get re-indexed again.
732+
if let modDate = file.fileModificationDate, inProgress?.fileModificationDate == modDate {
733+
return false
734+
} else {
735+
return true
736+
}
742737
}
743738
}
744-
if shouldScheduleIndexing {
745-
inProgressIndexTasks[file.file] = InProgressIndexStore(
746-
state: .creatingIndexTask,
747-
fileModificationDate: file.fileModificationDate
748-
)
749-
} else {
750-
alreadyScheduledTasks.insert(file.file)
751-
752-
}
753-
}
754-
if newIndexTasks > 0 {
755-
indexTasksWereScheduled(newIndexTasks)
756-
}
757-
filesToIndex = filesToIndex.filter { !alreadyScheduledTasks.contains($0.file) }
758739

759740
if filesToIndex.isEmpty {
760741
// Early exit if there are no files to index.
@@ -767,7 +748,12 @@ package final actor SemanticIndexManager {
767748
// to index the low-level targets ASAP.
768749
var filesByTarget: [BuildTargetIdentifier: [(FileToIndex)]] = [:]
769750

770-
for fileToIndex in filesToIndex.map(\.file) {
751+
// The number of index tasks that don't currently have an in-progress task associated with it.
752+
// The denominator in the index progress should get incremented by this amount.
753+
// We don't want to increment the denominator for tasks that already have an index in progress.
754+
var newIndexTasks = 0
755+
756+
for (fileToIndex, fileModificationDate) in filesToIndex {
771757
guard let target = await buildSystemManager.canonicalTarget(for: fileToIndex.mainFile) else {
772758
logger.error(
773759
"Not indexing \(fileToIndex.forLogging) because the target could not be determined"
@@ -780,8 +766,21 @@ package final actor SemanticIndexManager {
780766
continue
781767
}
782768

769+
if inProgressIndexTasks[fileToIndex] == nil {
770+
// If `inProgressIndexTasks[fileToIndex]` is not `nil`, this new index task is replacing another index task.
771+
// We are thus not indexing a new file and thus shouldn't increment the denominator of the indexing status.
772+
newIndexTasks += 1
773+
}
774+
inProgressIndexTasks[fileToIndex] = InProgressIndexStore(
775+
state: .creatingIndexTask,
776+
fileModificationDate: fileModificationDate
777+
)
778+
783779
filesByTarget[target, default: []].append(fileToIndex)
784780
}
781+
if newIndexTasks > 0 {
782+
indexTasksWereScheduled(newIndexTasks)
783+
}
785784

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

Sources/SourceKitLSP/IndexProgressManager.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ actor IndexProgressManager {
109109
} else {
110110
message = "\(finishedTasks) / \(queuedIndexTasks)"
111111
}
112+
logger.debug("In-progress index tasks: \(indexTasks.map(\.key.sourceFile))")
112113
if queuedIndexTasks != 0 {
113114
percentage = Int(Double(finishedTasks) / Double(queuedIndexTasks) * 100)
114115
} else {

Tests/SourceKitLSPTests/BackgroundIndexingTests.swift

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

21862235
extension HoverResponseContents {

0 commit comments

Comments
 (0)