| 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_dart.dart'; |
| 10 import 'codegen_tools.dart'; | 11 import 'codegen_tools.dart'; |
| 11 import 'from_html.dart'; | 12 import 'from_html.dart'; |
| 12 import 'implied_types.dart'; | 13 import 'implied_types.dart'; |
| 13 import 'to_html.dart'; | 14 import 'to_html.dart'; |
| 14 | 15 |
| 15 import 'package:html5lib/dom.dart' as dom; | 16 import 'package:html5lib/dom.dart' as dom; |
| 16 | 17 |
| 17 /** | 18 /** |
| 18 * Container for code that can be used to translate a data type from JSON. | 19 * Container for code that can be used to translate a data type from JSON. |
| 19 */ | 20 */ |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 }; | 179 }; |
| 179 | 180 |
| 180 /** | 181 /** |
| 181 * Callback type used to represent arbitrary code generation. | 182 * Callback type used to represent arbitrary code generation. |
| 182 */ | 183 */ |
| 183 typedef void CodegenCallback(); | 184 typedef void CodegenCallback(); |
| 184 | 185 |
| 185 /** | 186 /** |
| 186 * Visitor which produces Dart code representing the API. | 187 * Visitor which produces Dart code representing the API. |
| 187 */ | 188 */ |
| 188 class CodegenProtocolVisitor extends HierarchicalApiVisitor with CodeGenerator { | 189 class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator { |
| 189 /** | |
| 190 * Type references in the spec that are named something else in Dart. | |
| 191 */ | |
| 192 static const Map<String, String> _typeRenames = const { | |
| 193 'long': 'int', | |
| 194 'object': 'Map', | |
| 195 }; | |
| 196 | |
| 197 /** | 190 /** |
| 198 * Class members for which the constructor argument should be optional, even | 191 * Class members for which the constructor argument should be optional, even |
| 199 * if the member is not an optional part of the protocol. For list types, | 192 * if the member is not an optional part of the protocol. For list types, |
| 200 * the constructor will default the member to the empty list. | 193 * the constructor will default the member to the empty list. |
| 201 */ | 194 */ |
| 202 static const Map<String, List<String>> _optionalConstructorArguments = const { | 195 static const Map<String, List<String>> _optionalConstructorArguments = const { |
| 203 'AnalysisErrorFixes': const ['fixes'], | 196 'AnalysisErrorFixes': const ['fixes'], |
| 204 'SourceChange': const ['edits', 'linkedEditGroups'], | 197 'SourceChange': const ['edits', 'linkedEditGroups'], |
| 205 'SourceFileEdit': const ['edits'], | 198 'SourceFileEdit': const ['edits'], |
| 206 'TypeHierarchyItem': const ['interfaces', 'mixins', 'subclasses'], | 199 'TypeHierarchyItem': const ['interfaces', 'mixins', 'subclasses'], |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 case 'SourceChange': | 553 case 'SourceChange': |
| 561 docComment( | 554 docComment( |
| 562 [new dom.Text('Adds [edit] to the [FileEdit] for the given [file].')
]); | 555 [new dom.Text('Adds [edit] to the [FileEdit] for the given [file].')
]); |
| 563 writeln('void addEdit(String file, int fileStamp, SourceEdit edit) =>'); | 556 writeln('void addEdit(String file, int fileStamp, SourceEdit edit) =>'); |
| 564 writeln(' _addEditToSourceChange(this, file, fileStamp, edit);'); | 557 writeln(' _addEditToSourceChange(this, file, fileStamp, edit);'); |
| 565 writeln(); | 558 writeln(); |
| 566 docComment( | 559 docComment( |
| 567 [new dom.Text('Adds [edit] to the [FileEdit] for the given [source].
')]); | 560 [new dom.Text('Adds [edit] to the [FileEdit] for the given [source].
')]); |
| 568 writeln('void addSourceEdit(engine.AnalysisContext context,'); | 561 writeln('void addSourceEdit(engine.AnalysisContext context,'); |
| 569 writeln(' engine.Source source, SourceEdit edit) =>'); | 562 writeln(' engine.Source source, SourceEdit edit) =>'); |
| 570 writeln(' _addSourceEditToSourceChange(this, context, source, edit);'
); | 563 writeln( |
| 564 ' _addSourceEditToSourceChange(this, context, source, edit);'); |
| 571 writeln(); | 565 writeln(); |
| 572 docComment( | 566 docComment( |
| 573 [new dom.Text('Adds [edit] to the [FileEdit] for the given [element]
.')]); | 567 [new dom.Text('Adds [edit] to the [FileEdit] for the given [element]
.')]); |
| 574 writeln('void addElementEdit(engine.Element element, SourceEdit edit) =>
'); | 568 writeln( |
| 569 'void addElementEdit(engine.Element element, SourceEdit edit) =>'); |
| 575 writeln(' _addElementEditToSourceChange(this, element, edit);'); | 570 writeln(' _addElementEditToSourceChange(this, element, edit);'); |
| 576 writeln(); | 571 writeln(); |
| 577 docComment([new dom.Text('Adds the given [FileEdit].')]); | 572 docComment([new dom.Text('Adds the given [FileEdit].')]); |
| 578 writeln('void addFileEdit(SourceFileEdit edit) {'); | 573 writeln('void addFileEdit(SourceFileEdit edit) {'); |
| 579 indent(() { | 574 indent(() { |
| 580 writeln('edits.add(edit);'); | 575 writeln('edits.add(edit);'); |
| 581 }); | 576 }); |
| 582 writeln('}'); | 577 writeln('}'); |
| 583 writeln(); | 578 writeln(); |
| 584 docComment([new dom.Text('Adds the given [LinkedEditGroup].')]); | 579 docComment([new dom.Text('Adds the given [LinkedEditGroup].')]); |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 } | 972 } |
| 978 | 973 |
| 979 /** | 974 /** |
| 980 * Emit the method for decoding an object from JSON. | 975 * Emit the method for decoding an object from JSON. |
| 981 */ | 976 */ |
| 982 void emitObjectFromJsonConstructor(String className, TypeObject type, | 977 void emitObjectFromJsonConstructor(String className, TypeObject type, |
| 983 ImpliedType impliedType) { | 978 ImpliedType impliedType) { |
| 984 String humanReadableNameString = | 979 String humanReadableNameString = |
| 985 literalString(impliedType.humanReadableName); | 980 literalString(impliedType.humanReadableName); |
| 986 if (className == 'RefactoringFeedback') { | 981 if (className == 'RefactoringFeedback') { |
| 987 writeln('factory RefactoringFeedback.fromJson(JsonDecoder jsonDecoder, ' | 982 writeln( |
| 988 'String jsonPath, Object json, Map responseJson) {'); | 983 'factory RefactoringFeedback.fromJson(JsonDecoder jsonDecoder, ' |
| 984 'String jsonPath, Object json, Map responseJson) {'); |
| 989 indent(() { | 985 indent(() { |
| 990 writeln('return _refactoringFeedbackFromJson(jsonDecoder, jsonPath, ' | 986 writeln( |
| 991 'json, responseJson);'); | 987 'return _refactoringFeedbackFromJson(jsonDecoder, jsonPath, ' |
| 988 'json, responseJson);'); |
| 992 }); | 989 }); |
| 993 writeln('}'); | 990 writeln('}'); |
| 994 return; | 991 return; |
| 995 } | 992 } |
| 996 if (className == 'RefactoringOptions') { | 993 if (className == 'RefactoringOptions') { |
| 997 writeln('factory RefactoringOptions.fromJson(JsonDecoder jsonDecoder, ' | 994 writeln( |
| 998 'String jsonPath, Object json, RefactoringKind kind) {'); | 995 'factory RefactoringOptions.fromJson(JsonDecoder jsonDecoder, ' |
| 996 'String jsonPath, Object json, RefactoringKind kind) {'); |
| 999 indent(() { | 997 indent(() { |
| 1000 writeln('return _refactoringOptionsFromJson(jsonDecoder, jsonPath, ' | 998 writeln( |
| 1001 'json, kind);'); | 999 'return _refactoringOptionsFromJson(jsonDecoder, jsonPath, ' 'json,
kind);'); |
| 1002 }); | 1000 }); |
| 1003 writeln('}'); | 1001 writeln('}'); |
| 1004 return; | 1002 return; |
| 1005 } | 1003 } |
| 1006 writeln( | 1004 writeln( |
| 1007 'factory $className.fromJson(JsonDecoder jsonDecoder, String jsonPath, O
bject json) {'); | 1005 'factory $className.fromJson(JsonDecoder jsonDecoder, String jsonPath, O
bject json) {'); |
| 1008 indent(() { | 1006 indent(() { |
| 1009 writeln('if (json == null) {'); | 1007 writeln('if (json == null) {'); |
| 1010 indent(() { | 1008 indent(() { |
| 1011 writeln('json = {};'); | 1009 writeln('json = {};'); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1105 | 1103 |
| 1106 /** | 1104 /** |
| 1107 * Compute the code necessary to translate [type] from JSON. | 1105 * Compute the code necessary to translate [type] from JSON. |
| 1108 */ | 1106 */ |
| 1109 FromJsonCode fromJsonCode(TypeDecl type) { | 1107 FromJsonCode fromJsonCode(TypeDecl type) { |
| 1110 if (type is TypeReference) { | 1108 if (type is TypeReference) { |
| 1111 TypeDefinition referencedDefinition = api.types[type.typeName]; | 1109 TypeDefinition referencedDefinition = api.types[type.typeName]; |
| 1112 if (referencedDefinition != null) { | 1110 if (referencedDefinition != null) { |
| 1113 TypeDecl referencedType = referencedDefinition.type; | 1111 TypeDecl referencedType = referencedDefinition.type; |
| 1114 if (referencedType is TypeObject || referencedType is TypeEnum) { | 1112 if (referencedType is TypeObject || referencedType is TypeEnum) { |
| 1115 return new FromJsonSnippet( | 1113 return new FromJsonSnippet((String jsonPath, String json) { |
| 1116 (String jsonPath, String json) { | 1114 String typeName = dartType(type); |
| 1117 String typeName = dartType(type); | 1115 if (typeName == 'RefactoringFeedback') { |
| 1118 if (typeName == 'RefactoringFeedback') { | 1116 return |
| 1119 return 'new $typeName.fromJson(jsonDecoder, $jsonPath, $json,
json)'; | 1117 'new $typeName.fromJson(jsonDecoder, $jsonPath, $json, json)'; |
| 1120 } else if (typeName == 'RefactoringOptions') { | 1118 } else if (typeName == 'RefactoringOptions') { |
| 1121 return 'new $typeName.fromJson(jsonDecoder, $jsonPath, $json,
kind)'; | 1119 return |
| 1122 } else { | 1120 'new $typeName.fromJson(jsonDecoder, $jsonPath, $json, kind)'; |
| 1123 return 'new $typeName.fromJson(jsonDecoder, $jsonPath, $json)'
; | 1121 } else { |
| 1124 } | 1122 return 'new $typeName.fromJson(jsonDecoder, $jsonPath, $json)'; |
| 1125 }); | 1123 } |
| 1124 }); |
| 1126 } else { | 1125 } else { |
| 1127 return fromJsonCode(referencedType); | 1126 return fromJsonCode(referencedType); |
| 1128 } | 1127 } |
| 1129 } else { | 1128 } else { |
| 1130 switch (type.typeName) { | 1129 switch (type.typeName) { |
| 1131 case 'String': | 1130 case 'String': |
| 1132 return new FromJsonFunction('jsonDecoder._decodeString'); | 1131 return new FromJsonFunction('jsonDecoder._decodeString'); |
| 1133 case 'bool': | 1132 case 'bool': |
| 1134 return new FromJsonFunction('jsonDecoder._decodeBool'); | 1133 return new FromJsonFunction('jsonDecoder._decodeBool'); |
| 1135 case 'int': | 1134 case 'int': |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1271 writeln('}'); | 1270 writeln('}'); |
| 1272 return true; | 1271 return true; |
| 1273 } | 1272 } |
| 1274 | 1273 |
| 1275 /** | 1274 /** |
| 1276 * Create a string literal that evaluates to [s]. | 1275 * Create a string literal that evaluates to [s]. |
| 1277 */ | 1276 */ |
| 1278 String literalString(String s) { | 1277 String literalString(String s) { |
| 1279 return JSON.encode(s); | 1278 return JSON.encode(s); |
| 1280 } | 1279 } |
| 1281 | |
| 1282 /** | |
| 1283 * Convert the given [TypeDecl] to a Dart type. | |
| 1284 */ | |
| 1285 String dartType(TypeDecl type) { | |
| 1286 if (type is TypeReference) { | |
| 1287 String typeName = type.typeName; | |
| 1288 TypeDefinition referencedDefinition = api.types[typeName]; | |
| 1289 if (_typeRenames.containsKey(typeName)) { | |
| 1290 return _typeRenames[typeName]; | |
| 1291 } | |
| 1292 if (referencedDefinition == null) { | |
| 1293 return typeName; | |
| 1294 } | |
| 1295 TypeDecl referencedType = referencedDefinition.type; | |
| 1296 if (referencedType is TypeObject || referencedType is TypeEnum) { | |
| 1297 return typeName; | |
| 1298 } | |
| 1299 return dartType(referencedType); | |
| 1300 } else if (type is TypeList) { | |
| 1301 return 'List<${dartType(type.itemType)}>'; | |
| 1302 } else if (type is TypeMap) { | |
| 1303 return 'Map<${dartType(type.keyType)}, ${dartType(type.valueType)}>'; | |
| 1304 } else if (type is TypeUnion) { | |
| 1305 return 'dynamic'; | |
| 1306 } else { | |
| 1307 throw new Exception("Can't convert to a dart type"); | |
| 1308 } | |
| 1309 } | |
| 1310 } | 1280 } |
| 1311 | 1281 |
| 1312 final GeneratedFile target = | 1282 final GeneratedFile target = |
| 1313 new GeneratedFile('../../lib/src/generated_protocol.dart', () { | 1283 new GeneratedFile('../../lib/src/generated_protocol.dart', () { |
| 1314 CodegenProtocolVisitor visitor = new CodegenProtocolVisitor(readApi()); | 1284 CodegenProtocolVisitor visitor = new CodegenProtocolVisitor(readApi()); |
| 1315 return visitor.collectCode(visitor.visitApi); | 1285 return visitor.collectCode(visitor.visitApi); |
| 1316 }); | 1286 }); |
| 1317 | 1287 |
| 1318 /** | 1288 /** |
| 1319 * Translate spec_input.html into protocol_matchers.dart. | 1289 * Translate spec_input.html into protocol_matchers.dart. |
| 1320 */ | 1290 */ |
| 1321 main() { | 1291 main() { |
| 1322 target.generate(); | 1292 target.generate(); |
| 1323 } | 1293 } |
| OLD | NEW |