Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Unified Diff: pkg/analyzer_plugin/tool/spec/codegen_matchers.dart

Issue 2664213003: Add the generator and the generated files (Closed)
Patch Set: add missed files Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer_plugin/tool/spec/codegen_matchers.dart
diff --git a/pkg/analyzer_plugin/tool/spec/codegen_matchers.dart b/pkg/analyzer_plugin/tool/spec/codegen_matchers.dart
new file mode 100644
index 0000000000000000000000000000000000000000..1d18ef78dab5cdc89c56e662cdd5e4388daf568d
--- /dev/null
+++ b/pkg/analyzer_plugin/tool/spec/codegen_matchers.dart
@@ -0,0 +1,187 @@
+// 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 "matchers.dart".
+ */
+import 'dart:convert';
+
+import 'package:analyzer/src/codegen/tools.dart';
+
+import 'api.dart';
+import 'from_html.dart';
+import 'implied_types.dart';
+import 'to_html.dart';
+
+final GeneratedFile target = new GeneratedFile(
+ 'test/integration/support/protocol_matchers.dart', (String pkgPath) {
+ CodegenMatchersVisitor visitor = new CodegenMatchersVisitor(readApi(pkgPath));
+ return visitor.collectCode(visitor.visitApi);
+});
+
+class CodegenMatchersVisitor extends HierarchicalApiVisitor with CodeGenerator {
+ /**
+ * Visitor used to produce doc comments.
+ */
+ final ToHtmlVisitor toHtmlVisitor;
+
+ /**
+ * Short human-readable string describing the context of the matcher being
+ * created.
+ */
+ String context;
+
+ CodegenMatchersVisitor(Api api)
+ : toHtmlVisitor = new ToHtmlVisitor(api),
+ super(api) {
+ codeGeneratorSettings.commentLineLength = 79;
+ codeGeneratorSettings.languageName = 'dart';
+ }
+
+ /**
+ * Create a matcher for the part of the API called [name], optionally
+ * clarified by [nameSuffix]. The matcher should verify that its input
+ * matches the given [type].
+ */
+ void makeMatcher(ImpliedType impliedType) {
+ context = impliedType.humanReadableName;
+ docComment(toHtmlVisitor.collectHtml(() {
+ toHtmlVisitor.p(() {
+ toHtmlVisitor.write(context);
+ });
+ if (impliedType.type != null) {
+ toHtmlVisitor.showType(null, impliedType.type);
+ }
+ }));
+ write('final Matcher ${camelJoin(['is', impliedType.camelName])} = ');
+ if (impliedType.type == null) {
+ write('isNull');
+ } else {
+ visitTypeDecl(impliedType.type);
+ }
+ writeln(';');
+ writeln();
+ }
+
+ /**
+ * Generate a map describing the given set of fields, for use as the
+ * 'requiredFields' or 'optionalFields' argument to the [MatchesJsonObject]
+ * constructor.
+ */
+ void outputObjectFields(Iterable<TypeObjectField> fields) {
+ if (fields.isEmpty) {
+ write('null');
+ return;
+ }
+ writeln('{');
+ indent(() {
+ bool commaNeeded = false;
+ for (TypeObjectField field in fields) {
+ if (commaNeeded) {
+ writeln(',');
+ }
+ write('${JSON.encode(field.name)}: ');
+ if (field.value != null) {
+ write('equals(${JSON.encode(field.value)})');
+ } else {
+ visitTypeDecl(field.type);
+ }
+ commaNeeded = true;
+ }
+ writeln();
+ });
+ write('}');
+ }
+
+ @override
+ visitApi() {
+ outputHeader(year: '2017');
+ writeln();
+ writeln('/**');
+ writeln(' * Matchers for data types defined in the analysis server API');
+ writeln(' */');
+ writeln("import 'package:test/test.dart';");
+ writeln();
+ writeln("import 'integration_tests.dart';");
+ writeln();
+ for (ImpliedType impliedType in computeImpliedTypes(api).values) {
+ makeMatcher(impliedType);
+ }
+ }
+
+ @override
+ visitTypeEnum(TypeEnum typeEnum) {
+ writeln('new MatchesEnum(${JSON.encode(context)}, [');
+ indent(() {
+ bool commaNeeded = false;
+ for (TypeEnumValue value in typeEnum.values) {
+ if (commaNeeded) {
+ writeln(',');
+ }
+ write('${JSON.encode(value.value)}');
+ commaNeeded = true;
+ }
+ writeln();
+ });
+ write('])');
+ }
+
+ @override
+ visitTypeList(TypeList typeList) {
+ write('isListOf(');
+ visitTypeDecl(typeList.itemType);
+ write(')');
+ }
+
+ @override
+ visitTypeMap(TypeMap typeMap) {
+ write('isMapOf(');
+ visitTypeDecl(typeMap.keyType);
+ write(', ');
+ visitTypeDecl(typeMap.valueType);
+ write(')');
+ }
+
+ @override
+ void visitTypeObject(TypeObject typeObject) {
+ writeln('new LazyMatcher(() => new MatchesJsonObject(');
+ indent(() {
+ write('${JSON.encode(context)}, ');
+ Iterable<TypeObjectField> requiredFields =
+ typeObject.fields.where((TypeObjectField field) => !field.optional);
+ outputObjectFields(requiredFields);
+ List<TypeObjectField> optionalFields = typeObject.fields
+ .where((TypeObjectField field) => field.optional)
+ .toList();
+ if (optionalFields.isNotEmpty) {
+ write(', optionalFields: ');
+ outputObjectFields(optionalFields);
+ }
+ });
+ write('))');
+ }
+
+ @override
+ void visitTypeReference(TypeReference typeReference) {
+ String typeName = typeReference.typeName;
+ if (typeName == 'long') {
+ typeName = 'int';
+ }
+ write(camelJoin(['is', typeName]));
+ }
+
+ @override
+ void visitTypeUnion(TypeUnion typeUnion) {
+ bool commaNeeded = false;
+ write('isOneOf([');
+ for (TypeDecl choice in typeUnion.choices) {
+ if (commaNeeded) {
+ write(', ');
+ }
+ visitTypeDecl(choice);
+ commaNeeded = true;
+ }
+ write('])');
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698