diff --git a/Sources/SKTestSupport/TestJSONRPCConnection.swift b/Sources/SKTestSupport/TestJSONRPCConnection.swift deleted file mode 100644 index 19a45e466..000000000 --- a/Sources/SKTestSupport/TestJSONRPCConnection.swift +++ /dev/null @@ -1,238 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -import InProcessClient -@_spi(SourceKitLSP) public import LanguageServerProtocol -@_spi(SourceKitLSP) import LanguageServerProtocolExtensions -@_spi(SourceKitLSP) package import LanguageServerProtocolTransport -import SwiftExtensions -@_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions -import XCTest - -package import class Foundation.Pipe - -package final class TestJSONRPCConnection: Sendable { - package let clientToServer: Pipe = Pipe() - package let serverToClient: Pipe = Pipe() - - /// Mocks a client (aka. editor) that can send requests to the LSP server. - package let client: TestClient - - /// The connection with which the client can send requests and notifications to the LSP server and using which it - /// receives replies to the requests. - package let clientToServerConnection: JSONRPCConnection - - /// Mocks an LSP server that handles requests from the client. - package let server: TestServer - - /// The connection with which the server can send requests and notifications to the client and using which it - /// receives replies to the requests. - package let serverToClientConnection: JSONRPCConnection - - package init(allowUnexpectedNotification: Bool = true) { - clientToServerConnection = JSONRPCConnection( - name: "client", - protocol: testMessageRegistry, - inFD: serverToClient.fileHandleForReading, - outFD: clientToServer.fileHandleForWriting - ) - - serverToClientConnection = JSONRPCConnection( - name: "server", - protocol: testMessageRegistry, - inFD: clientToServer.fileHandleForReading, - outFD: serverToClient.fileHandleForWriting - ) - - client = TestClient( - connectionToServer: clientToServerConnection, - allowUnexpectedNotification: allowUnexpectedNotification - ) - server = TestServer(client: serverToClientConnection) - - clientToServerConnection.start(receiveHandler: client) { - // Keep the pipes alive until we close the connection. - withExtendedLifetime(self) {} - } - serverToClientConnection.start(receiveHandler: server) { - // Keep the pipes alive until we close the connection. - withExtendedLifetime(self) {} - } - } - - package func close() { - clientToServerConnection.close() - serverToClientConnection.close() - } -} - -package struct TestLocalConnection { - package let client: TestClient - package let clientConnection: LocalConnection = LocalConnection(receiverName: "Test") - package let server: TestServer - package let serverConnection: LocalConnection = LocalConnection(receiverName: "Test") - - package init(allowUnexpectedNotification: Bool = true) { - client = TestClient(connectionToServer: serverConnection, allowUnexpectedNotification: allowUnexpectedNotification) - server = TestServer(client: clientConnection) - - clientConnection.start(handler: client) - serverConnection.start(handler: server) - } - - package func close() { - clientConnection.close() - serverConnection.close() - } -} - -package actor TestClient: MessageHandler { - /// The connection to the LSP server. - package let connectionToServer: any Connection - - private let messageHandlingQueue = AsyncQueue() - - private var oneShotNotificationHandlers: [((Any) -> Void)] = [] - - private let allowUnexpectedNotification: Bool - - package init(connectionToServer: any Connection, allowUnexpectedNotification: Bool = true) { - self.connectionToServer = connectionToServer - self.allowUnexpectedNotification = allowUnexpectedNotification - } - - package func appendOneShotNotificationHandler(_ handler: @escaping (N) -> Void) { - oneShotNotificationHandlers.append({ anyNotification in - guard let notification = anyNotification as? N else { - fatalError("received notification of the wrong type \(anyNotification); expected \(N.self)") - } - handler(notification) - }) - } - - /// The LSP server sent a notification to the client. Handle it. - package nonisolated func handle(_ notification: some NotificationType) { - messageHandlingQueue.async { - await self.handleNotificationImpl(notification) - } - } - - package func handleNotificationImpl(_ notification: some NotificationType) { - guard !oneShotNotificationHandlers.isEmpty else { - if allowUnexpectedNotification { return } - fatalError("unexpected notification \(notification)") - } - let handler = oneShotNotificationHandlers.removeFirst() - handler(notification) - } - - /// The LSP server sent a request to the client. Handle it. - package nonisolated func handle( - _ request: Request, - id: RequestID, - reply: @escaping (LSPResult) -> Void - ) { - reply(.failure(.methodNotFound(Request.method))) - } - - /// Send a notification to the LSP server. - package nonisolated func send(_ notification: some NotificationType) { - connectionToServer.send(notification) - } - - /// Send a request to the LSP server and (asynchronously) receive a reply. - package nonisolated func send( - _ request: Request, - reply: @Sendable @escaping (LSPResult) -> Void - ) -> RequestID { - return connectionToServer.send(request, reply: reply) - } -} - -package final class TestServer: MessageHandler { - package let client: any Connection - - init(client: any Connection) { - self.client = client - } - - /// The client sent a notification to the server. Handle it. - package func handle(_ notification: some NotificationType) { - if notification is EchoNotification { - self.client.send(notification) - } else { - fatalError("Unhandled notification") - } - } - - /// The client sent a request to the server. Handle it. - package func handle( - _ request: Request, - id: RequestID, - reply: @escaping (LSPResult) -> Void - ) { - if let params = request as? EchoRequest { - reply(.success(params.string as! Request.Response)) - } else if let params = request as? EchoError { - if let code = params.code { - reply(.failure(ResponseError(code: code, message: params.message!))) - } else { - reply(.success(VoidResponse() as! Request.Response)) - } - } else { - fatalError("Unhandled request") - } - } -} - -// MARK: Test requests - -private let testMessageRegistry = MessageRegistry( - requests: [EchoRequest.self, EchoError.self], - notifications: [EchoNotification.self, ShowMessageNotification.self] -) - -extension String: LanguageServerProtocol.ResponseType {} - -package struct EchoRequest: RequestType { - package static let method: String = "test_server/echo" - package typealias Response = String - - package var string: String - - package init(string: String) { - self.string = string - } -} - -package struct EchoError: RequestType { - package static let method: String = "test_server/echo_error" - package typealias Response = VoidResponse - - package var code: ErrorCode? - package var message: String? - - package init(code: ErrorCode? = nil, message: String? = nil) { - self.code = code - self.message = message - } -} - -package struct EchoNotification: NotificationType { - package static let method: String = "test_server/echo_note" - - package var string: String - - package init(string: String) { - self.string = string - } -}