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

Side by Side Diff: pkg/analysis_server/tool/spec/from_html.dart

Issue 725143004: Format and sort analyzer and analysis_server packages. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * Code for reading an HTML API description. 6 * Code for reading an HTML API description.
7 */ 7 */
8 library from.html; 8 library from.html;
9 9
10 import 'dart:io'; 10 import 'dart:io';
11 11
12 import 'package:html5lib/dom.dart' as dom; 12 import 'package:html5lib/dom.dart' as dom;
13 import 'package:html5lib/parser.dart' as parser; 13 import 'package:html5lib/parser.dart' as parser;
14 14
15 import 'api.dart'; 15 import 'api.dart';
16 import 'html_tools.dart'; 16 import 'html_tools.dart';
17 17
18 /** 18 const List<String> specialElements = const [
19 * Check that the given [element] has the given [expectedName]. 19 'domain',
20 */ 20 'feedback',
21 void checkName(dom.Element element, String expectedName, [String context]) { 21 'object',
22 if (element.localName != expectedName) { 22 'refactorings',
23 if (context == null) { 23 'refactoring',
24 context = element.localName; 24 'type',
25 } 25 'types',
26 throw new Exception( 26 'request',
27 '$context: Expected $expectedName, found ${element.localName}'); 27 'notification',
28 } 28 'params',
29 } 29 'result',
30 30 'field',
31 /** 31 'list',
32 * Check that the given [element] has all of the attributes in 32 'map',
33 * [requiredAttributes], possibly some of the attributes in 33 'enum',
34 * [optionalAttributes], and no others. 34 'key',
35 */ 35 'value',
36 void checkAttributes(dom.Element element, List<String> 36 'options',
37 requiredAttributes, String context, {List<String> optionalAttributes: const []}) 37 'ref',
38 { 38 'code',
39 Set<String> attributesFound = new Set<String>(); 39 'version',
40 element.attributes.forEach((String name, String value) { 40 'union'];
41 if (!requiredAttributes.contains(name) && !optionalAttributes.contains(name
42 )) {
43 throw new Exception(
44 '$context: Unexpected attribute in ${element.localName}: $name');
45 }
46 attributesFound.add(name);
47 });
48 for (String expectedAttribute in requiredAttributes) {
49 if (!attributesFound.contains(expectedAttribute)) {
50 throw new Exception(
51 '$context: ${element.localName} must contain attribute ${expectedAttri bute}');
52 }
53 }
54 }
55
56 const List<String> specialElements = const ['domain', 'feedback', 'object',
57 'refactorings', 'refactoring', 'type', 'types', 'request', 'notification',
58 'params', 'result', 'field', 'list', 'map', 'enum', 'key', 'value', 'options ',
59 'ref', 'code', 'version', 'union'];
60
61 typedef void ElementProcessor(dom.Element element);
62 typedef void TextProcessor(dom.Text text);
63
64 void recurse(dom.Element parent, String context, Map<String, ElementProcessor>
65 elementProcessors) {
66 for (String key in elementProcessors.keys) {
67 if (!specialElements.contains(key)) {
68 throw new Exception('$context: $key is not a special element');
69 }
70 }
71 for (dom.Node node in parent.nodes) {
72 if (node is dom.Element) {
73 if (elementProcessors.containsKey(node.localName)) {
74 elementProcessors[node.localName](node);
75 } else if (specialElements.contains(node.localName)) {
76 throw new Exception('$context: Unexpected use of <${node.localName}');
77 } else {
78 recurse(node, context, elementProcessors);
79 }
80 }
81 }
82 }
83
84 dom.Element getAncestor(dom.Element html, String name, String context) {
85 dom.Element ancestor = html.parent;
86 while (ancestor != null) {
87 if (ancestor.localName == name) {
88 return ancestor;
89 }
90 ancestor = ancestor.parent;
91 }
92 throw new Exception(
93 '$context: <${html.localName}> must be nested within <$name>');
94 }
95 41
96 /** 42 /**
97 * Create an [Api] object from an HTML representation such as: 43 * Create an [Api] object from an HTML representation such as:
98 * 44 *
99 * <html> 45 * <html>
100 * ... 46 * ...
101 * <body> 47 * <body>
102 * ... <version>1.0</version> ... 48 * ... <version>1.0</version> ...
103 * <domain name="...">...</domain> <!-- zero or more --> 49 * <domain name="...">...</domain> <!-- zero or more -->
104 * <types>...</types> 50 * <types>...</types>
(...skipping 24 matching lines...) Expand all
129 } 75 }
130 }); 76 });
131 if (versions.length != 1) { 77 if (versions.length != 1) {
132 throw new Exception('The API must contain exactly one <version> element'); 78 throw new Exception('The API must contain exactly one <version> element');
133 } 79 }
134 api = new Api(versions[0], domains, types, refactorings, html); 80 api = new Api(versions[0], domains, types, refactorings, html);
135 return api; 81 return api;
136 } 82 }
137 83
138 /** 84 /**
139 * Create a [Refactorings] object from an HTML representation such as: 85 * Check that the given [element] has all of the attributes in
140 * 86 * [requiredAttributes], possibly some of the attributes in
141 * <refactorings> 87 * [optionalAttributes], and no others.
142 * <refactoring kind="...">...</refactoring> <!-- zero or more -->
143 * </refactorings>
144 */ 88 */
145 Refactorings refactoringsFromHtml(dom.Element html) { 89 void checkAttributes(dom.Element element, List<String> requiredAttributes,
146 checkName(html, 'refactorings'); 90 String context, {List<String> optionalAttributes: const [
147 String context = 'refactorings'; 91 ]}) {
148 checkAttributes(html, [], context); 92 Set<String> attributesFound = new Set<String>();
149 List<Refactoring> refactorings = <Refactoring>[]; 93 element.attributes.forEach((String name, String value) {
150 recurse(html, context, { 94 if (!requiredAttributes.contains(name) &&
151 'refactoring': (dom.Element child) { 95 !optionalAttributes.contains(name)) {
152 refactorings.add(refactoringFromHtml(child)); 96 throw new Exception(
97 '$context: Unexpected attribute in ${element.localName}: $name');
153 } 98 }
99 attributesFound.add(name);
154 }); 100 });
155 return new Refactorings(refactorings, html); 101 for (String expectedAttribute in requiredAttributes) {
102 if (!attributesFound.contains(expectedAttribute)) {
103 throw new Exception(
104 '$context: ${element.localName} must contain attribute ${expectedAttri bute}');
105 }
106 }
156 } 107 }
157 108
158 /** 109 /**
159 * Create a [Refactoring] object from an HTML representation such as: 110 * Check that the given [element] has the given [expectedName].
160 *
161 * <refactoring kind="refactoringKind">
162 * <feedback>...</feedback> <!-- optional -->
163 * <options>...</options> <!-- optional -->
164 * </refactoring>
165 *
166 * <feedback> and <options> have the same form as <object>, as described in
167 * [typeDeclFromHtml].
168 *
169 * Child elements can occur in any order.
170 */ 111 */
171 Refactoring refactoringFromHtml(dom.Element html) { 112 void checkName(dom.Element element, String expectedName, [String context]) {
172 checkName(html, 'refactoring'); 113 if (element.localName != expectedName) {
173 String kind = html.attributes['kind']; 114 if (context == null) {
174 String context = kind != null ? kind : 'refactoring'; 115 context = element.localName;
175 checkAttributes(html, ['kind'], context);
176 TypeDecl feedback;
177 TypeDecl options;
178 recurse(html, context, {
179 'feedback': (dom.Element child) {
180 feedback = typeObjectFromHtml(child, '$context.feedback');
181 },
182 'options': (dom.Element child) {
183 options = typeObjectFromHtml(child, '$context.options');
184 } 116 }
185 }); 117 throw new Exception(
186 return new Refactoring(kind, feedback, options, html); 118 '$context: Expected $expectedName, found ${element.localName}');
119 }
187 } 120 }
188
189 /**
190 * Create a [Types] object from an HTML representation such as:
191 *
192 * <types>
193 * <type name="...">...</type> <!-- zero or more -->
194 * </types>
195 */
196 Types typesFromHtml(dom.Element html) {
197 checkName(html, 'types');
198 String context = 'types';
199 checkAttributes(html, [], context);
200 Map<String, TypeDefinition> types = <String, TypeDefinition> {};
201 recurse(html, context, {
202 'type': (dom.Element child) {
203 TypeDefinition typeDefinition = typeDefinitionFromHtml(child);
204 types[typeDefinition.name] = typeDefinition;
205 }
206 });
207 return new Types(types, html);
208 }
209
210 /**
211 * Create a [TypeDefinition] object from an HTML representation such as:
212 *
213 * <type name="typeName">
214 * TYPE
215 * </type>
216 *
217 * Where TYPE is any HTML that can be parsed by [typeDeclFromHtml].
218 *
219 * Child elements can occur in any order.
220 */
221 TypeDefinition typeDefinitionFromHtml(dom.Element html) {
222 checkName(html, 'type');
223 String name = html.attributes['name'];
224 String context = name != null ? name : 'type';
225 checkAttributes(html, ['name'], context);
226 TypeDecl type = processContentsAsType(html, context);
227 return new TypeDefinition(name, type, html);
228 }
229
230 /** 121 /**
231 * Create a [Domain] object from an HTML representation such as: 122 * Create a [Domain] object from an HTML representation such as:
232 * 123 *
233 * <domain name="domainName"> 124 * <domain name="domainName">
234 * <request method="...">...</request> <!-- zero or more --> 125 * <request method="...">...</request> <!-- zero or more -->
235 * <notification event="...">...</notification> <!-- zero or more --> 126 * <notification event="...">...</notification> <!-- zero or more -->
236 * </domain> 127 * </domain>
237 * 128 *
238 * Child elements can occur in any order. 129 * Child elements can occur in any order.
239 */ 130 */
240 Domain domainFromHtml(dom.Element html) { 131 Domain domainFromHtml(dom.Element html) {
241 checkName(html, 'domain'); 132 checkName(html, 'domain');
242 String name = html.attributes['name']; 133 String name = html.attributes['name'];
243 String context = name != null ? name : 'domain'; 134 String context = name != null ? name : 'domain';
244 checkAttributes(html, ['name'], context); 135 checkAttributes(html, ['name'], context);
245 List<Request> requests = <Request>[]; 136 List<Request> requests = <Request>[];
246 List<Notification> notifications = <Notification>[]; 137 List<Notification> notifications = <Notification>[];
247 recurse(html, context, { 138 recurse(html, context, {
248 'request': (dom.Element child) { 139 'request': (dom.Element child) {
249 requests.add(requestFromHtml(child, context)); 140 requests.add(requestFromHtml(child, context));
250 }, 141 },
251 'notification': (dom.Element child) { 142 'notification': (dom.Element child) {
252 notifications.add(notificationFromHtml(child, context)); 143 notifications.add(notificationFromHtml(child, context));
253 } 144 }
254 }); 145 });
255 return new Domain(name, requests, notifications, html); 146 return new Domain(name, requests, notifications, html);
256 } 147 }
257 148
258 /** 149 dom.Element getAncestor(dom.Element html, String name, String context) {
259 * Create a [Request] object from an HTML representation such as: 150 dom.Element ancestor = html.parent;
260 * 151 while (ancestor != null) {
261 * <request method="methodName"> 152 if (ancestor.localName == name) {
262 * <params>...</params> <!-- optional --> 153 return ancestor;
263 * <result>...</result> <!-- optional -->
264 * </request>
265 *
266 * Note that the method name should not include the domain name.
267 *
268 * <params> and <result> have the same form as <object>, as described in
269 * [typeDeclFromHtml].
270 *
271 * Child elements can occur in any order.
272 */
273 Request requestFromHtml(dom.Element html, String context) {
274 String domainName = getAncestor(html, 'domain', context).attributes['name'];
275 checkName(html, 'request', context);
276 String method = html.attributes['method'];
277 context = '$context.${method != null ? method : 'method'}';
278 checkAttributes(html, ['method'], context);
279 TypeDecl params;
280 TypeDecl result;
281 recurse(html, context, {
282 'params': (dom.Element child) {
283 params = typeObjectFromHtml(child, '$context.params');
284 },
285 'result': (dom.Element child) {
286 result = typeObjectFromHtml(child, '$context.result');
287 } 154 }
288 }); 155 ancestor = ancestor.parent;
289 return new Request(domainName, method, params, result, html); 156 }
157 throw new Exception(
158 '$context: <${html.localName}> must be nested within <$name>');
290 } 159 }
291 160
292 /** 161 /**
293 * Create a [Notification] object from an HTML representation such as: 162 * Create a [Notification] object from an HTML representation such as:
294 * 163 *
295 * <notification event="methodName"> 164 * <notification event="methodName">
296 * <params>...</params> <!-- optional --> 165 * <params>...</params> <!-- optional -->
297 * </notification> 166 * </notification>
298 * 167 *
299 * Note that the event name should not include the domain name. 168 * Note that the event name should not include the domain name.
300 * 169 *
301 * <params> has the same form as <object>, as described in [typeDeclFromHtml]. 170 * <params> has the same form as <object>, as described in [typeDeclFromHtml].
302 * 171 *
303 * Child elements can occur in any order. 172 * Child elements can occur in any order.
304 */ 173 */
305 Notification notificationFromHtml(dom.Element html, String context) { 174 Notification notificationFromHtml(dom.Element html, String context) {
306 String domainName = getAncestor(html, 'domain', context).attributes['name']; 175 String domainName = getAncestor(html, 'domain', context).attributes['name'];
307 checkName(html, 'notification', context); 176 checkName(html, 'notification', context);
308 String event = html.attributes['event']; 177 String event = html.attributes['event'];
309 context = '$context.${event != null ? event : 'event'}'; 178 context = '$context.${event != null ? event : 'event'}';
310 checkAttributes(html, ['event'], context); 179 checkAttributes(html, ['event'], context);
311 TypeDecl params; 180 TypeDecl params;
312 recurse(html, context, { 181 recurse(html, context, {
313 'params': (dom.Element child) { 182 'params': (dom.Element child) {
314 params = typeObjectFromHtml(child, '$context.params'); 183 params = typeObjectFromHtml(child, '$context.params');
315 } 184 }
316 }); 185 });
317 return new Notification(domainName, event, params, html); 186 return new Notification(domainName, event, params, html);
318 } 187 }
188
319 /** 189 /**
320 * Create a single of [TypeDecl] corresponding to the type defined inside the 190 * Create a single of [TypeDecl] corresponding to the type defined inside the
321 * given HTML element. 191 * given HTML element.
322 */ 192 */
323 TypeDecl processContentsAsType(dom.Element html, String context) { 193 TypeDecl processContentsAsType(dom.Element html, String context) {
324 List<TypeDecl> types = processContentsAsTypes(html, context); 194 List<TypeDecl> types = processContentsAsTypes(html, context);
325 if (types.length != 1) { 195 if (types.length != 1) {
326 throw new Exception('$context: Exactly one type must be specified'); 196 throw new Exception('$context: Exactly one type must be specified');
327 } 197 }
328 return types[0]; 198 return types[0];
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 'enum': (dom.Element child) { 266 'enum': (dom.Element child) {
397 types.add(typeEnumFromHtml(child, context)); 267 types.add(typeEnumFromHtml(child, context));
398 }, 268 },
399 'ref': (dom.Element child) { 269 'ref': (dom.Element child) {
400 checkAttributes(child, [], context); 270 checkAttributes(child, [], context);
401 types.add(new TypeReference(innerText(child), child)); 271 types.add(new TypeReference(innerText(child), child));
402 }, 272 },
403 'union': (dom.Element child) { 273 'union': (dom.Element child) {
404 checkAttributes(child, ['field'], context); 274 checkAttributes(child, ['field'], context);
405 String field = child.attributes['field']; 275 String field = child.attributes['field'];
406 types.add(new TypeUnion(processContentsAsTypes(child, context), field, 276 types.add(
407 child)); 277 new TypeUnion(processContentsAsTypes(child, context), field, child));
408 } 278 }
409 }); 279 });
410 return types; 280 return types;
411 } 281 }
412 282
413 /** 283 /**
284 * Read the API description from the file 'spec_input.html'.
285 */
286 Api readApi() {
287 File htmlFile = new File('spec_input.html');
288 String htmlContents = htmlFile.readAsStringSync();
289 dom.Document document = parser.parse(htmlContents);
290 return apiFromHtml(document.firstChild);
291 }
292
293 void recurse(dom.Element parent, String context, Map<String,
294 ElementProcessor> elementProcessors) {
295 for (String key in elementProcessors.keys) {
296 if (!specialElements.contains(key)) {
297 throw new Exception('$context: $key is not a special element');
298 }
299 }
300 for (dom.Node node in parent.nodes) {
301 if (node is dom.Element) {
302 if (elementProcessors.containsKey(node.localName)) {
303 elementProcessors[node.localName](node);
304 } else if (specialElements.contains(node.localName)) {
305 throw new Exception('$context: Unexpected use of <${node.localName}');
306 } else {
307 recurse(node, context, elementProcessors);
308 }
309 }
310 }
311 }
312
313 /**
314 * Create a [Refactoring] object from an HTML representation such as:
315 *
316 * <refactoring kind="refactoringKind">
317 * <feedback>...</feedback> <!-- optional -->
318 * <options>...</options> <!-- optional -->
319 * </refactoring>
320 *
321 * <feedback> and <options> have the same form as <object>, as described in
322 * [typeDeclFromHtml].
323 *
324 * Child elements can occur in any order.
325 */
326 Refactoring refactoringFromHtml(dom.Element html) {
327 checkName(html, 'refactoring');
328 String kind = html.attributes['kind'];
329 String context = kind != null ? kind : 'refactoring';
330 checkAttributes(html, ['kind'], context);
331 TypeDecl feedback;
332 TypeDecl options;
333 recurse(html, context, {
334 'feedback': (dom.Element child) {
335 feedback = typeObjectFromHtml(child, '$context.feedback');
336 },
337 'options': (dom.Element child) {
338 options = typeObjectFromHtml(child, '$context.options');
339 }
340 });
341 return new Refactoring(kind, feedback, options, html);
342 }
343
344 /**
345 * Create a [Refactorings] object from an HTML representation such as:
346 *
347 * <refactorings>
348 * <refactoring kind="...">...</refactoring> <!-- zero or more -->
349 * </refactorings>
350 */
351 Refactorings refactoringsFromHtml(dom.Element html) {
352 checkName(html, 'refactorings');
353 String context = 'refactorings';
354 checkAttributes(html, [], context);
355 List<Refactoring> refactorings = <Refactoring>[];
356 recurse(html, context, {
357 'refactoring': (dom.Element child) {
358 refactorings.add(refactoringFromHtml(child));
359 }
360 });
361 return new Refactorings(refactorings, html);
362 }
363
364 /**
365 * Create a [Request] object from an HTML representation such as:
366 *
367 * <request method="methodName">
368 * <params>...</params> <!-- optional -->
369 * <result>...</result> <!-- optional -->
370 * </request>
371 *
372 * Note that the method name should not include the domain name.
373 *
374 * <params> and <result> have the same form as <object>, as described in
375 * [typeDeclFromHtml].
376 *
377 * Child elements can occur in any order.
378 */
379 Request requestFromHtml(dom.Element html, String context) {
380 String domainName = getAncestor(html, 'domain', context).attributes['name'];
381 checkName(html, 'request', context);
382 String method = html.attributes['method'];
383 context = '$context.${method != null ? method : 'method'}';
384 checkAttributes(html, ['method'], context);
385 TypeDecl params;
386 TypeDecl result;
387 recurse(html, context, {
388 'params': (dom.Element child) {
389 params = typeObjectFromHtml(child, '$context.params');
390 },
391 'result': (dom.Element child) {
392 result = typeObjectFromHtml(child, '$context.result');
393 }
394 });
395 return new Request(domainName, method, params, result, html);
396 }
397
398 /**
399 * Create a [TypeDefinition] object from an HTML representation such as:
400 *
401 * <type name="typeName">
402 * TYPE
403 * </type>
404 *
405 * Where TYPE is any HTML that can be parsed by [typeDeclFromHtml].
406 *
407 * Child elements can occur in any order.
408 */
409 TypeDefinition typeDefinitionFromHtml(dom.Element html) {
410 checkName(html, 'type');
411 String name = html.attributes['name'];
412 String context = name != null ? name : 'type';
413 checkAttributes(html, ['name'], context);
414 TypeDecl type = processContentsAsType(html, context);
415 return new TypeDefinition(name, type, html);
416 }
417 /**
414 * Create a [TypeEnum] from an HTML description. 418 * Create a [TypeEnum] from an HTML description.
415 */ 419 */
416 TypeEnum typeEnumFromHtml(dom.Element html, String context) { 420 TypeEnum typeEnumFromHtml(dom.Element html, String context) {
417 checkName(html, 'enum', context); 421 checkName(html, 'enum', context);
418 checkAttributes(html, [], context); 422 checkAttributes(html, [], context);
419 List<TypeEnumValue> values = <TypeEnumValue>[]; 423 List<TypeEnumValue> values = <TypeEnumValue>[];
420 recurse(html, context, { 424 recurse(html, context, {
421 'value': (dom.Element child) { 425 'value': (dom.Element child) {
422 values.add(typeEnumValueFromHtml(child, context)); 426 values.add(typeEnumValueFromHtml(child, context));
423 } 427 }
(...skipping 22 matching lines...) Expand all
446 values.add(text); 450 values.add(text);
447 } 451 }
448 }); 452 });
449 if (values.length != 1) { 453 if (values.length != 1) {
450 throw new Exception('$context: Exactly one value must be specified'); 454 throw new Exception('$context: Exactly one value must be specified');
451 } 455 }
452 return new TypeEnumValue(values[0], html); 456 return new TypeEnumValue(values[0], html);
453 } 457 }
454 458
455 /** 459 /**
456 * Create a [TypeObject] from an HTML description.
457 */
458 TypeObject typeObjectFromHtml(dom.Element html, String context) {
459 checkAttributes(html, [], context);
460 List<TypeObjectField> fields = <TypeObjectField>[];
461 recurse(html, context, {
462 'field': (dom.Element child) {
463 fields.add(typeObjectFieldFromHtml(child, context));
464 }
465 });
466 return new TypeObject(fields, html);
467 }
468
469 /**
470 * Create a [TypeObjectField] from an HTML description such as: 460 * Create a [TypeObjectField] from an HTML description such as:
471 * 461 *
472 * <field name="fieldName"> 462 * <field name="fieldName">
473 * TYPE 463 * TYPE
474 * </field> 464 * </field>
475 * 465 *
476 * Where TYPE is any HTML that can be parsed by [typeDeclFromHtml]. 466 * Where TYPE is any HTML that can be parsed by [typeDeclFromHtml].
477 * 467 *
478 * In addition, the attribute optional="true" may be used to specify that the 468 * In addition, the attribute optional="true" may be used to specify that the
479 * field is optional, and the attribute value="..." may be used to specify that 469 * field is optional, and the attribute value="..." may be used to specify that
480 * the field is required to have a certain value. 470 * the field is required to have a certain value.
481 * 471 *
482 * Child elements can occur in any order. 472 * Child elements can occur in any order.
483 */ 473 */
484 TypeObjectField typeObjectFieldFromHtml(dom.Element html, String context) { 474 TypeObjectField typeObjectFieldFromHtml(dom.Element html, String context) {
485 checkName(html, 'field', context); 475 checkName(html, 'field', context);
486 String name = html.attributes['name']; 476 String name = html.attributes['name'];
487 context = '$context.${name != null ? name : 'field'}'; 477 context = '$context.${name != null ? name : 'field'}';
488 checkAttributes(html, ['name'], context, optionalAttributes: ['optional', 478 checkAttributes(
489 'value']); 479 html,
480 ['name'],
481 context,
482 optionalAttributes: ['optional', 'value']);
490 bool optional = false; 483 bool optional = false;
491 String optionalString = html.attributes['optional']; 484 String optionalString = html.attributes['optional'];
492 if (optionalString != null) { 485 if (optionalString != null) {
493 switch (optionalString) { 486 switch (optionalString) {
494 case 'true': 487 case 'true':
495 optional = true; 488 optional = true;
496 break; 489 break;
497 case 'false': 490 case 'false':
498 optional = false; 491 optional = false;
499 break; 492 break;
500 default: 493 default:
501 throw new Exception( 494 throw new Exception(
502 '$context: field contains invalid "optional" attribute: "$optionalSt ring"'); 495 '$context: field contains invalid "optional" attribute: "$optionalSt ring"');
503 } 496 }
504 } 497 }
505 String value = html.attributes['value']; 498 String value = html.attributes['value'];
506 TypeDecl type = processContentsAsType(html, context); 499 TypeDecl type = processContentsAsType(html, context);
507 return new TypeObjectField(name, type, html, optional: optional, value: value 500 return new TypeObjectField(
508 ); 501 name,
502 type,
503 html,
504 optional: optional,
505 value: value);
509 } 506 }
510 507
511 /** 508 /**
512 * Read the API description from the file 'spec_input.html'. 509 * Create a [TypeObject] from an HTML description.
513 */ 510 */
514 Api readApi() { 511 TypeObject typeObjectFromHtml(dom.Element html, String context) {
515 File htmlFile = new File('spec_input.html'); 512 checkAttributes(html, [], context);
516 String htmlContents = htmlFile.readAsStringSync(); 513 List<TypeObjectField> fields = <TypeObjectField>[];
517 dom.Document document = parser.parse(htmlContents); 514 recurse(html, context, {
518 return apiFromHtml(document.firstChild); 515 'field': (dom.Element child) {
516 fields.add(typeObjectFieldFromHtml(child, context));
517 }
518 });
519 return new TypeObject(fields, html);
519 } 520 }
521
522 /**
523 * Create a [Types] object from an HTML representation such as:
524 *
525 * <types>
526 * <type name="...">...</type> <!-- zero or more -->
527 * </types>
528 */
529 Types typesFromHtml(dom.Element html) {
530 checkName(html, 'types');
531 String context = 'types';
532 checkAttributes(html, [], context);
533 Map<String, TypeDefinition> types = <String, TypeDefinition>{};
534 recurse(html, context, {
535 'type': (dom.Element child) {
536 TypeDefinition typeDefinition = typeDefinitionFromHtml(child);
537 types[typeDefinition.name] = typeDefinition;
538 }
539 });
540 return new Types(types, html);
541 }
542
543 typedef void ElementProcessor(dom.Element element);
544
545 typedef void TextProcessor(dom.Text text);
OLDNEW
« no previous file with comments | « pkg/analysis_server/tool/spec/codegen_tools.dart ('k') | pkg/analysis_server/tool/spec/generate_all.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698