| // 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!))); |
| } |
| } |