Skip to content

Commit 3f9dedd

Browse files
committed
If a BSP server fails to initialize, show the error message to the user
When the BSP server fails to initialize, it can’t give us any compiler arguments and we won’t be able to provide semantic functionality. Show the message to the user so they can do something about fixing it instead having to dig into SourceKit-LSP logs.
1 parent 47ca76b commit 3f9dedd

File tree

2 files changed

+57
-9
lines changed

2 files changed

+57
-9
lines changed

Sources/BuildServerIntegration/BuildServerManager.swift

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,10 @@ package actor BuildServerManager: QueueBasedMessageHandler {
329329
/// preferred over `buildServerAdapter` because no messages must be sent to the build server before initialization
330330
/// finishes.
331331
private var buildServerAdapterAfterInitialized: BuildServerAdapter? {
332-
get async {
333-
_ = await initializeResult.value
332+
get async throws {
333+
guard await initializeResult.value != nil else {
334+
throw ResponseError.unknown("Build server failed to initialize")
335+
}
334336
return buildServerAdapter
335337
}
336338
}
@@ -505,8 +507,9 @@ package actor BuildServerManager: QueueBasedMessageHandler {
505507
logger.fault("If we have a connectionToBuildServer, we must have had a buildServerSpec")
506508
return nil
507509
}
508-
let initializeResponse = await orLog("Initializing build server") {
509-
try await buildServerAdapter.send(
510+
let initializeResponse: InitializeBuildResponse?
511+
do {
512+
initializeResponse = try await buildServerAdapter.send(
510513
InitializeBuildRequest(
511514
displayName: "SourceKit-LSP",
512515
version: "",
@@ -515,7 +518,19 @@ package actor BuildServerManager: QueueBasedMessageHandler {
515518
capabilities: BuildClientCapabilities(languageIds: [.c, .cpp, .objective_c, .objective_cpp, .swift])
516519
)
517520
)
521+
} catch {
522+
initializeResponse = nil
523+
let errorMessage: String
524+
if let error = error as? ResponseError {
525+
errorMessage = error.message
526+
} else {
527+
errorMessage = "\(error)"
528+
}
529+
connectionToClient.send(
530+
ShowMessageNotification(type: .error, message: "Failed to initialize build server: \(errorMessage)")
531+
)
518532
}
533+
519534
if let initializeResponse, !(initializeResponse.sourceKitData?.sourceKitOptionsProvider ?? false),
520535
case .external(let externalBuildServerAdapter) = buildServerAdapter
521536
{
@@ -559,7 +574,7 @@ package actor BuildServerManager: QueueBasedMessageHandler {
559574
package func shutdown() async {
560575
// Clear any pending work done progresses from the build server.
561576
self.workDoneProgressManagers.removeAll()
562-
guard let buildServerAdapter = await self.buildServerAdapterAfterInitialized else {
577+
guard let buildServerAdapter = try? await self.buildServerAdapterAfterInitialized else {
563578
return
564579
}
565580
await orLog("Sending shutdown request to build server") {
@@ -898,7 +913,7 @@ package actor BuildServerManager: QueueBasedMessageHandler {
898913
in target: BuildTargetIdentifier,
899914
language: Language
900915
) async throws -> FileBuildSettings? {
901-
guard let buildServerAdapter = await buildServerAdapterAfterInitialized else {
916+
guard let buildServerAdapter = try await buildServerAdapterAfterInitialized else {
902917
return nil
903918
}
904919
let request = TextDocumentSourceKitOptionsRequest(
@@ -1158,7 +1173,7 @@ package actor BuildServerManager: QueueBasedMessageHandler {
11581173
}
11591174

11601175
private func buildTargets() async throws -> [BuildTargetIdentifier: BuildTargetInfo] {
1161-
guard let buildServerAdapter = await buildServerAdapterAfterInitialized else {
1176+
guard let buildServerAdapter = try await buildServerAdapterAfterInitialized else {
11621177
return [:]
11631178
}
11641179

@@ -1198,7 +1213,7 @@ package actor BuildServerManager: QueueBasedMessageHandler {
11981213
}
11991214

12001215
package func sourceFiles(in targets: Set<BuildTargetIdentifier>) async throws -> [SourcesItem] {
1201-
guard let buildServerAdapter = await buildServerAdapterAfterInitialized, !targets.isEmpty else {
1216+
guard let buildServerAdapter = try await buildServerAdapterAfterInitialized, !targets.isEmpty else {
12021217
return []
12031218
}
12041219

@@ -1414,7 +1429,7 @@ package actor BuildServerManager: QueueBasedMessageHandler {
14141429
// MARK: Informing BuildSererManager about changes
14151430

14161431
package func filesDidChange(_ events: [FileEvent]) async {
1417-
if let buildServerAdapter = await buildServerAdapterAfterInitialized {
1432+
if let buildServerAdapter = try? await buildServerAdapterAfterInitialized {
14181433
await buildServerAdapter.send(OnWatchedFilesDidChangeNotification(changes: events))
14191434
}
14201435

Tests/BuildServerIntegrationTests/ExternalBuildServerTests.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,4 +647,37 @@ final class ExternalBuildServerTests: XCTestCase {
647647
}
648648
try await fulfillmentOfOrThrow(preparationFinished)
649649
}
650+
651+
func testBuildServerFailsToInitialize() async throws {
652+
actor BuildServer: CustomBuildServer {
653+
let inProgressRequestsTracker = CustomBuildServerInProgressRequestTracker()
654+
655+
init(projectRoot: URL, connectionToSourceKitLSP: any Connection) {}
656+
657+
func initializeBuildRequest(_ request: InitializeBuildRequest) async throws -> InitializeBuildResponse {
658+
throw ResponseError.unknown("Initialization failed with bad error")
659+
}
660+
661+
func buildTargetSourcesRequest(_ request: BuildTargetSourcesRequest) async throws -> BuildTargetSourcesResponse {
662+
throw ResponseError.unknown("Not expected to get called")
663+
}
664+
665+
func textDocumentSourceKitOptionsRequest(
666+
_ request: TextDocumentSourceKitOptionsRequest
667+
) async throws -> TextDocumentSourceKitOptionsResponse? {
668+
throw ResponseError.unknown("Not expected to get called")
669+
}
670+
}
671+
672+
let project = try await CustomBuildServerTestProject(
673+
files: [
674+
"Test.swift": """
675+
func 1️⃣myTestFunc() {}
676+
"""
677+
],
678+
buildServer: BuildServer.self
679+
)
680+
let message = try await project.testClient.nextNotification(ofType: ShowMessageNotification.self)
681+
assertContains(message.message, "Initialization failed with bad error")
682+
}
650683
}

0 commit comments

Comments
 (0)