Skip to content

Commit 6d491ab

Browse files
committed
Change the Request type to be a fileprivate RequestAndReply in SourceKitServer
Since asyncifying all the request handling, `Request` only had a few lingering uses. Remove most of them and shrink it down to a type that only contains the request’s parameters and the reply block of the corresponding type. And while we’re doing this, also move `NotificationType.forLogging` out of the `LanguageServerProtocol` module to remove the dependency from `LanguageServerProtocol` on `LSPLogging`. Resolves #881 Resolves #936 rdar://116705662 rdar://117562587
1 parent 204b1ce commit 6d491ab

File tree

7 files changed

+122
-195
lines changed

7 files changed

+122
-195
lines changed

Package.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ let package = Package(
102102
.target(
103103
name: "LanguageServerProtocol",
104104
dependencies: [
105-
"LSPLogging",
106105
"SKSupport",
107106
.product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"),
108107
],

Sources/LSPTestSupport/TestJSONRPCConnection.swift

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ public final class TestMessageHandler: MessageHandler {
8787
}
8888

8989
var oneShotNotificationHandlers: [((Any) -> Void)] = []
90-
var oneShotRequestHandlers: [((Any) -> Void)] = []
9190

9291
public var allowUnexpectedNotification: Bool = true
9392

@@ -100,15 +99,6 @@ public final class TestMessageHandler: MessageHandler {
10099
})
101100
}
102101

103-
public func appendOneShotRequestHandler<R>(_ handler: @escaping (Request<R>) -> Void) {
104-
oneShotRequestHandlers.append({ anyRequest in
105-
guard let request = anyRequest as? Request<R> else {
106-
fatalError("received request of the wrong type \(anyRequest); expected \(R.self)")
107-
}
108-
handler(request)
109-
})
110-
}
111-
112102
public func handle(_ notification: some NotificationType, from clientID: ObjectIdentifier) {
113103
guard !oneShotNotificationHandlers.isEmpty else {
114104
if allowUnexpectedNotification { return }
@@ -124,13 +114,7 @@ public final class TestMessageHandler: MessageHandler {
124114
from clientID: ObjectIdentifier,
125115
reply: @escaping (LSPResult<R.Response>) -> Void
126116
) {
127-
let request = Request(params, id: id, clientID: clientID, reply: reply)
128-
129-
guard !oneShotRequestHandlers.isEmpty else {
130-
fatalError("unexpected request \(request)")
131-
}
132-
let handler = oneShotRequestHandlers.removeFirst()
133-
handler(request)
117+
reply(.failure(.methodNotFound(R.method)))
134118
}
135119
}
136120

@@ -172,28 +156,12 @@ public final class TestServer: MessageHandler {
172156
reply: @escaping (LSPResult<R.Response>) -> Void
173157
) {
174158
if let params = params as? EchoRequest {
175-
let req = Request(
176-
params,
177-
id: id,
178-
clientID: clientID,
179-
reply: { result in
180-
reply(result.map({ $0 as! R.Response }))
181-
}
182-
)
183-
req.reply(req.params.string)
159+
reply(.success(params.string as! R.Response))
184160
} else if let params = params as? EchoError {
185-
let req = Request(
186-
params,
187-
id: id,
188-
clientID: clientID,
189-
reply: { result in
190-
reply(result.map({ $0 as! R.Response }))
191-
}
192-
)
193-
if let code = req.params.code {
194-
req.reply(.failure(ResponseError(code: code, message: req.params.message!)))
161+
if let code = params.code {
162+
reply(.failure(ResponseError(code: code, message: params.message!)))
195163
} else {
196-
req.reply(VoidResponse())
164+
reply(.success(VoidResponse() as! R.Response))
197165
}
198166
} else {
199167
fatalError("Unhandled request")

Sources/LanguageServerProtocol/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ add_library(LanguageServerProtocol STATIC
77
MessageRegistry.swift
88
Messages.swift
99
PositionRange.swift
10-
Request.swift
1110
RequestID.swift
1211

1312
Notifications/CancelRequestNotification.swift

Sources/SourceKitLSP/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ add_library(SourceKitLSP STATIC
33
CapabilityRegistry.swift
44
DocumentManager.swift
55
IndexStoreDB+MainFilesProvider.swift
6+
LoggableMessageTypes.swift
67
ResponseError+Init.swift
78
Sequence+AsyncMap.swift
89
SourceKitIndexDelegate.swift

Sources/SourceKitLSP/Clang/ClangLanguageServer.swift

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -294,26 +294,18 @@ actor ClangLanguageServerShim: ToolchainLanguageServer, MessageHandler {
294294
reply: @escaping (LSPResult<R.Response>) -> Void
295295
) {
296296
clangdMessageHandlingQueue.async {
297-
let request = Request(
298-
params,
299-
id: id,
300-
clientID: clientID,
301-
reply: { result in
302-
reply(result)
303-
}
304-
)
305297
guard let sourceKitServer = await self.sourceKitServer else {
306298
// `SourceKitServer` has been destructed. We are tearing down the language
307299
// server. Nothing left to do.
308-
request.reply(.failure(.unknown("Connection to the editor closed")))
300+
reply(.failure(.unknown("Connection to the editor closed")))
309301
return
310302
}
311303

312304
do {
313-
let result = try await sourceKitServer.sendRequestToClient(request.params)
314-
request.reply(.success(result))
305+
let result = try await sourceKitServer.sendRequestToClient(params)
306+
reply(.success(result))
315307
} catch {
316-
request.reply(.failure(ResponseError(error)))
308+
reply(.failure(ResponseError(error)))
317309
}
318310
}
319311
}

Sources/LanguageServerProtocol/Request.swift renamed to Sources/SourceKitLSP/LoggableMessageTypes.swift

Lines changed: 16 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -12,66 +12,11 @@
1212

1313
import Foundation
1414
import LSPLogging
15-
16-
/// A request object, wrapping the parameters of a `RequestType` and tracking its state.
17-
public final class Request<R: RequestType> {
18-
19-
public typealias Params = R
20-
21-
public typealias Response = R.Response
22-
23-
/// The request id from the client.
24-
public let id: RequestID
25-
26-
/// The client of the request.
27-
public let clientID: ObjectIdentifier
28-
29-
/// The request parameters.
30-
public let params: Params
31-
32-
private var replyBlock: (LSPResult<Response>) -> Void
33-
34-
/// Whether a reply has been made. Every request must reply exactly once.
35-
private var replied: Bool = false {
36-
willSet {
37-
precondition(replied == false, "replied to \(id) more than once")
38-
}
39-
}
40-
41-
public init(
42-
_ request: Params,
43-
id: RequestID,
44-
clientID: ObjectIdentifier,
45-
reply: @escaping (LSPResult<Response>) -> Void
46-
) {
47-
self.id = id
48-
self.clientID = clientID
49-
self.params = request
50-
self.replyBlock = reply
51-
}
52-
53-
deinit {
54-
precondition(replied, "request \(id) never received a reply")
55-
}
56-
57-
/// Reply to the request with `result`.
58-
///
59-
/// This must be called exactly once for each request.
60-
public func reply(_ result: LSPResult<Response>) {
61-
replied = true
62-
replyBlock(result)
63-
}
64-
65-
/// Reply to the request with `.success(result)`.
66-
public func reply(_ result: Response) {
67-
reply(.success(result))
68-
}
69-
}
15+
import LanguageServerProtocol
7016

7117
fileprivate extension Encodable {
7218
var prettyPrintJSON: String {
7319
let encoder = JSONEncoder()
74-
encoder.outputFormatting.insert(.sortedKeys)
7520
encoder.outputFormatting.insert(.prettyPrinted)
7621
guard let data = try? encoder.encode(self) else {
7722
return "\(self)"
@@ -85,17 +30,24 @@ fileprivate extension Encodable {
8530
}
8631
}
8732

88-
extension Request: CustomStringConvertible, CustomLogStringConvertible {
33+
fileprivate struct AnyRequestType: CustomLogStringConvertible {
34+
let request: any RequestType
35+
8936
public var description: String {
9037
return """
91-
\(R.method)
92-
\(params.prettyPrintJSON)
38+
\(type(of: request).method)
39+
\(request.prettyPrintJSON)
9340
"""
9441
}
9542

9643
public var redactedDescription: String {
97-
// FIXME: (logging) Log the non-critical parts of the request
98-
return "Request<\(R.method)>"
44+
return "\(type(of: request).method)"
45+
}
46+
}
47+
48+
extension RequestType {
49+
public var forLogging: CustomLogStringConvertibleWrapper {
50+
return AnyRequestType(request: self).forLogging
9951
}
10052
}
10153

@@ -104,14 +56,13 @@ fileprivate struct AnyNotificationType: CustomLogStringConvertible {
10456

10557
public var description: String {
10658
return """
107-
\(type(of: notification))
59+
\(type(of: notification).method)
10860
\(notification.prettyPrintJSON)
10961
"""
11062
}
11163

11264
public var redactedDescription: String {
113-
// FIXME: (logging) Log the non-critical parts of the notification
114-
return "\(type(of: notification))"
65+
return "\(type(of: notification).method)"
11566
}
11667
}
11768

0 commit comments

Comments
 (0)