Skip to content

Commit ea21175

Browse files
committed
Create BuildSystem in BuiltInBuildSystemAdapter
This finalizes the move of `BuiltInBuildSystem` creation into `BuiltInBuildSystemAdapter` and means that we can set the message handler of the `BuiltInBuildSystem` during initialization instead of using a setter method.
1 parent 9f40880 commit ea21175

11 files changed

+114
-92
lines changed

Sources/BuildSystemIntegration/BuildServerBuildSystem.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,12 @@ package actor BuildServerBuildSystem: MessageHandler {
7777

7878
package weak var messageHandler: BuiltInBuildSystemMessageHandler?
7979

80-
package func setMessageHandler(_ messageHandler: any BuiltInBuildSystemMessageHandler) {
81-
self.messageHandler = messageHandler
82-
}
83-
8480
/// The build settings that have been received from the build server.
8581
private var buildSettings: [DocumentURI: FileBuildSettings] = [:]
8682

8783
package init(
8884
projectRoot: AbsolutePath,
85+
messageHandler: BuiltInBuildSystemMessageHandler?,
8986
fileSystem: FileSystem = localFileSystem
9087
) async throws {
9188
let configPath = projectRoot.appending(component: "buildServer.json")
@@ -105,17 +102,18 @@ package actor BuildServerBuildSystem: MessageHandler {
105102
#endif
106103
self.projectRoot = projectRoot
107104
self.serverConfig = config
105+
self.messageHandler = messageHandler
108106
try await self.initializeBuildServer()
109107
}
110108

111109
/// Creates a build system using the Build Server Protocol config.
112110
///
113111
/// - Returns: nil if `projectRoot` has no config or there is an error parsing it.
114-
package init?(projectRoot: AbsolutePath?) async {
112+
package init?(projectRoot: AbsolutePath?, messageHandler: BuiltInBuildSystemMessageHandler?) async {
115113
guard let projectRoot else { return nil }
116114

117115
do {
118-
try await self.init(projectRoot: projectRoot)
116+
try await self.init(projectRoot: projectRoot, messageHandler: messageHandler)
119117
} catch is FileSystemError {
120118
// config file was missing, no build server for this workspace
121119
return nil

Sources/BuildSystemIntegration/BuildSystem.swift

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import SKOptions
1717
import ToolchainRegistry
1818

1919
import struct TSCBasic.AbsolutePath
20+
import struct TSCBasic.RelativePath
2021

2122
/// Defines how well a `BuildSystem` can handle a file with a given URI.
2223
package enum FileHandlingCapability: Comparable, Sendable {
@@ -98,11 +99,6 @@ package protocol BuiltInBuildSystem: AnyObject, Sendable {
9899
/// context.
99100
func setDelegate(_ delegate: BuildSystemDelegate?) async
100101

101-
/// Set the message handler that is used to send messages from the build system to SourceKit-LSP.
102-
// FIXME: (BSP Migration) This should be set in the initializer but can't right now because BuiltInBuildSystemAdapter is not
103-
// responsible for creating the build system.
104-
func setMessageHandler(_ messageHandler: BuiltInBuildSystemMessageHandler) async
105-
106102
/// Whether the build system is capable of preparing a target for indexing, ie. if the `prepare` methods has been
107103
/// implemented.
108104
var supportsPreparation: Bool { get }

Sources/BuildSystemIntegration/BuildSystemManager.swift

Lines changed: 12 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import SwiftExtensions
1919
import ToolchainRegistry
2020

2121
import struct TSCBasic.AbsolutePath
22-
import struct TSCBasic.RelativePath
2322

2423
#if canImport(os)
2524
import os
@@ -58,35 +57,6 @@ fileprivate class RequestCache<Request: RequestType & Hashable> {
5857
}
5958
}
6059

61-
/// Create a build system of the given type.
62-
private func createBuildSystem(
63-
ofType buildSystemType: WorkspaceType,
64-
projectRoot: AbsolutePath,
65-
options: SourceKitLSPOptions,
66-
swiftpmTestHooks: SwiftPMTestHooks,
67-
toolchainRegistry: ToolchainRegistry,
68-
reloadPackageStatusCallback: @Sendable @escaping (ReloadPackageStatus) async -> Void
69-
) async -> BuiltInBuildSystem? {
70-
switch buildSystemType {
71-
case .buildServer:
72-
return await BuildServerBuildSystem(projectRoot: projectRoot)
73-
case .compilationDatabase:
74-
return CompilationDatabaseBuildSystem(
75-
projectRoot: projectRoot,
76-
searchPaths: (options.compilationDatabaseOrDefault.searchPaths ?? [])
77-
.compactMap { try? RelativePath(validating: $0) }
78-
)
79-
case .swiftPM:
80-
return await SwiftPMBuildSystem(
81-
projectRoot: projectRoot,
82-
toolchainRegistry: toolchainRegistry,
83-
options: options,
84-
reloadPackageStatusCallback: reloadPackageStatusCallback,
85-
testHooks: swiftpmTestHooks
86-
)
87-
}
88-
}
89-
9060
/// `BuildSystem` that integrates client-side information such as main-file lookup as well as providing
9161
/// common functionality such as caching.
9262
///
@@ -136,7 +106,9 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
136106
}
137107

138108
package var supportsPreparation: Bool {
139-
return buildSystem?.underlyingBuildSystem.supportsPreparation ?? false
109+
get async {
110+
return await buildSystem?.underlyingBuildSystem.supportsPreparation ?? false
111+
}
140112
}
141113

142114
package init(
@@ -146,29 +118,16 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
146118
swiftpmTestHooks: SwiftPMTestHooks,
147119
reloadPackageStatusCallback: @Sendable @escaping (ReloadPackageStatus) async -> Void
148120
) async {
149-
let buildSystem: BuiltInBuildSystem?
150-
if let (buildSystemType, projectRoot) = buildSystemKind {
151-
buildSystem = await createBuildSystem(
152-
ofType: buildSystemType,
153-
projectRoot: projectRoot,
154-
options: options,
155-
swiftpmTestHooks: swiftpmTestHooks,
156-
toolchainRegistry: toolchainRegistry,
157-
reloadPackageStatusCallback: reloadPackageStatusCallback
158-
)
159-
} else {
160-
buildSystem = nil
161-
}
162-
let buildSystemHasDelegate = await buildSystem?.delegate != nil
163-
precondition(!buildSystemHasDelegate)
164121
self.fallbackBuildSystem = FallbackBuildSystem(options: options.fallbackBuildSystemOrDefault)
165122
self.toolchainRegistry = toolchainRegistry
166-
self.buildSystem =
167-
if let buildSystem {
168-
await BuiltInBuildSystemAdapter(buildSystem: buildSystem, messageHandler: self)
169-
} else {
170-
nil
171-
}
123+
self.buildSystem = await BuiltInBuildSystemAdapter(
124+
buildSystemKind: buildSystemKind,
125+
toolchainRegistry: toolchainRegistry,
126+
options: options,
127+
swiftpmTestHooks: swiftpmTestHooks,
128+
reloadPackageStatusCallback: reloadPackageStatusCallback,
129+
messageHandler: self
130+
)
172131
await self.buildSystem?.underlyingBuildSystem.setDelegate(self)
173132
}
174133

@@ -189,7 +148,7 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
189148
self.toolchainRegistry = toolchainRegistry
190149
self.buildSystem =
191150
if let testBuildSystem {
192-
await BuiltInBuildSystemAdapter(buildSystem: testBuildSystem, messageHandler: self)
151+
await BuiltInBuildSystemAdapter(testBuildSystem: testBuildSystem, messageHandler: self)
193152
} else {
194153
nil
195154
}

Sources/BuildSystemIntegration/BuiltInBuildSystemAdapter.swift

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@
1313
import BuildServerProtocol
1414
import LanguageServerProtocol
1515
import SKLogging
16+
import SKOptions
1617
import SKSupport
18+
import ToolchainRegistry
19+
20+
import struct TSCBasic.AbsolutePath
21+
import struct TSCBasic.RelativePath
1722

1823
// FIXME: (BSP Migration) This should be a MessageHandler once we have migrated all build system queries to BSP and can use
1924
// LocalConnection for the communication.
@@ -29,22 +34,84 @@ package protocol BuiltInBuildSystemMessageHandler: AnyObject, Sendable {
2934
func sendRequestToSourceKitLSP<R: RequestType>(_ request: R) async throws -> R.Response
3035
}
3136

37+
/// Create a build system of the given type.
38+
private func createBuildSystem(
39+
ofType buildSystemType: WorkspaceType,
40+
projectRoot: AbsolutePath,
41+
options: SourceKitLSPOptions,
42+
swiftpmTestHooks: SwiftPMTestHooks,
43+
toolchainRegistry: ToolchainRegistry,
44+
messageHandler: BuiltInBuildSystemMessageHandler,
45+
reloadPackageStatusCallback: @Sendable @escaping (ReloadPackageStatus) async -> Void
46+
) async -> BuiltInBuildSystem? {
47+
switch buildSystemType {
48+
case .buildServer:
49+
return await BuildServerBuildSystem(projectRoot: projectRoot, messageHandler: messageHandler)
50+
case .compilationDatabase:
51+
return CompilationDatabaseBuildSystem(
52+
projectRoot: projectRoot,
53+
searchPaths: (options.compilationDatabaseOrDefault.searchPaths ?? []).compactMap {
54+
try? RelativePath(validating: $0)
55+
},
56+
messageHandler: messageHandler
57+
)
58+
case .swiftPM:
59+
return await SwiftPMBuildSystem(
60+
projectRoot: projectRoot,
61+
toolchainRegistry: toolchainRegistry,
62+
options: options,
63+
messageHandler: messageHandler,
64+
reloadPackageStatusCallback: reloadPackageStatusCallback,
65+
testHooks: swiftpmTestHooks
66+
)
67+
}
68+
}
69+
3270
/// A type that outwardly acts as a build server conforming to the Build System Integration Protocol and internally uses
3371
/// a `BuiltInBuildSystem` to satisfy the requests.
3472
package actor BuiltInBuildSystemAdapter: BuiltInBuildSystemMessageHandler {
3573
/// The underlying build system
3674
// FIXME: (BSP Migration) This should be private, all messages should go through BSP. Only accessible from the outside for transition
3775
// purposes.
38-
package let underlyingBuildSystem: BuiltInBuildSystem
76+
private(set) package var underlyingBuildSystem: BuiltInBuildSystem!
3977
private let messageHandler: any BuiltInBuildSystemAdapterDelegate
4078

41-
init(
42-
buildSystem: BuiltInBuildSystem,
79+
init?(
80+
buildSystemKind: (WorkspaceType, projectRoot: AbsolutePath)?,
81+
toolchainRegistry: ToolchainRegistry,
82+
options: SourceKitLSPOptions,
83+
swiftpmTestHooks: SwiftPMTestHooks,
84+
reloadPackageStatusCallback: @Sendable @escaping (ReloadPackageStatus) async -> Void,
4385
messageHandler: any BuiltInBuildSystemAdapterDelegate
4486
) async {
87+
guard let (buildSystemType, projectRoot) = buildSystemKind else {
88+
return nil
89+
}
90+
self.messageHandler = messageHandler
91+
92+
let buildSystem = await createBuildSystem(
93+
ofType: buildSystemType,
94+
projectRoot: projectRoot,
95+
options: options,
96+
swiftpmTestHooks: swiftpmTestHooks,
97+
toolchainRegistry: toolchainRegistry,
98+
messageHandler: self,
99+
reloadPackageStatusCallback: reloadPackageStatusCallback
100+
)
101+
guard let buildSystem else {
102+
return nil
103+
}
104+
45105
self.underlyingBuildSystem = buildSystem
106+
}
107+
108+
/// - Important: For testing purposes only
109+
init(
110+
testBuildSystem: BuiltInBuildSystem,
111+
messageHandler: any BuiltInBuildSystemAdapterDelegate
112+
) async {
113+
self.underlyingBuildSystem = testBuildSystem
46114
self.messageHandler = messageHandler
47-
await buildSystem.setMessageHandler(self)
48115
}
49116

50117
package func send<R: RequestType>(_ request: R) async throws -> R.Response {

Sources/BuildSystemIntegration/CompilationDatabaseBuildSystem.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,6 @@ package actor CompilationDatabaseBuildSystem {
5050

5151
package weak var messageHandler: BuiltInBuildSystemMessageHandler?
5252

53-
package func setMessageHandler(_ messageHandler: any BuiltInBuildSystemMessageHandler) {
54-
self.messageHandler = messageHandler
55-
}
56-
5753
package let projectRoot: AbsolutePath
5854

5955
let searchPaths: [RelativePath]
@@ -87,11 +83,13 @@ package actor CompilationDatabaseBuildSystem {
8783
package init?(
8884
projectRoot: AbsolutePath,
8985
searchPaths: [RelativePath],
86+
messageHandler: (any BuiltInBuildSystemMessageHandler)?,
9087
fileSystem: FileSystem = localFileSystem
9188
) {
9289
self.fileSystem = fileSystem
9390
self.projectRoot = projectRoot
9491
self.searchPaths = searchPaths
92+
self.messageHandler = messageHandler
9593
if let compdb = tryLoadCompilationDatabase(directory: projectRoot, additionalSearchPaths: searchPaths, fileSystem) {
9694
self.compdb = compdb
9795
} else {

Sources/BuildSystemIntegration/SwiftPMBuildSystem.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,6 @@ package actor SwiftPMBuildSystem {
182182

183183
package weak var messageHandler: BuiltInBuildSystemMessageHandler?
184184

185-
package func setMessageHandler(_ messageHandler: any BuiltInBuildSystemMessageHandler) {
186-
self.messageHandler = messageHandler
187-
}
188-
189185
/// This callback is informed when `reloadPackage` starts and ends executing.
190186
private var reloadPackageStatusCallback: (ReloadPackageStatus) async -> Void
191187

@@ -277,6 +273,7 @@ package actor SwiftPMBuildSystem {
277273
toolchainRegistry: ToolchainRegistry,
278274
fileSystem: FileSystem = localFileSystem,
279275
options: SourceKitLSPOptions,
276+
messageHandler: (any BuiltInBuildSystemMessageHandler)?,
280277
reloadPackageStatusCallback: @escaping (ReloadPackageStatus) async -> Void = { _ in },
281278
testHooks: SwiftPMTestHooks
282279
) async throws {
@@ -292,6 +289,7 @@ package actor SwiftPMBuildSystem {
292289

293290
self.toolchain = toolchain
294291
self.testHooks = testHooks
292+
self.messageHandler = messageHandler
295293

296294
guard let destinationToolchainBinDir = toolchain.swiftc?.parentDirectory else {
297295
throw Error.cannotDetermineHostToolchain
@@ -408,6 +406,7 @@ package actor SwiftPMBuildSystem {
408406
projectRoot: TSCBasic.AbsolutePath,
409407
toolchainRegistry: ToolchainRegistry,
410408
options: SourceKitLSPOptions,
409+
messageHandler: any BuiltInBuildSystemMessageHandler,
411410
reloadPackageStatusCallback: @escaping (ReloadPackageStatus) async -> Void,
412411
testHooks: SwiftPMTestHooks
413412
) async {
@@ -417,6 +416,7 @@ package actor SwiftPMBuildSystem {
417416
toolchainRegistry: toolchainRegistry,
418417
fileSystem: localFileSystem,
419418
options: options,
419+
messageHandler: messageHandler,
420420
reloadPackageStatusCallback: reloadPackageStatusCallback,
421421
testHooks: testHooks
422422
)

Tests/BuildSystemIntegrationTests/BuildServerBuildSystemTests.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ final class BuildServerBuildSystemTests: XCTestCase {
5353
let buildFolder = try! AbsolutePath(validating: NSTemporaryDirectory())
5454

5555
func testServerInitialize() async throws {
56-
let buildSystem = try await BuildServerBuildSystem(projectRoot: root)
56+
let buildSystem = try await BuildServerBuildSystem(projectRoot: root, messageHandler: nil)
5757

5858
assertEqual(
5959
await buildSystem.indexDatabasePath,
@@ -66,7 +66,6 @@ final class BuildServerBuildSystemTests: XCTestCase {
6666
}
6767

6868
func testFileRegistration() async throws {
69-
let buildSystem = try await BuildServerBuildSystem(projectRoot: root)
7069

7170
let fileUrl = URL(fileURLWithPath: "/some/file/path")
7271
let expectation = XCTestExpectation(description: "\(fileUrl) settings updated")
@@ -75,14 +74,14 @@ final class BuildServerBuildSystemTests: XCTestCase {
7574
// BuildSystemManager has a weak reference to delegate. Keep it alive.
7675
_fixLifetime(buildSystemDelegate)
7776
}
77+
let buildSystem = try await BuildServerBuildSystem(projectRoot: root, messageHandler: buildSystemDelegate)
7878
await buildSystem.setDelegate(buildSystemDelegate)
7979
await buildSystem.registerForChangeNotifications(for: DocumentURI(fileUrl))
8080

8181
XCTAssertEqual(XCTWaiter.wait(for: [expectation], timeout: defaultTimeout), .completed)
8282
}
8383

8484
func testBuildTargetsChanged() async throws {
85-
let buildSystem = try await BuildServerBuildSystem(projectRoot: root)
8685

8786
let fileUrl = URL(fileURLWithPath: "/some/file/path")
8887
let expectation = XCTestExpectation(description: "target changed")
@@ -102,7 +101,7 @@ final class BuildServerBuildSystemTests: XCTestCase {
102101
// BuildSystemManager has a weak reference to delegate. Keep it alive.
103102
_fixLifetime(buildSystemDelegate)
104103
}
105-
await buildSystem.setMessageHandler(buildSystemDelegate)
104+
let buildSystem = try await BuildServerBuildSystem(projectRoot: root, messageHandler: buildSystemDelegate)
106105
await buildSystem.registerForChangeNotifications(for: DocumentURI(fileUrl))
107106

108107
try await fulfillmentOfOrThrow([expectation])

Tests/BuildSystemIntegrationTests/BuildSystemManagerTests.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -464,12 +464,6 @@ class ManualBuildSystem: BuiltInBuildSystem {
464464
self.delegate = delegate
465465
}
466466

467-
weak var messageHandler: BuiltInBuildSystemMessageHandler?
468-
469-
func setMessageHandler(_ messageHandler: any BuiltInBuildSystemMessageHandler) {
470-
self.messageHandler = messageHandler
471-
}
472-
473467
package nonisolated var supportsPreparation: Bool { false }
474468

475469
func buildSettings(

Tests/BuildSystemIntegrationTests/CompilationDatabaseTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ private func checkCompilationDatabaseBuildSystem(
421421
let buildSystem = CompilationDatabaseBuildSystem(
422422
projectRoot: try AbsolutePath(validating: "/a"),
423423
searchPaths: try [RelativePath(validating: ".")],
424+
messageHandler: nil,
424425
fileSystem: fs
425426
)
426427
try await block(XCTUnwrap(buildSystem))

0 commit comments

Comments
 (0)