Skip to content

Commit 757a029

Browse files
committed
Log messages from the build server and clangd
Log messages sent to clangd and the build server in a similar way that we log requests to sourcekitd. Fixes #886 rdar://116705677
1 parent ce9fdf9 commit 757a029

File tree

10 files changed

+109
-20
lines changed

10 files changed

+109
-20
lines changed

Sources/LSPTestSupport/TestJSONRPCConnection.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,14 @@ public final class TestJSONRPCConnection {
2626

2727
public init() {
2828
clientConnection = JSONRPCConnection(
29+
name: "client",
2930
protocol: testMessageRegistry,
3031
inFD: serverToClient.fileHandleForReading,
3132
outFD: clientToServer.fileHandleForWriting
3233
)
3334

3435
serverConnection = JSONRPCConnection(
36+
name: "server",
3537
protocol: testMessageRegistry,
3638
inFD: clientToServer.fileHandleForReading,
3739
outFD: serverToClient.fileHandleForWriting

Sources/LanguageServerProtocolJSONRPC/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
add_library(LanguageServerProtocolJSONRPC STATIC
22
DisableSigpipe.swift
33
JSONRPCConnection.swift
4+
LoggableMessageTypes.swift
45
MessageCoding.swift
56
MessageSplitting.swift)
67
set_target_properties(LanguageServerProtocolJSONRPC PROPERTIES

Sources/LanguageServerProtocolJSONRPC/JSONRPCConnection.swift

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ import struct CDispatch.dispatch_fd_t
2424
/// For example, inside a language server, the `JSONRPCConnection` takes the language service implemenation as its `receiveHandler` and itself provides the client connection for sending notifications and callbacks.
2525
public final class JSONRPCConnection {
2626

27+
/// A name of the endpoint for this connection, used for logging, e.g. `clangd`.
28+
let name: String
29+
2730
var receiveHandler: MessageHandler? = nil
2831

2932
/// The queue on which we read the data
@@ -66,11 +69,13 @@ public final class JSONRPCConnection {
6669
var closeHandler: (() async -> Void)? = nil
6770

6871
public init(
72+
name: String,
6973
protocol messageRegistry: MessageRegistry,
7074
inFD: FileHandle,
7175
outFD: FileHandle,
7276
syncRequests: Bool = false
7377
) {
78+
self.name = name
7479
#if os(Linux) || os(Android)
7580
// We receive a `SIGPIPE` if we write to a pipe that points to a crashed process. This in particular happens if the target of a `JSONRPCConnection` has crashed and we try to send it a message.
7681
// On Darwin, `DispatchIO` ignores `SIGPIPE` for the pipes handled by it, but that features is not available on Linux.
@@ -410,22 +415,36 @@ public final class JSONRPCConnection {
410415
_nextRequestID += 1
411416
return .number(_nextRequestID)
412417
}
413-
414418
}
415419

416420
extension JSONRPCConnection: Connection {
417421
// MARK: Connection interface
418422

419423
public func send<Notification>(_ notification: Notification) where Notification: NotificationType {
420-
guard readyToSend() else { return }
424+
guard readyToSend() else {
425+
logger.error(
426+
"""
427+
Not sending notification to \(self.name, privacy: .public) because connection is not ready to send
428+
\(notification.forLogging)
429+
"""
430+
)
431+
return
432+
}
433+
logger.info(
434+
"""
435+
Sending notification to \(self.name, privacy: .public)
436+
\(notification.forLogging)
437+
"""
438+
)
421439
send { encoder in
422440
return try encoder.encode(JSONRPCMessage.notification(notification))
423441
}
424442
}
425443

426-
public func send<Request>(_ request: Request, reply: @escaping (LSPResult<Request.Response>) -> Void) -> RequestID
427-
where Request: RequestType {
428-
444+
public func send<Request: RequestType>(
445+
_ request: Request,
446+
reply: @escaping (LSPResult<Request.Response>) -> Void
447+
) -> RequestID {
429448
let id: RequestID = self.queue.sync {
430449
let id = nextRequestID()
431450

@@ -439,12 +458,36 @@ extension JSONRPCConnection: Connection {
439458
responseType: Request.Response.self,
440459
queue: queue,
441460
replyHandler: { anyResult in
442-
reply(anyResult.map { $0 as! Request.Response })
461+
let result = anyResult.map { $0 as! Request.Response }
462+
switch result {
463+
case .success(let response):
464+
logger.info(
465+
"""
466+
Received reply for request \(id, privacy: .public) from \(self.name, privacy: .public)
467+
\(response.forLogging)
468+
"""
469+
)
470+
case .failure(let error):
471+
logger.error(
472+
"""
473+
Received error for request \(id, privacy: .public) from \(self.name, privacy: .public)
474+
\(error.forLogging)
475+
"""
476+
)
477+
}
478+
reply(result)
443479
}
444480
)
445481
return id
446482
}
447483

484+
logger.info(
485+
"""
486+
Sending request to \(self.name, privacy: .public) (id: \(id, privacy: .public)):
487+
\(request.forLogging)
488+
"""
489+
)
490+
448491
send { encoder in
449492
return try encoder.encode(JSONRPCMessage.request(request, id: id))
450493
}

Sources/SKSupport/LoggableMessageTypes.swift renamed to Sources/LanguageServerProtocolJSONRPC/LoggableMessageTypes.swift

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,6 @@ fileprivate extension Encodable {
3131
}
3232
}
3333

34-
// MARK: - DocumentURI
35-
36-
extension DocumentURI {
37-
public var redactedDescription: String {
38-
return "<DocumentURI length=\(description.count) hash=\(description.hashForLogging)>"
39-
}
40-
}
41-
#if swift(<5.10)
42-
extension DocumentURI: CustomLogStringConvertible {}
43-
#else
44-
extension DocumentURI: @retroactive CustomLogStringConvertible {}
45-
#endif
46-
4734
// MARK: - RequestType
4835

4936
fileprivate struct AnyRequestType: CustomLogStringConvertible {

Sources/SKCore/BuildServerBuildSystem.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,12 @@ public actor BuildServerBuildSystem: MessageHandler {
191191
///
192192
/// We need to notify the delegate about any updated build settings.
193193
public nonisolated func handle(_ params: some NotificationType, from clientID: ObjectIdentifier) {
194+
logger.info(
195+
"""
196+
Received notification from build server:
197+
\(params.forLogging)
198+
"""
199+
)
194200
bspMessageHandlingQueue.async {
195201
if let params = params as? BuildTargetsChangedNotification {
196202
await self.handleBuildTargetsChanged(params)
@@ -209,6 +215,12 @@ public actor BuildServerBuildSystem: MessageHandler {
209215
from clientID: ObjectIdentifier,
210216
reply: @escaping (LSPResult<R.Response>) -> Void
211217
) {
218+
logger.info(
219+
"""
220+
Received request from build server:
221+
\(params.forLogging)
222+
"""
223+
)
212224
reply(.failure(ResponseError.methodNotFound(R.method)))
213225
}
214226

@@ -339,6 +351,7 @@ private func makeJSONRPCBuildServer(
339351
let serverToClient = Pipe()
340352

341353
let connection = JSONRPCConnection(
354+
name: "build server",
342355
protocol: BuildServerProtocol.bspRegistry,
343356
inFD: serverToClient.fileHandleForReading,
344357
outFD: clientToServer.fileHandleForWriting

Sources/SKSupport/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ add_library(SKSupport STATIC
66
ByteString.swift
77
Connection+Send.swift
88
dlopen.swift
9+
DocumentURI+CustomLogStringConvertible.swift
910
FileSystem.swift
1011
LineTable.swift
11-
LoggableMessageTypes.swift
1212
Random.swift
1313
Result.swift
1414
ThreadSafeBox.swift
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Foundation
14+
import LSPLogging
15+
import LanguageServerProtocol
16+
17+
// MARK: - DocumentURI
18+
19+
extension DocumentURI {
20+
public var redactedDescription: String {
21+
return "<DocumentURI length=\(description.count) hash=\(description.hashForLogging)>"
22+
}
23+
}
24+
#if swift(<5.10)
25+
extension DocumentURI: CustomLogStringConvertible {}
26+
#else
27+
extension DocumentURI: @retroactive CustomLogStringConvertible {}
28+
#endif

Sources/SourceKitLSP/Clang/ClangLanguageServer.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ actor ClangLanguageServerShim: ToolchainLanguageServer, MessageHandler {
200200
let clangdToUs: Pipe = Pipe()
201201

202202
let connectionToClangd = JSONRPCConnection(
203+
name: "clangd",
203204
protocol: MessageRegistry.lspProtocol,
204205
inFD: clangdToUs.fileHandleForReading,
205206
outFD: usToClangd.fileHandleForWriting
@@ -302,6 +303,12 @@ actor ClangLanguageServerShim: ToolchainLanguageServer, MessageHandler {
302303
///
303304
/// We should either handle it ourselves or forward it to the editor.
304305
nonisolated func handle(_ params: some NotificationType, from clientID: ObjectIdentifier) {
306+
logger.info(
307+
"""
308+
Received notification from clangd:
309+
\(params.forLogging)
310+
"""
311+
)
305312
clangdMessageHandlingQueue.async {
306313
switch params {
307314
case let publishDiags as PublishDiagnosticsNotification:
@@ -324,6 +331,12 @@ actor ClangLanguageServerShim: ToolchainLanguageServer, MessageHandler {
324331
from clientID: ObjectIdentifier,
325332
reply: @escaping (LSPResult<R.Response>) -> Void
326333
) {
334+
logger.info(
335+
"""
336+
Received request from clangd:
337+
\(params.forLogging)
338+
"""
339+
)
327340
clangdMessageHandlingQueue.async {
328341
guard let sourceKitServer = await self.sourceKitServer else {
329342
// `SourceKitServer` has been destructed. We are tearing down the language

Sources/sourcekit-lsp/SourceKitLSP.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ struct SourceKitLSP: ParsableCommand {
221221
let realStdoutHandle = FileHandle(fileDescriptor: realStdout, closeOnDealloc: false)
222222

223223
let clientConnection = JSONRPCConnection(
224+
name: "client",
224225
protocol: MessageRegistry.lspProtocol,
225226
inFD: FileHandle.standardInput,
226227
outFD: realStdoutHandle,

Tests/LanguageServerProtocolJSONRPCTests/ConnectionTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ class ConnectionTests: XCTestCase {
252252
expectation.assertForOverFulfill = true
253253

254254
let conn = JSONRPCConnection(
255+
name: "test",
255256
protocol: MessageRegistry(requests: [], notifications: []),
256257
inFD: to.fileHandleForReading,
257258
outFD: from.fileHandleForWriting

0 commit comments

Comments
 (0)