Skip to content

Commit cab5adc

Browse files
authored
Merge pull request #1449 from ahoppen/6.0/merge-main-2024-06-07
Merge `main` into `release/6.0`
2 parents 047c914 + 6966a6b commit cab5adc

27 files changed

+453
-242
lines changed

Documentation/Background Indexing.md renamed to Documentation/Enable Experimental Background Indexing.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ Next, point your editor to use the just-built copy of SourceKit-LSP and enable b
2222
"swift.sourcekit-lsp.serverArguments": [ "--experimental-feature", "background-indexing" ],
2323
```
2424

25+
Background indexing requires a Swift 6 toolchain. You can download Swift 6 nightly toolchains from https://www.swift.org/download/#swift-60-development.
26+
2527
## Known issues
2628

27-
- The only supported toolchain for background indexing are currently [Swift 6.0 nightly toolchain snapshots](https://www.swift.org/download/#swift-60-development). Older toolchains are not supported and the nightly toolchains from `main` are having issues because building a target non-deterministically builds for tools or the destination [#1288](https://github.com/apple/sourcekit-lsp/pull/1288#issuecomment-2111400459) [rdar://128100158](rdar://128100158)
2829
- Not really a background indexing related issue but Swift nightly toolchain snapshots are crashing on macOS 14.4 and 14.5 (swift#73327)[https://github.com/apple/swift/issues/73327]
2930
- Workaround: Run the toolchains on an older version of macOS, if possible
3031
- Background Indexing is only supported for SwiftPM projects [#1269](https://github.com/apple/sourcekit-lsp/issues/1269), [#1271](https://github.com/apple/sourcekit-lsp/issues/1271)

Sources/Diagnose/DiagnoseCommand.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,7 @@ public struct DiagnoseCommand: AsyncParsableCommand {
407407
// is responsible for showing the diagnose bundle location to the user
408408
if self.bundleOutputPath == nil {
409409
do {
410-
let process = try Process.launch(arguments: ["open", "-R", bundlePath.path], workingDirectory: nil)
411-
try await process.waitUntilExitSendingSigIntOnTaskCancellation()
410+
_ = try await Process.run(arguments: ["open", "-R", bundlePath.path], workingDirectory: nil)
412411
} catch {
413412
// If revealing the bundle in Finder should fail, we don't care. We still printed the bundle path to stdout.
414413
}

Sources/Diagnose/IndexCommand.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,23 @@ public struct IndexCommand: AsyncParsableCommand {
6868
)
6969
var toolchainOverride: String?
7070

71+
@Option(
72+
name: .customLong("experimental-index-feature"),
73+
help: """
74+
Enable an experimental sourcekit-lsp feature.
75+
Available features are: \(ExperimentalFeature.allCases.map(\.rawValue).joined(separator: ", "))
76+
"""
77+
)
78+
var experimentalFeatures: [ExperimentalFeature] = []
79+
7180
@Option(help: "The path to the project that should be indexed")
7281
var project: String
7382

7483
public init() {}
7584

7685
public func run() async throws {
7786
var serverOptions = SourceKitLSPServer.Options()
87+
serverOptions.experimentalFeatures = Set(experimentalFeatures)
7888
serverOptions.experimentalFeatures.insert(.backgroundIndexing)
7989

8090
let installPath =
@@ -109,3 +119,9 @@ fileprivate extension SourceKitLSPServer {
109119
}
110120
}
111121
}
122+
123+
#if compiler(>=6)
124+
extension ExperimentalFeature: @retroactive ExpressibleByArgument {}
125+
#else
126+
extension ExperimentalFeature: ExpressibleByArgument {}
127+
#endif

Sources/Diagnose/MergeSwiftFiles.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@ extension RequestInfo {
2727

2828
progressUpdate(0, "Merging all .swift files into a single file")
2929

30+
let compilerArgs = compilerArgs.filter { $0 != "-primary-file" && !$0.hasSuffix(".swift") } + ["$FILE"]
3031
let mergedRequestInfo = RequestInfo(
3132
requestTemplate: requestTemplate,
3233
offset: offset,
33-
compilerArgs: compilerArgs.filter { !$0.hasSuffix(".swift") } + ["$FILE"],
34+
compilerArgs: compilerArgs,
3435
fileContents: mergedFile
3536
)
3637

Sources/Diagnose/ReduceFrontendCommand.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,17 +96,18 @@ public struct ReduceFrontendCommand: AsyncParsableCommand {
9696
reproducerPredicate: nsPredicate
9797
)
9898

99+
defer {
100+
progressBar.complete(success: true)
101+
}
99102
let reducedRequestInfo = try await reduceFrontendIssue(
100103
frontendArgs: frontendArgs,
101104
using: executor
102105
) { progress, message in
103106
progressBar.update(step: Int(progress * 100), total: 100, text: message)
104107
}
105108

106-
progressBar.complete(success: true)
107-
108109
print("Reduced compiler arguments:")
109-
print(reducedRequestInfo.compilerArgs)
110+
print(reducedRequestInfo.compilerArgs.joined(separator: " "))
110111

111112
print("")
112113
print("Reduced file contents:")

Sources/Diagnose/RequestInfo.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,12 @@ public struct RequestInfo: Sendable {
121121

122122
// Inline the file list so we can reduce the compiler arguments by removing individual source files.
123123
// A couple `output-filelist`-related compiler arguments don't work with the file list inlined. Remove them as they
124-
// are unlikely to be responsible for the swift-frontend cache
124+
// are unlikely to be responsible for the swift-frontend cache.
125+
// `-index-system-modules` is invalid when no output file lists are specified.
125126
while let frontendArg = iterator.next() {
126127
switch frontendArg {
127-
case "-supplementary-output-file-map", "-output-filelist", "-index-unit-output-path-filelist":
128+
case "-supplementary-output-file-map", "-output-filelist", "-index-unit-output-path-filelist",
129+
"-index-system-modules":
128130
_ = iterator.next()
129131
case "-filelist":
130132
guard let fileList = iterator.next() else {

Sources/SKCore/BuildServerBuildSystem.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,10 @@ extension BuildServerBuildSystem: BuildSystem {
278278
return nil
279279
}
280280

281+
public func toolchain(for uri: DocumentURI, _ language: Language) async -> SKCore.Toolchain? {
282+
return nil
283+
}
284+
281285
public func configuredTargets(for document: DocumentURI) async -> [ConfiguredTarget] {
282286
return [ConfiguredTarget(targetID: "dummy", runDestinationID: "dummy")]
283287
}

Sources/SKCore/BuildSystem.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,11 @@ public protocol BuildSystem: AnyObject, Sendable {
179179
/// If `nil` is returned, the language based on the file's extension.
180180
func defaultLanguage(for document: DocumentURI) async -> Language?
181181

182+
/// The toolchain that should be used to open the given document.
183+
///
184+
/// If `nil` is returned, then the default toolchain for the given language is used.
185+
func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain?
186+
182187
/// Register the given file for build-system level change notifications, such
183188
/// as command line flag changes, dependency changes, etc.
184189
///

Sources/SKCore/BuildSystemManager.swift

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,18 @@ extension BuildSystemManager {
104104

105105
/// Returns the toolchain that should be used to process the given document.
106106
public func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain? {
107-
// To support multiple toolchains within a single workspace, we need to ask the build system which toolchain to use
108-
// for this document.
109-
return await toolchainRegistry.defaultToolchain(for: language)
107+
if let toolchain = await buildSystem?.toolchain(for: uri, language) {
108+
return toolchain
109+
}
110+
111+
switch language {
112+
case .swift:
113+
return await toolchainRegistry.preferredToolchain(containing: [\.sourcekitd, \.swift, \.swiftc])
114+
case .c, .cpp, .objective_c, .objective_cpp:
115+
return await toolchainRegistry.preferredToolchain(containing: [\.clang, \.clangd])
116+
default:
117+
return nil
118+
}
110119
}
111120

112121
/// - Note: Needed so we can set the delegate from a different isolation context.

Sources/SKCore/CompilationDatabaseBuildSystem.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ extension CompilationDatabaseBuildSystem: BuildSystem {
119119
return nil
120120
}
121121

122+
public func toolchain(for uri: DocumentURI, _ language: Language) async -> SKCore.Toolchain? {
123+
return nil
124+
}
125+
122126
public func configuredTargets(for document: DocumentURI) async -> [ConfiguredTarget] {
123127
return [ConfiguredTarget(targetID: "dummy", runDestinationID: "dummy")]
124128
}

Sources/SKCore/IndexTaskID.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public enum IndexTaskID: Sendable {
1919
case updateIndexStore(id: UInt32)
2020

2121
private static func numberToEmojis(_ number: Int, numEmojis: Int) -> String {
22-
let emojis = ["🟥", "🟩", "🟦", "🟧", "⬜️", "🟪", "⬛️", "🟨", "🟫"]
22+
let emojis = ["🟥", "🟩", "🟦", "⬜️", "🟪", "⬛️", "🟨", "🟫"]
2323
var number = abs(number)
2424
var result = ""
2525
for _ in 0..<numEmojis {
@@ -36,11 +36,12 @@ public enum IndexTaskID: Sendable {
3636
public var emojiRepresentation: String {
3737
// Multiply by 2 and optionally add 1 to make sure preparation and update index store have distinct IDs.
3838
// Run .hashValue to make sure we semi-randomly pick new emoji markers for new tasks
39+
let numEmojis = 3
3940
switch self {
4041
case .preparation(id: let id):
41-
return Self.numberToEmojis((id * 2).hashValue, numEmojis: 2)
42+
return Self.numberToEmojis((id * 2).hashValue, numEmojis: numEmojis)
4243
case .updateIndexStore(id: let id):
43-
return Self.numberToEmojis((id * 2 + 1).hashValue, numEmojis: 2)
44+
return Self.numberToEmojis((id * 2 + 1).hashValue, numEmojis: numEmojis)
4445
}
4546
}
4647
}

Sources/SKCore/TaskScheduler.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,3 +541,25 @@ fileprivate extension Collection<Int> {
541541
return result
542542
}
543543
}
544+
545+
/// Version of the `withTaskPriorityChangedHandler` where the body doesn't throw.
546+
fileprivate func withTaskPriorityChangedHandler(
547+
initialPriority: TaskPriority = Task.currentPriority,
548+
pollingInterval: Duration = .seconds(0.1),
549+
@_inheritActorContext operation: @escaping @Sendable () async -> Void,
550+
taskPriorityChanged: @escaping @Sendable () -> Void
551+
) async {
552+
do {
553+
try await withTaskPriorityChangedHandler(
554+
initialPriority: initialPriority,
555+
pollingInterval: pollingInterval,
556+
operation: operation as @Sendable () async throws -> Void,
557+
taskPriorityChanged: taskPriorityChanged
558+
)
559+
} catch is CancellationError {
560+
} catch {
561+
// Since `operation` does not throw, the only error we expect `withTaskPriorityChangedHandler` to throw is a
562+
// `CancellationError`, in which case we can just return.
563+
logger.fault("Unexpected error thrown from withTaskPriorityChangedHandler: \(error.forLogging)")
564+
}
565+
}

Sources/SKCore/ToolchainRegistry.swift

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -246,26 +246,14 @@ public final actor ToolchainRegistry {
246246
return darwinToolchainOverride ?? ToolchainRegistry.darwinDefaultToolchainIdentifier
247247
}
248248

249-
/// The toolchain to use for a document in the given language if the build system doesn't override it.
250-
func defaultToolchain(for language: Language) -> Toolchain? {
251-
let supportsLang = { (toolchain: Toolchain) -> Bool in
252-
// FIXME: the fact that we're looking at clangd/sourcekitd instead of the compiler indicates this method needs a parameter stating what kind of tool we're looking for.
253-
switch language {
254-
case .swift:
255-
return toolchain.sourcekitd != nil
256-
case .c, .cpp, .objective_c, .objective_cpp:
257-
return toolchain.clangd != nil
258-
default:
259-
return false
260-
}
261-
}
262-
263-
if let toolchain = self.default, supportsLang(toolchain) {
249+
/// Returns the preferred toolchain that contains all the tools at the given key paths.
250+
public func preferredToolchain(containing requiredTools: [KeyPath<Toolchain, AbsolutePath?>]) -> Toolchain? {
251+
if let toolchain = self.default, requiredTools.allSatisfy({ toolchain[keyPath: $0] != nil }) {
264252
return toolchain
265253
}
266254

267255
for toolchain in toolchains {
268-
if supportsLang(toolchain) {
256+
if requiredTools.allSatisfy({ toolchain[keyPath: $0] != nil }) {
269257
return toolchain
270258
}
271259
}

Sources/SKSupport/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ add_library(SKSupport STATIC
99
FileSystem.swift
1010
LineTable.swift
1111
PipeAsStringHandler.swift
12-
Process+LaunchWithWorkingDirectoryIfPossible.swift
13-
Process+WaitUntilExitWithCancellation.swift
12+
Process+Run.swift
1413
Random.swift
1514
Result.swift
1615
SwitchableProcessResultExitStatus.swift

Sources/SKSupport/Process+LaunchWithWorkingDirectoryIfPossible.swift

Lines changed: 0 additions & 70 deletions
This file was deleted.

0 commit comments

Comments
 (0)