Skip to content

Commit acefe9a

Browse files
DanTupCommit Queue
authored and
Commit Queue
committed
[analysis_server] Extract LSP registration options from ServerCapabilitiesComputer
This is a non-functional refactor that extracts the growing set of capabilities and options from ServerCapabilitiesComputer into files alongside the handlers they relate to. The motivation for this is that for LSP-over-Legacy we'll need to accept client capabilities (and return server capabilities). The server capabilities will be different to the standard LSP ones (they will be a subset, and we might not support dynamic registration - at least initially). However the features we do support will have the same registration options, so to avoid duplicating them this moves the registration options away from the creation of the ServerCapabilities. In future, we might consider further wrapping up a "feature" (which consists of these registration options, and the related handlers), but this change is already quite large and I just wanted to progress capabilities for LSP-over-Legacy so we can handle things like Code Actions (which require executeCommand and possible reverse-requests for applyEdit). Change-Id: Iecd0aa36626fa44826f7d4dbd6e6c0d758075239 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/319840 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]>
1 parent 94a0ce7 commit acefe9a

32 files changed

+1052
-423
lines changed

pkg/analysis_server/lib/src/lsp/constants.dart

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,48 @@ const dartSignatureHelpTriggerCharacters = <String>['('];
4545
/// Characters to trigger formatting when format-on-type is enabled.
4646
const dartTypeFormattingCharacters = ['}', ';'];
4747

48+
/// A [TextDocumentFilterWithScheme] for Analysis Options files.
49+
final analysisOptionsFile = TextDocumentFilterWithScheme(
50+
language: 'yaml', scheme: 'file', pattern: '**/analysis_options.yaml');
51+
4852
/// A [ProgressToken] used for reporting progress while the server is analyzing.
4953
final analyzingProgressToken = ProgressToken.t2('ANALYZING');
5054

55+
/// A [TextDocumentFilterWithScheme] for Dart file.
56+
final dartFiles =
57+
TextDocumentFilterWithScheme(language: 'dart', scheme: 'file');
58+
5159
final emptyWorkspaceEdit = WorkspaceEdit();
5260

61+
final fileOperationRegistrationOptions = FileOperationRegistrationOptions(
62+
filters: [
63+
FileOperationFilter(
64+
scheme: 'file',
65+
pattern: FileOperationPattern(
66+
glob: '**/*.dart',
67+
matches: FileOperationPatternKind.file,
68+
),
69+
),
70+
FileOperationFilter(
71+
scheme: 'file',
72+
pattern: FileOperationPattern(
73+
glob: '**/',
74+
matches: FileOperationPatternKind.folder,
75+
),
76+
)
77+
],
78+
);
79+
80+
/// A [TextDocumentFilterWithScheme] for Fix Data files.
81+
final fixDataFile = TextDocumentFilterWithScheme(
82+
language: 'yaml',
83+
scheme: 'file',
84+
pattern: '**/lib/{fix_data.yaml,fix_data/**.yaml}');
85+
86+
/// A [TextDocumentFilterWithScheme] for Pubspec files.
87+
final pubspecFile = TextDocumentFilterWithScheme(
88+
language: 'yaml', scheme: 'file', pattern: '**/pubspec.yaml');
89+
5390
/// Constants for command IDs that are exchanged between LSP client/server.
5491
abstract class Commands {
5592
/// A list of all commands IDs that can be sent to the client to inform which

pkg/analysis_server/lib/src/lsp/handlers/handler_call_hierarchy.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,36 @@ import 'package:analysis_server/lsp_protocol/protocol_special.dart';
99
import 'package:analysis_server/src/analysis_server.dart';
1010
import 'package:analysis_server/src/computer/computer_call_hierarchy.dart'
1111
as call_hierarchy;
12+
import 'package:analysis_server/src/lsp/constants.dart';
1213
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
1314
import 'package:analysis_server/src/lsp/mapping.dart';
15+
import 'package:analysis_server/src/lsp/registration/feature_registration.dart';
1416
import 'package:analyzer/dart/analysis/results.dart';
1517
import 'package:analyzer/dart/analysis/session.dart';
1618
import 'package:analyzer/source/line_info.dart';
1719
import 'package:analyzer/source/source_range.dart';
1820

21+
typedef StaticOptions
22+
= Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>;
23+
24+
class CallHierarchyRegistrations extends FeatureRegistration
25+
with SingleDynamicRegistration, StaticRegistration<StaticOptions> {
26+
CallHierarchyRegistrations(super.info);
27+
28+
@override
29+
ToJsonable? get options =>
30+
CallHierarchyRegistrationOptions(documentSelector: [dartFiles]);
31+
32+
@override
33+
Method get registrationMethod => Method.textDocument_prepareCallHierarchy;
34+
35+
@override
36+
StaticOptions get staticOptions => Either3.t1(true);
37+
38+
@override
39+
bool get supportsDynamic => clientDynamic.callHierarchy;
40+
}
41+
1942
/// A handler for `callHierarchy/incoming` that returns the incoming calls for
2043
/// the target supplied by the client.
2144
class IncomingCallHierarchyHandler extends _AbstractCallHierarchyCallsHandler<

pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44

55
import 'package:analysis_server/lsp_protocol/protocol.dart';
66
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
7+
import 'package:analysis_server/src/lsp/registration/feature_registration.dart';
78

8-
class WorkspaceFoldersHandler
9+
typedef StaticOptions = Either2<bool, String>;
10+
11+
class ChangeWorkspaceFoldersHandler
912
extends LspMessageHandler<DidChangeWorkspaceFoldersParams, void> {
1013
// Whether to update analysis roots based on the open workspace folders.
1114
bool updateAnalysisRoots;
1215

13-
WorkspaceFoldersHandler(super.server)
16+
ChangeWorkspaceFoldersHandler(super.server)
1417
: updateAnalysisRoots =
1518
!server.initializationOptions.onlyAnalyzeProjectsWithOpenFiles;
1619

@@ -46,3 +49,17 @@ class WorkspaceFoldersHandler
4649
return folders.map((wf) => pathContext.fromUri(wf.uri)).toList();
4750
}
4851
}
52+
53+
class ChangeWorkspaceFoldersRegistrations extends FeatureRegistration
54+
with StaticRegistration<StaticOptions> {
55+
ChangeWorkspaceFoldersRegistrations(super.info);
56+
57+
@override
58+
List<LspDynamicRegistration> get dynamicRegistrations => [];
59+
60+
@override
61+
StaticOptions get staticOptions => Either2.t1(true);
62+
63+
@override
64+
bool get supportsDynamic => false;
65+
}

pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@
55
import 'dart:async';
66

77
import 'package:analysis_server/lsp_protocol/protocol.dart';
8+
import 'package:analysis_server/src/lsp/constants.dart';
89
import 'package:analysis_server/src/lsp/handlers/code_actions/abstract_code_actions_producer.dart';
910
import 'package:analysis_server/src/lsp/handlers/code_actions/analysis_options.dart';
1011
import 'package:analysis_server/src/lsp/handlers/code_actions/dart.dart';
1112
import 'package:analysis_server/src/lsp/handlers/code_actions/plugins.dart';
1213
import 'package:analysis_server/src/lsp/handlers/code_actions/pubspec.dart';
1314
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
1415
import 'package:analysis_server/src/lsp/mapping.dart';
16+
import 'package:analysis_server/src/lsp/registration/feature_registration.dart';
1517
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
1618
import 'package:collection/collection.dart' show groupBy;
1719

20+
typedef StaticOptions = Either2<bool, CodeActionOptions>;
21+
1822
class CodeActionHandler
1923
extends LspMessageHandler<CodeActionParams, TextDocumentCodeActionResult> {
2024
CodeActionHandler(super.server);
@@ -220,6 +224,36 @@ class CodeActionHandler
220224
}
221225
}
222226

227+
class CodeActionRegistrations extends FeatureRegistration
228+
with SingleDynamicRegistration, StaticRegistration<StaticOptions> {
229+
CodeActionRegistrations(super.info);
230+
231+
bool get codeActionLiteralSupport => clientCapabilities.literalCodeActions;
232+
233+
@override
234+
ToJsonable? get options => CodeActionRegistrationOptions(
235+
documentSelector: fullySupportedTypes,
236+
codeActionKinds: DartCodeActionKind.serverSupportedKinds,
237+
);
238+
239+
@override
240+
Method get registrationMethod => Method.textDocument_codeAction;
241+
242+
@override
243+
StaticOptions get staticOptions =>
244+
// "The `CodeActionOptions` return type is only valid if the client
245+
// signals code action literal support via the property
246+
// `textDocument.codeAction.codeActionLiteralSupport`."
247+
codeActionLiteralSupport
248+
? Either2.t2(CodeActionOptions(
249+
codeActionKinds: DartCodeActionKind.serverSupportedKinds,
250+
))
251+
: Either2.t1(true);
252+
253+
@override
254+
bool get supportsDynamic => clientDynamic.codeActions;
255+
}
256+
223257
/// Sorts [CodeActionWithPriority]s by priority, and removes duplicates keeping
224258
/// the one nearest [range].
225259
class _CodeActionSorter {

pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ import 'dart:math' as math;
77
import 'package:analysis_server/lsp_protocol/protocol.dart' hide Declaration;
88
import 'package:analysis_server/src/computer/computer_hover.dart';
99
import 'package:analysis_server/src/lsp/client_capabilities.dart';
10+
import 'package:analysis_server/src/lsp/constants.dart';
1011
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
1112
import 'package:analysis_server/src/lsp/mapping.dart';
13+
import 'package:analysis_server/src/lsp/registration/feature_registration.dart';
1214
import 'package:analysis_server/src/provisional/completion/completion_core.dart';
1315
import 'package:analysis_server/src/services/completion/completion_performance.dart';
1416
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
@@ -790,6 +792,66 @@ class CompletionHandler
790792
}
791793
}
792794

795+
class CompletionRegistrations extends FeatureRegistration
796+
with StaticRegistration<CompletionOptions> {
797+
CompletionRegistrations(super.info);
798+
799+
@override
800+
List<LspDynamicRegistration> get dynamicRegistrations {
801+
return [
802+
// Trigger and commit characters are specific to Dart, so register them
803+
// separately to the others.
804+
(
805+
Method.textDocument_completion,
806+
CompletionRegistrationOptions(
807+
documentSelector: [dartFiles],
808+
triggerCharacters: dartCompletionTriggerCharacters,
809+
allCommitCharacters:
810+
previewCommitCharacters ? dartCompletionCommitCharacters : null,
811+
resolveProvider: true,
812+
),
813+
),
814+
(
815+
Method.textDocument_completion,
816+
CompletionRegistrationOptions(
817+
documentSelector: nonDartCompletionTypes,
818+
resolveProvider: true,
819+
),
820+
),
821+
];
822+
}
823+
824+
/// Types of documents we support completion for that are not Dart.
825+
///
826+
/// We use two dynamic registrations because for Dart we support trigger
827+
/// characters but for other kinds of files we do not.
828+
List<TextDocumentFilterWithScheme> get nonDartCompletionTypes {
829+
final pluginTypesExcludingDart =
830+
pluginTypes.where((filter) => filter.pattern != '**/*.dart');
831+
832+
return {
833+
...pluginTypesExcludingDart,
834+
pubspecFile,
835+
analysisOptionsFile,
836+
fixDataFile,
837+
}.toList();
838+
}
839+
840+
bool get previewCommitCharacters =>
841+
clientConfiguration.global.previewCommitCharacters;
842+
843+
@override
844+
CompletionOptions get staticOptions => CompletionOptions(
845+
triggerCharacters: dartCompletionTriggerCharacters,
846+
allCommitCharacters:
847+
previewCommitCharacters ? dartCompletionCommitCharacters : null,
848+
resolveProvider: true,
849+
);
850+
851+
@override
852+
bool get supportsDynamic => clientDynamic.completion;
853+
}
854+
793855
/// A set of completion items split into ranked and unranked items.
794856
class _CompletionResults {
795857
/// Items that can be ranked using their relevance/sortText.

pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:analysis_server/protocol/protocol_generated.dart'
77
hide AnalysisGetNavigationParams;
88
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
99
import 'package:analysis_server/src/lsp/mapping.dart';
10+
import 'package:analysis_server/src/lsp/registration/feature_registration.dart';
1011
import 'package:analysis_server/src/plugin/result_merger.dart';
1112
import 'package:analysis_server/src/protocol_server.dart' show NavigationTarget;
1213
import 'package:analyzer/dart/analysis/results.dart';
@@ -21,6 +22,8 @@ import 'package:analyzer_plugin/utilities/analyzer_converter.dart';
2122
import 'package:analyzer_plugin/utilities/navigation/navigation_dart.dart';
2223
import 'package:collection/collection.dart';
2324

25+
typedef StaticOptions = Either2<bool, DefinitionOptions>;
26+
2427
class DefinitionHandler extends LspMessageHandler<TextDocumentPositionParams,
2528
TextDocumentDefinitionResult> with LspPluginRequestHandlerMixin {
2629
DefinitionHandler(super.server);
@@ -269,3 +272,21 @@ class DefinitionHandler extends LspMessageHandler<TextDocumentPositionParams,
269272
return parsedLibrary.getElementDeclaration(element);
270273
}
271274
}
275+
276+
class DefinitionRegistrations extends FeatureRegistration
277+
with SingleDynamicRegistration, StaticRegistration<StaticOptions> {
278+
DefinitionRegistrations(super.info);
279+
280+
@override
281+
ToJsonable? get options =>
282+
TextDocumentRegistrationOptions(documentSelector: fullySupportedTypes);
283+
284+
@override
285+
Method get registrationMethod => Method.textDocument_definition;
286+
287+
@override
288+
StaticOptions get staticOptions => Either2.t1(true);
289+
290+
@override
291+
bool get supportsDynamic => clientDynamic.definition;
292+
}

pkg/analysis_server/lib/src/lsp/handlers/handler_document_color.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@
55
import 'package:analysis_server/lsp_protocol/protocol.dart';
66
import 'package:analysis_server/src/computer/computer_color.dart'
77
show ColorComputer, ColorReference;
8+
import 'package:analysis_server/src/lsp/constants.dart';
89
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
910
import 'package:analysis_server/src/lsp/mapping.dart';
11+
import 'package:analysis_server/src/lsp/registration/feature_registration.dart';
1012
import 'package:analyzer/dart/analysis/results.dart';
1113

14+
typedef StaticOptions
15+
= Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>;
16+
1217
/// Handles textDocument/documentColor requests.
1318
///
1419
/// This request is sent by the client to the server to request the locations
@@ -58,3 +63,21 @@ class DocumentColorHandler
5863
return success(colors.map(toColorInformation).toList());
5964
}
6065
}
66+
67+
class DocumentColorRegistrations extends FeatureRegistration
68+
with SingleDynamicRegistration, StaticRegistration<StaticOptions> {
69+
DocumentColorRegistrations(super.info);
70+
71+
@override
72+
DocumentColorRegistrationOptions get options =>
73+
DocumentColorRegistrationOptions(documentSelector: [dartFiles]);
74+
75+
@override
76+
Method get registrationMethod => Method.textDocument_documentColor;
77+
78+
@override
79+
StaticOptions get staticOptions => Either3.t3(options);
80+
81+
@override
82+
bool get supportsDynamic => clientDynamic.colorProvider;
83+
}

pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import 'package:analysis_server/src/domains/analysis/occurrences.dart';
77
import 'package:analysis_server/src/domains/analysis/occurrences_dart.dart';
88
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
99
import 'package:analysis_server/src/lsp/mapping.dart';
10+
import 'package:analysis_server/src/lsp/registration/feature_registration.dart';
11+
12+
typedef StaticOptions = Either2<bool, DocumentHighlightOptions>;
1013

1114
class DocumentHighlightsHandler extends SharedMessageHandler<
1215
TextDocumentPositionParams, List<DocumentHighlight>?> {
@@ -53,3 +56,21 @@ class DocumentHighlightsHandler extends SharedMessageHandler<
5356
});
5457
}
5558
}
59+
60+
class DocumentHighlightsRegistrations extends FeatureRegistration
61+
with SingleDynamicRegistration, StaticRegistration<StaticOptions> {
62+
DocumentHighlightsRegistrations(super.info);
63+
64+
@override
65+
ToJsonable? get options =>
66+
TextDocumentRegistrationOptions(documentSelector: fullySupportedTypes);
67+
68+
@override
69+
Method get registrationMethod => Method.textDocument_documentHighlight;
70+
71+
@override
72+
StaticOptions get staticOptions => Either2.t1(true);
73+
74+
@override
75+
bool get supportsDynamic => clientDynamic.documentHighlights;
76+
}

0 commit comments

Comments
 (0)