| 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 |