Skip to content

Commit 0028cf9

Browse files
authored
Merge pull request #1684 from ahoppen/no-bsp-messages-before-initialize
Don’t send messages to the BSP server before the `build/initialize` request returns
2 parents 5df19cc + 82e0036 commit 0028cf9

File tree

1 file changed

+29
-12
lines changed

1 file changed

+29
-12
lines changed

Sources/BuildSystemIntegration/BuildSystemManager.swift

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,20 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
116116
private var buildSystem: BuiltInBuildSystemAdapter?
117117

118118
/// 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+
}
120133

121134
/// If the underlying build system is a `TestBuildSystem`, return it. Otherwise, `nil`
122135
///
@@ -224,9 +237,9 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
224237
if let buildSystem {
225238
let connectionToBuildSystem = LocalConnection(receiverName: "Build system")
226239
connectionToBuildSystem.start(handler: buildSystem)
227-
self.connectionToBuildSystem = connectionToBuildSystem
240+
self._connectionToBuildSystem = connectionToBuildSystem
228241
} else {
229-
self.connectionToBuildSystem = nil
242+
self._connectionToBuildSystem = nil
230243
}
231244
// The debounce duration of 500ms was chosen arbitrarily without any measurements.
232245
self.filesDependenciesUpdatedDebouncer = Debouncer(
@@ -247,15 +260,15 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
247260
// TODO: Forward file watch patterns from this initialize request to the client
248261
// (https://github.com/swiftlang/sourcekit-lsp/issues/1671)
249262
initializeResult = Task { () -> InitializeBuildResponse? in
250-
guard let connectionToBuildSystem else {
263+
guard let _connectionToBuildSystem else {
251264
return nil
252265
}
253266
guard let buildSystemKind else {
254267
logger.fault("If we have a connectionToBuildSystem, we must have had a buildSystemKind")
255268
return nil
256269
}
257270
let initializeResponse = await orLog("Initializing build system") {
258-
try await connectionToBuildSystem.send(
271+
try await _connectionToBuildSystem.send(
259272
InitializeBuildRequest(
260273
displayName: "SourceKit-LSP",
261274
version: "",
@@ -265,17 +278,19 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
265278
)
266279
)
267280
}
268-
connectionToBuildSystem.send(OnBuildInitializedNotification())
281+
_connectionToBuildSystem.send(OnBuildInitializedNotification())
269282
return initializeResponse
270283
}
271284
}
272285

273286
deinit {
274287
// Shut down the build server before closing the connection to it
275-
Task { [connectionToBuildSystem] in
288+
Task { [connectionToBuildSystem = _connectionToBuildSystem, initializeResult] in
276289
guard let connectionToBuildSystem else {
277290
return
278291
}
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
279294
await orLog("Sending shutdown request to build server") {
280295
_ = try await connectionToBuildSystem.send(BuildShutdownRequest())
281296
connectionToBuildSystem.send(OnBuildExitNotification())
@@ -524,7 +539,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
524539
in target: BuildTargetIdentifier,
525540
language: Language
526541
) async throws -> FileBuildSettings? {
527-
guard let connectionToBuildSystem else {
542+
guard let connectionToBuildSystem = await connectionToBuildSystem else {
528543
return nil
529544
}
530545
let request = TextDocumentSourceKitOptionsRequest(
@@ -582,7 +597,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
582597
else {
583598
return nil
584599
}
585-
if connectionToBuildSystem == nil {
600+
if await connectionToBuildSystem == nil {
586601
// If there is no build system and we only have the fallback build system, we will never get real build settings.
587602
// Consider the build settings non-fallback.
588603
settings.isFallback = false
@@ -724,7 +739,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
724739
}
725740

726741
private func buildTargets() async throws -> [BuildTargetIdentifier: BuildTargetInfo] {
727-
guard let connectionToBuildSystem else {
742+
guard let connectionToBuildSystem = await connectionToBuildSystem else {
728743
return [:]
729744
}
730745

@@ -761,7 +776,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
761776
}
762777

763778
package func sourceFiles(in targets: Set<BuildTargetIdentifier>) async throws -> [SourcesItem] {
764-
guard let connectionToBuildSystem else {
779+
guard let connectionToBuildSystem = await connectionToBuildSystem else {
765780
return []
766781
}
767782

@@ -904,7 +919,9 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
904919
// MARK: Informing BuildSystemManager about changes
905920

906921
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+
}
908925

909926
var targetsWithUpdatedDependencies: Set<BuildTargetIdentifier> = []
910927
// If a Swift file within a target is updated, reload all the other files within the target since they might be

0 commit comments

Comments
 (0)