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

Side by Side Diff: pkg/analysis_server/spec/codegen_matchers.dart

Issue 443873006: Add analysis server API specification and related tools. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 /**
6 * Code generation for the file "matchers.dart".
7 */
8 library CodegenMatchers;
scheglov 2014/08/06 18:20:39 AFAIK library names should be all lower case with
Paul Berry 2014/08/06 18:32:43 Done.
9
10 import 'dart:convert';
11 import 'dart:io';
12
13 import 'api.dart';
14 import 'codegen_tools.dart';
15 import 'from_html.dart';
16 import 'to_html.dart';
17
18 class CodegenMatchersVisitor extends HierarchicalApiVisitor with CodeGenerator {
19 /**
20 * Visitor used to produce doc comments.
21 */
22 final ToHtmlVisitor toHtmlVisitor;
23
24 /**
25 * Short human-readable string describing the context of the matcher being
26 * created.
27 */
28 String context;
29
30 CodegenMatchersVisitor(Api api)
31 : super(api),
32 toHtmlVisitor = new ToHtmlVisitor(api);
33
34 /**
35 * Create a matcher for the part of the API called [name], optionally
36 * clarified by [nameSuffix]. The matcher should verify that its input
37 * matches the given [type].
38 */
39 void makeMatcher(String name, String nameSuffix, TypeDecl type) {
40 context = name;
41 List<String> nameParts = ['is'];
42 nameParts.addAll(name.split('.'));
43 if (nameSuffix != null) {
44 context += ' $nameSuffix';
45 nameParts.add(nameSuffix);
46 }
47 docComment(toHtmlVisitor.collectHtml(() {
48 toHtmlVisitor.p(() {
49 toHtmlVisitor.write(context);
50 });
51 if (type != null) {
52 toHtmlVisitor.showType(null, type);
53 }
54 }), false);
55 write('final Matcher ${camelJoin(nameParts)} = ');
56 if (type == null) {
57 write('isNull');
58 } else {
59 visitTypeDecl(type);
60 }
61 writeln(';');
62 writeln();
63 }
64
65 @override
66 visitApi() {
67 outputHeader();
68 writeln('/**');
69 writeln(' * Matchers for data types defined in the analysis server API');
70 writeln(' */');
71 writeln('library test.integration.protocol.matchers;');
72 writeln();
73 writeln("import 'package:unittest/unittest.dart';");
74 writeln();
75 writeln("import 'integration_tests.dart';");
76 writeln();
77 writeln();
78 super.visitApi();
79 }
80
81 @override
82 visitNotification(Notification notification) {
83 makeMatcher(notification.longEvent, 'params', notification.params);
84 }
85
86 @override
87 visitRequest(Request request) {
88 makeMatcher(request.longMethod, 'params', request.params);
89 makeMatcher(request.longMethod, 'result', request.result);
90 }
91
92 @override
93 visitRefactoring(Refactoring refactoring) {
94 String camelKind = camelJoin(refactoring.kind.toLowerCase().split('_'));
95 makeMatcher(camelKind, 'feedback', refactoring.feedback);
96 makeMatcher(camelKind, 'options', refactoring.options);
97 }
98
99 @override
100 visitTypeDefinition(TypeDefinition typeDefinition) {
101 makeMatcher(typeDefinition.name, null, typeDefinition.type);
102 }
103
104 @override
105 visitTypeEnum(TypeEnum typeEnum) {
106 writeln('isIn([');
107 indent(() {
108 bool commaNeeded = false;
109 for (TypeEnumValue value in typeEnum.values) {
110 if (commaNeeded) {
111 writeln(',');
112 }
113 write('${JSON.encode(value.value)}');
114 commaNeeded = true;
115 }
116 writeln();
117 });
118 write('])');
119 }
120
121 @override
122 visitTypeList(TypeList typeList) {
123 write('isListOf(');
124 visitTypeDecl(typeList.itemType);
125 write(')');
126 }
127
128 @override
129 visitTypeMap(TypeMap typeMap) {
130 write('isMapOf(');
131 visitTypeDecl(typeMap.keyType);
132 write(', ');
133 visitTypeDecl(typeMap.valueType);
134 write(')');
135 }
136
137 @override
138 void visitTypeObject(TypeObject typeObject) {
139 writeln('new MatchesJsonObject(');
140 indent(() {
141 write('${JSON.encode(context)}, ');
142 Iterable<TypeObjectField> requiredFields = typeObject.fields.where(
143 (TypeObjectField field) => !field.optional);
144 outputObjectFields(requiredFields);
145 List<TypeObjectField> optionalFields = typeObject.fields.where(
146 (TypeObjectField field) => field.optional).toList();
147 if (optionalFields.isNotEmpty) {
148 write(', optionalFields: ');
149 outputObjectFields(optionalFields);
150 }
151 });
152 write(')');
153 }
154
155 /**
156 * Generate a map describing the given set of fields, for use as the
157 * 'requiredFields' or 'optionalFields' argument to the [MatchesJsonObject]
158 * constructor.
159 */
160 void outputObjectFields(Iterable<TypeObjectField> fields) {
161 if (fields.isEmpty) {
162 write('null');
163 return;
164 }
165 writeln('{');
166 indent(() {
167 bool commaNeeded = false;
168 for (TypeObjectField field in fields) {
169 if (commaNeeded) {
170 writeln(',');
171 }
172 write('${JSON.encode(field.name)}: ');
173 visitTypeDecl(field.type);
174 commaNeeded = true;
175 }
176 writeln();
177 });
178 write('}');
179 }
180
181 @override
182 void visitTypeReference(TypeReference typeReference) {
183 write(camelJoin(['is', typeReference.typeName]));
184 }
185 }
186
187 /**
188 * Translate spec_input.html into protocol_matchers.dart.
189 */
190 main() {
191 CodegenMatchersVisitor visitor = new CodegenMatchersVisitor(readApi());
192 String code = visitor.collectCode(visitor.visitApi);
193 File outputFile = new File('../test/integration/protocol_matchers.dart');
194 outputFile.writeAsStringSync(code);
195 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698