| // Copyright (c) 2017, 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/src/codegen/tools.dart'; | |
| import 'package:front_end/src/codegen/tools.dart'; | |
| import 'api.dart'; | |
| import 'codegen_dart.dart'; | |
| import 'from_html.dart'; | |
| final GeneratedFile target = new GeneratedFile( | |
| 'lib/protocol/protocol_constants.dart', (String pkgPath) async { | |
| CodegenVisitor visitor = new CodegenVisitor(readApi(pkgPath)); | |
| return visitor.collectCode(visitor.visitApi); | |
| }); | |
| /** | |
| * A visitor that produces Dart code defining constants associated with the API. | |
| */ | |
| class CodegenVisitor extends DartCodegenVisitor with CodeGenerator { | |
| CodegenVisitor(Api api) : super(api) { | |
| codeGeneratorSettings.commentLineLength = 79; | |
| codeGeneratorSettings.languageName = 'dart'; | |
| } | |
| /** | |
| * Generate all of the constants associates with the [api]. | |
| */ | |
| void generateConstants() { | |
| _ConstantVisitor visitor = new _ConstantVisitor(api); | |
| visitor.visitApi(); | |
| List<_Constant> constants = visitor.constants; | |
| constants.sort((first, second) => first.name.compareTo(second.name)); | |
| for (_Constant constant in constants) { | |
| generateContant(constant); | |
| } | |
| } | |
| /** | |
| * Generate the given [constant]. | |
| */ | |
| void generateContant(_Constant constant) { | |
| write('const String '); | |
| write(constant.name); | |
| write(' = '); | |
| write(constant.value); | |
| writeln(';'); | |
| } | |
| @override | |
| visitApi() { | |
| outputHeader(year: '2017'); | |
| writeln(); | |
| generateConstants(); | |
| } | |
| } | |
| /** | |
| * A representation of a constant that is to be generated. | |
| */ | |
| class _Constant { | |
| /** | |
| * The name of the constant. | |
| */ | |
| final String name; | |
| /** | |
| * The value of the constant. | |
| */ | |
| final String value; | |
| /** | |
| * Initialize a newly created constant. | |
| */ | |
| _Constant(this.name, this.value); | |
| } | |
| /** | |
| * A visitor that visits an API to compute a list of constants to be generated. | |
| */ | |
| class _ConstantVisitor extends HierarchicalApiVisitor { | |
| /** | |
| * The list of constants to be generated. | |
| */ | |
| List<_Constant> constants = <_Constant>[]; | |
| /** | |
| * Initialize a newly created visitor to visit the given [api]. | |
| */ | |
| _ConstantVisitor(Api api) : super(api); | |
| @override | |
| void visitNotification(Notification notification) { | |
| String domainName = notification.domainName; | |
| String event = notification.event; | |
| String constantName = _generateName(domainName, 'notification', event); | |
| constants.add(new _Constant(constantName, "'$domainName.$event'")); | |
| _addFieldConstants(constantName, notification.params); | |
| } | |
| @override | |
| void visitRequest(Request request) { | |
| String domainName = request.domainName; | |
| String method = request.method; | |
| String requestConstantName = _generateName(domainName, 'request', method); | |
| constants.add(new _Constant(requestConstantName, "'$domainName.$method'")); | |
| _addFieldConstants(requestConstantName, request.params); | |
| String responseConstantName = _generateName(domainName, 'response', method); | |
| _addFieldConstants(responseConstantName, request.result); | |
| } | |
| /** | |
| * Generate a constant for each of the fields in the given [type], where the | |
| * name of each constant will be composed from the [parentName] and the name | |
| * of the field. | |
| */ | |
| void _addFieldConstants(String parentName, TypeObject type) { | |
| if (type == null) { | |
| return; | |
| } | |
| type.fields.forEach((TypeObjectField field) { | |
| String name = field.name; | |
| List<String> components = <String>[]; | |
| components.add(parentName); | |
| components.addAll(_split(name)); | |
| String fieldConstantName = _fromComponents(components); | |
| constants.add(new _Constant(fieldConstantName, "'$name'")); | |
| }); | |
| } | |
| /** | |
| * Return a name generated by converting each of the given [components] to an | |
| * uppercase equivalent, then joining them with underscores. | |
| */ | |
| String _fromComponents(List<String> components) => | |
| components.map((String component) => component.toUpperCase()).join('_'); | |
| /** | |
| * Generate a name from the [domainName], [kind] and [name] components. | |
| */ | |
| String _generateName(String domainName, String kind, String name) { | |
| List<String> components = <String>[]; | |
| components.addAll(_split(domainName)); | |
| components.add(kind); | |
| components.addAll(_split(name)); | |
| return _fromComponents(components); | |
| } | |
| /** | |
| * Return the components of the given [string] that are indicated by an upper | |
| * case letter. | |
| */ | |
| Iterable<String> _split(String first) { | |
| RegExp regExp = new RegExp('[A-Z]'); | |
| List<String> components = <String>[]; | |
| int start = 1; | |
| int index = first.indexOf(regExp, start); | |
| while (index >= 0) { | |
| components.add(first.substring(start - 1, index)); | |
| start = index + 1; | |
| index = first.indexOf(regExp, start); | |
| } | |
| components.add(first.substring(start - 1)); | |
| return components; | |
| } | |
| } |