diff --git a/client/src/common/workspaceFolder.ts b/client/src/common/workspaceFolder.ts index c97c2ff02..62564c22e 100644 --- a/client/src/common/workspaceFolder.ts +++ b/client/src/common/workspaceFolder.ts @@ -7,10 +7,10 @@ import * as UUID from './utils/uuid'; import { workspace, Disposable, WorkspaceFolder as VWorkspaceFolder, WorkspaceFoldersChangeEvent as VWorkspaceFoldersChangeEvent } from 'vscode'; -import { DynamicFeature, RegistrationData, FeatureClient, NextSignature, FeatureState } from './features'; +import { DynamicFeature, RegistrationData, FeatureClient, NextSignature, FeatureState, ensure } from './features'; import { - ClientCapabilities, InitializeParams, CancellationToken, ServerCapabilities, WorkspaceFoldersRequest, WorkspaceFolder, - DidChangeWorkspaceFoldersNotification, DidChangeWorkspaceFoldersParams, RegistrationType + ClientCapabilities, WorkspaceFoldersClientCapabilities, InitializeParams, CancellationToken, ServerCapabilities, WorkspaceFoldersRequest, WorkspaceFolder, + DidChangeWorkspaceFoldersNotification, DidChangeWorkspaceFoldersParams, RegistrationType, } from 'vscode-languageserver-protocol'; function access(target: T | undefined, key: K): T[K] | undefined { @@ -68,8 +68,8 @@ export class WorkspaceFoldersFeature implements DynamicFeature { } public fillClientCapabilities(capabilities: ClientCapabilities): void { - capabilities.workspace = capabilities.workspace || {}; - capabilities.workspace.workspaceFolders = true; + const workspaceFoldersSupport = ensure(ensure(ensure(capabilities, 'workspace')!, 'workspaceFolders')! as WorkspaceFoldersClientCapabilities, 'changeNotifications')!; + workspaceFoldersSupport.dynamicRegistration = true; } public initialize(capabilities: ServerCapabilities): void { diff --git a/protocol/metaModel.json b/protocol/metaModel.json index 9830cdda4..ab2602496 100644 --- a/protocol/metaModel.json +++ b/protocol/metaModel.json @@ -2081,6 +2081,7 @@ "method": "workspace/didChangeWorkspaceFolders", "typeName": "DidChangeWorkspaceFoldersNotification", "messageDirection": "clientToServer", + "clientCapability": "workspace.workspaceFolders.changeNotifications", "serverCapability": "workspace.workspaceFolders.changeNotifications", "params": { "kind": "reference", @@ -11206,8 +11207,17 @@ { "name": "workspaceFolders", "type": { - "kind": "base", - "name": "boolean" + "kind": "or", + "items": [ + { + "kind": "base", + "name": "boolean" + }, + { + "kind": "reference", + "name": "WorkspaceFoldersClientCapabilities" + } + ] }, "optional": true, "documentation": "The client has support for workspace folders.\n\n@since 3.6.0", @@ -12256,6 +12266,33 @@ ], "documentation": "The client capabilities of a {@link ExecuteCommandRequest}." }, + { + "name": "WorkspaceFoldersClientCapabilities", + "properties": [ + { + "name": "changeNotifications", + "type": { + "kind": "literal", + "value": { + "properties": [ + { + "name": "dynamicRegistration", + "type": { + "kind": "base", + "name": "boolean" + }, + "optional": true, + "documentation": "Whether the client supports dynamic registration for the\n`workspace/didChangeWorkspaceFolders` notification." + } + ] + } + }, + "optional": true, + "documentation": "The client has support for workspace folder change notifications.\n\n@since 3.18.0", + "since": "3.18.0" + } + ] + }, { "name": "SemanticTokensWorkspaceClientCapabilities", "properties": [ diff --git a/protocol/src/common/protocol.ts b/protocol/src/common/protocol.ts index cbea662f4..e484b6a8f 100644 --- a/protocol/src/common/protocol.ts +++ b/protocol/src/common/protocol.ts @@ -31,7 +31,7 @@ import { import { WorkspaceFoldersRequest, DidChangeWorkspaceFoldersNotification, DidChangeWorkspaceFoldersParams, - WorkspaceFoldersChangeEvent, WorkspaceFoldersInitializeParams, WorkspaceFoldersServerCapabilities + WorkspaceFoldersChangeEvent, WorkspaceFoldersInitializeParams, WorkspaceFoldersClientCapabilities, WorkspaceFoldersServerCapabilities } from './protocol.workspaceFolder'; import { @@ -605,7 +605,7 @@ export interface WorkspaceClientCapabilities { * * @since 3.6.0 */ - workspaceFolders?: boolean; + workspaceFolders?: boolean | WorkspaceFoldersClientCapabilities; /** * The client supports `workspace/configuration` requests. @@ -4404,7 +4404,9 @@ export { InlineCompletionClientCapabilities, InlineCompletionOptions, InlineCompletionParams, InlineCompletionRegistrationOptions, InlineCompletionRequest, // Text Document Content TextDocumentContentClientCapabilities, TextDocumentContentOptions, TextDocumentContentRegistrationOptions, TextDocumentContentParams, TextDocumentContentResult, - TextDocumentContentRequest, TextDocumentContentRefreshParams, TextDocumentContentRefreshRequest + TextDocumentContentRequest, TextDocumentContentRefreshParams, TextDocumentContentRefreshRequest, + // Workspace Folders + WorkspaceFoldersClientCapabilities }; // To be backwards compatible diff --git a/protocol/src/common/protocol.workspaceFolder.ts b/protocol/src/common/protocol.workspaceFolder.ts index 5fcdefb13..78ef6343d 100644 --- a/protocol/src/common/protocol.workspaceFolder.ts +++ b/protocol/src/common/protocol.workspaceFolder.ts @@ -21,6 +21,21 @@ export interface WorkspaceFoldersInitializeParams { workspaceFolders?: WorkspaceFolder[] | null; } +export interface WorkspaceFoldersClientCapabilities { + /** + * The client has support for workspace folder change notifications. + * + * @since 3.18.0 + */ + changeNotifications?: { + /** + * Whether the client supports dynamic registration for the + * `workspace/didChangeWorkspaceFolders` notification. + */ + dynamicRegistration?: boolean; + }; +} + export interface WorkspaceFoldersServerCapabilities { /** @@ -62,7 +77,7 @@ export namespace DidChangeWorkspaceFoldersNotification { export const type = new ProtocolNotificationType(method); export type HandlerSignature = NotificationHandler; export type MiddlewareSignature = (params: DidChangeWorkspaceFoldersParams, next: HandlerSignature) => void; - export const capabilities = CM.create(undefined, 'workspace.workspaceFolders.changeNotifications'); + export const capabilities = CM.create('workspace.workspaceFolders.changeNotifications', 'workspace.workspaceFolders.changeNotifications'); } /** diff --git a/server/src/common/workspaceFolder.ts b/server/src/common/workspaceFolder.ts index b3a3b345b..7d3bd71d5 100644 --- a/server/src/common/workspaceFolder.ts +++ b/server/src/common/workspaceFolder.ts @@ -6,7 +6,7 @@ import { Event, Emitter, Disposable, ClientCapabilities, WorkspaceFolder, WorkspaceFoldersChangeEvent, DidChangeWorkspaceFoldersNotification, - WorkspaceFoldersRequest, ServerCapabilities + WorkspaceFoldersRequest, ServerCapabilities, WorkspaceFoldersClientCapabilities } from 'vscode-languageserver-protocol'; import type { Feature, _RemoteWorkspace } from './server'; @@ -28,7 +28,7 @@ export const WorkspaceFoldersFeature: Feature<_RemoteWorkspace, WorkspaceFolders public initialize(capabilities: ClientCapabilities): void { super.initialize(capabilities); const workspaceCapabilities = capabilities.workspace; - if (workspaceCapabilities && workspaceCapabilities.workspaceFolders) { + if (workspaceCapabilities && (workspaceCapabilities.workspaceFolders as WorkspaceFoldersClientCapabilities).changeNotifications) { this._onDidChangeWorkspaceFolders = new Emitter(); this.connection.onNotification(DidChangeWorkspaceFoldersNotification.type, (params) => { this._onDidChangeWorkspaceFolders!.fire(params.event); @@ -53,4 +53,4 @@ export const WorkspaceFoldersFeature: Feature<_RemoteWorkspace, WorkspaceFolders return this._onDidChangeWorkspaceFolders.event; } }; -}; \ No newline at end of file +};