OLD | NEW |
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'; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 if (!attributesFound.contains(expectedAttribute)) { | 44 if (!attributesFound.contains(expectedAttribute)) { |
45 throw new Exception( | 45 throw new Exception( |
46 '${element.localName} must contain attribute ${expectedAttribute}'); | 46 '${element.localName} must contain attribute ${expectedAttribute}'); |
47 } | 47 } |
48 } | 48 } |
49 } | 49 } |
50 | 50 |
51 const List<String> specialElements = const ['domain', 'feedback', | 51 const List<String> specialElements = const ['domain', 'feedback', |
52 'object', 'refactorings', 'refactoring', 'type', 'types', 'request', | 52 'object', 'refactorings', 'refactoring', 'type', 'types', 'request', |
53 'notification', 'params', 'result', 'field', 'list', 'map', 'enum', 'key', | 53 'notification', 'params', 'result', 'field', 'list', 'map', 'enum', 'key', |
54 'value', 'options', 'ref', 'code', 'version']; | 54 'value', 'options', 'ref', 'code', 'version', 'union']; |
55 | 55 |
56 typedef void ElementProcessor(dom.Element element); | 56 typedef void ElementProcessor(dom.Element element); |
57 typedef void TextProcessor(dom.Text text); | 57 typedef void TextProcessor(dom.Text text); |
58 | 58 |
59 void recurse(dom.Element parent, Map<String, ElementProcessor> | 59 void recurse(dom.Element parent, Map<String, ElementProcessor> |
60 elementProcessors) { | 60 elementProcessors) { |
61 for (String key in elementProcessors.keys) { | 61 for (String key in elementProcessors.keys) { |
62 if (!specialElements.contains(key)) { | 62 if (!specialElements.contains(key)) { |
63 throw new Exception('$key is not a special element'); | 63 throw new Exception('$key is not a special element'); |
64 } | 64 } |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 checkAttributes(html, ['event']); | 296 checkAttributes(html, ['event']); |
297 String event = html.attributes['event']; | 297 String event = html.attributes['event']; |
298 TypeDecl params; | 298 TypeDecl params; |
299 recurse(html, { | 299 recurse(html, { |
300 'params': (dom.Element child) { | 300 'params': (dom.Element child) { |
301 params = typeObjectFromHtml(child); | 301 params = typeObjectFromHtml(child); |
302 } | 302 } |
303 }); | 303 }); |
304 return new Notification(domainName, event, params, html); | 304 return new Notification(domainName, event, params, html); |
305 } | 305 } |
| 306 /** |
| 307 * Create a single of [TypeDecl] corresponding to the type defined inside the |
| 308 * given HTML element. |
| 309 */ |
| 310 TypeDecl processContentsAsType(dom.Element html) { |
| 311 List<TypeDecl> types = processContentsAsTypes(html); |
| 312 if (types.length != 1) { |
| 313 throw new Exception('Exactly one type must be specified'); |
| 314 } |
| 315 return types[0]; |
| 316 } |
306 | 317 |
307 /** | 318 /** |
308 * Create a [TypeDecl] from an HTML description. The following forms are | 319 * Create a list of [TypeDecl]s corresponding to the types defined inside the |
309 * supported. | 320 * given HTML element. The following forms are supported. |
310 * | 321 * |
311 * To refer to a type declared elsewhere (or a built-in type): | 322 * To refer to a type declared elsewhere (or a built-in type): |
312 * | 323 * |
313 * <ref>typeName</ref> | 324 * <ref>typeName</ref> |
314 * | 325 * |
315 * For a list: <list>ItemType</list> | 326 * For a list: <list>ItemType</list> |
316 * | 327 * |
317 * For a map: <map><key>KeyType</key><value>ValueType</value></map> | 328 * For a map: <map><key>KeyType</key><value>ValueType</value></map> |
318 * | 329 * |
319 * For a JSON object: | 330 * For a JSON object: |
320 * | 331 * |
321 * <object> | 332 * <object> |
322 * <field name="...">...</field> <!-- zero or more --> | 333 * <field name="...">...</field> <!-- zero or more --> |
323 * </object> | 334 * </object> |
324 * | 335 * |
325 * For an enum: | 336 * For an enum: |
326 * | 337 * |
327 * <enum> | 338 * <enum> |
328 * <value>...</value> <!-- zero or more --> | 339 * <value>...</value> <!-- zero or more --> |
329 * </enum> | 340 * </enum> |
| 341 * |
| 342 * For a union type: |
| 343 * <union> |
| 344 * TYPE <!-- zero or more --> |
| 345 * </union> |
330 */ | 346 */ |
331 TypeDecl processContentsAsType(dom.Element html) { | 347 List<TypeDecl> processContentsAsTypes(dom.Element html) { |
332 List<TypeDecl> types = <TypeDecl>[]; | 348 List<TypeDecl> types = <TypeDecl>[]; |
333 recurse(html, { | 349 recurse(html, { |
334 'object': (dom.Element child) { | 350 'object': (dom.Element child) { |
335 types.add(typeObjectFromHtml(child)); | 351 types.add(typeObjectFromHtml(child)); |
336 }, | 352 }, |
337 'list': (dom.Element child) { | 353 'list': (dom.Element child) { |
338 checkAttributes(child, []); | 354 checkAttributes(child, []); |
339 types.add(new TypeList(processContentsAsType(child), child)); | 355 types.add(new TypeList(processContentsAsType(child), child)); |
340 }, | 356 }, |
341 'map': (dom.Element child) { | 357 'map': (dom.Element child) { |
(...skipping 21 matching lines...) Expand all Loading... |
363 throw new Exception('Value type not specified'); | 379 throw new Exception('Value type not specified'); |
364 } | 380 } |
365 types.add(new TypeMap(keyType, valueType, child)); | 381 types.add(new TypeMap(keyType, valueType, child)); |
366 }, | 382 }, |
367 'enum': (dom.Element child) { | 383 'enum': (dom.Element child) { |
368 types.add(typeEnumFromHtml(child)); | 384 types.add(typeEnumFromHtml(child)); |
369 }, | 385 }, |
370 'ref': (dom.Element child) { | 386 'ref': (dom.Element child) { |
371 checkAttributes(child, []); | 387 checkAttributes(child, []); |
372 types.add(new TypeReference(innerText(child), child)); | 388 types.add(new TypeReference(innerText(child), child)); |
| 389 }, |
| 390 'union': (dom.Element child) { |
| 391 checkAttributes(child, []); |
| 392 types.add(new TypeUnion(processContentsAsTypes(child), child)); |
373 } | 393 } |
374 }); | 394 }); |
375 if (types.length != 1) { | 395 return types; |
376 throw new Exception('Exactly one type must be specified'); | |
377 } | |
378 return types[0]; | |
379 } | 396 } |
380 | 397 |
381 /** | 398 /** |
382 * Create a [TypeEnum] from an HTML description. | 399 * Create a [TypeEnum] from an HTML description. |
383 */ | 400 */ |
384 TypeEnum typeEnumFromHtml(dom.Element html) { | 401 TypeEnum typeEnumFromHtml(dom.Element html) { |
385 checkName(html, 'enum'); | 402 checkName(html, 'enum'); |
386 checkAttributes(html, []); | 403 checkAttributes(html, []); |
387 List<TypeEnumValue> values = <TypeEnumValue>[]; | 404 List<TypeEnumValue> values = <TypeEnumValue>[]; |
388 recurse(html, { | 405 recurse(html, { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 | 493 |
477 /** | 494 /** |
478 * Read the API description from the file 'spec_input.html'. | 495 * Read the API description from the file 'spec_input.html'. |
479 */ | 496 */ |
480 Api readApi() { | 497 Api readApi() { |
481 File htmlFile = new File('spec_input.html'); | 498 File htmlFile = new File('spec_input.html'); |
482 String htmlContents = htmlFile.readAsStringSync(); | 499 String htmlContents = htmlFile.readAsStringSync(); |
483 dom.Document document = parser.parse(htmlContents); | 500 dom.Document document = parser.parse(htmlContents); |
484 return apiFromHtml(document.firstChild); | 501 return apiFromHtml(document.firstChild); |
485 } | 502 } |
OLD | NEW |