| Index: pkg/analyzer_plugin/tool/spec/codegen_inttest_methods.dart
|
| diff --git a/pkg/analyzer_plugin/tool/spec/codegen_inttest_methods.dart b/pkg/analyzer_plugin/tool/spec/codegen_inttest_methods.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7dc16bd3b4e824b9c40632286cba0ec4ba6e42e0
|
| --- /dev/null
|
| +++ b/pkg/analyzer_plugin/tool/spec/codegen_inttest_methods.dart
|
| @@ -0,0 +1,260 @@
|
| +// 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.
|
| +
|
| +/**
|
| + * Code generation for the file "integration_test_methods.dart".
|
| + */
|
| +import 'dart:convert';
|
| +
|
| +import 'package:analyzer/src/codegen/tools.dart';
|
| +
|
| +import 'api.dart';
|
| +import 'codegen_dart.dart';
|
| +import 'from_html.dart';
|
| +import 'to_html.dart';
|
| +
|
| +final GeneratedFile target = new GeneratedFile(
|
| + 'test/integration/support/integration_test_methods.dart', (String pkgPath) {
|
| + CodegenInttestMethodsVisitor visitor =
|
| + new CodegenInttestMethodsVisitor(readApi(pkgPath));
|
| + return visitor.collectCode(visitor.visitApi);
|
| +});
|
| +
|
| +/**
|
| + * Visitor that generates the code for integration_test_methods.dart
|
| + */
|
| +class CodegenInttestMethodsVisitor extends DartCodegenVisitor
|
| + with CodeGenerator {
|
| + /**
|
| + * Visitor used to produce doc comments.
|
| + */
|
| + final ToHtmlVisitor toHtmlVisitor;
|
| +
|
| + /**
|
| + * Code snippets concatenated to initialize all of the class fields.
|
| + */
|
| + List<String> fieldInitializationCode = <String>[];
|
| +
|
| + /**
|
| + * Code snippets concatenated to produce the contents of the switch statement
|
| + * for dispatching notifications.
|
| + */
|
| + List<String> notificationSwitchContents = <String>[];
|
| +
|
| + CodegenInttestMethodsVisitor(Api api)
|
| + : toHtmlVisitor = new ToHtmlVisitor(api),
|
| + super(api) {
|
| + codeGeneratorSettings.commentLineLength = 79;
|
| + codeGeneratorSettings.languageName = 'dart';
|
| + }
|
| +
|
| + /**
|
| + * Generate a function argument for the given parameter field.
|
| + */
|
| + String formatArgument(TypeObjectField field) =>
|
| + '${dartType(field.type)} ${field.name}';
|
| +
|
| + /**
|
| + * Figure out the appropriate Dart type for data having the given API
|
| + * protocol [type].
|
| + */
|
| + String jsonType(TypeDecl type) {
|
| + type = resolveTypeReferenceChain(type);
|
| + if (type is TypeEnum) {
|
| + return 'String';
|
| + } else if (type is TypeList) {
|
| + return 'List<${jsonType(type.itemType)}>';
|
| + } else if (type is TypeMap) {
|
| + return 'Map<String, ${jsonType(type.valueType)}>';
|
| + } else if (type is TypeObject) {
|
| + return 'Map<String, dynamic>';
|
| + } else if (type is TypeReference) {
|
| + switch (type.typeName) {
|
| + case 'String':
|
| + case 'int':
|
| + case 'bool':
|
| + // These types correspond exactly to Dart types
|
| + return type.typeName;
|
| + case 'object':
|
| + return 'Map<String, dynamic>';
|
| + default:
|
| + throw new Exception(type.typeName);
|
| + }
|
| + } else if (type is TypeUnion) {
|
| + return 'Object';
|
| + } else {
|
| + throw new Exception('Unexpected kind of TypeDecl');
|
| + }
|
| + }
|
| +
|
| + @override
|
| + visitApi() {
|
| + outputHeader(year: '2017');
|
| + writeln();
|
| + writeln('/**');
|
| + writeln(' * Convenience methods for running integration tests');
|
| + writeln(' */');
|
| + writeln("import 'dart:async';");
|
| + writeln();
|
| + writeln(
|
| + "import 'package:analyzer_plugin/protocol/generated_protocol.dart';");
|
| + writeln(
|
| + "import 'package:analyzer_plugin/src/protocol/protocol_internal.dart';");
|
| + writeln("import 'package:test/test.dart';");
|
| + writeln();
|
| + writeln("import 'integration_tests.dart';");
|
| + writeln("import 'protocol_matchers.dart';");
|
| + writeln();
|
| + writeln('/**');
|
| + writeln(' * Convenience methods for running integration tests');
|
| + writeln(' */');
|
| + writeln('abstract class IntegrationTestMixin {');
|
| + indent(() {
|
| + writeln('Server get server;');
|
| + super.visitApi();
|
| + writeln();
|
| + docComment(toHtmlVisitor.collectHtml(() {
|
| + toHtmlVisitor.writeln('Initialize the fields in InttestMixin, and');
|
| + toHtmlVisitor.writeln('ensure that notifications will be handled.');
|
| + }));
|
| + writeln('void initializeInttestMixin() {');
|
| + indent(() {
|
| + write(fieldInitializationCode.join());
|
| + });
|
| + writeln('}');
|
| + writeln();
|
| + docComment(toHtmlVisitor.collectHtml(() {
|
| + toHtmlVisitor.writeln('Dispatch the notification named [event], and');
|
| + toHtmlVisitor.writeln('containing parameters [params], to the');
|
| + toHtmlVisitor.writeln('appropriate stream.');
|
| + }));
|
| + writeln('void dispatchNotification(String event, params) {');
|
| + indent(() {
|
| + writeln('ResponseDecoder decoder = new ResponseDecoder(null);');
|
| + writeln('switch (event) {');
|
| + indent(() {
|
| + write(notificationSwitchContents.join());
|
| + writeln('default:');
|
| + indent(() {
|
| + writeln("fail('Unexpected notification: \$event');");
|
| + writeln('break;');
|
| + });
|
| + });
|
| + writeln('}');
|
| + });
|
| + writeln('}');
|
| + });
|
| + writeln('}');
|
| + }
|
| +
|
| + @override
|
| + visitNotification(Notification notification) {
|
| + String streamName =
|
| + camelJoin(['on', notification.domainName, notification.event]);
|
| + String className = camelJoin(
|
| + [notification.domainName, notification.event, 'params'],
|
| + doCapitalize: true);
|
| + writeln();
|
| + docComment(toHtmlVisitor.collectHtml(() {
|
| + toHtmlVisitor.translateHtml(notification.html);
|
| + toHtmlVisitor.describePayload(notification.params, 'Parameters');
|
| + }));
|
| + writeln('Stream<$className> $streamName;');
|
| + writeln();
|
| + docComment(toHtmlVisitor.collectHtml(() {
|
| + toHtmlVisitor.write('Stream controller for [$streamName].');
|
| + }));
|
| + writeln('StreamController<$className> _$streamName;');
|
| + fieldInitializationCode.add(collectCode(() {
|
| + writeln('_$streamName = new StreamController<$className>(sync: true);');
|
| + writeln('$streamName = _$streamName.stream.asBroadcastStream();');
|
| + }));
|
| + notificationSwitchContents.add(collectCode(() {
|
| + writeln('case ${JSON.encode(notification.longEvent)}:');
|
| + indent(() {
|
| + String paramsValidator = camelJoin(
|
| + ['is', notification.domainName, notification.event, 'params']);
|
| + writeln('outOfTestExpect(params, $paramsValidator);');
|
| + String constructorCall;
|
| + if (notification.params == null) {
|
| + constructorCall = 'new $className()';
|
| + } else {
|
| + constructorCall =
|
| + "new $className.fromJson(decoder, 'params', params)";
|
| + }
|
| + writeln('_$streamName.add($constructorCall);');
|
| + writeln('break;');
|
| + });
|
| + }));
|
| + }
|
| +
|
| + @override
|
| + visitRequest(Request request) {
|
| + String methodName = camelJoin(['send', request.domainName, request.method]);
|
| + List<String> args = <String>[];
|
| + List<String> optionalArgs = <String>[];
|
| + if (request.params != null) {
|
| + for (TypeObjectField field in request.params.fields) {
|
| + if (field.optional) {
|
| + optionalArgs.add(formatArgument(field));
|
| + } else {
|
| + args.add(formatArgument(field));
|
| + }
|
| + }
|
| + }
|
| + if (optionalArgs.isNotEmpty) {
|
| + args.add('{${optionalArgs.join(', ')}}');
|
| + }
|
| + writeln();
|
| + docComment(toHtmlVisitor.collectHtml(() {
|
| + toHtmlVisitor.translateHtml(request.html);
|
| + toHtmlVisitor.describePayload(request.params, 'Parameters');
|
| + toHtmlVisitor.describePayload(request.result, 'Returns');
|
| + }));
|
| + String resultClass;
|
| + String futureClass;
|
| + if (request.result == null) {
|
| + futureClass = 'Future';
|
| + } else {
|
| + resultClass = camelJoin([request.domainName, request.method, 'result'],
|
| + doCapitalize: true);
|
| + futureClass = 'Future<$resultClass>';
|
| + }
|
| + writeln('$futureClass $methodName(${args.join(', ')}) async {');
|
| + indent(() {
|
| + String requestClass = camelJoin(
|
| + [request.domainName, request.method, 'params'],
|
| + doCapitalize: true);
|
| + String paramsVar = 'null';
|
| + if (request.params != null) {
|
| + paramsVar = 'params';
|
| + List<String> args = <String>[];
|
| + List<String> optionalArgs = <String>[];
|
| + for (TypeObjectField field in request.params.fields) {
|
| + if (field.optional) {
|
| + optionalArgs.add('${field.name}: ${field.name}');
|
| + } else {
|
| + args.add(field.name);
|
| + }
|
| + }
|
| + args.addAll(optionalArgs);
|
| + writeln('var params = new $requestClass(${args.join(', ')}).toJson();');
|
| + }
|
| + String methodJson = JSON.encode(request.longMethod);
|
| + writeln('var result = await server.send($methodJson, $paramsVar);');
|
| + if (request.result != null) {
|
| + String kind = 'null';
|
| + if (requestClass == 'EditGetRefactoringParams') {
|
| + kind = 'kind';
|
| + }
|
| + writeln('ResponseDecoder decoder = new ResponseDecoder($kind);');
|
| + writeln("return new $resultClass.fromJson(decoder, 'result', result);");
|
| + } else {
|
| + writeln('outOfTestExpect(result, isNull);');
|
| + writeln('return null;');
|
| + }
|
| + });
|
| + writeln('}');
|
| + }
|
| +}
|
|
|