Skip to content

Commit 41ddebb

Browse files
authored
Merge pull request #2280 from ahoppen/file-index-batching-preparation
A couple refactorings to necessary to support multi-file indexing
2 parents 1982798 + 7860893 commit 41ddebb

File tree

5 files changed

+170
-119
lines changed

5 files changed

+170
-119
lines changed

Sources/BuildServerIntegration/BuildServerManager.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -757,10 +757,12 @@ package actor BuildServerManager: QueueBasedMessageHandler {
757757

758758
// MARK: Build server queries
759759

760-
/// Returns the toolchain that should be used to process the given document.
760+
/// Returns the toolchain that should be used to process the given target.
761+
///
762+
/// If `target` is `nil` or the build server does not explicitly specify a toolchain for this target, the preferred
763+
/// toolchain for the given language is returned.
761764
package func toolchain(
762-
for uri: DocumentURI,
763-
in target: BuildTargetIdentifier?,
765+
for target: BuildTargetIdentifier?,
764766
language: Language
765767
) async -> Toolchain? {
766768
let toolchainPath = await orLog("Getting toolchain from build targets") { () -> URL? in

Sources/SemanticIndex/SemanticIndexManager.swift

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ private struct InProgressIndexStore {
9191
var fileModificationDate: Date?
9292
}
9393

94+
/// The information that's needed to index a file within a given target.
95+
package struct FileIndexInfo: Sendable, Hashable {
96+
package let file: FileToIndex
97+
package let language: Language
98+
package let target: BuildTargetIdentifier
99+
package let outputPath: OutputPath
100+
}
101+
94102
/// Status of document indexing / target preparation in `inProgressIndexAndPreparationTasks`.
95103
package enum IndexTaskStatus: Comparable {
96104
case scheduled
@@ -500,10 +508,13 @@ package final actor SemanticIndexManager {
500508
continue
501509
}
502510
// If this is a source file, just index it.
511+
guard let language = await buildServerManager.defaultLanguage(for: uri, in: target) else {
512+
continue
513+
}
503514
didFindTargetToIndex = true
504515
filesToReIndex.append(
505516
(
506-
FileIndexInfo(file: .indexableFile(uri), target: target, outputPath: outputPath),
517+
FileIndexInfo(file: .indexableFile(uri), language: language, target: target, outputPath: outputPath),
507518
modifiedFilesIndex.modificationDate(of: uri)
508519
)
509520
)
@@ -543,10 +554,14 @@ package final actor SemanticIndexManager {
543554
{
544555
continue
545556
}
557+
guard let language = await buildServerManager.defaultLanguage(for: uri, in: targetAndOutputPath.key) else {
558+
continue
559+
}
546560
filesToReIndex.append(
547561
(
548562
FileIndexInfo(
549563
file: .headerFile(header: uri, mainFile: mainFile),
564+
language: language,
550565
target: targetAndOutputPath.key,
551566
outputPath: outputPath
552567
),
@@ -722,16 +737,20 @@ package final actor SemanticIndexManager {
722737
}
723738
}
724739

725-
/// Update the index store for the given files, assuming that their targets have already been prepared.
740+
/// Update the index store for the given files, assuming that their targets has already been prepared.
726741
private func updateIndexStore(
727-
for filesAndTargets: [FileIndexInfo],
742+
for fileAndOutputPaths: [FileAndOutputPath],
743+
target: BuildTargetIdentifier,
744+
language: Language,
728745
indexFilesWithUpToDateUnit: Bool,
729746
preparationTaskID: UUID,
730747
priority: TaskPriority?
731748
) async {
732749
let taskDescription = AnyIndexTaskDescription(
733750
UpdateIndexStoreTaskDescription(
734-
filesToIndex: filesAndTargets,
751+
filesToIndex: fileAndOutputPaths,
752+
target: target,
753+
language: language,
735754
buildServerManager: self.buildServerManager,
736755
index: index,
737756
indexStoreUpToDateTracker: indexStoreUpToDateTracker,
@@ -747,7 +766,13 @@ package final actor SemanticIndexManager {
747766
self.indexProgressStatusDidChange()
748767
return
749768
}
750-
for fileAndTarget in filesAndTargets {
769+
for fileAndOutputPath in fileAndOutputPaths {
770+
let fileAndTarget = FileIndexInfo(
771+
file: fileAndOutputPath.file,
772+
language: language,
773+
target: target,
774+
outputPath: fileAndOutputPath.outputPath
775+
)
751776
switch self.inProgressIndexTasks[fileAndTarget]?.state {
752777
case .updatingIndexStore(let registeredTask, _):
753778
if registeredTask == OpaqueQueuedIndexTask(task) {
@@ -763,7 +788,13 @@ package final actor SemanticIndexManager {
763788
}
764789
self.indexProgressStatusDidChange()
765790
}
766-
for fileAndTarget in filesAndTargets {
791+
for fileAndOutputPath in fileAndOutputPaths {
792+
let fileAndTarget = FileIndexInfo(
793+
file: fileAndOutputPath.file,
794+
language: language,
795+
target: target,
796+
outputPath: fileAndOutputPath.outputPath
797+
)
767798
switch inProgressIndexTasks[fileAndTarget]?.state {
768799
case .waitingForPreparation(preparationTaskID, let indexTask), .preparing(preparationTaskID, let indexTask):
769800
inProgressIndexTasks[fileAndTarget]?.state = .updatingIndexStore(
@@ -854,13 +885,7 @@ package final actor SemanticIndexManager {
854885
var newIndexTasks = 0
855886

856887
for (fileIndexInfo, fileModificationDate) in filesToIndex {
857-
guard
858-
let language = await buildServerManager.defaultLanguage(
859-
for: fileIndexInfo.file.mainFile,
860-
in: fileIndexInfo.target
861-
),
862-
UpdateIndexStoreTaskDescription.canIndex(language: language)
863-
else {
888+
guard UpdateIndexStoreTaskDescription.canIndex(language: fileIndexInfo.language) else {
864889
continue
865890
}
866891

@@ -933,17 +958,34 @@ package final actor SemanticIndexManager {
933958
// And after preparation is done, index the files in the targets.
934959
await withTaskGroup(of: Void.self) { taskGroup in
935960
for target in targetsBatch {
936-
// TODO: Once swiftc supports indexing of multiple files in a single invocation, increase the batch size to
937-
// allow it to share AST builds between multiple files within a target.
938-
// (https://github.com/swiftlang/sourcekit-lsp/issues/1268)
939-
for fileBatch in filesByTarget[target]!.partition(intoBatchesOfSize: 1) {
940-
taskGroup.addTask {
941-
await self.updateIndexStore(
942-
for: fileBatch,
943-
indexFilesWithUpToDateUnit: indexFilesWithUpToDateUnit,
944-
preparationTaskID: preparationTaskID,
945-
priority: priority
946-
)
961+
var filesByLanguage: [Language: [FileIndexInfo]] = [:]
962+
for fileInfo in filesByTarget[target]! {
963+
filesByLanguage[fileInfo.language, default: []].append(fileInfo)
964+
}
965+
for (language, fileInfos) in filesByLanguage {
966+
// TODO: Once swiftc supports indexing of multiple files in a single invocation, increase the batch size to
967+
// allow it to share AST builds between multiple files within a target.
968+
// (https://github.com/swiftlang/sourcekit-lsp/issues/1268)
969+
for fileBatch in fileInfos.partition(intoBatchesOfSize: 1) {
970+
taskGroup.addTask {
971+
let fileAndOutputPaths: [FileAndOutputPath] = fileBatch.compactMap {
972+
guard $0.target == target else {
973+
logger.fault(
974+
"FileIndexInfo refers to different target than should be indexed \($0.target.forLogging) vs \(target.forLogging)"
975+
)
976+
return nil
977+
}
978+
return FileAndOutputPath(file: $0.file, outputPath: $0.outputPath)
979+
}
980+
await self.updateIndexStore(
981+
for: fileAndOutputPaths,
982+
target: target,
983+
language: language,
984+
indexFilesWithUpToDateUnit: indexFilesWithUpToDateUnit,
985+
preparationTaskID: preparationTaskID,
986+
priority: priority
987+
)
988+
}
947989
}
948990
}
949991
}

0 commit comments

Comments
 (0)