@@ -116,7 +116,20 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
116
116
private var buildSystem : BuiltInBuildSystemAdapter ?
117
117
118
118
/// The connection through which the `BuildSystemManager` can send requests to the build system.
119
- private var connectionToBuildSystem : Connection ?
119
+ ///
120
+ /// Access to this property should generally go through the non-underscored version, which waits until the build
121
+ /// server is initialized so that no messages can be sent to the BSP server before initialization finishes.
122
+ private var _connectionToBuildSystem : Connection ?
123
+
124
+ /// The connection to the build system. Will not yield the connection until the build server is initialized,
125
+ /// preventing accidental sending of messages to the build server before it is initialized.
126
+ private var connectionToBuildSystem : Connection ? {
127
+ get async {
128
+ // Wait until initialization finishes.
129
+ _ = await initializeResult. value
130
+ return _connectionToBuildSystem
131
+ }
132
+ }
120
133
121
134
/// If the underlying build system is a `TestBuildSystem`, return it. Otherwise, `nil`
122
135
///
@@ -224,9 +237,9 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
224
237
if let buildSystem {
225
238
let connectionToBuildSystem = LocalConnection ( receiverName: " Build system " )
226
239
connectionToBuildSystem. start ( handler: buildSystem)
227
- self . connectionToBuildSystem = connectionToBuildSystem
240
+ self . _connectionToBuildSystem = connectionToBuildSystem
228
241
} else {
229
- self . connectionToBuildSystem = nil
242
+ self . _connectionToBuildSystem = nil
230
243
}
231
244
// The debounce duration of 500ms was chosen arbitrarily without any measurements.
232
245
self . filesDependenciesUpdatedDebouncer = Debouncer (
@@ -247,15 +260,15 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
247
260
// TODO: Forward file watch patterns from this initialize request to the client
248
261
// (https://github.com/swiftlang/sourcekit-lsp/issues/1671)
249
262
initializeResult = Task { ( ) -> InitializeBuildResponse ? in
250
- guard let connectionToBuildSystem else {
263
+ guard let _connectionToBuildSystem else {
251
264
return nil
252
265
}
253
266
guard let buildSystemKind else {
254
267
logger. fault ( " If we have a connectionToBuildSystem, we must have had a buildSystemKind " )
255
268
return nil
256
269
}
257
270
let initializeResponse = await orLog ( " Initializing build system " ) {
258
- try await connectionToBuildSystem . send (
271
+ try await _connectionToBuildSystem . send (
259
272
InitializeBuildRequest (
260
273
displayName: " SourceKit-LSP " ,
261
274
version: " " ,
@@ -265,17 +278,19 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
265
278
)
266
279
)
267
280
}
268
- connectionToBuildSystem . send ( OnBuildInitializedNotification ( ) )
281
+ _connectionToBuildSystem . send ( OnBuildInitializedNotification ( ) )
269
282
return initializeResponse
270
283
}
271
284
}
272
285
273
286
deinit {
274
287
// Shut down the build server before closing the connection to it
275
- Task { [ connectionToBuildSystem] in
288
+ Task { [ connectionToBuildSystem = _connectionToBuildSystem , initializeResult ] in
276
289
guard let connectionToBuildSystem else {
277
290
return
278
291
}
292
+ // We are accessing the raw connection to the build server, so we need to ensure that it has been initialized here
293
+ _ = await initializeResult? . value
279
294
await orLog ( " Sending shutdown request to build server " ) {
280
295
_ = try await connectionToBuildSystem. send ( BuildShutdownRequest ( ) )
281
296
connectionToBuildSystem. send ( OnBuildExitNotification ( ) )
@@ -524,7 +539,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
524
539
in target: BuildTargetIdentifier ,
525
540
language: Language
526
541
) async throws -> FileBuildSettings ? {
527
- guard let connectionToBuildSystem else {
542
+ guard let connectionToBuildSystem = await connectionToBuildSystem else {
528
543
return nil
529
544
}
530
545
let request = TextDocumentSourceKitOptionsRequest (
@@ -582,7 +597,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
582
597
else {
583
598
return nil
584
599
}
585
- if connectionToBuildSystem == nil {
600
+ if await connectionToBuildSystem == nil {
586
601
// If there is no build system and we only have the fallback build system, we will never get real build settings.
587
602
// Consider the build settings non-fallback.
588
603
settings. isFallback = false
@@ -724,7 +739,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
724
739
}
725
740
726
741
private func buildTargets( ) async throws -> [ BuildTargetIdentifier : BuildTargetInfo ] {
727
- guard let connectionToBuildSystem else {
742
+ guard let connectionToBuildSystem = await connectionToBuildSystem else {
728
743
return [ : ]
729
744
}
730
745
@@ -761,7 +776,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
761
776
}
762
777
763
778
package func sourceFiles( in targets: Set < BuildTargetIdentifier > ) async throws -> [ SourcesItem ] {
764
- guard let connectionToBuildSystem else {
779
+ guard let connectionToBuildSystem = await connectionToBuildSystem else {
765
780
return [ ]
766
781
}
767
782
@@ -904,7 +919,9 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
904
919
// MARK: Informing BuildSystemManager about changes
905
920
906
921
package func filesDidChange( _ events: [ FileEvent ] ) async {
907
- connectionToBuildSystem? . send ( OnWatchedFilesDidChangeNotification ( changes: events) )
922
+ if let connectionToBuildSystem = await connectionToBuildSystem {
923
+ connectionToBuildSystem. send ( OnWatchedFilesDidChangeNotification ( changes: events) )
924
+ }
908
925
909
926
var targetsWithUpdatedDependencies: Set< BuildTargetIdentifier> = [ ]
910
927
// If a Swift file within a target is updated, reload all the other files within the target since they might be
0 commit comments