blob: 27cf61a721d81a4c06bea78e0ba9ad91bded4d88 [file] [log] [blame]
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/handlers/handler_states.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
class IntializedMessageHandler extends MessageHandler<InitializedParams, void> {
final List<String> openWorkspacePaths;
final bool onlyAnalyzeProjectsWithOpenFiles, suggestFromUnimportedLibraries;
IntializedMessageHandler(
LspAnalysisServer server,
this.openWorkspacePaths,
this.onlyAnalyzeProjectsWithOpenFiles,
this.suggestFromUnimportedLibraries,
) : super(server);
Method get handlesMessage => Method.initialized;
@override
LspJsonHandler<InitializedParams> get jsonHandler =>
InitializedParams.jsonHandler;
ErrorOr<void> handle(InitializedParams params, CancellationToken token) {
server.messageHandler = new InitializedStateMessageHandler(
server,
onlyAnalyzeProjectsWithOpenFiles,
suggestFromUnimportedLibraries,
);
_performDynamicRegistration();
if (!onlyAnalyzeProjectsWithOpenFiles) {
server.setAnalysisRoots(openWorkspacePaths);
}
return success();
}
/// If the client supports dynamic registrations we can tell it what methods
/// we support for which documents. For example, this allows us to ask for
/// file edits for .dart as well as pubspec.yaml but only get hover/completion
/// calls for .dart. This functionality may not be supported by the client, in
/// which case they will use the ServerCapabilities to know which methods we
/// support and it will be up to them to decide which file types they will
/// send requests for.
Future<void> _performDynamicRegistration() async {
final dartFiles = DocumentFilter('dart', 'file', null);
final pubspecFile = DocumentFilter('yaml', 'file', '**/pubspec.yaml');
final analysisOptionsFile =
DocumentFilter('yaml', 'file', '**/analysis_options.yaml');
final allTypes = [dartFiles, pubspecFile, analysisOptionsFile];
// TODO(dantup): When we support plugins, we will need to collect their
// requirements too. For example, the Angular plugin might wish to add HTML
// `DocumentFilter('html', 'file', null)` to many of these requests.
int _lastRegistrationId = 1;
final registrations = <Registration>[];
/// Helper for creating registrations with IDs.
void register(bool condition, Method method, [ToJsonable options]) {
if (condition == true) {
registrations.add(Registration(
(_lastRegistrationId++).toString(), method.toJson(), options));
}
}
final textCapabilities = server.clientCapabilities?.textDocument;
register(
textCapabilities?.synchronization?.dynamicRegistration,
Method.textDocument_didOpen,
TextDocumentRegistrationOptions(allTypes),
);
register(
textCapabilities?.synchronization?.dynamicRegistration,
Method.textDocument_didClose,
TextDocumentRegistrationOptions(allTypes),
);
register(
textCapabilities?.synchronization?.dynamicRegistration,
Method.textDocument_didChange,
TextDocumentChangeRegistrationOptions(
TextDocumentSyncKind.Incremental, allTypes),
);
register(
server.clientCapabilities?.textDocument?.completion?.dynamicRegistration,
Method.textDocument_completion,
CompletionRegistrationOptions(
dartCompletionTriggerCharacters,
null,
true,
[dartFiles],
),
);
register(
textCapabilities?.hover?.dynamicRegistration,
Method.textDocument_hover,
TextDocumentRegistrationOptions([dartFiles]),
);
register(
textCapabilities?.signatureHelp?.dynamicRegistration,
Method.textDocument_signatureHelp,
SignatureHelpRegistrationOptions(
dartSignatureHelpTriggerCharacters, [dartFiles]),
);
register(
server.clientCapabilities?.textDocument?.references?.dynamicRegistration,
Method.textDocument_references,
TextDocumentRegistrationOptions([dartFiles]),
);
register(
textCapabilities?.documentHighlight?.dynamicRegistration,
Method.textDocument_documentHighlight,
TextDocumentRegistrationOptions([dartFiles]),
);
register(
textCapabilities?.documentSymbol?.dynamicRegistration,
Method.textDocument_documentSymbol,
TextDocumentRegistrationOptions([dartFiles]),
);
register(
server.clientCapabilities?.textDocument?.formatting?.dynamicRegistration,
Method.textDocument_formatting,
TextDocumentRegistrationOptions([dartFiles]),
);
register(
textCapabilities?.onTypeFormatting?.dynamicRegistration,
Method.textDocument_onTypeFormatting,
DocumentOnTypeFormattingRegistrationOptions(
dartTypeFormattingCharacters.first,
dartTypeFormattingCharacters.skip(1).toList(),
[dartFiles],
),
);
register(
server.clientCapabilities?.textDocument?.definition?.dynamicRegistration,
Method.textDocument_definition,
TextDocumentRegistrationOptions([dartFiles]),
);
register(
textCapabilities?.implementation?.dynamicRegistration,
Method.textDocument_implementation,
TextDocumentRegistrationOptions([dartFiles]),
);
register(
server.clientCapabilities?.textDocument?.codeAction?.dynamicRegistration,
Method.textDocument_codeAction,
CodeActionRegistrationOptions(
[dartFiles], DartCodeActionKind.serverSupportedKinds),
);
register(
textCapabilities?.rename?.dynamicRegistration,
Method.textDocument_rename,
RenameRegistrationOptions(true, [dartFiles]),
);
register(
textCapabilities?.foldingRange?.dynamicRegistration,
Method.textDocument_foldingRange,
TextDocumentRegistrationOptions([dartFiles]),
);
// Only send the registration request if we have at least one (since
// otherwise we don't know that the client supports registerCapability).
if (registrations.isNotEmpty) {
final registrationResponse = await server.sendRequest(
Method.client_registerCapability,
RegistrationParams(registrations),
);
if (registrationResponse.error != null) {
server.logErrorToClient(
'Failed to register capabilities with client: '
'(${registrationResponse.error.code}) '
'${registrationResponse.error.message}',
);
}
}
}
}