diff --git a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart index 2a76affb6dd..5c387b4f026 100644 --- a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart +++ b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart @@ -57,7 +57,7 @@ class ClientDynamicRegistrations { _capabilities.textDocument?.callHierarchy?.dynamicRegistration ?? false; bool get codeActions => - _capabilities.textDocument?.foldingRange?.dynamicRegistration ?? false; + _capabilities.textDocument?.codeAction?.dynamicRegistration ?? false; bool get colorProvider => _capabilities.textDocument?.colorProvider?.dynamicRegistration ?? false; diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart index c9f79e250f1..a2ad0a87a68 100644 --- a/pkg/analysis_server/test/lsp/initialization_test.dart +++ b/pkg/analysis_server/test/lsp/initialization_test.dart @@ -35,6 +35,27 @@ class InitializationTest extends AbstractLspAnalysisServerTest { await pumpEventQueue(times: 5000); } + Future assertDynamicRegistration( + String name, Set expectedResult) async { + // Check that when the server calls client/registerCapability it only includes + // the items we advertised dynamic registration support for. + final registrations = []; + await monitorDynamicRegistrations( + registrations, + () => initialize( + textDocumentCapabilities: withGivenTextDocumentDynamicRegistrations( + emptyTextDocumentClientCapabilities, name), + workspaceCapabilities: withGivenWorkspaceDynamicRegistrations( + emptyWorkspaceClientCapabilities, name)), + ); + + final registeredMethods = + registrations.map((registration) => registration.method).toSet(); + final result = expectedResult.map((method) => method.toJson()).toSet(); + + expect(registeredMethods, equals(result)); + } + TextDocumentRegistrationOptions registrationOptionsFor( List registrations, Method method, @@ -243,6 +264,97 @@ class InitializationTest extends AbstractLspAnalysisServerTest { await Future.wait([registrationsDone, unregistrationsDone]); } + Future test_dynamicRegistration_config_allHierarchy() => + assertDynamicRegistration( + 'callHierarchy', {Method.textDocument_prepareCallHierarchy}); + + Future test_dynamicRegistration_config_codeAction() => + assertDynamicRegistration('codeAction', {Method.textDocument_codeAction}); + + Future test_dynamicRegistration_config_colorProvider() => + assertDynamicRegistration( + 'colorProvider', {Method.textDocument_documentColor}); + + Future test_dynamicRegistration_config_completion() => + assertDynamicRegistration('completion', {Method.textDocument_completion}); + + Future test_dynamicRegistration_config_definition() => + assertDynamicRegistration('definition', {Method.textDocument_definition}); + + Future test_dynamicRegistration_config_didChangeConfiguration() => + assertDynamicRegistration( + 'didChangeConfiguration', {Method.workspace_didChangeConfiguration}); + + Future test_dynamicRegistration_config_documentHighlight() => + assertDynamicRegistration( + 'documentHighlight', {Method.textDocument_documentHighlight}); + + Future test_dynamicRegistration_config_documentSymbol() => + assertDynamicRegistration( + 'documentSymbol', {Method.textDocument_documentSymbol}); + + Future test_dynamicRegistration_config_fileOperations() => + assertDynamicRegistration( + 'fileOperations', {Method.workspace_willRenameFiles}); + + Future test_dynamicRegistration_config_foldingRange() => + assertDynamicRegistration( + 'foldingRange', {Method.textDocument_foldingRange}); + + Future test_dynamicRegistration_config_formatting() => + assertDynamicRegistration('formatting', {Method.textDocument_formatting}); + + Future test_dynamicRegistration_config_hover() => + assertDynamicRegistration('hover', {Method.textDocument_hover}); + + Future test_dynamicRegistration_config_implementation() => + assertDynamicRegistration( + 'implementation', {Method.textDocument_implementation}); + + Future test_dynamicRegistration_config_inlayHint() => + assertDynamicRegistration('inlayHint', {Method.textDocument_inlayHint}); + + Future test_dynamicRegistration_config_onTypeFormatting() => + assertDynamicRegistration( + 'onTypeFormatting', {Method.textDocument_onTypeFormatting}); + + Future test_dynamicRegistration_config_rangeFormatting() => + assertDynamicRegistration( + 'rangeFormatting', {Method.textDocument_rangeFormatting}); + + Future test_dynamicRegistration_config_references() => + assertDynamicRegistration('references', {Method.textDocument_references}); + + Future test_dynamicRegistration_config_rename() => + assertDynamicRegistration('rename', {Method.textDocument_rename}); + + Future test_dynamicRegistration_config_selectionRange() => + assertDynamicRegistration( + 'selectionRange', {Method.textDocument_selectionRange}); + + Future test_dynamicRegistration_config_semanticTokens() => + assertDynamicRegistration( + 'semanticTokens', {CustomMethods.semanticTokenDynamicRegistration}); + + Future test_dynamicRegistration_config_signatureHelp() => + assertDynamicRegistration( + 'signatureHelp', {Method.textDocument_signatureHelp}); + + Future test_dynamicRegistration_config_synchronization() => + assertDynamicRegistration('synchronization', { + Method.textDocument_didOpen, + Method.textDocument_didChange, + Method.textDocument_didClose + }); + + Future test_dynamicRegistration_config_typeDefinition() => + assertDynamicRegistration( + 'typeDefinition', {Method.textDocument_typeDefinition}); + + Future test_dynamicRegistration_config_typeHierarchy() => + assertDynamicRegistration( + 'typeHierarchy', {Method.textDocument_prepareTypeHierarchy}); + Future test_dynamicRegistration_containsAppropriateSettings() async { // Basic check that the server responds with the capabilities we'd expect, // for ex including analysis_options.yaml in text synchronization but not @@ -355,22 +467,6 @@ class InitializationTest extends AbstractLspAnalysisServerTest { expect(didGetRegisterCapabilityRequest, isFalse); } - Future test_dynamicRegistration_onlyForClientSupportedMethods() async { - // Check that when the server calls client/registerCapability it only includes - // the items we advertised dynamic registration support for. - final registrations = []; - await monitorDynamicRegistrations( - registrations, - () => initialize( - textDocumentCapabilities: withHoverDynamicRegistration( - emptyTextDocumentClientCapabilities)), - ); - - expect(registrations, hasLength(1)); - expect(registrations.single.method, - equals(Method.textDocument_hover.toJson())); - } - Future test_dynamicRegistration_suppressesStaticRegistration() async { // If the client sends dynamicRegistration settings then there // should not be static registrations for the same capabilities. diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart index 3c60e1a635f..7b9391b2969 100644 --- a/pkg/analysis_server/test/lsp/server_abstract.dart +++ b/pkg/analysis_server/test/lsp/server_abstract.dart @@ -515,6 +515,32 @@ mixin ClientCapabilitiesHelperMixin { }); } + TextDocumentClientCapabilities withGivenTextDocumentDynamicRegistrations( + TextDocumentClientCapabilities source, + String name, + ) { + final json = name == 'semanticTokens' + ? SemanticTokensClientCapabilities( + dynamicRegistration: true, + requests: SemanticTokensClientCapabilitiesRequests(), + formats: [], + tokenModifiers: [], + tokenTypes: []).toJson() + : {'dynamicRegistration': true}; + return extendTextDocumentCapabilities(source, { + name: json, + }); + } + + WorkspaceClientCapabilities withGivenWorkspaceDynamicRegistrations( + WorkspaceClientCapabilities source, + String name, + ) { + return extendWorkspaceCapabilities(source, { + name: {'dynamicRegistration': true}, + }); + } + TextDocumentClientCapabilities withHierarchicalDocumentSymbolSupport( TextDocumentClientCapabilities source, ) {