Files
sourcekit-lsp/Sources/SKTestSupport/TestServer.swift
Saleem Abdulrasool 6a275d134c Fix the Pipe handling on Windows to be correct
This actually addresses the real issue that was ignored earlier about
pipes on Windows.  The FileHandle cannot provide a non-owning file
descriptor (the returned file descriptor would need to be explicitly
`_close`'d by the receiver).  Foundation now vends a `_handle` accessor
to the OS primitive handle.  Use this to create the dispatch loop for
messaging.  We now create the JSONRPCConnection from handles on Windows
which actually should help enable running some of the tests on Windows
as well.
2020-11-02 09:55:58 -08:00

115 lines
3.6 KiB
Swift

//===----------------------------------------------------------------------===//
//
// 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 SKSupport
import SKCore
import TSCUtility
import LanguageServerProtocol
import LanguageServerProtocolJSONRPC
import SourceKitLSP
import class Foundation.Pipe
import LSPTestSupport
public final class TestSourceKitServer {
public enum ConnectionKind {
case local, jsonrpc
}
enum ConnectionImpl {
case local(
clientConnection: LocalConnection,
serverConnection: LocalConnection)
case jsonrpc(
clientToServer: Pipe,
serverToClient: Pipe,
clientConnection: JSONRPCConnection,
serverConnection: JSONRPCConnection)
}
public static let serverOptions: SourceKitServer.Options = SourceKitServer.Options()
public let client: TestClient
let connImpl: ConnectionImpl
public var hasShutdown: Bool = false
/// The server, if it is in the same process.
public let server: SourceKitServer?
public init(connectionKind: ConnectionKind = .local) {
switch connectionKind {
case .local:
let clientConnection = LocalConnection()
let serverConnection = LocalConnection()
client = TestClient(server: serverConnection)
server = SourceKitServer(client: clientConnection, options: Self.serverOptions, onExit: {
clientConnection.close()
})
clientConnection.start(handler: client)
serverConnection.start(handler: server!)
connImpl = .local(clientConnection: clientConnection, serverConnection: serverConnection)
case .jsonrpc:
let clientToServer: Pipe = Pipe()
let serverToClient: Pipe = Pipe()
let clientConnection = JSONRPCConnection(
protocol: MessageRegistry.lspProtocol,
inFD: serverToClient.fileHandleForReading,
outFD: clientToServer.fileHandleForWriting
)
let serverConnection = JSONRPCConnection(
protocol: MessageRegistry.lspProtocol,
inFD: clientToServer.fileHandleForReading,
outFD: serverToClient.fileHandleForWriting
)
client = TestClient(server: clientConnection)
server = SourceKitServer(client: serverConnection, options: Self.serverOptions, onExit: {
serverConnection.close()
})
clientConnection.start(receiveHandler: client) {
// FIXME: keep the pipes alive until we close the connection. This
// should be fixed systemically.
withExtendedLifetime((clientToServer, serverToClient)) {}
}
serverConnection.start(receiveHandler: server!) {
// FIXME: keep the pipes alive until we close the connection. This
// should be fixed systemically.
withExtendedLifetime((clientToServer, serverToClient)) {}
}
connImpl = .jsonrpc(
clientToServer: clientToServer,
serverToClient: serverToClient,
clientConnection: clientConnection,
serverConnection: serverConnection)
}
}
deinit {
close()
}
func close() {
if !hasShutdown {
hasShutdown = true
_ = try! self.client.sendSync(ShutdownRequest())
self.client.send(ExitNotification())
}
}
}