@@ -109,16 +109,36 @@ fileprivate extension InitializeBuildResponse {
109
109
/// the `BuiltInBuildSystem` protocol. For external (aka. out-of-process, aka. BSP servers) build systems, this means
110
110
/// that we need to manage the external build system's lifetime.
111
111
private enum BuildSystemAdapter {
112
- case builtIn( BuiltInBuildSystemAdapter )
112
+ case builtIn( BuiltInBuildSystemAdapter , connectionToBuildSystem : any Connection )
113
113
case external( ExternalBuildSystemAdapter )
114
+
115
+ /// Send a notification to the build server.
116
+ func send( _ notification: some NotificationType ) async {
117
+ switch self {
118
+ case . builtIn( _, let connectionToBuildSystem) :
119
+ connectionToBuildSystem. send ( notification)
120
+ case . external( let external) :
121
+ await external. send ( notification)
122
+ }
123
+ }
124
+
125
+ /// Send a request to the build server.
126
+ func send< Request: RequestType > ( _ request: Request ) async throws -> Request . Response {
127
+ switch self {
128
+ case . builtIn( _, let connectionToBuildSystem) :
129
+ return try await connectionToBuildSystem. send ( request)
130
+ case . external( let external) :
131
+ return try await external. send ( request)
132
+ }
133
+ }
114
134
}
115
135
116
136
private extension BuildSystemKind {
117
137
private static func createBuiltInBuildSystemAdapter(
118
138
projectRoot: AbsolutePath ,
119
139
messagesToSourceKitLSPHandler: any MessageHandler ,
120
140
_ createBuildSystem: @Sendable ( _ connectionToSourceKitLSP: any Connection ) async throws -> BuiltInBuildSystem ?
121
- ) async -> ( buildSystemAdapter : BuildSystemAdapter , connectionToBuildSystem : any Connection ) ? {
141
+ ) async -> BuildSystemAdapter ? {
122
142
let connectionToSourceKitLSP = LocalConnection ( receiverName: " BuildSystemManager " )
123
143
connectionToSourceKitLSP. start ( handler: messagesToSourceKitLSPHandler)
124
144
@@ -136,7 +156,7 @@ private extension BuildSystemKind {
136
156
)
137
157
let connectionToBuildSystem = LocalConnection ( receiverName: " Build system " )
138
158
connectionToBuildSystem. start ( handler: buildSystemAdapter)
139
- return ( . builtIn( buildSystemAdapter) , connectionToBuildSystem)
159
+ return . builtIn( buildSystemAdapter, connectionToBuildSystem : connectionToBuildSystem)
140
160
}
141
161
142
162
/// Create a `BuildSystemAdapter` that manages a build system of this kind and return a connection that can be used
@@ -146,7 +166,7 @@ private extension BuildSystemKind {
146
166
options: SourceKitLSPOptions ,
147
167
buildSystemTestHooks testHooks: BuildSystemTestHooks ,
148
168
messagesToSourceKitLSPHandler: any MessageHandler
149
- ) async -> ( buildSystemAdapter : BuildSystemAdapter , connectionToBuildSystem : any Connection ) ? {
169
+ ) async -> BuildSystemAdapter ? {
150
170
switch self {
151
171
case . buildServer( projectRoot: let projectRoot) :
152
172
let buildSystem = await orLog ( " Creating external build system " ) {
@@ -160,7 +180,7 @@ private extension BuildSystemKind {
160
180
return nil
161
181
}
162
182
logger. log ( " Created external build server at \( projectRoot. pathString) " )
163
- return ( . external( buildSystem) , buildSystem . connectionToBuildServer )
183
+ return . external( buildSystem)
164
184
case . compilationDatabase( projectRoot: let projectRoot) :
165
185
return await Self . createBuiltInBuildSystemAdapter (
166
186
projectRoot: projectRoot,
@@ -217,32 +237,26 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
217
237
/// get `fileBuildSettingsChanged` and `filesDependenciesUpdated` callbacks.
218
238
private var watchedFiles : [ DocumentURI : ( mainFile: DocumentURI , language: Language ) ] = [ : ]
219
239
220
- /// The connection through which the `BuildSystemManager` can send requests to the build system.
221
- ///
222
- /// Access to this property should generally go through the non-underscored version, which waits until the build
223
- /// server is initialized so that no messages can be sent to the BSP server before initialization finishes.
224
- private var _connectionToBuildSystem : Connection ?
240
+ /// The build system adapter that is used to answer build system queries.
241
+ private var buildSystemAdapter : BuildSystemAdapter ?
225
242
226
- /// The connection to the build system. Will not yield the connection until the build server is initialized,
227
- /// preventing accidental sending of messages to the build server before it is initialized.
228
- private var connectionToBuildSystem : Connection ? {
243
+ /// The build system adapter after initialization finishes. When sending messages to the BSP server, this should be
244
+ /// preferred over `buildSystemAdapter` because no messages must be sent to the build server before initialization
245
+ /// finishes.
246
+ private var buildSystemAdapterAfterInitialized : BuildSystemAdapter ? {
229
247
get async {
230
- // Wait until initialization finishes.
231
248
_ = await initializeResult. value
232
- return _connectionToBuildSystem
249
+ return buildSystemAdapter
233
250
}
234
251
}
235
252
236
- /// The build system adapter that is used to answer build system queries.
237
- private var buildSystemAdapter : BuildSystemAdapter ?
238
-
239
253
/// If the underlying build system is a `TestBuildSystem`, return it. Otherwise, `nil`
240
254
///
241
255
/// - Important: For testing purposes only.
242
256
package var testBuildSystem : TestBuildSystem ? {
243
257
get async {
244
258
switch buildSystemAdapter {
245
- case . builtIn( let builtInBuildSystemAdapter) : return await builtInBuildSystemAdapter. testBuildSystem
259
+ case . builtIn( let builtInBuildSystemAdapter, _ ) : return await builtInBuildSystemAdapter. testBuildSystem
246
260
case . external: return nil
247
261
case nil : return nil
248
262
}
@@ -327,14 +341,12 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
327
341
self . toolchainRegistry = toolchainRegistry
328
342
self . options = options
329
343
self . projectRoot = buildSystemKind? . projectRoot
330
- let buildSystemAdapterAndConnection = await buildSystemKind? . createBuildSystemAdapter (
344
+ self . buildSystemAdapter = await buildSystemKind? . createBuildSystemAdapter (
331
345
toolchainRegistry: toolchainRegistry,
332
346
options: options,
333
347
buildSystemTestHooks: buildSystemTestHooks,
334
348
messagesToSourceKitLSPHandler: WeakMessageHandler ( self )
335
349
)
336
- self . buildSystemAdapter = buildSystemAdapterAndConnection? . buildSystemAdapter
337
- self . _connectionToBuildSystem = buildSystemAdapterAndConnection? . connectionToBuildSystem
338
350
339
351
// The debounce duration of 500ms was chosen arbitrarily without any measurements.
340
352
self . filesDependenciesUpdatedDebouncer = Debouncer (
@@ -355,15 +367,15 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
355
367
// TODO: Forward file watch patterns from this initialize request to the client
356
368
// (https://github.com/swiftlang/sourcekit-lsp/issues/1671)
357
369
initializeResult = Task { ( ) -> InitializeBuildResponse ? in
358
- guard let _connectionToBuildSystem else {
370
+ guard let buildSystemAdapter else {
359
371
return nil
360
372
}
361
373
guard let buildSystemKind else {
362
374
logger. fault ( " If we have a connectionToBuildSystem, we must have had a buildSystemKind " )
363
375
return nil
364
376
}
365
377
let initializeResponse = await orLog ( " Initializing build system " ) {
366
- try await _connectionToBuildSystem . send (
378
+ try await buildSystemAdapter . send (
367
379
InitializeBuildRequest (
368
380
displayName: " SourceKit-LSP " ,
369
381
version: " " ,
@@ -389,27 +401,26 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
389
401
underlyingBuildSystem: legacyBuildServer,
390
402
connectionToSourceKitLSP: legacyBuildServer. connectionToSourceKitLSP
391
403
)
392
- self . buildSystemAdapter = . builtIn( adapter)
393
404
let connectionToBuildSystem = LocalConnection ( receiverName: " Legacy BSP server " )
394
405
connectionToBuildSystem. start ( handler: adapter)
395
- self . _connectionToBuildSystem = connectionToBuildSystem
406
+ self . buildSystemAdapter = . builtIn ( adapter , connectionToBuildSystem: connectionToBuildSystem )
396
407
}
397
- _connectionToBuildSystem . send ( OnBuildInitializedNotification ( ) )
408
+ await buildSystemAdapter . send ( OnBuildInitializedNotification ( ) )
398
409
return initializeResponse
399
410
}
400
411
}
401
412
402
413
deinit {
403
414
// Shut down the build server before closing the connection to it
404
- Task { [ connectionToBuildSystem = _connectionToBuildSystem , initializeResult] in
405
- guard let connectionToBuildSystem else {
415
+ Task { [ buildSystemAdapter , initializeResult] in
416
+ guard let buildSystemAdapter else {
406
417
return
407
418
}
408
419
// We are accessing the raw connection to the build server, so we need to ensure that it has been initialized here
409
420
_ = await initializeResult? . value
410
421
await orLog ( " Sending shutdown request to build server " ) {
411
- _ = try await connectionToBuildSystem . send ( BuildShutdownRequest ( ) )
412
- connectionToBuildSystem . send ( OnBuildExitNotification ( ) )
422
+ _ = try await buildSystemAdapter . send ( BuildShutdownRequest ( ) )
423
+ await buildSystemAdapter . send ( OnBuildExitNotification ( ) )
413
424
}
414
425
}
415
426
}
@@ -655,7 +666,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
655
666
in target: BuildTargetIdentifier ,
656
667
language: Language
657
668
) async throws -> FileBuildSettings ? {
658
- guard let connectionToBuildSystem = await connectionToBuildSystem else {
669
+ guard let buildSystemAdapter = await buildSystemAdapterAfterInitialized else {
659
670
return nil
660
671
}
661
672
let request = TextDocumentSourceKitOptionsRequest (
@@ -670,7 +681,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
670
681
// very quickly from `settings(for:language:)`.
671
682
// https://github.com/apple/sourcekit-lsp/issues/1181
672
683
let response = try await cachedSourceKitOptions. get ( request) { request in
673
- try await connectionToBuildSystem . send ( request)
684
+ try await buildSystemAdapter . send ( request)
674
685
}
675
686
guard let response else {
676
687
return nil
@@ -713,7 +724,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
713
724
else {
714
725
return nil
715
726
}
716
- if await connectionToBuildSystem == nil {
727
+ if buildSystemAdapter == nil {
717
728
// If there is no build system and we only have the fallback build system, we will never get real build settings.
718
729
// Consider the build settings non-fallback.
719
730
settings. isFallback = false
@@ -768,7 +779,9 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
768
779
769
780
package func waitForUpToDateBuildGraph( ) async {
770
781
await orLog ( " Waiting for build system updates " ) {
771
- let _: VoidResponse ? = try await connectionToBuildSystem? . send ( WorkspaceWaitForBuildSystemUpdatesRequest ( ) )
782
+ let _: VoidResponse ? = try await buildSystemAdapterAfterInitialized? . send (
783
+ WorkspaceWaitForBuildSystemUpdatesRequest ( )
784
+ )
772
785
}
773
786
// Handle any messages the build system might have sent us while updating.
774
787
await self . messageHandlingQueue. async ( metadata: . stateChange) { } . valuePropagatingCancellation
@@ -836,7 +849,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
836
849
}
837
850
838
851
package func prepare( targets: Set < BuildTargetIdentifier > ) async throws {
839
- let _: VoidResponse ? = try await connectionToBuildSystem ? . send (
852
+ let _: VoidResponse ? = try await buildSystemAdapterAfterInitialized ? . send (
840
853
BuildTargetPrepareRequest ( targets: targets. sorted { $0. uri. stringValue < $1. uri. stringValue } )
841
854
)
842
855
await orLog ( " Calling fileDependenciesUpdated " ) {
@@ -855,13 +868,13 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
855
868
}
856
869
857
870
private func buildTargets( ) async throws -> [ BuildTargetIdentifier : BuildTargetInfo ] {
858
- guard let connectionToBuildSystem = await connectionToBuildSystem else {
871
+ guard let buildSystemAdapter = await buildSystemAdapterAfterInitialized else {
859
872
return [ : ]
860
873
}
861
874
862
875
let request = WorkspaceBuildTargetsRequest ( )
863
876
let result = try await cachedBuildTargets. get ( request) { request in
864
- let buildTargets = try await connectionToBuildSystem . send ( request) . targets
877
+ let buildTargets = try await buildSystemAdapter . send ( request) . targets
865
878
let ( depths, dependents) = await self . targetDepthsAndDependents ( for: buildTargets)
866
879
var result : [ BuildTargetIdentifier : BuildTargetInfo ] = [ : ]
867
880
result. reserveCapacity ( buildTargets. count)
@@ -898,7 +911,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
898
911
}
899
912
900
913
package func sourceFiles( in targets: Set < BuildTargetIdentifier > ) async throws -> [ SourcesItem ] {
901
- guard let connectionToBuildSystem = await connectionToBuildSystem , !targets. isEmpty else {
914
+ guard let buildSystemAdapter = await buildSystemAdapterAfterInitialized , !targets. isEmpty else {
902
915
return [ ]
903
916
}
904
917
@@ -916,7 +929,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
916
929
917
930
let request = BuildTargetSourcesRequest ( targets: targets. sorted { $0. uri. stringValue < $1. uri. stringValue } )
918
931
let response = try await cachedTargetSources. get ( request) { request in
919
- try await connectionToBuildSystem . send ( request)
932
+ try await buildSystemAdapter . send ( request)
920
933
}
921
934
return response. items
922
935
}
@@ -1041,8 +1054,8 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
1041
1054
// MARK: Informing BuildSystemManager about changes
1042
1055
1043
1056
package func filesDidChange( _ events: [ FileEvent ] ) async {
1044
- if let connectionToBuildSystem = await connectionToBuildSystem {
1045
- connectionToBuildSystem . send ( OnWatchedFilesDidChangeNotification ( changes: events) )
1057
+ if let buildSystemAdapter = await buildSystemAdapterAfterInitialized {
1058
+ await buildSystemAdapter . send ( OnWatchedFilesDidChangeNotification ( changes: events) )
1046
1059
}
1047
1060
1048
1061
var targetsWithUpdatedDependencies: Set< BuildTargetIdentifier> = [ ]
0 commit comments