Skip to content

Commit 5c4f1ca

Browse files
committed
Make UpdateIndexStoreTaskDescription.updateIndexStore handle mulitple files
This pushes multi-file indexing one level closer to the actual compiler invocation.
1 parent 690fd92 commit 5c4f1ca

File tree

1 file changed

+84
-76
lines changed

1 file changed

+84
-76
lines changed

Sources/SemanticIndex/UpdateIndexStoreTaskDescription.swift

Lines changed: 84 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,7 @@ package struct UpdateIndexStoreTaskDescription: IndexTaskDescription {
189189
"Starting updating index store with priority \(Task.currentPriority.rawValue, privacy: .public): \(filesToIndexDescription)"
190190
)
191191
let filesToIndex = filesToIndex.sorted(by: { $0.file.sourceFile.stringValue < $1.file.sourceFile.stringValue })
192-
// TODO: Once swiftc supports it, we should group files by target and index files within the same target together
193-
// in one swiftc invocation. (https://github.com/swiftlang/sourcekit-lsp/issues/1268)
194-
for fileIndexInfo in filesToIndex {
195-
await updateIndexStore(forSingleFile: fileIndexInfo.file, outputPath: fileIndexInfo.outputPath)
196-
}
192+
await updateIndexStore(forFiles: filesToIndex)
197193
// If we know the output paths, make sure that we load their units into indexstore-db. We would eventually also
198194
// pick the units up through file watching but that would leave a short time period in which we think that
199195
// indexing has finished (because the index process has terminated) but when the new symbols aren't present in
@@ -233,88 +229,100 @@ package struct UpdateIndexStoreTaskDescription: IndexTaskDescription {
233229
}
234230
}
235231

236-
private func updateIndexStore(forSingleFile file: FileToIndex, outputPath: OutputPath) async {
237-
guard await !indexStoreUpToDateTracker.isUpToDate(file.sourceFile, target) else {
232+
private func updateIndexStore(forFiles fileInfos: [FileAndOutputPath]) async {
233+
let fileInfos = await fileInfos.asyncFilter { fileInfo in
238234
// If we know that the file is up-to-date without having ot hit the index, do that because it's fastest.
239-
return
240-
}
241-
guard
242-
indexFilesWithUpToDateUnit
243-
|| !index.checked(for: .modifiedFiles).hasUpToDateUnit(
244-
for: file.sourceFile,
245-
mainFile: file.mainFile,
246-
outputPath: outputPath
247-
)
248-
else {
249-
logger.debug("Not indexing \(file.forLogging) because index has an up-to-date unit")
250-
// We consider a file's index up-to-date if we have any up-to-date unit. Changing build settings does not
251-
// invalidate the up-to-date status of the index.
252-
return
253-
}
254-
if file.mainFile != file.sourceFile {
255-
logger.log("Updating index store of \(file.forLogging) using main file \(file.mainFile.forLogging)")
256-
}
257-
guard let language = await buildServerManager.defaultLanguage(for: file.mainFile, in: target) else {
258-
logger.error("Not indexing \(file.forLogging) because its language could not be determined")
259-
return
260-
}
261-
let buildSettings = await buildServerManager.buildSettings(
262-
for: file.mainFile,
263-
in: target,
264-
language: language,
265-
fallbackAfterTimeout: false
266-
)
267-
guard let buildSettings else {
268-
logger.error("Not indexing \(file.forLogging) because it has no compiler arguments")
269-
return
235+
if await indexStoreUpToDateTracker.isUpToDate(fileInfo.file.sourceFile, target) {
236+
return false
237+
}
238+
if indexFilesWithUpToDateUnit {
239+
return true
240+
}
241+
let hasUpToDateUnit = index.checked(for: .modifiedFiles).hasUpToDateUnit(
242+
for: fileInfo.sourceFile,
243+
mainFile: fileInfo.mainFile,
244+
outputPath: fileInfo.outputPath
245+
)
246+
if !hasUpToDateUnit {
247+
logger.debug("Not indexing \(fileInfo.file.forLogging) because index has an up-to-date unit")
248+
// We consider a file's index up-to-date if we have any up-to-date unit. Changing build settings does not
249+
// invalidate the up-to-date status of the index.
250+
}
251+
return !hasUpToDateUnit
270252
}
271-
if buildSettings.isFallback {
272-
// Fallback build settings don’t even have an indexstore path set, so they can't generate index data that we would
273-
// pick up. Also, indexing with fallback args has some other problems:
274-
// - If it did generate a unit file, we would consider the file’s index up-to-date even if the compiler arguments
275-
// change, which means that we wouldn't get any up-to-date-index even when we have build settings for the file.
276-
// - It's unlikely that the index from a single file with fallback arguments will be very useful as it can't tie
277-
// into the rest of the project.
278-
// So, don't index the file.
279-
logger.error("Not indexing \(file.forLogging) because it has fallback compiler arguments")
253+
if fileInfos.isEmpty {
280254
return
281255
}
282-
guard let toolchain = await buildServerManager.toolchain(for: target, language: language) else {
283-
logger.error(
284-
"Not updating index store for \(file.forLogging) because no toolchain could be determined for the document"
256+
for fileInfo in fileInfos where fileInfo.mainFile != fileInfo.sourceFile {
257+
logger.log(
258+
"Updating index store of \(fileInfo.file.forLogging) using main file \(fileInfo.mainFile.forLogging)"
285259
)
286-
return
287260
}
288-
let startDate = Date()
289-
switch language.semanticKind {
290-
case .swift:
291-
do {
292-
try await updateIndexStore(
293-
forSwiftFile: file.mainFile,
294-
buildSettings: buildSettings,
295-
toolchain: toolchain
261+
262+
for fileInfo in fileInfos {
263+
guard let language = await buildServerManager.defaultLanguage(for: fileInfo.mainFile, in: target) else {
264+
logger.error("Not indexing \(fileInfo.file.forLogging) because its language could not be determined")
265+
continue
266+
}
267+
let buildSettings = await buildServerManager.buildSettings(
268+
for: fileInfo.mainFile,
269+
in: target,
270+
language: language,
271+
fallbackAfterTimeout: false
272+
)
273+
guard let buildSettings else {
274+
logger.error("Not indexing \(fileInfo.file.forLogging) because it has no compiler arguments")
275+
continue
276+
}
277+
if buildSettings.isFallback {
278+
// Fallback build settings don’t even have an indexstore path set, so they can't generate index data that we would
279+
// pick up. Also, indexing with fallback args has some other problems:∂
280+
// - If it did generate a unit file, we would consider the file’s index up-to-date even if the compiler arguments
281+
// change, which means that we wouldn't get any up-to-date-index even when we have build settings for the file.
282+
// - It's unlikely that the index from a single file with fallback arguments will be very useful as it can't tie
283+
// into the rest of the project.
284+
// So, don't index the file.
285+
logger.error("Not indexing \(fileInfo.file.forLogging) because it has fallback compiler arguments")
286+
continue
287+
}
288+
289+
guard let toolchain = await buildServerManager.toolchain(for: target, language: buildSettings.language) else {
290+
logger.fault(
291+
"Unable to determine toolchain to index \(buildSettings.language.description, privacy: .public) files in \(target.forLogging)"
296292
)
297-
} catch {
298-
logger.error("Updating index store for \(file.forLogging) failed: \(error.forLogging)")
299-
BuildSettingsLogger.log(settings: buildSettings, for: file.mainFile)
293+
continue
300294
}
301-
case .clang:
302-
do {
303-
try await updateIndexStore(
304-
forClangFile: file.mainFile,
305-
buildSettings: buildSettings,
306-
toolchain: toolchain
295+
let startDate = Date()
296+
switch buildSettings.language.semanticKind {
297+
case .swift:
298+
do {
299+
try await updateIndexStore(
300+
forSwiftFile: fileInfo.mainFile,
301+
buildSettings: buildSettings,
302+
toolchain: toolchain
303+
)
304+
} catch {
305+
logger.error("Updating index store for \(fileInfo.mainFile) failed: \(error.forLogging)")
306+
BuildSettingsLogger.log(settings: buildSettings, for: fileInfo.mainFile)
307+
}
308+
case .clang:
309+
do {
310+
try await updateIndexStore(
311+
forClangFile: fileInfo.mainFile,
312+
buildSettings: buildSettings,
313+
toolchain: toolchain
314+
)
315+
} catch {
316+
logger.error("Updating index store for \(fileInfo.mainFile.forLogging) failed: \(error.forLogging)")
317+
BuildSettingsLogger.log(settings: buildSettings, for: fileInfo.mainFile)
318+
}
319+
case nil:
320+
logger.error(
321+
"Not updating index store for \(fileInfo.mainFile.forLogging) because it is a language that is not supported by background indexing"
307322
)
308-
} catch {
309-
logger.error("Updating index store for \(file) failed: \(error.forLogging)")
310-
BuildSettingsLogger.log(settings: buildSettings, for: file.mainFile)
311323
}
312-
case nil:
313-
logger.error(
314-
"Not updating index store for \(file) because it is a language that is not supported by background indexing"
315-
)
324+
await indexStoreUpToDateTracker.markUpToDate([(fileInfo.sourceFile, target)], updateOperationStartDate: startDate)
316325
}
317-
await indexStoreUpToDateTracker.markUpToDate([(file.sourceFile, target)], updateOperationStartDate: startDate)
318326
}
319327

320328
/// If `args` does not contain an `-index-store-path` argument, add it, pointing to the build server's index store

0 commit comments

Comments
 (0)