299dabac5f
All we have to do is ignore it in some generated files, and then it is enforced in all other lib, tool, test files. Change-Id: I5822db725f9c632820323dd20f5d4b6554808c26 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/464624 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
161 lines
5.1 KiB
Dart
161 lines
5.1 KiB
Dart
// 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_utilities/tools.dart';
|
|
|
|
import 'api.dart';
|
|
import 'codegen_dart.dart';
|
|
import 'from_html.dart';
|
|
|
|
final GeneratedFile clientTarget = GeneratedFile(
|
|
'analysis_server_client/lib/src/protocol/protocol_constants.dart',
|
|
(pkgRoot) async {
|
|
var visitor = _CodegenVisitor(readApi(pkgRoot));
|
|
return visitor.collectCode(visitor.visitApi);
|
|
},
|
|
);
|
|
|
|
final GeneratedFile serverTarget = GeneratedFile(
|
|
'analysis_server/lib/protocol/protocol_constants.dart',
|
|
(pkgRoot) async {
|
|
var visitor = _CodegenVisitor(readApi(pkgRoot));
|
|
return visitor.collectCode(visitor.visitApi);
|
|
},
|
|
);
|
|
|
|
final _upperCaseLettersPattern = RegExp('[A-Z]');
|
|
|
|
/// Generate a name from the [domainName], [kind] and [name] components.
|
|
String generateConstName(String domainName, String kind, String name) {
|
|
return _fromComponents([..._split(domainName), kind, ..._split(name)]);
|
|
}
|
|
|
|
/// Returns a name generated by converting each of the given [components] to an
|
|
/// uppercase equivalent, then joining them with underscores.
|
|
String _fromComponents(List<String> components) {
|
|
var joinedName = components
|
|
.map((s) => '${s[0].toUpperCase()}${s.substring(1)}')
|
|
.join();
|
|
return '${joinedName[0].toLowerCase()}${joinedName.substring(1)}';
|
|
}
|
|
|
|
/// Returns the components of the given String that are indicated by an upper
|
|
/// case letter.
|
|
Iterable<String> _split(String first) {
|
|
var components = <String>[];
|
|
var start = 1;
|
|
var index = first.indexOf(_upperCaseLettersPattern, start);
|
|
while (index >= 0) {
|
|
components.add(first.substring(start - 1, index));
|
|
start = index + 1;
|
|
index = first.indexOf(_upperCaseLettersPattern, start);
|
|
}
|
|
components.add(first.substring(start - 1));
|
|
return components;
|
|
}
|
|
|
|
/// A visitor that produces Dart code defining constants associated with the
|
|
/// API.
|
|
class _CodegenVisitor extends DartCodegenVisitor with CodeGenerator {
|
|
_CodegenVisitor(super.api) {
|
|
codeGeneratorSettings.commentLineLength = 79;
|
|
codeGeneratorSettings.docCommentStartMarker = null;
|
|
codeGeneratorSettings.docCommentLineLeader = '/// ';
|
|
codeGeneratorSettings.docCommentEndMarker = null;
|
|
codeGeneratorSettings.languageName = 'dart';
|
|
}
|
|
|
|
/// Generate the given [constant].
|
|
void generateConstant(_Constant constant) {
|
|
write('const String ');
|
|
write(constant.name);
|
|
write(' = ');
|
|
write(constant.value);
|
|
writeln(';');
|
|
}
|
|
|
|
/// Generate all of the constants associated with the [api].
|
|
void generateConstants() {
|
|
writeln('// ignore: constant_identifier_names');
|
|
writeln("const String PROTOCOL_VERSION = '${api.version}';");
|
|
writeln();
|
|
var visitor = _ConstantVisitor(api);
|
|
visitor.visitApi();
|
|
var constants = visitor.constants;
|
|
constants.sort((first, second) => first.name.compareTo(second.name));
|
|
for (var constant in constants) {
|
|
generateConstant(constant);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void 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(super.api);
|
|
|
|
@override
|
|
void visitNotification(Notification notification) {
|
|
var domainName = notification.domainName;
|
|
var event = notification.event;
|
|
|
|
var constantName = generateConstName(domainName, 'notification', event);
|
|
constants.add(_Constant(constantName, "'$domainName.$event'"));
|
|
_addFieldConstants(constantName, notification.params);
|
|
}
|
|
|
|
@override
|
|
void visitRequest(Request request) {
|
|
var domainName = request.domainName;
|
|
var method = request.method;
|
|
|
|
var requestConstantName = generateConstName(domainName, 'request', method);
|
|
constants.add(_Constant(requestConstantName, "'$domainName.$method'"));
|
|
_addFieldConstants(requestConstantName, request.params);
|
|
|
|
var responseConstantName = generateConstName(
|
|
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;
|
|
}
|
|
for (var field in type.fields) {
|
|
var name = field.name;
|
|
var fieldConstantName = _fromComponents([parentName, ..._split(name)]);
|
|
constants.add(_Constant(fieldConstantName, "'$name'"));
|
|
}
|
|
}
|
|
}
|