diff --git a/Sources/LSPTestSupport/TestJSONRPCConnection.swift b/Sources/LSPTestSupport/TestJSONRPCConnection.swift index 3fd041f3..fc86eb43 100644 --- a/Sources/LSPTestSupport/TestJSONRPCConnection.swift +++ b/Sources/LSPTestSupport/TestJSONRPCConnection.swift @@ -88,7 +88,6 @@ public final class TestClient: MessageHandler { self.server = server } - public var replyQueue: DispatchQueue = DispatchQueue(label: "testclient-reply-queue") var oneShotNotificationHandlers: [((Any) -> Void)] = [] var oneShotRequestHandlers: [((Any) -> Void)] = [] @@ -157,13 +156,8 @@ extension TestClient: Connection { } /// Send a request to the language server and (asynchronously) receive a reply. - public func send(_ request: Request, queue: DispatchQueue, reply: @escaping (LSPResult) -> Void) -> RequestID where Request: RequestType { - return server.send(request, queue: queue, reply: reply) - } - - /// Convenience method to get reply on replyQueue. public func send(_ request: Request, reply: @escaping (LSPResult) -> Void) -> RequestID where Request: RequestType { - return send(request, queue: replyQueue, reply: reply) + return server.send(request, reply: reply) } diff --git a/Sources/LanguageServerProtocol/Connection.swift b/Sources/LanguageServerProtocol/Connection.swift index 2795b523..6580d671 100644 --- a/Sources/LanguageServerProtocol/Connection.swift +++ b/Sources/LanguageServerProtocol/Connection.swift @@ -19,7 +19,7 @@ public protocol Connection: AnyObject { func send(_: Notification) where Notification: NotificationType /// Send a request and (asynchronously) receive a reply. - func send(_: Request, queue: DispatchQueue, reply: @escaping (LSPResult) -> Void) -> RequestID where Request: RequestType + func send(_: Request, reply: @escaping (LSPResult) -> Void) -> RequestID where Request: RequestType /// Send a request synchronously. **Use wisely**. func sendSync(_: Request) throws -> Request.Response where Request: RequestType @@ -29,7 +29,7 @@ extension Connection { public func sendSync(_ request: Request) throws -> Request.Response where Request: RequestType { var result: LSPResult? = nil let semaphore = DispatchSemaphore(value: 0) - _ = send(request, queue: DispatchQueue.global()) { _result in + _ = send(request) { _result in result = _result semaphore.signal() } @@ -119,23 +119,18 @@ extension LocalConnection: Connection { public func send( _ request: Request, - queue: DispatchQueue, reply: @escaping (LSPResult) -> Void ) -> RequestID { let id = nextRequestID() guard let handler = self.handler else { - queue.async { - reply(.failure(.serverCancelled)) - } + reply(.failure(.serverCancelled)) return id } precondition(self.state == .started) handler.handle(request, id: id, from: ObjectIdentifier(self)) { result in - queue.async { - reply(result) - } + reply(result) } return id diff --git a/Sources/LanguageServerProtocolJSONRPC/JSONRPCConnection.swift b/Sources/LanguageServerProtocolJSONRPC/JSONRPCConnection.swift index 9dd61875..8e560c00 100644 --- a/Sources/LanguageServerProtocolJSONRPC/JSONRPCConnection.swift +++ b/Sources/LanguageServerProtocolJSONRPC/JSONRPCConnection.swift @@ -408,7 +408,7 @@ extension JSONRPCConnection: Connection { } } - public func send(_ request: Request, queue: DispatchQueue, reply: @escaping (LSPResult) -> Void) -> RequestID where Request: RequestType { + public func send(_ request: Request, reply: @escaping (LSPResult) -> Void) -> RequestID where Request: RequestType { let id: RequestID = self.queue.sync { let id = nextRequestID() @@ -423,10 +423,9 @@ extension JSONRPCConnection: Connection { responseType: Request.Response.self, queue: queue, replyHandler: { anyResult in - queue.async { - reply(anyResult.map { $0 as! Request.Response }) - } - }) + reply(anyResult.map { $0 as! Request.Response }) + } + ) return id } diff --git a/Sources/SKCore/BuildServerBuildSystem.swift b/Sources/SKCore/BuildServerBuildSystem.swift index 166d2cea..d5f2e7ba 100644 --- a/Sources/SKCore/BuildServerBuildSystem.swift +++ b/Sources/SKCore/BuildServerBuildSystem.swift @@ -119,13 +119,13 @@ public actor BuildServerBuildSystem: MessageHandler { deinit { if let buildServer = self.buildServer { - _ = buildServer.send(ShutdownBuild(), queue: DispatchQueue.global(), reply: { result in + _ = buildServer.send(ShutdownBuild()) { result in if let error = result.failure { log("error shutting down build server: \(error)") } buildServer.send(ExitBuildNotification()) buildServer.close() - }) + } } } @@ -239,7 +239,7 @@ extension BuildServerBuildSystem: BuildSystem { public func registerForChangeNotifications(for uri: DocumentURI, language: Language) { let request = RegisterForChanges(uri: uri, action: .register) - _ = self.buildServer?.send(request, queue: requestQueue, reply: { result in + _ = self.buildServer?.send(request) { result in Task { if let error = result.failure { log("error registering \(uri): \(error)", level: .error) @@ -249,18 +249,18 @@ extension BuildServerBuildSystem: BuildSystem { await self.buildSettingsChanged(for: uri, settings: nil) } } - }) + } } /// Unregister the given file for build-system level change notifications, such as command /// line flag changes, dependency changes, etc. public func unregisterForChangeNotifications(for uri: DocumentURI) { let request = RegisterForChanges(uri: uri, action: .unregister) - _ = self.buildServer?.send(request, queue: requestQueue, reply: { result in + _ = self.buildServer?.send(request) { result in if let error = result.failure { log("error unregistering \(uri): \(error)", level: .error) } - }) + } } public func filesDidChange(_ events: [FileEvent]) {} diff --git a/Sources/SourceKitLSP/Clang/ClangLanguageServer.swift b/Sources/SourceKitLSP/Clang/ClangLanguageServer.swift index 661f08af..87cbeb49 100644 --- a/Sources/SourceKitLSP/Clang/ClangLanguageServer.swift +++ b/Sources/SourceKitLSP/Clang/ClangLanguageServer.swift @@ -41,10 +41,6 @@ extension NSLock { /// requests and notifications **from** clangd, not from the editor, and it will /// forward these requests and notifications to the editor. actor ClangLanguageServerShim: ToolchainLanguageServer, MessageHandler { - // FIXME: (async) Remove once `Connection.send` has been asyncified. - /// The queue on which clangd calls us back. - public let clangdCommunicationQueue: DispatchQueue = DispatchQueue(label: "language-server-queue", qos: .userInitiated) - /// The queue on which all messages that originate from clangd are handled. /// /// These are requests and notifications sent *from* clangd, not replies from @@ -314,7 +310,7 @@ actor ClangLanguageServerShim: ToolchainLanguageServer, MessageHandler { /// The cancellation token from the original request is automatically linked to the forwarded /// request such that cancelling the original request will cancel the forwarded request. func forwardRequestToClangd(_ request: Request) { - let id = clangd.send(request.params, queue: clangdCommunicationQueue) { result in + let id = clangd.send(request.params) { result in request.reply(result) } request.cancellationToken.addCancellationHandler { @@ -331,7 +327,7 @@ actor ClangLanguageServerShim: ToolchainLanguageServer, MessageHandler { /// The response of the request is returned asynchronously as the return value. func forwardRequestToClangd(_ request: R) async throws -> R.Response { try await withCheckedThrowingContinuation { continuation in - _ = clangd.send(request, queue: clangdCommunicationQueue) { result in + _ = clangd.send(request) { result in switch result { case .success(let response): continuation.resume(returning: response) @@ -423,7 +419,7 @@ extension ClangLanguageServerShim { public func shutdown() async { await withCheckedContinuation { continuation in - _ = clangd.send(ShutdownRequest(), queue: self.clangdCommunicationQueue) { [weak self] _ in + _ = clangd.send(ShutdownRequest()) { [weak self] _ in guard let self else { return } Task { await self.clangd.send(ExitNotification()) diff --git a/Sources/SourceKitLSP/SourceKitServer.swift b/Sources/SourceKitLSP/SourceKitServer.swift index be60324e..83e7f44c 100644 --- a/Sources/SourceKitLSP/SourceKitServer.swift +++ b/Sources/SourceKitLSP/SourceKitServer.swift @@ -96,7 +96,7 @@ final actor WorkDoneProgressState { if state == .noProgress { state = .creating // Discard the handle. We don't support cancellation of the creation of a work done progress. - _ = server.client.send(CreateWorkDoneProgressRequest(token: token), queue: server.clientCommunicationQueue) { result in + _ = server.client.send(CreateWorkDoneProgressRequest(token: token)) { result in if result.success != nil { if self.activeTasks == 0 { // ActiveTasks might have been decreased while we created the `WorkDoneProgress` @@ -133,10 +133,6 @@ final actor WorkDoneProgressState { /// and cross-language support. Requests may be dispatched to language-specific services or handled /// centrally, but this is transparent to the client. public actor SourceKitServer { - // FIXME: (async) We can remove this if we migrate client.send to be async and it thus doesn't take a queue anymore. - /// The queue on which we communicate with the client. - public let clientCommunicationQueue: DispatchQueue = DispatchQueue(label: "language-server-queue", qos: .userInitiated) - /// The queue on which all messages (notifications, requests, responses) are /// handled. /// @@ -280,7 +276,7 @@ public actor SourceKitServer { /// Send the given request to the editor. public func sendRequestToClient(_ request: R) async throws -> R.Response { try await withCheckedThrowingContinuation { continuation in - _ = client.send(request, queue: clientCommunicationQueue) { result in + _ = client.send(request) { result in continuation.resume(with: result) } // FIXME: (async) Handle cancellation @@ -902,7 +898,7 @@ extension SourceKitServer { _ registry: CapabilityRegistry ) { let req = RegisterCapabilityRequest(registrations: [registration]) - let _ = client.send(req, queue: clientCommunicationQueue) { result in + let _ = client.send(req) { result in if let error = result.failure { log("Failed to dynamically register for \(registration.method): \(error)", level: .error) registry.remove(registration: registration)