blob: 160c52d5d140a98d49e52903481191aa94f6923a [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:analyzer_utilities/tools.dart';
import 'package:html/dom.dart';
import 'api.dart';
import 'codegen_dart.dart';
import 'codegen_protocol_constants.dart' show generateConstName;
import 'from_html.dart';
GeneratedFile clientTarget() {
return GeneratedFile(
'../analysis_server_client/lib/handler/notification_handler.dart',
(String pkgPath) async {
var visitor = CodegenNotificationHandlerVisitor(readApi(pkgPath));
return visitor.collectCode(visitor.visitApi);
});
}
String _capitalize(String name) =>
'${name.substring(0, 1).toUpperCase()}${name.substring(1)}';
List<String> _generateDartDoc(Element html) => html.children
.where((Element elem) => elem.localName == 'p')
.map<String>((Element elem) => elem.text.trim())
.toList();
String _generateNotificationMethodName(String domainName, String event) =>
'on${_capitalize(domainName)}${_capitalize(event)}';
String _generateParamTypeName(String domainName, String event) =>
'${_capitalize(domainName)}${_capitalize(event)}Params';
/// Visitor which produces Dart code representing the API.
class CodegenNotificationHandlerVisitor extends DartCodegenVisitor
with CodeGenerator {
CodegenNotificationHandlerVisitor(Api api) : super(api) {
codeGeneratorSettings.commentLineLength = 79;
codeGeneratorSettings.docCommentStartMarker = null;
codeGeneratorSettings.docCommentLineLeader = '/// ';
codeGeneratorSettings.docCommentEndMarker = null;
codeGeneratorSettings.languageName = 'dart';
}
void emitDartdoc(List<String> dartdoc) {
var first = true;
for (var paragraph in dartdoc) {
if (first) {
first = false;
} else {
writeln(' ///');
}
for (var line in paragraph.split(RegExp('\r?\n'))) {
writeln(' /// ${line.trim()}');
}
}
}
void emitImports() {
writeln("import 'package:analysis_server_client/protocol.dart';");
}
void emitNotificationHandler() {
var visitor = _NotificationVisitor(api)..visitApi();
final notifications = visitor.notificationConstants;
notifications.sort((n1, n2) => n1.constName.compareTo(n2.constName));
writeln('''
/// [NotificationHandler] processes analysis server notifications
/// and dispatches those notifications to different methods based upon
/// the type of notification. Clients may override
/// any of the "on<EventName>" methods that are of interest.
///
/// Clients may mix-in this class, but may not implement it.
mixin NotificationHandler {
void handleEvent(Notification notification) {
var params = notification.params;
var decoder = ResponseDecoder(null);
switch (notification.event) {
''');
for (var notification in notifications) {
writeln(' case ${notification.constName}:');
writeln(' ${notification.methodName}(');
writeln(' ${notification.paramsTypeName}');
writeln(" .fromJson(decoder, 'params', params));");
writeln(' break;');
}
writeln(' default:');
writeln(' onUnknownNotification(notification.event, params);');
writeln(' break;');
writeln(' }');
writeln(' }');
for (var notification in notifications) {
writeln();
emitDartdoc(notification.dartdoc);
writeln(' void ${notification.methodName}(');
writeln(' ${notification.paramsTypeName} params) {');
writeln(' }');
}
writeln();
writeln(' /// Reports a notification that is not processed');
writeln(' /// by any other notification handlers.');
writeln(' void onUnknownNotification(String event, params) {}');
writeln('}');
}
@override
void visitApi() {
outputHeader(year: '2018');
writeln();
emitImports();
emitNotificationHandler();
}
}
class _Notification {
final String constName;
final String methodName;
final String paramsTypeName;
final List<String> dartdoc;
_Notification(
this.constName, this.methodName, this.paramsTypeName, this.dartdoc);
}
class _NotificationVisitor extends HierarchicalApiVisitor {
final notificationConstants = <_Notification>[];
_NotificationVisitor(Api api) : super(api);
@override
void visitNotification(Notification notification) {
notificationConstants.add(_Notification(
generateConstName(
notification.domainName, 'notification', notification.event),
_generateNotificationMethodName(
notification.domainName, notification.event),
_generateParamTypeName(notification.domainName, notification.event),
_generateDartDoc(notification.html!)));
}
}