Skip to content

Commit 6b88cfe

Browse files
authored
Merge pull request swiftlang#1533 from ahoppen/background-indexing-configuration-option
Make background indexing a proper option in `SourceKitLSPOptions`
2 parents d066dae + d8e0fff commit 6b88cfe

15 files changed

+141
-128
lines changed

Sources/Diagnose/IndexCommand.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ public struct IndexCommand: AsyncParsableCommand {
8282
public init() {}
8383

8484
public func run() async throws {
85-
let options = SourceKitLSPOptions(experimentalFeatures: Set(experimentalFeatures).union([.backgroundIndexing]))
85+
let options = SourceKitLSPOptions(
86+
backgroundIndexing: true,
87+
experimentalFeatures: Set(experimentalFeatures)
88+
)
8689

8790
let installPath =
8891
if let toolchainOverride, let toolchain = Toolchain(try AbsolutePath(validating: toolchainOverride)) {

Sources/SKCore/SourceKitLSPOptions.swift

Lines changed: 79 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,18 @@ public struct SourceKitLSPOptions: Sendable, Codable {
140140
public var maxCoresPercentageToUseForBackgroundIndexing: Double?
141141
public var updateIndexStoreTimeout: Int?
142142

143+
public var maxCoresPercentageToUseForBackgroundIndexingOrDefault: Double {
144+
return maxCoresPercentageToUseForBackgroundIndexing ?? 1
145+
}
146+
147+
public var updateIndexStoreTimeoutOrDefault: Duration {
148+
if let updateIndexStoreTimeout {
149+
.seconds(updateIndexStoreTimeout)
150+
} else {
151+
.seconds(120)
152+
}
153+
}
154+
143155
public init(
144156
indexStorePath: String? = nil,
145157
indexDatabasePath: String? = nil,
@@ -166,16 +178,19 @@ public struct SourceKitLSPOptions: Sendable, Codable {
166178
}
167179
}
168180

169-
public var swiftPM: SwiftPMOptions?
170-
public var compilationDatabase: CompilationDatabaseOptions?
171-
public var fallbackBuildSystem: FallbackBuildSystemOptions?
181+
public var swiftPM: SwiftPMOptions
182+
public var compilationDatabase: CompilationDatabaseOptions
183+
public var fallbackBuildSystem: FallbackBuildSystemOptions
172184
public var clangdOptions: [String]?
173-
public var index: IndexOptions?
185+
public var index: IndexOptions
174186

175187
/// Default workspace type (buildserver|compdb|swiftpm). Overrides workspace type selection logic.
176188
public var defaultWorkspaceType: WorkspaceType?
177189
public var generatedFilesPath: String?
178190

191+
/// Whether background indexing is enabled.
192+
public var backgroundIndexing: Bool?
193+
179194
/// Experimental features that are enabled.
180195
public var experimentalFeatures: Set<ExperimentalFeature>? = nil
181196

@@ -184,25 +199,29 @@ public struct SourceKitLSPOptions: Sendable, Codable {
184199
///
185200
/// This is mostly intended for testing purposes so we don't need to wait the debouncing time to get a diagnostics
186201
/// notification when running unit tests.
187-
public var swiftPublishDiagnosticsDebounce: Double? = nil
202+
public var swiftPublishDiagnosticsDebounceDuration: Double? = nil
188203

189-
public var swiftPublishDiagnosticsDebounceDuration: TimeInterval {
190-
if let workDoneProgressDebounce {
191-
return workDoneProgressDebounce
204+
public var swiftPublishDiagnosticsDebounceDurationOrDefault: Duration {
205+
if let swiftPublishDiagnosticsDebounceDuration {
206+
return .seconds(swiftPublishDiagnosticsDebounceDuration)
192207
}
193-
return 2 /* seconds */
208+
return .seconds(2)
194209
}
195210

196211
/// When a task is started that should be displayed to the client as a work done progress, how many milliseconds to
197212
/// wait before actually starting the work done progress. This prevents flickering of the work done progress in the
198213
/// client for short-lived index tasks which end within this duration.
199-
public var workDoneProgressDebounce: Double? = nil
214+
public var workDoneProgressDebounceDuration: Double? = nil
200215

201-
public var workDoneProgressDebounceDuration: Duration {
202-
if let workDoneProgressDebounce {
203-
return .seconds(workDoneProgressDebounce)
216+
public var workDoneProgressDebounceDurationOrDefault: Duration {
217+
if let workDoneProgressDebounceDuration {
218+
return .seconds(workDoneProgressDebounceDuration)
204219
}
205-
return .seconds(0)
220+
return .seconds(1)
221+
}
222+
223+
public var backgroundIndexingOrDefault: Bool {
224+
return backgroundIndexing ?? false
206225
}
207226

208227
public init(
@@ -213,9 +232,10 @@ public struct SourceKitLSPOptions: Sendable, Codable {
213232
index: IndexOptions = .init(),
214233
defaultWorkspaceType: WorkspaceType? = nil,
215234
generatedFilesPath: String? = nil,
235+
backgroundIndexing: Bool? = nil,
216236
experimentalFeatures: Set<ExperimentalFeature>? = nil,
217-
swiftPublishDiagnosticsDebounce: Double? = nil,
218-
workDoneProgressDebounce: Double? = nil
237+
swiftPublishDiagnosticsDebounceDuration: Double? = nil,
238+
workDoneProgressDebounceDuration: Double? = nil
219239
) {
220240
self.swiftPM = swiftPM
221241
self.fallbackBuildSystem = fallbackBuildSystem
@@ -224,9 +244,10 @@ public struct SourceKitLSPOptions: Sendable, Codable {
224244
self.index = index
225245
self.generatedFilesPath = generatedFilesPath
226246
self.defaultWorkspaceType = defaultWorkspaceType
247+
self.backgroundIndexing = backgroundIndexing
227248
self.experimentalFeatures = experimentalFeatures
228-
self.swiftPublishDiagnosticsDebounce = swiftPublishDiagnosticsDebounce
229-
self.workDoneProgressDebounce = workDoneProgressDebounce
249+
self.swiftPublishDiagnosticsDebounceDuration = swiftPublishDiagnosticsDebounceDuration
250+
self.workDoneProgressDebounceDuration = workDoneProgressDebounceDuration
230251
}
231252

232253
public init?(path: URL?) {
@@ -236,7 +257,7 @@ public struct SourceKitLSPOptions: Sendable, Codable {
236257
guard
237258
let decoded = orLog(
238259
"Parsing config.json",
239-
{ try JSONDecoder().decode(SourceKitLSPOptions.self, from: contents) }
260+
{ try JSONDecoder().decode(Self.self, from: contents) }
240261
)
241262
else {
242263
return nil
@@ -246,23 +267,25 @@ public struct SourceKitLSPOptions: Sendable, Codable {
246267

247268
public static func merging(base: SourceKitLSPOptions, override: SourceKitLSPOptions?) -> SourceKitLSPOptions {
248269
return SourceKitLSPOptions(
249-
swiftPM: SwiftPMOptions.merging(base: base.swiftPM ?? .init(), override: override?.swiftPM),
270+
swiftPM: SwiftPMOptions.merging(base: base.swiftPM, override: override?.swiftPM),
250271
fallbackBuildSystem: FallbackBuildSystemOptions.merging(
251-
base: base.fallbackBuildSystem ?? .init(),
272+
base: base.fallbackBuildSystem,
252273
override: override?.fallbackBuildSystem
253274
),
254275
compilationDatabase: CompilationDatabaseOptions.merging(
255-
base: base.compilationDatabase ?? .init(),
276+
base: base.compilationDatabase,
256277
override: override?.compilationDatabase
257278
),
258279
clangdOptions: override?.clangdOptions ?? base.clangdOptions,
259-
index: IndexOptions.merging(base: base.index ?? .init(), override: override?.index),
280+
index: IndexOptions.merging(base: base.index, override: override?.index),
260281
defaultWorkspaceType: override?.defaultWorkspaceType ?? base.defaultWorkspaceType,
261282
generatedFilesPath: override?.generatedFilesPath ?? base.generatedFilesPath,
283+
backgroundIndexing: override?.backgroundIndexing ?? base.backgroundIndexing,
262284
experimentalFeatures: override?.experimentalFeatures ?? base.experimentalFeatures,
263-
swiftPublishDiagnosticsDebounce: override?.swiftPublishDiagnosticsDebounce
264-
?? base.swiftPublishDiagnosticsDebounce,
265-
workDoneProgressDebounce: override?.workDoneProgressDebounce ?? base.workDoneProgressDebounce
285+
swiftPublishDiagnosticsDebounceDuration: override?.swiftPublishDiagnosticsDebounceDuration
286+
?? base.swiftPublishDiagnosticsDebounceDuration,
287+
workDoneProgressDebounceDuration: override?.workDoneProgressDebounceDuration
288+
?? base.workDoneProgressDebounceDuration
266289
)
267290
}
268291

@@ -279,4 +302,34 @@ public struct SourceKitLSPOptions: Sendable, Codable {
279302
}
280303
return experimentalFeatures.contains(feature)
281304
}
305+
306+
public init(from decoder: any Decoder) throws {
307+
let container = try decoder.container(keyedBy: CodingKeys.self)
308+
309+
self.swiftPM = try container.decodeIfPresent(SwiftPMOptions.self, forKey: CodingKeys.swiftPM) ?? .init()
310+
self.compilationDatabase =
311+
try container.decodeIfPresent(CompilationDatabaseOptions.self, forKey: CodingKeys.compilationDatabase) ?? .init()
312+
self.fallbackBuildSystem =
313+
try container.decodeIfPresent(FallbackBuildSystemOptions.self, forKey: CodingKeys.fallbackBuildSystem) ?? .init()
314+
self.clangdOptions = try container.decodeIfPresent([String].self, forKey: CodingKeys.clangdOptions)
315+
self.index = try container.decodeIfPresent(IndexOptions.self, forKey: CodingKeys.index) ?? .init()
316+
self.defaultWorkspaceType = try container.decodeIfPresent(
317+
WorkspaceType.self,
318+
forKey: CodingKeys.defaultWorkspaceType
319+
)
320+
self.generatedFilesPath = try container.decodeIfPresent(String.self, forKey: CodingKeys.generatedFilesPath)
321+
self.backgroundIndexing = try container.decodeIfPresent(Bool.self, forKey: CodingKeys.backgroundIndexing)
322+
self.experimentalFeatures = try container.decodeIfPresent(
323+
Set<ExperimentalFeature>.self,
324+
forKey: CodingKeys.experimentalFeatures
325+
)
326+
self.swiftPublishDiagnosticsDebounceDuration = try container.decodeIfPresent(
327+
Double.self,
328+
forKey: CodingKeys.swiftPublishDiagnosticsDebounceDuration
329+
)
330+
self.workDoneProgressDebounceDuration = try container.decodeIfPresent(
331+
Double.self,
332+
forKey: CodingKeys.workDoneProgressDebounceDuration
333+
)
334+
}
282335
}

Sources/SKSupport/ExperimentalFeatures.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@
1313
/// An experimental feature that can be enabled by passing `--experimental-feature` to `sourcekit-lsp` on the command
1414
/// line. The raw value of this feature is how it is named on the command line.
1515
public enum ExperimentalFeature: String, Codable, Sendable, CaseIterable {
16-
/// Enable background indexing.
17-
case backgroundIndexing = "background-indexing"
18-
1916
/// Add `--experimental-prepare-for-indexing` to the `swift build` command run to prepare a target for indexing.
2017
case swiftpmPrepareForIndexing = "swiftpm-prepare-for-indexing"
2118

Sources/SKSwiftPMWorkspace/SwiftPMBuildSystem.swift

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public actor SwiftPMBuildSystem {
131131
private let workspacePath: TSCAbsolutePath
132132

133133
/// Options that allow the user to pass extra compiler flags.
134-
private let options: SourceKitLSPOptions.SwiftPMOptions
134+
private let options: SourceKitLSPOptions
135135

136136
/// The directory containing `Package.swift`.
137137
@_spi(Testing)
@@ -175,12 +175,9 @@ public actor SwiftPMBuildSystem {
175175
logger.log(level: diagnostic.severity.asLogLevel, "SwiftPM log: \(diagnostic.description)")
176176
})
177177

178-
/// Whether to pass `--experimental-prepare-for-indexing` to `swift build` as part of preparation.
179-
private let experimentalFeatures: Set<ExperimentalFeature>
180-
181178
/// Whether the `SwiftPMBuildSystem` is pointed at a `.index-build` directory that's independent of the
182179
/// user's build.
183-
private var isForIndexBuild: Bool { experimentalFeatures.contains(.backgroundIndexing) }
180+
private var isForIndexBuild: Bool { options.backgroundIndexingOrDefault }
184181

185182
private let testHooks: SwiftPMTestHooks
186183

@@ -196,8 +193,7 @@ public actor SwiftPMBuildSystem {
196193
workspacePath: TSCAbsolutePath,
197194
toolchainRegistry: ToolchainRegistry,
198195
fileSystem: FileSystem = localFileSystem,
199-
options: SourceKitLSPOptions.SwiftPMOptions,
200-
experimentalFeatures: Set<ExperimentalFeature>,
196+
options: SourceKitLSPOptions,
201197
reloadPackageStatusCallback: @escaping (ReloadPackageStatus) async -> Void = { _ in },
202198
testHooks: SwiftPMTestHooks
203199
) async throws {
@@ -209,7 +205,6 @@ public actor SwiftPMBuildSystem {
209205
}
210206

211207
self.toolchain = toolchain
212-
self.experimentalFeatures = experimentalFeatures
213208
self.testHooks = testHooks
214209

215210
guard let packageRoot = findPackageDirectory(containing: workspacePath, fileSystem) else {
@@ -250,9 +245,9 @@ public actor SwiftPMBuildSystem {
250245
forRootPackage: AbsolutePath(packageRoot),
251246
fileSystem: fileSystem
252247
)
253-
if experimentalFeatures.contains(.backgroundIndexing) {
248+
if options.backgroundIndexingOrDefault {
254249
location.scratchDirectory = AbsolutePath(packageRoot.appending(component: ".index-build"))
255-
} else if let scratchDirectory = options.scratchPath,
250+
} else if let scratchDirectory = options.swiftPM.scratchPath,
256251
let scratchDirectoryPath = try? AbsolutePath(validating: scratchDirectory)
257252
{
258253
location.scratchDirectory = scratchDirectoryPath
@@ -269,18 +264,18 @@ public actor SwiftPMBuildSystem {
269264
)
270265

271266
let buildConfiguration: PackageModel.BuildConfiguration
272-
switch options.configuration {
267+
switch options.swiftPM.configuration {
273268
case .debug, nil:
274269
buildConfiguration = .debug
275270
case .release:
276271
buildConfiguration = .release
277272
}
278273

279274
let buildFlags = BuildFlags(
280-
cCompilerFlags: options.cCompilerFlags ?? [],
281-
cxxCompilerFlags: options.cxxCompilerFlags ?? [],
282-
swiftCompilerFlags: options.swiftCompilerFlags ?? [],
283-
linkerFlags: options.linkerFlags ?? []
275+
cCompilerFlags: options.swiftPM.cCompilerFlags ?? [],
276+
cxxCompilerFlags: options.swiftPM.cxxCompilerFlags ?? [],
277+
swiftCompilerFlags: options.swiftPM.swiftCompilerFlags ?? [],
278+
linkerFlags: options.swiftPM.linkerFlags ?? []
284279
)
285280

286281
self.toolsBuildParameters = try BuildParameters(
@@ -334,8 +329,7 @@ public actor SwiftPMBuildSystem {
334329
public init?(
335330
uri: DocumentURI,
336331
toolchainRegistry: ToolchainRegistry,
337-
options: SourceKitLSPOptions.SwiftPMOptions,
338-
experimentalFeatures: Set<ExperimentalFeature>,
332+
options: SourceKitLSPOptions,
339333
reloadPackageStatusCallback: @escaping (ReloadPackageStatus) async -> Void,
340334
testHooks: SwiftPMTestHooks
341335
) async {
@@ -348,7 +342,6 @@ public actor SwiftPMBuildSystem {
348342
toolchainRegistry: toolchainRegistry,
349343
fileSystem: localFileSystem,
350344
options: options,
351-
experimentalFeatures: experimentalFeatures,
352345
reloadPackageStatusCallback: reloadPackageStatusCallback,
353346
testHooks: testHooks
354347
)
@@ -635,14 +628,14 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
635628
"--disable-index-store",
636629
"--target", target.targetID,
637630
]
638-
if let configuration = options.configuration {
631+
if let configuration = options.swiftPM.configuration {
639632
arguments += ["-c", configuration.rawValue]
640633
}
641-
arguments += options.cCompilerFlags?.flatMap { ["-Xcc", $0] } ?? []
642-
arguments += options.cxxCompilerFlags?.flatMap { ["-Xcxx", $0] } ?? []
643-
arguments += options.swiftCompilerFlags?.flatMap { ["-Xswiftc", $0] } ?? []
644-
arguments += options.linkerFlags?.flatMap { ["-Xlinker", $0] } ?? []
645-
if experimentalFeatures.contains(.swiftpmPrepareForIndexing) {
634+
arguments += options.swiftPM.cCompilerFlags?.flatMap { ["-Xcc", $0] } ?? []
635+
arguments += options.swiftPM.cxxCompilerFlags?.flatMap { ["-Xcxx", $0] } ?? []
636+
arguments += options.swiftPM.swiftCompilerFlags?.flatMap { ["-Xswiftc", $0] } ?? []
637+
arguments += options.swiftPM.linkerFlags?.flatMap { ["-Xlinker", $0] } ?? []
638+
if options.hasExperimentalFeature(.swiftpmPrepareForIndexing) {
646639
arguments.append("--experimental-prepare-for-indexing")
647640
}
648641
if Task.isCancelled {

Sources/SKTestSupport/TestSourceKitLSPClient.swift

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import XCTest
2424

2525
extension SourceKitLSPOptions {
2626
public static func testDefault(experimentalFeatures: Set<ExperimentalFeature>? = nil) -> SourceKitLSPOptions {
27-
return SourceKitLSPOptions(experimentalFeatures: experimentalFeatures, swiftPublishDiagnosticsDebounce: 0)
27+
return SourceKitLSPOptions(experimentalFeatures: experimentalFeatures, swiftPublishDiagnosticsDebounceDuration: 0)
2828
}
2929
}
3030

@@ -108,13 +108,10 @@ public final class TestSourceKitLSPClient: MessageHandler, Sendable {
108108
) async throws {
109109
var options = options
110110
if let globalModuleCache {
111-
options.swiftPM = options.swiftPM ?? SourceKitLSPOptions.SwiftPMOptions()
112-
options.swiftPM!.swiftCompilerFlags =
113-
(options.swiftPM!.swiftCompilerFlags ?? []) + ["-module-cache-path", globalModuleCache.path]
114-
}
115-
if enableBackgroundIndexing {
116-
options.experimentalFeatures = (options.experimentalFeatures ?? []).union([.backgroundIndexing])
111+
options.swiftPM.swiftCompilerFlags =
112+
(options.swiftPM.swiftCompilerFlags ?? []) + ["-module-cache-path", globalModuleCache.path]
117113
}
114+
options.backgroundIndexing = enableBackgroundIndexing
118115

119116
var notificationYielder: AsyncStream<any NotificationType>.Continuation!
120117
self.notifications = AsyncStream { continuation in

Sources/SourceKitLSP/CreateBuildSystem.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ func createBuildSystem(
3838
return await SwiftPMBuildSystem(
3939
uri: rootUri,
4040
toolchainRegistry: toolchainRegistry,
41-
options: options.swiftPM ?? .init(),
42-
experimentalFeatures: options.experimentalFeatures ?? [],
41+
options: options,
4342
reloadPackageStatusCallback: reloadPackageStatusCallback,
4443
testHooks: testHooks.swiftpmTestHooks
4544
)
@@ -48,7 +47,7 @@ func createBuildSystem(
4847
func createCompilationDatabaseBuildSystem(rootPath: AbsolutePath) -> CompilationDatabaseBuildSystem? {
4948
return CompilationDatabaseBuildSystem(
5049
projectRoot: rootPath,
51-
searchPaths: (options.compilationDatabase?.searchPaths ?? []).compactMap { try? RelativePath(validating: $0) }
50+
searchPaths: (options.compilationDatabase.searchPaths ?? []).compactMap { try? RelativePath(validating: $0) }
5251
)
5352
}
5453

Sources/SourceKitLSP/IndexProgressManager.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ actor IndexProgressManager {
128128
workDoneProgress = await WorkDoneProgressManager(
129129
server: sourceKitLSPServer,
130130
tokenPrefix: "indexing",
131-
initialDebounce: sourceKitLSPServer.options.workDoneProgressDebounceDuration,
131+
initialDebounce: sourceKitLSPServer.options.workDoneProgressDebounceDurationOrDefault,
132132
title: "Indexing",
133133
message: message,
134134
percentage: percentage

Sources/SourceKitLSP/SourceKitLSPServer.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ public actor SourceKitLSPServer {
214214

215215
self.client = client
216216
let processorCount = ProcessInfo.processInfo.processorCount
217-
let lowPriorityCores = (options.index?.maxCoresPercentageToUseForBackgroundIndexing ?? 1) * Double(processorCount)
217+
let lowPriorityCores = options.index.maxCoresPercentageToUseForBackgroundIndexingOrDefault * Double(processorCount)
218218
self.indexTaskScheduler = TaskScheduler(maxConcurrentTasksByPriority: [
219219
(TaskPriority.medium, processorCount),
220220
(TaskPriority.low, max(Int(lowPriorityCores), 1)),
@@ -940,7 +940,7 @@ extension SourceKitLSPServer {
940940
self?.indexProgressManager.indexProgressStatusDidChange()
941941
}
942942
)
943-
if let workspace, options.hasExperimentalFeature(.backgroundIndexing), workspace.semanticIndexManager == nil,
943+
if let workspace, options.backgroundIndexingOrDefault, workspace.semanticIndexManager == nil,
944944
!self.didSendBackgroundIndexingNotSupportedNotification
945945
{
946946
self.sendNotificationToClient(

0 commit comments

Comments
 (0)