diff --git a/Contributor Documentation/BSP Extensions.md b/Contributor Documentation/BSP Extensions.md index 88c234fbd..37265f3f3 100644 --- a/Contributor Documentation/BSP Extensions.md +++ b/Contributor Documentation/BSP Extensions.md @@ -28,7 +28,7 @@ export interface SourceKitInitializeBuildResponseData { /** Whether the build server supports the `buildTarget/prepare` request */ prepareProvider?: bool; - /** Whether the server implements the `textDocument/sourceKitOptions` request. */ + /** Whether the server implements the `sourcekit/textDocument/sourceKitOptions` request. */ sourceKitOptionsProvider?: bool; /** The files to watch for changes. @@ -91,7 +91,7 @@ If `data` contains a string value for the `workDoneProgressTitle` key, then the `changes` can be `null` to indicate that all targets have changed. -## `buildTarget/prepare` +## `sourcekit/buildTarget/prepare` The prepare build target request is sent from the client to the server to prepare the given list of build targets for editor functionality. @@ -99,10 +99,13 @@ To do so, the build server should perform any work that is necessary to typechec The server communicates during the initialize handshake whether this method is supported or not by setting `prepareProvider: true` in `SourceKitInitializeBuildResponseData`. -- method: `buildTarget/prepare` +- method: `sourcekit/buildTarget/prepare` - params: `PrepareParams` - result: `void` +> [!NOTE] +> This request was previously named `buildTarget/prepare`. The old name is still accepted for backward compatibility. + ```ts export interface PrepareParams { /** A list of build targets to prepare. */ @@ -156,7 +159,7 @@ export interface SourceKitSourceItemData { } ``` -## `textDocument/sourceKitOptions` +## `sourcekit/textDocument/sourceKitOptions` The `TextDocumentSourceKitOptionsRequest` request is sent from the client to the server to query for the list of compiler options necessary to compile this file in the given target. @@ -164,10 +167,15 @@ The build settings are considered up-to-date and can be cached by SourceKit-LSP The request may return `nil` if it doesn't have any build settings for this file in the given target. -- method: `textDocument/sourceKitOptions` +- method: `sourcekit/textDocument/sourceKitOptions` - params: `TextDocumentSourceKitOptionsParams` - result: `TextDocumentSourceKitOptionsResult` +> [!NOTE] +> This request was previously named `textDocument/sourceKitOptions`. The old name is still accepted for backward compatibility. + +Also note that the `data` field in `TextDocumentSourceKitOptionsResult` is exposed to LSP clients via `sourcekit/workspace/sourceKitOptions` (previously `workspace/_sourceKitOptions`). + ```ts export interface TextDocumentSourceKitOptionsRequest { /** The URI of the document to get options for */ @@ -236,10 +244,13 @@ SourceKit-LSP may send file change notifications for a superset of the files tha Definition is the same as in LSP. -## `workspace/waitForBuildSystemUpdates` +## `sourcekit/workspace/waitForBuildSystemUpdates` This request is a no-op and doesn't have any effects. If the build server is currently updating the build graph, this request should return after those updates have finished processing. -- method: `workspace/waitForBuildSystemUpdates` +- method: `sourcekit/workspace/waitForBuildSystemUpdates` + +> [!NOTE] +> This request was previously named `workspace/waitForBuildSystemUpdates`. The old name is still accepted for backward compatibility. diff --git a/Contributor Documentation/LSP Extensions.md b/Contributor Documentation/LSP Extensions.md index bb50e437c..aa38d48fe 100644 --- a/Contributor Documentation/LSP Extensions.md +++ b/Contributor Documentation/LSP Extensions.md @@ -103,10 +103,13 @@ interface SKCompletionOptions { } ``` -## `textDocument/doccDocumentation` +## `sourcekit/textDocument/doccDocumentation` New request that generates documentation for a symbol at a given cursor location. +> [!NOTE] +> This request was previously named `textDocument/doccDocumentation`. The old name is still accepted for backward compatibility. + Primarily designed to support live preview of Swift documentation in editors. This request looks up the nearest documentable symbol (if any) at a given cursor location within @@ -124,7 +127,7 @@ failed LSP error code (-32803) that contains a human-readable error message. Thi be displayed within the live preview editor to indicate that something has gone wrong. At the moment this request is only available on macOS and Linux. SourceKit-LSP will advertise -`textDocument/doccDocumentation` in its experimental server capabilities if it supports it. +`sourcekit/textDocument/doccDocumentation` in its experimental server capabilities if it supports it. - params: `DoccDocumentationParams` - result: `DoccDocumentationResponse` @@ -285,10 +288,13 @@ interface SymbolDetails { } ``` -## `textDocument/tests` +## `sourcekit/textDocument/tests` New request that returns symbols for all the test classes and test methods within a file. +> [!NOTE] +> This request was previously named `textDocument/tests`. The old name is still accepted for backward compatibility. + - params: `DocumentTestsParams` - result: `TestItem[]` @@ -368,10 +374,13 @@ export interface DocumentTestsParams { } ``` -## `sourceKit/_isIndexing` +## `sourcekit/isIndexing` Request from the client to the server querying whether SourceKit-LSP is currently performing an background indexing tasks, including target preparation. +> [!NOTE] +> This request was previously named `sourceKit/_isIndexing`. The old name is still accepted for backward compatibility. + > [!IMPORTANT] > This request is experimental and may be modified or removed in future versions of SourceKit-LSP without notice. Do not rely on it. @@ -448,7 +457,7 @@ export interface WorkspaceSymbolNamesResult { } ``` -## `window/didChangeActiveDocument` +## `sourcekit/window/didChangeActiveDocument` New notification from the client to the server, telling SourceKit-LSP which document is the currently active primary document. @@ -456,10 +465,13 @@ This notification should only be called for documents that the editor has opened By default, SourceKit-LSP infers the currently active editor document from the last document that received a request. If the client supports active reporting of the currently active document, it should check for the -`window/didChangeActiveDocument` experimental server capability. If that capability is present, it should respond with -the `window/didChangeActiveDocument` experimental client capability and send this notification whenever the currently +`sourcekit/window/didChangeActiveDocument` experimental server capability. If that capability is present, it should respond with +the `sourcekit/window/didChangeActiveDocument` experimental client capability and send this notification whenever the currently active document changes. +> [!NOTE] +> This notification was previously named `window/didChangeActiveDocument`. The old name is still accepted for backward compatibility. + - params: `DidChangeActiveDocumentParams` ```ts @@ -533,12 +545,15 @@ export interface StructuredLogEnd { } ``` -## `workspace/_setOptions` +## `sourcekit/workspace/setOptions` New request to modify runtime options of SourceKit-LSP. Any options not specified in this request will be left as-is. +> [!NOTE] +> This request was previously named `workspace/_setOptions`. The old name is still accepted for backward compatibility. + > [!IMPORTANT] > This request is experimental, guarded behind the `set-options-request` experimental feature, and may be modified or removed in future versions of SourceKit-LSP without notice. Do not rely on it. @@ -554,12 +569,15 @@ export interface SetOptionsParams { } ``` -## `workspace/_sourceKitOptions` +## `sourcekit/workspace/sourceKitOptions` New request from the client to the server to retrieve the compiler arguments that SourceKit-LSP uses to process the document. This request does not require the document to be opened in SourceKit-LSP. This is also why it has the `workspace/` instead of the `textDocument/` prefix. +> [!NOTE] +> This request was previously named `workspace/_sourceKitOptions`. The old name is still accepted for backward compatibility. + > [!IMPORTANT] > This request is experimental, guarded behind the `sourcekit-options-request` experimental feature, and may be modified or removed in future versions of SourceKit-LSP without notice. Do not rely on it. @@ -651,12 +669,15 @@ export interface SourceKitOptionsResult { } ``` -## `workspace/_outputPaths` +## `sourcekit/workspace/outputPaths` New request from the client to the server to retrieve the output paths of a target (see the `buildTarget/outputPaths` BSP request). This request will only succeed if the build server supports the `buildTarget/outputPaths` request. +> [!NOTE] +> This request was previously named `workspace/_outputPaths`. The old name is still accepted for backward compatibility. + > [!IMPORTANT] > This request is experimental, guarded behind the `output-paths-request` experimental feature, and may be modified or removed in future versions of SourceKit-LSP without notice. Do not rely on it. @@ -685,12 +706,15 @@ export interface OutputPathsResult { } ``` -## `workspace/getReferenceDocument` +## `sourcekit/workspace/getReferenceDocument` Request from the client to the server asking for contents of a URI having a custom scheme. For example: "sourcekit-lsp:" -Enable the experimental client capability `"workspace/getReferenceDocument"` so that the server responds with reference document URLs for certain requests or commands whenever possible. +Enable the experimental client capability `"sourcekit/workspace/getReferenceDocument"` so that the server responds with reference document URLs for certain requests or commands whenever possible. + +> [!NOTE] +> This request was previously named `workspace/getReferenceDocument`. The old name is still accepted for backward compatibility. - params: `GetReferenceDocumentParams` @@ -712,13 +736,16 @@ export interface GetReferenceDocumentResult { } ``` -## `workspace/peekDocuments` +## `sourcekit/workspace/peekDocuments` Request from the server to the client to show the given documents in a "peeked" editor. This request is handled by the client to show the given documents in a "peeked" editor (i.e. inline with / inside the editor canvas). -It requires the experimental client capability `"workspace/peekDocuments"` to use. +It requires the experimental client capability `"sourcekit/workspace/peekDocuments"` to use. + +> [!NOTE] +> This request was previously named `workspace/peekDocuments`. The old name is still accepted for backward compatibility. - params: `PeekDocumentsParams` - result: `PeekDocumentsResult` @@ -749,7 +776,7 @@ export interface PeekDocumentsResult { } ``` -## `workspace/playgrounds` +## `sourcekit/workspace/playgrounds` New request for returning the list of all #Playground macros in the workspace. @@ -758,9 +785,12 @@ jumping to the locations where the #Playground macro was expanded. The request fetches the list of all macros found in the workspace, returning the location, identifier, and optional label when available for each #Playground macro expansion. If you want to keep the list of playgrounds up to date without needing to -call `workspace/playgrounds` each time a document is changed, you can filter for `swift.play` CodeLens returned by the `textDocument/codelens` request. +call `sourcekit/workspace/playgrounds` each time a document is changed, you can filter for `swift.play` CodeLens returned by the `textDocument/codelens` request. + +SourceKit-LSP will advertise `sourcekit/workspace/playgrounds` in its experimental server capabilities if it supports it. -SourceKit-LSP will advertise `workspace/playgrounds` in its experimental server capabilities if it supports it. +> [!NOTE] +> This request was previously named `workspace/playgrounds`. The old name is still accepted for backward compatibility. - params: `WorkspacePlaygroundParams` - result: `Playground[]` @@ -795,10 +825,13 @@ export interface Playground { } ``` -## `workspace/synchronize` +## `sourcekit/workspace/synchronize` Request from the client to the server to wait for SourceKit-LSP to handle all ongoing requests and, optionally, wait for background activity to finish. +> [!NOTE] +> This request was previously named `workspace/synchronize`. The old name is still accepted for backward compatibility. + This method is intended to be used in automated environments which need to wait for background activity to finish before executing requests that rely on that background activity to finish. Examples of such cases are: - Automated tests that need to wait for background indexing to finish and then checking the result of request results - Automated tests that need to wait for requests like file changes to be handled and checking behavior after those have been processed @@ -837,10 +870,13 @@ export interface SynchronizeParams { } ``` -## `workspace/tests` +## `sourcekit/workspace/tests` New request that returns symbols for all the test classes and test methods within the current workspace. +> [!NOTE] +> This request was previously named `workspace/tests`. The old name is still accepted for backward compatibility. + - params: `WorkspaceTestsParams` - result: `TestItem[]` @@ -848,12 +884,15 @@ New request that returns symbols for all the test classes and test methods withi export interface WorkspaceTestsParams {} ``` -## `workspace/triggerReindex` +## `sourcekit/workspace/triggerReindex` New request to re-index all files open in the SourceKit-LSP server. Users should not need to rely on this request. The index should always be updated automatically in the background. Having to invoke this request means there is a bug in SourceKit-LSP's automatic re-indexing. It does, however, offer a workaround to re-index files when such a bug occurs where otherwise there would be no workaround. +> [!NOTE] +> This request was previously named `workspace/triggerReindex`. The old name is still accepted for backward compatibility. + - params: `TriggerReindexParams` - result: `void` diff --git a/Sources/BuildServerIntegration/BuildServerManager.swift b/Sources/BuildServerIntegration/BuildServerManager.swift index 4471fd2da..cb72efc19 100644 --- a/Sources/BuildServerIntegration/BuildServerManager.swift +++ b/Sources/BuildServerIntegration/BuildServerManager.swift @@ -628,13 +628,29 @@ package actor BuildServerManager: QueueBasedMessageHandler { } let initializeResponse: InitializeBuildResponse? do { + var experimentalCapabilities: [String: LSPAny] = [:] + func addCapability(_ method: String, _ value: LSPAny) { + experimentalCapabilities[method] = value + if let legacy = MessageRegistry.bspLegacyNames[method] { + experimentalCapabilities[legacy] = value + } + } + // client -> server + addCapability(BuildTargetPrepareRequest.method, .dictionary(["version": .int(1)])) + addCapability(TextDocumentSourceKitOptionsRequest.method, .dictionary(["version": .int(1)])) + addCapability(WorkspaceWaitForBuildSystemUpdatesRequest.method, .dictionary(["version": .int(1)])) + // server -> client + addCapability(FileOptionsChangedNotification.method, .dictionary(["version": .int(1)])) initializeResponse = try await buildServerAdapter.send( InitializeBuildRequest( displayName: "SourceKit-LSP", version: "", bspVersion: "2.2.0", rootUri: URI(buildServerSpec.projectRoot), - capabilities: BuildClientCapabilities(languageIds: [.c, .cpp, .objective_c, .objective_cpp, .swift]) + capabilities: BuildClientCapabilities( + languageIds: [.c, .cpp, .objective_c, .objective_cpp, .swift], + experimental: .dictionary(experimentalCapabilities) + ) ) ) } catch { diff --git a/Sources/BuildServerIntegration/ExternalBuildServerAdapter.swift b/Sources/BuildServerIntegration/ExternalBuildServerAdapter.swift index f3cc80bc0..19d44f1a3 100644 --- a/Sources/BuildServerIntegration/ExternalBuildServerAdapter.swift +++ b/Sources/BuildServerIntegration/ExternalBuildServerAdapter.swift @@ -190,7 +190,7 @@ actor ExternalBuildServerAdapter { var messagesToSourceKitLSPHandler: any MessageHandler /// The JSON-RPC connection between SourceKit-LSP and the BSP server. - private(set) var connectionToBuildServer: JSONRPCConnection? + private(set) var connectionToBuildServer: LegacyNameFallbackConnection? /// After a `build/initialize` request has been sent to the BSP server, that request, so we can replay it in case the /// server crashes. @@ -223,7 +223,10 @@ actor ExternalBuildServerAdapter { self.projectRoot = projectRoot self.serverConfig = config self.messagesToSourceKitLSPHandler = messagesToSourceKitLSPHandler - self.connectionToBuildServer = try await self.createConnectionToBspServer() + self.connectionToBuildServer = LegacyNameFallbackConnection( + try await self.createConnectionToBspServer(), + legacyNames: MessageRegistry.bspLegacyNames + ) } init( @@ -400,7 +403,10 @@ actor ExternalBuildServerAdapter { // crash recovery and doesn't need to gain it because it is deprecated). _ = try await restartedConnection.send(initializeRequest) restartedConnection.send(OnBuildInitializedNotification()) - self.connectionToBuildServer = restartedConnection + self.connectionToBuildServer = LegacyNameFallbackConnection( + restartedConnection, + legacyNames: MessageRegistry.bspLegacyNames + ) // The build targets might have changed after the restart. Send a `buildTarget/didChange` notification to // SourceKit-LSP to discard cached information. diff --git a/Sources/BuildServerIntegration/LegacyBuildServer.swift b/Sources/BuildServerIntegration/LegacyBuildServer.swift index e350a07a9..96e13361c 100644 --- a/Sources/BuildServerIntegration/LegacyBuildServer.swift +++ b/Sources/BuildServerIntegration/LegacyBuildServer.swift @@ -34,7 +34,7 @@ import ToolsProtocolsSwiftExtensions /// This build server should be phased out in favor of the pull-based settings model described in /// https://forums.swift.org/t/extending-functionality-of-build-server-protocol-with-sourcekit-lsp/74400 actor LegacyBuildServer: MessageHandler, BuiltInBuildServer { - private var buildServer: JSONRPCConnection? + private var buildServer: (any Connection)? /// The queue on which all messages that originate from the build server are /// handled. diff --git a/Sources/LanguageServerProtocolExtensions/CMakeLists.txt b/Sources/LanguageServerProtocolExtensions/CMakeLists.txt index 6a488b5d0..0b2a27668 100644 --- a/Sources/LanguageServerProtocolExtensions/CMakeLists.txt +++ b/Sources/LanguageServerProtocolExtensions/CMakeLists.txt @@ -1,6 +1,5 @@ add_library(LanguageServerProtocolExtensions STATIC - Connection+Send.swift DocumentURI+symlinkTarget.swift Language+Inference.swift ResponseError+Init.swift diff --git a/Sources/LanguageServerProtocolExtensions/Connection+Send.swift b/Sources/LanguageServerProtocolExtensions/Connection+Send.swift deleted file mode 100644 index 1118763be..000000000 --- a/Sources/LanguageServerProtocolExtensions/Connection+Send.swift +++ /dev/null @@ -1,38 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2023 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 -// -//===----------------------------------------------------------------------===// - -@_spi(SourceKitLSP) package import LanguageServerProtocol -import SwiftExtensions -@_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions - -extension Connection { - /// Send the given request to the connection and await its result. - /// - /// This method automatically sends a `CancelRequestNotification` to the - /// connection if the task it is executing in is being cancelled. - /// - /// - Warning: Because this message is `async`, it does not provide any ordering - /// guarantees. If you need to guarantee that messages are sent in-order - /// use the version with a completion handler. - // Disfavor this over Connection.send implemented in swift-tools-protocols by https://github.com/swiftlang/swift-tools-protocols/pull/28 - // TODO: Remove this file once we have updated the swift-tools-protocols dependency to include #28 - @_disfavoredOverload - package func send(_ request: R) async throws -> R.Response { - return try await withCancellableCheckedThrowingContinuation { continuation in - return self.send(request) { result in - continuation.resume(with: result) - } - } cancel: { requestID in - self.send(CancelRequestNotification(id: requestID)) - } - } -} diff --git a/Sources/LanguageServerProtocolExtensions/WorkDoneProgressManager.swift b/Sources/LanguageServerProtocolExtensions/WorkDoneProgressManager.swift index 58aacc500..0f1f3b933 100644 --- a/Sources/LanguageServerProtocolExtensions/WorkDoneProgressManager.swift +++ b/Sources/LanguageServerProtocolExtensions/WorkDoneProgressManager.swift @@ -12,6 +12,7 @@ import Foundation @_spi(SourceKitLSP) package import LanguageServerProtocol +import LanguageServerProtocolTransport @_spi(SourceKitLSP) import SKLogging import SwiftExtensions import ToolsProtocolsSwiftExtensions diff --git a/Sources/SKTestSupport/DummyBuildServerManagerConnectionToClient.swift b/Sources/SKTestSupport/DummyBuildServerManagerConnectionToClient.swift index f5ae164b8..e34f3ed67 100644 --- a/Sources/SKTestSupport/DummyBuildServerManagerConnectionToClient.swift +++ b/Sources/SKTestSupport/DummyBuildServerManagerConnectionToClient.swift @@ -29,6 +29,7 @@ package struct DummyBuildServerManagerConnectionToClient: BuildServerManagerConn package func send( _ request: Request, + method: String, id: RequestID, reply: @escaping @Sendable (LSPResult) -> Void ) { diff --git a/Sources/SourceKitLSP/CapabilityRegistry.swift b/Sources/SourceKitLSP/CapabilityRegistry.swift index 49e2fca6e..c3e6927cc 100644 --- a/Sources/SourceKitLSP/CapabilityRegistry.swift +++ b/Sources/SourceKitLSP/CapabilityRegistry.swift @@ -12,6 +12,7 @@ @_spi(SourceKitLSP) package import LanguageServerProtocol @_spi(SourceKitLSP) import LanguageServerProtocolExtensions +import LanguageServerProtocolTransport @_spi(SourceKitLSP) import SKLogging import SwiftExtensions @@ -104,14 +105,23 @@ package final actor CapabilityRegistry { package nonisolated var clientSupportsActiveDocumentNotification: Bool { return clientHasExperimentalCapability(DidChangeActiveDocumentNotification.method) + || MessageRegistry.lspLegacyNames[DidChangeActiveDocumentNotification.method].map { + clientHasExperimentalCapability($0) + } ?? false } package nonisolated var clientHasWorkspaceTestsRefreshSupport: Bool { return clientHasExperimentalCapability(WorkspaceTestsRefreshRequest.method) + || MessageRegistry.lspLegacyNames[WorkspaceTestsRefreshRequest.method].map { + clientHasExperimentalCapability($0) + } ?? false } package nonisolated var clientHasWorkspacePlaygroundsRefreshSupport: Bool { return clientHasExperimentalCapability(WorkspacePlaygroundsRefreshRequest.method) + || MessageRegistry.lspLegacyNames[WorkspacePlaygroundsRefreshRequest.method].map { + clientHasExperimentalCapability($0) + } ?? false } package nonisolated var clientHasWorkspaceGetReferenceDocumentSupport: Bool { diff --git a/Sources/SourceKitLSP/SourceKitLSPServer.swift b/Sources/SourceKitLSP/SourceKitLSPServer.swift index c9407bd43..83e82a67b 100644 --- a/Sources/SourceKitLSP/SourceKitLSPServer.swift +++ b/Sources/SourceKitLSP/SourceKitLSPServer.swift @@ -54,7 +54,7 @@ package actor SourceKitLSPServer { private let workspaceQueue = AsyncQueue() /// The connection to the editor. - package nonisolated let client: any Connection + nonisolated let client: LegacyNameFallbackConnection /// Set to `true` after the `SourceKitLSPServer` has send the reply to the `InitializeRequest`. /// @@ -179,7 +179,7 @@ package actor SourceKitLSPServer { self.hooks = hooks self.onExit = onExit - self.client = client + self.client = LegacyNameFallbackConnection(client, legacyNames: MessageRegistry.lspLegacyNames) self.indexTaskScheduler = TaskScheduler( maxConcurrentTasksByPriority: Self.maxConcurrentIndexingTasksByPriority(isIndexingPaused: false, options: options) ) @@ -1092,12 +1092,12 @@ extension SourceKitLSPServer { let onWorkspaceTestsChanged = capabilityRegistry!.clientHasWorkspaceTestsRefreshSupport ? { @Sendable [weak self] in - _ = Task { try await self?.client.send(WorkspaceTestsRefreshRequest()) } + _ = Task { try await self?.sendRequestToClient(WorkspaceTestsRefreshRequest()) } } : nil let onWorkspacePlaygroundsChanged = capabilityRegistry!.clientHasWorkspacePlaygroundsRefreshSupport ? { @Sendable [weak self] in - _ = Task { try await self?.client.send(WorkspacePlaygroundsRefreshRequest()) } + _ = Task { try await self?.sendRequestToClient(WorkspacePlaygroundsRefreshRequest()) } } : nil await entryPointManager.setCallbacks( onWorkspaceTestsChanged: onWorkspaceTestsChanged, @@ -1167,19 +1167,25 @@ extension SourceKitLSPServer { ? nil : ExecuteCommandOptions(commands: languageServiceRegistry.languageServices.flatMap { $0.type.builtInCommands }) - var experimentalCapabilities: [String: LSPAny] = [ - WorkspaceTestsRequest.method: ["version": 2], - WorkspaceTestsRefreshRequest.method: ["version": 1], - DocumentTestsRequest.method: ["version": 2], - TriggerReindexRequest.method: ["version": 1], - GetReferenceDocumentRequest.method: ["version": 1], - DidChangeActiveDocumentNotification.method: ["version": 1], - WorkspacePlaygroundsRefreshRequest.method: ["version": 1], - WorkspaceSymbolNamesRequest.method: ["version": 1], - WorkspaceSymbolInfoRequest.method: ["version": 1], - ] + var experimentalCapabilities: [String: LSPAny] = [:] + // Add both the current and legacy method names so old clients still discover the capability. + func addCapabilities(_ method: String, _ value: LSPAny) { + experimentalCapabilities[method] = value + if let legacy = MessageRegistry.lspLegacyNames[method] { experimentalCapabilities[legacy] = value } + } + addCapabilities(WorkspaceTestsRequest.method, ["version": 2]) + addCapabilities(WorkspaceTestsRefreshRequest.method, ["version": 1]) + addCapabilities(DocumentTestsRequest.method, ["version": 2]) + addCapabilities(DoccDocumentationRequest.method, ["version": 1]) + addCapabilities(TriggerReindexRequest.method, ["version": 1]) + addCapabilities(GetReferenceDocumentRequest.method, ["version": 1]) + addCapabilities(DidChangeActiveDocumentNotification.method, ["version": 1]) + addCapabilities(SynchronizeRequest.method, ["version": 1]) + addCapabilities(WorkspaceSymbolNamesRequest.method, ["version": 1]) + addCapabilities(WorkspaceSymbolInfoRequest.method, ["version": 1]) if let toolchain = await toolchainRegistry.preferredToolchain(containing: [\.swiftc]), toolchain.swiftPlay != nil { - experimentalCapabilities[WorkspacePlaygroundsRequest.method] = ["version": 1] + addCapabilities(WorkspacePlaygroundsRefreshRequest.method, ["version": 1]) + addCapabilities(WorkspacePlaygroundsRequest.method, ["version": 1]) } for (key, value) in languageServiceRegistry.languageServices.flatMap({ $0.type.experimentalCapabilities }) { if let existingValue = experimentalCapabilities[key] { diff --git a/Sources/SourceKitLSP/Workspace.swift b/Sources/SourceKitLSP/Workspace.swift index 142e23624..e7e98a0fe 100644 --- a/Sources/SourceKitLSP/Workspace.swift +++ b/Sources/SourceKitLSP/Workspace.swift @@ -16,6 +16,7 @@ import Foundation import IndexStoreDB @_spi(SourceKitLSP) package import LanguageServerProtocol @_spi(SourceKitLSP) import LanguageServerProtocolExtensions +import LanguageServerProtocolTransport @_spi(SourceKitLSP) import SKLogging import SKOptions package import SemanticIndex @@ -340,6 +341,7 @@ package final class Workspace: Sendable, BuildServerManagerDelegate { func send( _ request: Request, + method: String, id: RequestID, reply: @escaping @Sendable (LSPResult) -> Void ) { @@ -349,7 +351,7 @@ package final class Workspace: Sendable, BuildServerManagerDelegate { reply(.failure(ResponseError.unknown("Connection to the editor closed"))) return } - sourceKitLSPServer.client.send(request, id: id, reply: reply) + sourceKitLSPServer.client.send(request, method: method, id: id, reply: reply) } /// Whether the client can handle `WorkDoneProgress` requests.