diff --git a/Sources/LSPTestSupport/TestJSONRPCConnection.swift b/Sources/LSPTestSupport/TestJSONRPCConnection.swift index 51e54eb4..28e578b0 100644 --- a/Sources/LSPTestSupport/TestJSONRPCConnection.swift +++ b/Sources/LSPTestSupport/TestJSONRPCConnection.swift @@ -16,9 +16,6 @@ import XCTest import class Foundation.Pipe -// Workaround ambiguity with Foundation. -public typealias Notification = LanguageServerProtocol.Notification - public final class TestJSONRPCConnection { public let clientToServer: Pipe = Pipe() public let serverToClient: Pipe = Pipe() @@ -94,9 +91,9 @@ public final class TestMessageHandler: MessageHandler { public var allowUnexpectedNotification: Bool = true - public func appendOneShotNotificationHandler(_ handler: @escaping (Notification) -> Void) { + public func appendOneShotNotificationHandler(_ handler: @escaping (N) -> Void) { oneShotNotificationHandlers.append({ anyNote in - guard let note = anyNote as? Notification else { + guard let note = anyNote as? N else { fatalError("received notification of the wrong type \(anyNote); expected \(N.self)") } handler(note) @@ -112,9 +109,7 @@ public final class TestMessageHandler: MessageHandler { }) } - public func handle(_ params: N, from clientID: ObjectIdentifier) where N: NotificationType { - let notification = Notification(params, clientID: clientID) - + public func handle(_ notification: some NotificationType, from clientID: ObjectIdentifier) { guard !oneShotNotificationHandlers.isEmpty else { if allowUnexpectedNotification { return } fatalError("unexpected notification \(notification)") @@ -144,7 +139,7 @@ public final class TestMessageHandler: MessageHandler { extension TestMessageHandler: Connection { /// Send a notification to the language server. - public func send(_ notification: Notification) where Notification: NotificationType { + public func send(_ notification: some NotificationType) { server.send(notification) } @@ -164,10 +159,9 @@ public final class TestServer: MessageHandler { self.client = client } - public func handle(_ params: N, from clientID: ObjectIdentifier) { - let note = Notification(params, clientID: clientID) + public func handle(_ params: some NotificationType, from clientID: ObjectIdentifier) { if params is EchoNotification { - self.client.send(note.params) + self.client.send(params) } else { fatalError("Unhandled notification") } diff --git a/Sources/LanguageServerProtocol/Request.swift b/Sources/LanguageServerProtocol/Request.swift index ae148541..f801706e 100644 --- a/Sources/LanguageServerProtocol/Request.swift +++ b/Sources/LanguageServerProtocol/Request.swift @@ -76,23 +76,6 @@ public final class Request { public var isCancelled: Bool { return cancellationToken.isCancelled } } -/// A request object, wrapping the parameters of a `NotificationType`. -public final class Notification { - - public typealias Params = N - - /// The client of the request. - public let clientID: ObjectIdentifier - - /// The request parameters. - public let params: Params - - public init(_ notification: Params, clientID: ObjectIdentifier) { - self.clientID = clientID - self.params = notification - } -} - fileprivate extension Encodable { var prettyPrintJSON: String { let encoder = JSONEncoder() @@ -123,16 +106,24 @@ extension Request: CustomStringConvertible, CustomLogStringConvertible { } } -extension Notification: CustomStringConvertible, CustomLogStringConvertible { +fileprivate struct AnyNotificationType: CustomLogStringConvertible { + let notification: any NotificationType + public var description: String { return """ - \(N.method) - \(params.prettyPrintJSON) + \(type(of: notification)) + \(notification.prettyPrintJSON) """ } public var redactedDescription: String { // FIXME: (logging) Log the non-critical parts of the notification - return "Notification<\(N.method)>" + return "\(type(of: notification))" + } +} + +extension NotificationType { + public var forLogging: CustomLogStringConvertibleWrapper { + return AnyNotificationType(notification: self).forLogging } } diff --git a/Sources/SKCore/BuildServerBuildSystem.swift b/Sources/SKCore/BuildServerBuildSystem.swift index 5eff1bf6..97176f08 100644 --- a/Sources/SKCore/BuildServerBuildSystem.swift +++ b/Sources/SKCore/BuildServerBuildSystem.swift @@ -193,9 +193,9 @@ public actor BuildServerBuildSystem: MessageHandler { public nonisolated func handle(_ params: some NotificationType, from clientID: ObjectIdentifier) { bspMessageHandlingQueue.async { if let params = params as? BuildTargetsChangedNotification { - await self.handleBuildTargetsChanged(Notification(params, clientID: clientID)) + await self.handleBuildTargetsChanged(params) } else if let params = params as? FileOptionsChangedNotification { - await self.handleFileOptionsChanged(Notification(params, clientID: clientID)) + await self.handleFileOptionsChanged(params) } } } @@ -213,20 +213,20 @@ public actor BuildServerBuildSystem: MessageHandler { } func handleBuildTargetsChanged( - _ notification: LanguageServerProtocol.Notification + _ notification: BuildTargetsChangedNotification ) async { - await self.delegate?.buildTargetsChanged(notification.params.changes) + await self.delegate?.buildTargetsChanged(notification.changes) } func handleFileOptionsChanged( - _ notification: LanguageServerProtocol.Notification + _ notification: FileOptionsChangedNotification ) async { - let result = notification.params.updatedOptions + let result = notification.updatedOptions let settings = FileBuildSettings( compilerArguments: result.options, workingDirectory: result.workingDirectory ) - await self.buildSettingsChanged(for: notification.params.uri, settings: settings) + await self.buildSettingsChanged(for: notification.uri, settings: settings) } /// Record the new build settings for the given document and inform the delegate diff --git a/Sources/SourceKitLSP/Clang/ClangLanguageServer.swift b/Sources/SourceKitLSP/Clang/ClangLanguageServer.swift index afcba80c..f98f5986 100644 --- a/Sources/SourceKitLSP/Clang/ClangLanguageServer.swift +++ b/Sources/SourceKitLSP/Clang/ClangLanguageServer.swift @@ -274,7 +274,7 @@ actor ClangLanguageServerShim: ToolchainLanguageServer, MessageHandler { clangdMessageHandlingQueue.async { switch params { case let publishDiags as PublishDiagnosticsNotification: - await self.publishDiagnostics(Notification(publishDiags, clientID: clientID)) + await self.publishDiagnostics(publishDiags) default: // We don't know how to handle any other notifications and ignore them. logger.error("Ignoring unknown notification \(type(of: params))") @@ -367,8 +367,7 @@ extension ClangLanguageServerShim { /// Intercept clangd's `PublishDiagnosticsNotification` to withold it if we're using fallback /// build settings. - func publishDiagnostics(_ note: Notification) async { - let params = note.params + func publishDiagnostics(_ notification: PublishDiagnosticsNotification) async { // Technically, the publish diagnostics notification could still originate // from when we opened the file with fallback build settings and we could // have received real build settings since, which haven't been acknowledged @@ -380,7 +379,7 @@ extension ClangLanguageServerShim { // short and we expect clangd to send us new diagnostics with the updated // non-fallback settings very shortly after, which will override the // incorrect result, making it very temporary. - let buildSettings = await self.buildSettings(for: params.uri) + let buildSettings = await self.buildSettings(for: notification.uri) guard let sourceKitServer else { logger.fault("Cannot publish diagnostics because SourceKitServer has been destroyed") return @@ -389,13 +388,13 @@ extension ClangLanguageServerShim { // Fallback: send empty publish notification instead. await sourceKitServer.sendNotificationToClient( PublishDiagnosticsNotification( - uri: params.uri, - version: params.version, + uri: notification.uri, + version: notification.version, diagnostics: [] ) ) } else { - await sourceKitServer.sendNotificationToClient(note.params) + await sourceKitServer.sendNotificationToClient(notification) } } diff --git a/Sources/SourceKitLSP/SourceKitServer.swift b/Sources/SourceKitLSP/SourceKitServer.swift index 65fe9983..909186a1 100644 --- a/Sources/SourceKitLSP/SourceKitServer.swift +++ b/Sources/SourceKitLSP/SourceKitServer.swift @@ -617,9 +617,7 @@ extension SourceKitServer: MessageHandler { } } - private func handleImpl(_ params: some NotificationType, from clientID: ObjectIdentifier) async { - let notification = Notification(params, clientID: clientID) - + private func handleImpl(_ notification: some NotificationType, from clientID: ObjectIdentifier) async { logger.log( """ Received notification @@ -627,7 +625,7 @@ extension SourceKitServer: MessageHandler { """ ) - switch notification.params { + switch notification { case let notification as InitializedNotification: self.clientInitialized(notification) case let notification as CancelRequestNotification: @@ -2013,7 +2011,6 @@ private let minWorkspaceSymbolPatternLength = 3 /// The maximum number of results to return from a `workspace/symbol` request. private let maxWorkspaceSymbolResults = 4096 -public typealias Notification = LanguageServerProtocol.Notification public typealias Diagnostic = LanguageServerProtocol.Diagnostic extension IndexSymbolKind { diff --git a/Tests/LanguageServerProtocolJSONRPCTests/ConnectionTests.swift b/Tests/LanguageServerProtocolJSONRPCTests/ConnectionTests.swift index 919356e8..8e44744f 100644 --- a/Tests/LanguageServerProtocolJSONRPCTests/ConnectionTests.swift +++ b/Tests/LanguageServerProtocolJSONRPCTests/ConnectionTests.swift @@ -19,9 +19,6 @@ import XCTest import WinSDK #endif -// Workaround ambiguity with Foundation. -typealias Notification = LanguageServerProtocol.Notification - class ConnectionTests: XCTestCase { var connection: TestJSONRPCConnection! = nil @@ -60,8 +57,8 @@ class ConnectionTests: XCTestCase { let clientConnection = connection.clientConnection let expectation = self.expectation(description: "note received") - client.appendOneShotNotificationHandler { (note: Notification) in - XCTAssertEqual(note.params.string, "hello!") + client.appendOneShotNotificationHandler { (note: EchoNotification) in + XCTAssertEqual(note.string, "hello!") expectation.fulfill() } @@ -83,8 +80,8 @@ class ConnectionTests: XCTestCase { let expectation2 = self.expectation(description: "note received") - client.appendOneShotNotificationHandler { (note: Notification) in - XCTAssertEqual(note.params.string, "no way!") + client.appendOneShotNotificationHandler { (note: EchoNotification) in + XCTAssertEqual(note.string, "no way!") expectation2.fulfill() } @@ -125,8 +122,8 @@ class ConnectionTests: XCTestCase { let client = connection.client let expectation = self.expectation(description: "note received") - client.appendOneShotNotificationHandler { (note: Notification) in - XCTAssertEqual(note.params.string, "hello!") + client.appendOneShotNotificationHandler { (note: EchoNotification) in + XCTAssertEqual(note.string, "hello!") expectation.fulfill() } @@ -218,7 +215,7 @@ class ConnectionTests: XCTestCase { let server = connection.server let expectation = self.expectation(description: "received notification") - client.appendOneShotNotificationHandler { (note: Notification) in + client.appendOneShotNotificationHandler { (note: EchoNotification) in expectation.fulfill() } @@ -232,7 +229,7 @@ class ConnectionTests: XCTestCase { let client = connection.client let expectation = self.expectation(description: "received notification") - client.appendOneShotNotificationHandler { (note: Notification) in + client.appendOneShotNotificationHandler { (note: EchoNotification) in expectation.fulfill() } let notification = EchoNotification(string: "about to close!") diff --git a/Tests/LanguageServerProtocolTests/ConnectionTests.swift b/Tests/LanguageServerProtocolTests/ConnectionTests.swift index bc7e9b03..943d9bf9 100644 --- a/Tests/LanguageServerProtocolTests/ConnectionTests.swift +++ b/Tests/LanguageServerProtocolTests/ConnectionTests.swift @@ -14,9 +14,6 @@ import LSPTestSupport import LanguageServerProtocol import XCTest -// Workaround ambiguity with Foundation. -typealias Notification = LanguageServerProtocol.Notification - class ConnectionTests: XCTestCase { var connection: TestLocalConnection! = nil @@ -68,8 +65,8 @@ class ConnectionTests: XCTestCase { let client = connection.client let expectation = self.expectation(description: "note received") - client.appendOneShotNotificationHandler { (note: Notification) in - XCTAssertEqual(note.params.string, "hello!") + client.appendOneShotNotificationHandler { (note: EchoNotification) in + XCTAssertEqual(note.string, "hello!") expectation.fulfill() } diff --git a/Tests/SourceKitLSPTests/BuildSystemTests.swift b/Tests/SourceKitLSPTests/BuildSystemTests.swift index 82bf227f..28a8230d 100644 --- a/Tests/SourceKitLSPTests/BuildSystemTests.swift +++ b/Tests/SourceKitLSPTests/BuildSystemTests.swift @@ -25,9 +25,6 @@ fileprivate extension SourceKitServer { } } -// Workaround ambiguity with Foundation. -typealias LSPNotification = LanguageServerProtocol.Notification - /// Build system to be used for testing BuildSystem and BuildSystemDelegate functionality with SourceKitServer /// and other components. final class TestBuildSystem: BuildSystem { diff --git a/Tests/SourceKitLSPTests/LocalSwiftTests.swift b/Tests/SourceKitLSPTests/LocalSwiftTests.swift index 5e2d2512..0dd90dda 100644 --- a/Tests/SourceKitLSPTests/LocalSwiftTests.swift +++ b/Tests/SourceKitLSPTests/LocalSwiftTests.swift @@ -20,9 +20,6 @@ import SwiftParser import SwiftSyntax import XCTest -// Workaround ambiguity with Foundation. -typealias Notification = LanguageServerProtocol.Notification - final class LocalSwiftTests: XCTestCase { private let quickFixCapabilities = ClientCapabilities( textDocument: TextDocumentClientCapabilities(