Skip to content

Commit b7907b4

Browse files
authored
Merge pull request #1922 from ahoppen/inject-build-system
Allow injection of build systems into `SourceKitLSP`
2 parents 8d28ed1 + 31b1909 commit b7907b4

25 files changed

+192
-165
lines changed

Sources/BuildSystemIntegration/BuildSystemManager.swift

+12-25
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ private extension BuildSystemSpec {
145145
private static func createBuiltInBuildSystemAdapter(
146146
projectRoot: URL,
147147
messagesToSourceKitLSPHandler: any MessageHandler,
148-
buildSystemTestHooks: BuildSystemTestHooks,
148+
buildSystemHooks: BuildSystemHooks,
149149
_ createBuildSystem: @Sendable (_ connectionToSourceKitLSP: any Connection) async throws -> BuiltInBuildSystem?
150150
) async -> BuildSystemAdapter? {
151151
let connectionToSourceKitLSP = LocalConnection(
@@ -164,7 +164,7 @@ private extension BuildSystemSpec {
164164
let buildSystemAdapter = BuiltInBuildSystemAdapter(
165165
underlyingBuildSystem: buildSystem,
166166
connectionToSourceKitLSP: connectionToSourceKitLSP,
167-
buildSystemTestHooks: buildSystemTestHooks
167+
buildSystemHooks: buildSystemHooks
168168
)
169169
let connectionToBuildSystem = LocalConnection(
170170
receiverName: "\(type(of: buildSystem)) for \(projectRoot.lastPathComponent)"
@@ -178,7 +178,7 @@ private extension BuildSystemSpec {
178178
func createBuildSystemAdapter(
179179
toolchainRegistry: ToolchainRegistry,
180180
options: SourceKitLSPOptions,
181-
buildSystemTestHooks testHooks: BuildSystemTestHooks,
181+
buildSystemHooks: BuildSystemHooks,
182182
messagesToSourceKitLSPHandler: any MessageHandler
183183
) async -> BuildSystemAdapter? {
184184
switch self.kind {
@@ -199,7 +199,7 @@ private extension BuildSystemSpec {
199199
return await Self.createBuiltInBuildSystemAdapter(
200200
projectRoot: projectRoot,
201201
messagesToSourceKitLSPHandler: messagesToSourceKitLSPHandler,
202-
buildSystemTestHooks: testHooks
202+
buildSystemHooks: buildSystemHooks
203203
) { connectionToSourceKitLSP in
204204
CompilationDatabaseBuildSystem(
205205
projectRoot: projectRoot,
@@ -214,26 +214,26 @@ private extension BuildSystemSpec {
214214
return await Self.createBuiltInBuildSystemAdapter(
215215
projectRoot: projectRoot,
216216
messagesToSourceKitLSPHandler: messagesToSourceKitLSPHandler,
217-
buildSystemTestHooks: testHooks
217+
buildSystemHooks: buildSystemHooks
218218
) { connectionToSourceKitLSP in
219219
try await SwiftPMBuildSystem(
220220
projectRoot: projectRoot,
221221
toolchainRegistry: toolchainRegistry,
222222
options: options,
223223
connectionToSourceKitLSP: connectionToSourceKitLSP,
224-
testHooks: testHooks.swiftPMTestHooks
224+
testHooks: buildSystemHooks.swiftPMTestHooks
225225
)
226226
}
227227
#else
228228
return nil
229229
#endif
230-
case .testBuildSystem:
230+
case .injected(let injector):
231231
return await Self.createBuiltInBuildSystemAdapter(
232232
projectRoot: projectRoot,
233233
messagesToSourceKitLSPHandler: messagesToSourceKitLSPHandler,
234-
buildSystemTestHooks: testHooks
234+
buildSystemHooks: buildSystemHooks
235235
) { connectionToSourceKitLSP in
236-
TestBuildSystem(projectRoot: projectRoot, connectionToSourceKitLSP: connectionToSourceKitLSP)
236+
await injector.createBuildSystem(projectRoot: projectRoot, connectionToSourceKitLSP: connectionToSourceKitLSP)
237237
}
238238
}
239239
}
@@ -275,19 +275,6 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
275275
}
276276
}
277277

278-
/// If the underlying build system is a `TestBuildSystem`, return it. Otherwise, `nil`
279-
///
280-
/// - Important: For testing purposes only.
281-
package var testBuildSystem: TestBuildSystem? {
282-
get async {
283-
switch buildSystemAdapter {
284-
case .builtIn(let builtInBuildSystemAdapter, _): return await builtInBuildSystemAdapter.testBuildSystem
285-
case .external: return nil
286-
case nil: return nil
287-
}
288-
}
289-
}
290-
291278
/// Provider of file to main file mappings.
292279
private var mainFilesProvider: MainFilesProvider?
293280

@@ -367,7 +354,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
367354
toolchainRegistry: ToolchainRegistry,
368355
options: SourceKitLSPOptions,
369356
connectionToClient: BuildSystemManagerConnectionToClient,
370-
buildSystemTestHooks: BuildSystemTestHooks
357+
buildSystemHooks: BuildSystemHooks
371358
) async {
372359
self.toolchainRegistry = toolchainRegistry
373360
self.options = options
@@ -376,7 +363,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
376363
self.buildSystemAdapter = await buildSystemSpec?.createBuildSystemAdapter(
377364
toolchainRegistry: toolchainRegistry,
378365
options: options,
379-
buildSystemTestHooks: buildSystemTestHooks,
366+
buildSystemHooks: buildSystemHooks,
380367
messagesToSourceKitLSPHandler: WeakMessageHandler(self)
381368
)
382369

@@ -432,7 +419,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
432419
let adapter = BuiltInBuildSystemAdapter(
433420
underlyingBuildSystem: legacyBuildServer,
434421
connectionToSourceKitLSP: legacyBuildServer.connectionToSourceKitLSP,
435-
buildSystemTestHooks: buildSystemTestHooks
422+
buildSystemHooks: buildSystemHooks
436423
)
437424
let connectionToBuildSystem = LocalConnection(receiverName: "Legacy BSP server")
438425
connectionToBuildSystem.start(handler: adapter)

Sources/BuildSystemIntegration/BuildSystemTestHooks.swift

+16-4
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212

1313
#if compiler(>=6)
1414
package import LanguageServerProtocol
15+
package import Foundation
1516
#else
1617
import LanguageServerProtocol
18+
import Foundation
1719
#endif
1820

1921
package struct SwiftPMTestHooks: Sendable {
@@ -29,19 +31,29 @@ package struct SwiftPMTestHooks: Sendable {
2931
}
3032
}
3133

32-
package struct BuildSystemTestHooks: Sendable {
34+
/// When running SourceKit-LSP in-process, allows the creator of `SourceKitLSPServer` to create the build system instead
35+
/// of SourceKit-LSP creating build systems as needed.
36+
package protocol BuildSystemInjector: Sendable {
37+
func createBuildSystem(projectRoot: URL, connectionToSourceKitLSP: any Connection) async -> BuiltInBuildSystem
38+
}
39+
40+
package struct BuildSystemHooks: Sendable {
3341
package var swiftPMTestHooks: SwiftPMTestHooks
3442

3543
/// A hook that will be executed before a request is handled by a `BuiltInBuildSystem`.
3644
///
3745
/// This allows requests to be artificially delayed.
38-
package var handleRequest: (@Sendable (any RequestType) async -> Void)?
46+
package var preHandleRequest: (@Sendable (any RequestType) async -> Void)?
47+
48+
package var buildSystemInjector: BuildSystemInjector?
3949

4050
package init(
4151
swiftPMTestHooks: SwiftPMTestHooks = SwiftPMTestHooks(),
42-
handleRequest: (@Sendable (any RequestType) async -> Void)? = nil
52+
preHandleRequest: (@Sendable (any RequestType) async -> Void)? = nil,
53+
buildSystemInjector: BuildSystemInjector? = nil
4354
) {
4455
self.swiftPMTestHooks = swiftPMTestHooks
45-
self.handleRequest = handleRequest
56+
self.preHandleRequest = preHandleRequest
57+
self.buildSystemInjector = buildSystemInjector
4658
}
4759
}

Sources/BuildSystemIntegration/BuiltInBuildSystemAdapter.swift

+5-12
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ package struct BuildSystemSpec {
3030
case buildServer
3131
case compilationDatabase
3232
case swiftPM
33-
case testBuildSystem
33+
case injected(BuildSystemInjector)
3434
}
3535

3636
package var kind: Kind
@@ -59,25 +59,18 @@ actor BuiltInBuildSystemAdapter: QueueBasedMessageHandler {
5959
/// The connection with which messages are sent to `BuildSystemManager`.
6060
private let connectionToSourceKitLSP: LocalConnection
6161

62-
private let buildSystemTestHooks: BuildSystemTestHooks
63-
64-
/// If the underlying build system is a `TestBuildSystem`, return it. Otherwise, `nil`
65-
///
66-
/// - Important: For testing purposes only.
67-
var testBuildSystem: TestBuildSystem? {
68-
return underlyingBuildSystem as? TestBuildSystem
69-
}
62+
private let buildSystemHooks: BuildSystemHooks
7063

7164
/// Create a `BuiltInBuildSystemAdapter` form an existing `BuiltInBuildSystem` and connection to communicate messages
7265
/// from the build system to SourceKit-LSP.
7366
init(
7467
underlyingBuildSystem: BuiltInBuildSystem,
7568
connectionToSourceKitLSP: LocalConnection,
76-
buildSystemTestHooks: BuildSystemTestHooks
69+
buildSystemHooks: BuildSystemHooks
7770
) {
7871
self.underlyingBuildSystem = underlyingBuildSystem
7972
self.connectionToSourceKitLSP = connectionToSourceKitLSP
80-
self.buildSystemTestHooks = buildSystemTestHooks
73+
self.buildSystemHooks = buildSystemHooks
8174
}
8275

8376
deinit {
@@ -124,7 +117,7 @@ actor BuiltInBuildSystemAdapter: QueueBasedMessageHandler {
124117
reply: @Sendable @escaping (LSPResult<Request.Response>) -> Void
125118
) async {
126119
let request = RequestAndReply(request, reply: reply)
127-
await buildSystemTestHooks.handleRequest?(request.params)
120+
await buildSystemHooks.preHandleRequest?(request.params)
128121
switch request {
129122
case let request as RequestAndReply<BuildShutdownRequest>:
130123
await request.reply { VoidResponse() }

Sources/BuildSystemIntegration/DetermineBuildSystem.swift

+6-1
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,13 @@ import struct TSCBasic.AbsolutePath
3636
/// Returns `nil` if no build system can handle this workspace folder.
3737
package func determineBuildSystem(
3838
forWorkspaceFolder workspaceFolder: DocumentURI,
39-
options: SourceKitLSPOptions
39+
options: SourceKitLSPOptions,
40+
hooks: BuildSystemHooks
4041
) -> BuildSystemSpec? {
42+
if let workspaceURL = workspaceFolder.fileURL, let buildSystemInjector = hooks.buildSystemInjector {
43+
return BuildSystemSpec(kind: .injected(buildSystemInjector), projectRoot: workspaceURL)
44+
}
45+
4146
var buildSystemPreference: [WorkspaceType] = [
4247
.buildServer, .swiftPM, .compilationDatabase,
4348
]

Sources/InProcessClient/InProcessSourceKitLSPClient.swift

+7-14
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,22 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#if compiler(>=6)
1413
import BuildSystemIntegration
1514
public import Foundation
1615
public import LanguageServerProtocol
1716
import LanguageServerProtocolExtensions
18-
package import SKOptions
19-
import SourceKitLSP
2017
import SwiftExtensions
21-
import ToolchainRegistry
2218
import TSCExtensions
19+
import ToolchainRegistry
2320

2421
import struct TSCBasic.AbsolutePath
22+
23+
#if compiler(>=6)
24+
package import SKOptions
25+
package import SourceKitLSP
2526
#else
26-
import BuildSystemIntegration
27-
import Foundation
28-
import LanguageServerProtocol
29-
import LanguageServerProtocolExtensions
3027
import SKOptions
3128
import SourceKitLSP
32-
import SwiftExtensions
33-
import ToolchainRegistry
34-
import TSCExtensions
35-
36-
import struct TSCBasic.AbsolutePath
3729
#endif
3830

3931
/// Launches a `SourceKitLSPServer` in-process and allows sending messages to it.
@@ -63,6 +55,7 @@ public final class InProcessSourceKitLSPClient: Sendable {
6355
package init(
6456
toolchainPath: URL?,
6557
options: SourceKitLSPOptions = SourceKitLSPOptions(),
58+
hooks: Hooks = Hooks(),
6659
capabilities: ClientCapabilities = ClientCapabilities(),
6760
workspaceFolders: [WorkspaceFolder],
6861
messageHandler: any MessageHandler
@@ -72,7 +65,7 @@ public final class InProcessSourceKitLSPClient: Sendable {
7265
client: serverToClientConnection,
7366
toolchainRegistry: ToolchainRegistry(installPath: toolchainPath),
7467
options: options,
75-
testHooks: TestHooks(),
68+
hooks: hooks,
7669
onExit: {
7770
serverToClientConnection.close()
7871
}

Sources/SKTestSupport/MultiFileTestProject.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ package class MultiFileTestProject {
133133
initializationOptions: LSPAny? = nil,
134134
capabilities: ClientCapabilities = ClientCapabilities(),
135135
options: SourceKitLSPOptions = .testDefault(),
136-
testHooks: TestHooks = TestHooks(),
136+
hooks: Hooks = Hooks(),
137137
enableBackgroundIndexing: Bool = false,
138138
usePullDiagnostics: Bool = true,
139139
preInitialization: ((TestSourceKitLSPClient) -> Void)? = nil,
@@ -145,7 +145,7 @@ package class MultiFileTestProject {
145145

146146
self.testClient = try await TestSourceKitLSPClient(
147147
options: options,
148-
testHooks: testHooks,
148+
hooks: hooks,
149149
initializationOptions: initializationOptions,
150150
capabilities: capabilities,
151151
usePullDiagnostics: usePullDiagnostics,

Sources/SKTestSupport/SwiftPMTestProject.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ package class SwiftPMTestProject: MultiFileTestProject {
197197
initializationOptions: LSPAny? = nil,
198198
capabilities: ClientCapabilities = ClientCapabilities(),
199199
options: SourceKitLSPOptions = .testDefault(),
200-
testHooks: TestHooks = TestHooks(),
200+
hooks: Hooks = Hooks(),
201201
enableBackgroundIndexing: Bool = false,
202202
usePullDiagnostics: Bool = true,
203203
pollIndex: Bool = true,
@@ -238,7 +238,7 @@ package class SwiftPMTestProject: MultiFileTestProject {
238238
initializationOptions: initializationOptions,
239239
capabilities: capabilities,
240240
options: options,
241-
testHooks: testHooks,
241+
hooks: hooks,
242242
enableBackgroundIndexing: enableBackgroundIndexing,
243243
usePullDiagnostics: usePullDiagnostics,
244244
preInitialization: preInitialization,

Sources/SKTestSupport/TestSourceKitLSPClient.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ package final class TestSourceKitLSPClient: MessageHandler, Sendable {
146146
/// needed.
147147
package init(
148148
options: SourceKitLSPOptions = .testDefault(),
149-
testHooks: TestHooks = TestHooks(),
149+
hooks: Hooks = Hooks(),
150150
initialize: Bool = true,
151151
initializationOptions: LSPAny? = nil,
152152
capabilities: ClientCapabilities = ClientCapabilities(),
@@ -177,7 +177,7 @@ package final class TestSourceKitLSPClient: MessageHandler, Sendable {
177177
client: serverToClientConnection,
178178
toolchainRegistry: ToolchainRegistry.forTesting,
179179
options: options,
180-
testHooks: testHooks,
180+
hooks: hooks,
181181
onExit: {
182182
serverToClientConnection.close()
183183
}

Sources/SourceKitLSP/Clang/ClangLanguageService.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ actor ClangLanguageService: LanguageService, MessageHandler {
113113
sourceKitLSPServer: SourceKitLSPServer,
114114
toolchain: Toolchain,
115115
options: SourceKitLSPOptions,
116-
testHooks: TestHooks,
116+
hooks: Hooks,
117117
workspace: Workspace
118118
) async throws {
119119
guard let clangdPath = toolchain.clangd else {

Sources/SourceKitLSP/Documentation/DocumentationLanguageService.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ package actor DocumentationLanguageService: LanguageService, Sendable {
2929
sourceKitLSPServer: SourceKitLSPServer,
3030
toolchain: Toolchain,
3131
options: SourceKitLSPOptions,
32-
testHooks: TestHooks,
32+
hooks: Hooks,
3333
workspace: Workspace
3434
) async throws {}
3535

Sources/SourceKitLSP/LanguageService.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ package protocol LanguageService: AnyObject, Sendable {
109109
sourceKitLSPServer: SourceKitLSPServer,
110110
toolchain: Toolchain,
111111
options: SourceKitLSPOptions,
112-
testHooks: TestHooks,
112+
hooks: Hooks,
113113
workspace: Workspace
114114
) async throws
115115

0 commit comments

Comments
 (0)