Skip to content

Commit 851feba

Browse files
authored
Merge pull request #1649 from ahoppen/bsp-preparation
Start migration of the communication between SourceKit-LSP and build systems to happen via the Build Server Protocol (BSP)
2 parents 765c2c0 + b490a6f commit 851feba

36 files changed

+734
-342
lines changed

Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ let package = Package(
254254
dependencies: [
255255
"CAtomics",
256256
"LanguageServerProtocol",
257+
"LanguageServerProtocolJSONRPC",
257258
"SKLogging",
258259
"SwiftExtensions",
259260
.product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"),

Sources/BuildServerProtocol/BuildTargets.swift

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -211,44 +211,3 @@ public struct OutputsItem: Codable, Hashable, Sendable {
211211
/// The output paths for sources that belong to this build target.
212212
public var outputPaths: [URI]
213213
}
214-
215-
/// The build target changed notification is sent from the server to the client
216-
/// to signal a change in a build target. The server communicates during the
217-
/// initialize handshake whether this method is supported or not.
218-
public struct BuildTargetsChangedNotification: NotificationType {
219-
public static let method: String = "buildTarget/didChange"
220-
221-
public var changes: [BuildTargetEvent]
222-
223-
public init(changes: [BuildTargetEvent]) {
224-
self.changes = changes
225-
}
226-
}
227-
228-
public struct BuildTargetEvent: Codable, Hashable, Sendable {
229-
/// The identifier for the changed build target.
230-
public var target: BuildTargetIdentifier
231-
232-
/// The kind of change for this build target.
233-
public var kind: BuildTargetEventKind?
234-
235-
/// Any additional metadata about what information changed.
236-
public var data: LSPAny?
237-
238-
public init(target: BuildTargetIdentifier, kind: BuildTargetEventKind?, data: LSPAny?) {
239-
self.target = target
240-
self.kind = kind
241-
self.data = data
242-
}
243-
}
244-
245-
public enum BuildTargetEventKind: Int, Codable, Hashable, Sendable {
246-
/// The build target is new.
247-
case created = 1
248-
249-
/// The build target has changed.
250-
case changed = 2
251-
252-
/// The build target has been deleted.
253-
case deleted = 3
254-
}

Sources/BuildServerProtocol/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
add_library(BuildServerProtocol STATIC
22
BuildTargets.swift
3+
DidChangeBuildTargetNotification.swift
4+
DidChangeWatchedFilesNotification.swift
35
FileOptions.swift
46
InitializeBuild.swift
7+
InverseSourcesRequest.swift
58
Messages.swift
69
RegisterForChangeNotifications.swift
710
ShutdownBuild.swift)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import LanguageServerProtocol
14+
15+
/// The build target changed notification is sent from the server to the client
16+
/// to signal a change in a build target. The server communicates during the
17+
/// initialize handshake whether this method is supported or not.
18+
public struct DidChangeBuildTargetNotification: NotificationType, Equatable {
19+
public static let method: String = "buildTarget/didChange"
20+
21+
/// **(BSP Extension)**
22+
/// `changes` can be `nil` to indicate that all targets might have changed.
23+
public var changes: [BuildTargetEvent]?
24+
25+
public init(changes: [BuildTargetEvent]?) {
26+
self.changes = changes
27+
}
28+
}
29+
30+
public struct BuildTargetEvent: Codable, Hashable, Sendable {
31+
/// The identifier for the changed build target.
32+
public var target: BuildTargetIdentifier
33+
34+
/// The kind of change for this build target.
35+
public var kind: BuildTargetEventKind?
36+
37+
/// Kind of data to expect in the `data` field. If this field is not set, the kind of data is not specified.
38+
public var dataKind: String?
39+
40+
/// Any additional metadata about what information changed.
41+
public var data: LSPAny?
42+
43+
public init(target: BuildTargetIdentifier, kind: BuildTargetEventKind?, dataKind: String?, data: LSPAny?) {
44+
self.target = target
45+
self.kind = kind
46+
self.dataKind = dataKind
47+
self.data = data
48+
}
49+
}
50+
51+
public enum BuildTargetEventKind: Int, Codable, Hashable, Sendable {
52+
/// The build target is new.
53+
case created = 1
54+
55+
/// The build target has changed.
56+
case changed = 2
57+
58+
/// The build target has been deleted.
59+
case deleted = 3
60+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import LanguageServerProtocol
14+
15+
/// Notification sent from SourceKit-LSP to the build system to indicate that files within the project have been modified.
16+
public typealias DidChangeWatchedFilesNotification = LanguageServerProtocol.DidChangeWatchedFilesNotification
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import LanguageServerProtocol
14+
15+
public struct TextDocumentIdentifier: Codable, Sendable, Hashable {
16+
/// The text document's URI.
17+
public var uri: URI
18+
19+
public init(uri: URI) {
20+
self.uri = uri
21+
}
22+
}
23+
24+
/// The inverse sources request is sent from the client to the server to query for the list of build targets containing
25+
/// a text document. The server communicates during the initialize handshake whether this method is supported or not.
26+
/// This request can be viewed as the inverse of buildTarget/sources, except it only works for text documents and not
27+
/// directories.
28+
public struct InverseSourcesRequest: RequestType, Hashable {
29+
public static let method: String = "buildTarget/inverseSources"
30+
public typealias Response = InverseSourcesResponse
31+
32+
public var textDocument: TextDocumentIdentifier
33+
34+
public init(textDocument: TextDocumentIdentifier) {
35+
self.textDocument = textDocument
36+
}
37+
}
38+
39+
public struct InverseSourcesResponse: ResponseType, Hashable {
40+
public var targets: [BuildTargetIdentifier]
41+
42+
public init(targets: [BuildTargetIdentifier]) {
43+
self.targets = targets
44+
}
45+
}

Sources/BuildServerProtocol/Messages.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,18 @@
1212
import LanguageServerProtocol
1313

1414
fileprivate let requestTypes: [_RequestType.Type] = [
15-
BuildTargets.self,
1615
BuildTargetOutputPaths.self,
16+
BuildTargets.self,
1717
BuildTargetSources.self,
1818
InitializeBuild.self,
19+
InverseSourcesRequest.self,
1920
RegisterForChanges.self,
2021
ShutdownBuild.self,
2122
SourceKitOptions.self,
2223
]
2324

2425
fileprivate let notificationTypes: [NotificationType.Type] = [
25-
BuildTargetsChangedNotification.self,
26+
DidChangeBuildTargetNotification.self,
2627
ExitBuildNotification.self,
2728
FileOptionsChangedNotification.self,
2829
InitializedBuildNotification.self,

Sources/BuildSystemIntegration/BuildServerBuildSystem.swift

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ package actor BuildServerBuildSystem: MessageHandler {
7474
self.delegate = delegate
7575
}
7676

77+
package weak var messageHandler: BuiltInBuildSystemMessageHandler?
78+
79+
package func setMessageHandler(_ messageHandler: any BuiltInBuildSystemMessageHandler) {
80+
self.messageHandler = messageHandler
81+
}
82+
7783
/// The build settings that have been received from the build server.
7884
private var buildSettings: [DocumentURI: FileBuildSettings] = [:]
7985

@@ -194,7 +200,7 @@ package actor BuildServerBuildSystem: MessageHandler {
194200
"""
195201
)
196202
bspMessageHandlingQueue.async {
197-
if let params = params as? BuildTargetsChangedNotification {
203+
if let params = params as? DidChangeBuildTargetNotification {
198204
await self.handleBuildTargetsChanged(params)
199205
} else if let params = params as? FileOptionsChangedNotification {
200206
await self.handleFileOptionsChanged(params)
@@ -219,10 +225,8 @@ package actor BuildServerBuildSystem: MessageHandler {
219225
reply(.failure(ResponseError.methodNotFound(R.method)))
220226
}
221227

222-
func handleBuildTargetsChanged(
223-
_ notification: BuildTargetsChangedNotification
224-
) async {
225-
await self.delegate?.buildTargetsChanged(notification.changes)
228+
func handleBuildTargetsChanged(_ notification: DidChangeBuildTargetNotification) async {
229+
await self.messageHandler?.sendNotificationToSourceKitLSP(notification)
226230
}
227231

228232
func handleFileOptionsChanged(
@@ -254,7 +258,7 @@ private func readReponseDataKey(data: LSPAny?, key: String) -> String? {
254258
return nil
255259
}
256260

257-
extension BuildServerBuildSystem: BuildSystem {
261+
extension BuildServerBuildSystem: BuiltInBuildSystem {
258262
package nonisolated var supportsPreparation: Bool { false }
259263

260264
/// The build settings for the given file.
@@ -263,7 +267,7 @@ extension BuildServerBuildSystem: BuildSystem {
263267
/// server yet or if no build settings are available for this file.
264268
package func buildSettings(
265269
for document: DocumentURI,
266-
in target: ConfiguredTarget,
270+
in target: BuildTargetIdentifier,
267271
language: Language
268272
) async -> FileBuildSettings? {
269273
return buildSettings[document]
@@ -277,24 +281,24 @@ extension BuildServerBuildSystem: BuildSystem {
277281
return nil
278282
}
279283

280-
package func configuredTargets(for document: DocumentURI) async -> [ConfiguredTarget] {
281-
return [ConfiguredTarget(targetID: "dummy", runDestinationID: "dummy")]
284+
package func inverseSources(_ request: InverseSourcesRequest) -> InverseSourcesResponse {
285+
return InverseSourcesResponse(targets: [BuildTargetIdentifier.dummy])
282286
}
283287

284288
package func scheduleBuildGraphGeneration() {}
285289

286290
package func waitForUpToDateBuildGraph() async {}
287291

288-
package func topologicalSort(of targets: [ConfiguredTarget]) async -> [ConfiguredTarget]? {
292+
package func topologicalSort(of targets: [BuildTargetIdentifier]) async -> [BuildTargetIdentifier]? {
289293
return nil
290294
}
291295

292-
package func targets(dependingOn targets: [ConfiguredTarget]) -> [ConfiguredTarget]? {
296+
package func targets(dependingOn targets: [BuildTargetIdentifier]) -> [BuildTargetIdentifier]? {
293297
return nil
294298
}
295299

296300
package func prepare(
297-
targets: [ConfiguredTarget],
301+
targets: [BuildTargetIdentifier],
298302
logMessageToIndexLog: @Sendable (_ taskID: IndexTaskID, _ message: String) -> Void
299303
) async throws {
300304
throw PrepareNotSupportedError()
@@ -326,7 +330,7 @@ extension BuildServerBuildSystem: BuildSystem {
326330
}
327331
}
328332

329-
package func filesDidChange(_ events: [FileEvent]) {}
333+
package func didChangeWatchedFiles(notification: BuildServerProtocol.DidChangeWatchedFilesNotification) {}
330334

331335
package func fileHandlingCapability(for uri: DocumentURI) -> FileHandlingCapability {
332336
guard

0 commit comments

Comments
 (0)