| 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 library codegen.protocol; | 5 library codegen.protocol; |
| 6 | 6 |
| 7 import 'dart:convert'; | 7 import 'dart:convert'; |
| 8 | 8 |
| 9 import 'api.dart'; | 9 import 'api.dart'; |
| 10 import 'codegen_tools.dart'; | 10 import 'codegen_tools.dart'; |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 const Map<String, String> specialElementFlags = const { | 171 const Map<String, String> specialElementFlags = const { |
| 172 'abstract': '0x01', | 172 'abstract': '0x01', |
| 173 'const': '0x02', | 173 'const': '0x02', |
| 174 'final': '0x04', | 174 'final': '0x04', |
| 175 'static': '0x08', | 175 'static': '0x08', |
| 176 'private': '0x10', | 176 'private': '0x10', |
| 177 'deprecated': '0x20' | 177 'deprecated': '0x20' |
| 178 }; | 178 }; |
| 179 | 179 |
| 180 /** | 180 /** |
| 181 * Callback type used to represent arbitrary code generation. |
| 182 */ |
| 183 typedef void CodegenCallback(); |
| 184 |
| 185 /** |
| 181 * Visitor which produces Dart code representing the API. | 186 * Visitor which produces Dart code representing the API. |
| 182 */ | 187 */ |
| 183 class CodegenProtocolVisitor extends HierarchicalApiVisitor with CodeGenerator { | 188 class CodegenProtocolVisitor extends HierarchicalApiVisitor with CodeGenerator { |
| 184 /** | 189 /** |
| 185 * Type references in the spec that are named something else in Dart. | 190 * Type references in the spec that are named something else in Dart. |
| 186 */ | 191 */ |
| 187 static const Map<String, String> _typeRenames = const { | 192 static const Map<String, String> _typeRenames = const { |
| 188 'object': 'Object', | 193 'object': 'Object', |
| 189 }; | 194 }; |
| 190 | 195 |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 return false; | 445 return false; |
| 441 } | 446 } |
| 442 } | 447 } |
| 443 | 448 |
| 444 /** | 449 /** |
| 445 * Emit the constructor for an object class. | 450 * Emit the constructor for an object class. |
| 446 */ | 451 */ |
| 447 void emitObjectConstructor(TypeObject type, String className) { | 452 void emitObjectConstructor(TypeObject type, String className) { |
| 448 List<String> args = <String>[]; | 453 List<String> args = <String>[]; |
| 449 List<String> optionalArgs = <String>[]; | 454 List<String> optionalArgs = <String>[]; |
| 455 List<CodegenCallback> extraInitCode = <CodegenCallback>[]; |
| 450 for (TypeObjectField field in type.fields) { | 456 for (TypeObjectField field in type.fields) { |
| 451 if (field.value != null) { | 457 if (field.value != null) { |
| 452 continue; | 458 continue; |
| 453 } | 459 } |
| 454 String arg = 'this.${field.name}'; | 460 String arg = 'this.${field.name}'; |
| 455 if (field.optional) { | 461 if (field.optional) { |
| 456 optionalArgs.add(arg); | 462 optionalArgs.add(arg); |
| 463 TypeDecl fieldType = field.type; |
| 464 if (fieldType is TypeList) { |
| 465 extraInitCode.add(() { |
| 466 writeln('if (${field.name} == null) {'); |
| 467 indent(() { |
| 468 writeln('${field.name} = <${dartType(fieldType.itemType)}>[];'); |
| 469 }); |
| 470 writeln('}'); |
| 471 }); |
| 472 } |
| 457 } else { | 473 } else { |
| 458 args.add(arg); | 474 args.add(arg); |
| 459 } | 475 } |
| 460 } | 476 } |
| 461 if (optionalArgs.isNotEmpty) { | 477 if (optionalArgs.isNotEmpty) { |
| 462 args.add('{${optionalArgs.join(', ')}}'); | 478 args.add('{${optionalArgs.join(', ')}}'); |
| 463 } | 479 } |
| 464 writeln('$className(${args.join(', ')});'); | 480 write('$className(${args.join(', ')})'); |
| 481 if (extraInitCode.isEmpty) { |
| 482 writeln(';'); |
| 483 } else { |
| 484 writeln(' {'); |
| 485 indent(() { |
| 486 for (CodegenCallback callback in extraInitCode) { |
| 487 callback(); |
| 488 } |
| 489 }); |
| 490 writeln('}'); |
| 491 } |
| 465 } | 492 } |
| 466 | 493 |
| 467 /** | 494 /** |
| 468 * Emit the toJson() code for an object class. | 495 * Emit the toJson() code for an object class. |
| 469 */ | 496 */ |
| 470 void emitToJsonMember(TypeObject type) { | 497 void emitToJsonMember(TypeObject type) { |
| 471 writeln('Map<String, dynamic> toJson() {'); | 498 writeln('Map<String, dynamic> toJson() {'); |
| 472 indent(() { | 499 indent(() { |
| 473 writeln('Map<String, dynamic> result = {};'); | 500 writeln('Map<String, dynamic> result = {};'); |
| 474 for (TypeObjectField field in type.fields) { | 501 for (TypeObjectField field in type.fields) { |
| 475 String fieldNameString = literalString(field.name); | 502 String fieldNameString = literalString(field.name); |
| 476 if (field.value != null) { | 503 if (field.value != null) { |
| 477 writeln('result[$fieldNameString] = ${literalString(field.value)};'); | 504 writeln('result[$fieldNameString] = ${literalString(field.value)};'); |
| 478 continue; | 505 continue; |
| 479 } | 506 } |
| 480 String fieldToJson = toJsonCode(field.type).asSnippet(field.name); | 507 String fieldToJson = toJsonCode(field.type).asSnippet(field.name); |
| 481 String populateField = 'result[$fieldNameString] = $fieldToJson;'; | 508 String populateField = 'result[$fieldNameString] = $fieldToJson;'; |
| 482 if (field.optional) { | 509 if (field.optional) { |
| 483 writeln('if (${field.name} != null) {'); | 510 String condition; |
| 511 if (field.type is TypeList) { |
| 512 condition = '${field.name}.isNotEmpty'; |
| 513 } else { |
| 514 condition = '${field.name} != null'; |
| 515 } |
| 516 writeln('if ($condition) {'); |
| 484 indent(() { | 517 indent(() { |
| 485 writeln(populateField); | 518 writeln(populateField); |
| 486 }); | 519 }); |
| 487 writeln('}'); | 520 writeln('}'); |
| 488 } else { | 521 } else { |
| 489 writeln(populateField); | 522 writeln(populateField); |
| 490 } | 523 } |
| 491 } | 524 } |
| 492 writeln('return result;'); | 525 writeln('return result;'); |
| 493 }); | 526 }); |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 'throw jsonDecoder.mismatch(jsonPath, "equal " + $valueString)
;'); | 797 'throw jsonDecoder.mismatch(jsonPath, "equal " + $valueString)
;'); |
| 765 }); | 798 }); |
| 766 writeln('}'); | 799 writeln('}'); |
| 767 continue; | 800 continue; |
| 768 } | 801 } |
| 769 if (field.optional) { | 802 if (field.optional) { |
| 770 optionalArgs.add('${field.name}: ${field.name}'); | 803 optionalArgs.add('${field.name}: ${field.name}'); |
| 771 } else { | 804 } else { |
| 772 args.add(field.name); | 805 args.add(field.name); |
| 773 } | 806 } |
| 774 String fieldDartType = dartType(field.type); | 807 TypeDecl fieldType = field.type; |
| 808 String fieldDartType = dartType(fieldType); |
| 775 writeln('$fieldDartType ${field.name};'); | 809 writeln('$fieldDartType ${field.name};'); |
| 776 writeln('if (json.containsKey($fieldNameString)) {'); | 810 writeln('if (json.containsKey($fieldNameString)) {'); |
| 777 indent(() { | 811 indent(() { |
| 778 String toJson = fromJsonCode(field.type).asSnippet(jsonPath, | 812 String toJson = fromJsonCode(fieldType).asSnippet(jsonPath, |
| 779 fieldAccessor); | 813 fieldAccessor); |
| 780 writeln('${field.name} = $toJson;'); | 814 writeln('${field.name} = $toJson;'); |
| 781 }); | 815 }); |
| 782 write('}'); | 816 write('}'); |
| 783 if (!field.optional) { | 817 if (!field.optional) { |
| 784 writeln(' else {'); | 818 writeln(' else {'); |
| 785 indent(() { | 819 indent(() { |
| 786 writeln( | 820 writeln( |
| 787 "throw jsonDecoder.missingKey(jsonPath, $fieldNameString);"); | 821 "throw jsonDecoder.missingKey(jsonPath, $fieldNameString);"); |
| 788 }); | 822 }); |
| 789 writeln('}'); | 823 writeln('}'); |
| 824 } else if (fieldType is TypeList) { |
| 825 writeln(' else {'); |
| 826 indent(() { |
| 827 writeln('${field.name} = <${dartType(fieldType.itemType)}>[];'); |
| 828 }); |
| 829 writeln('}'); |
| 790 } else { | 830 } else { |
| 791 writeln(); | 831 writeln(); |
| 792 } | 832 } |
| 793 } | 833 } |
| 794 args.addAll(optionalArgs); | 834 args.addAll(optionalArgs); |
| 795 writeln('return new $className(${args.join(', ')});'); | 835 writeln('return new $className(${args.join(', ')});'); |
| 796 }); | 836 }); |
| 797 writeln('} else {'); | 837 writeln('} else {'); |
| 798 indent(() { | 838 indent(() { |
| 799 writeln( | 839 writeln( |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 CodegenProtocolVisitor visitor = new CodegenProtocolVisitor(readApi()); | 1073 CodegenProtocolVisitor visitor = new CodegenProtocolVisitor(readApi()); |
| 1034 return visitor.collectCode(visitor.visitApi); | 1074 return visitor.collectCode(visitor.visitApi); |
| 1035 }); | 1075 }); |
| 1036 | 1076 |
| 1037 /** | 1077 /** |
| 1038 * Translate spec_input.html into protocol_matchers.dart. | 1078 * Translate spec_input.html into protocol_matchers.dart. |
| 1039 */ | 1079 */ |
| 1040 main() { | 1080 main() { |
| 1041 target.generate(); | 1081 target.generate(); |
| 1042 } | 1082 } |
| OLD | NEW |