OLD | NEW |
1 // (c) 2015, the Dart Team. All rights reserved. Use of this | 1 // (c) 2015, the Dart Team. All rights reserved. Use of this |
2 // source code is governed by a BSD-style license that can be found in | 2 // source code is governed by a BSD-style license that can be found in |
3 // the LICENSE file. | 3 // the LICENSE file. |
4 | 4 |
5 library reflectable.src.transformer_implementation; | 5 library reflectable.src.transformer_implementation; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:convert'; | 8 import 'dart:convert'; |
9 import 'dart:io'; | 9 import 'dart:io'; |
10 import 'dart:math' show max; | 10 import 'dart:math' show max; |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 if (elementAnnotation.element is ConstructorElement) { | 232 if (elementAnnotation.element is ConstructorElement) { |
233 // If this is a constructor call, add the otherwise implicit 'const'. | 233 // If this is a constructor call, add the otherwise implicit 'const'. |
234 metadataParts.add("const $source"); | 234 metadataParts.add("const $source"); |
235 } else { | 235 } else { |
236 metadataParts.add(source); | 236 metadataParts.add(source); |
237 } | 237 } |
238 } | 238 } |
239 return "new UnmodifiableListView([${metadataParts.join(", ")}])"; | 239 return "new UnmodifiableListView([${metadataParts.join(", ")}])"; |
240 } | 240 } |
241 | 241 |
| 242 String get newInstanceString { |
| 243 List<String> constructorLines = new List<String>(); |
| 244 |
| 245 String name(int i) { |
| 246 String alphabet = "abcdefghijklmnopqrstuvwxyz"; |
| 247 int alphabetLength = alphabet.length; |
| 248 if (i < alphabetLength) { |
| 249 return "_${alphabet[i]}"; |
| 250 } |
| 251 return "_${alphabet[i % alphabetLength]}${i ~/ alphabetLength}"; |
| 252 } |
| 253 for (ConstructorElement constructor in constructors) { |
| 254 FunctionType type = constructor.type; |
| 255 int requiredPositionalCount = type.normalParameterTypes.length; |
| 256 int optionalPositionalCount = type.optionalParameterTypes.length; |
| 257 List<String> argumentNames = type.namedParameterTypes.keys.toList(); |
| 258 String positionals = new Iterable.generate( |
| 259 requiredPositionalCount, (int i) => name(i)).join(", "); |
| 260 String optionalsWithDefaults = new Iterable.generate( |
| 261 optionalPositionalCount, (int i) { |
| 262 String defaultValueCode = constructor.parameters[ |
| 263 requiredPositionalCount + i].defaultValueCode; |
| 264 String defaultValueString = |
| 265 defaultValueCode == null ? "" : " = $defaultValueCode"; |
| 266 return "${name(i + requiredPositionalCount)}$defaultValueString"; |
| 267 }).join(", "); |
| 268 String namedWithDefaults = new Iterable.generate(argumentNames.length, |
| 269 (int i) { |
| 270 // TODO(eernst, sigurdm, #8): Recreate the default values faithfully. |
| 271 // TODO(eernst, sigurdm, #8): Until that is done, recognize unhandled |
| 272 // cases, and emit error/warning. |
| 273 String defaultValueCode = constructor.parameters[ |
| 274 requiredPositionalCount + i].defaultValueCode; |
| 275 String defaultValueString = |
| 276 defaultValueCode == null ? "" : ": $defaultValueCode"; |
| 277 return "${argumentNames[i]}$defaultValueString"; |
| 278 }).join(", "); |
| 279 |
| 280 String optionalArguments = new Iterable.generate(optionalPositionalCount, |
| 281 (int i) => name(i + requiredPositionalCount)).join(", "); |
| 282 String namedArguments = |
| 283 argumentNames.map((String name) => "$name: $name").join(", "); |
| 284 List<String> parameterParts = new List<String>(); |
| 285 List<String> argumentParts = new List<String>(); |
| 286 if (requiredPositionalCount != 0) { |
| 287 parameterParts.add(positionals); |
| 288 argumentParts.add(positionals); |
| 289 } |
| 290 if (optionalPositionalCount != 0) { |
| 291 parameterParts.add("[$optionalsWithDefaults]"); |
| 292 argumentParts.add(optionalArguments); |
| 293 } |
| 294 if (argumentNames.isNotEmpty) { |
| 295 parameterParts.add("{${namedWithDefaults}}"); |
| 296 argumentParts.add(namedArguments); |
| 297 } |
| 298 constructorLines.add('case "${constructor.name}": ' |
| 299 'c = (${parameterParts.join(', ')}) => ' |
| 300 'new ${nameOfDeclaration(constructor)}' |
| 301 '(${argumentParts.join(", ")});'); |
| 302 constructorLines.add(' break;'); |
| 303 } |
| 304 return """newInstance(String constructorName, List positionalArguments, |
| 305 [Map<Symbol, dynamic> namedArguments]) { |
| 306 Function c; |
| 307 switch (constructorName) { |
| 308 ${constructorLines.join("\n ")} |
| 309 default: throw new NoSuchInvokeCapabilityError(${classElement.name}, |
| 310 constructorName, positionalArguments, namedArguments); |
| 311 } |
| 312 return Function.apply(c, positionalArguments, namedArguments); |
| 313 }"""; |
| 314 } |
| 315 |
242 void computeNames(Namer namer) { | 316 void computeNames(Namer namer) { |
243 staticClassMirrorName = namer.freshName("Static_${baseName}_ClassMirror"); | 317 staticClassMirrorName = namer.freshName("Static_${baseName}_ClassMirror"); |
244 staticInstanceMirrorName = | 318 staticInstanceMirrorName = |
245 namer.freshName("Static_${baseName}_InstanceMirror"); | 319 namer.freshName("Static_${baseName}_InstanceMirror"); |
246 } | 320 } |
247 } | 321 } |
248 | 322 |
249 /// A wrapper around a list of Capabilities. | 323 /// A wrapper around a list of Capabilities. |
250 /// Supports queries about the methods supported by the set of capabilities. | 324 /// Supports queries about the methods supported by the set of capabilities. |
251 class Capabilities { | 325 class Capabilities { |
(...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
903 Map<String, MethodMirror> get instanceMembers { | 977 Map<String, MethodMirror> get instanceMembers { |
904 if (_instanceMembersCache == null) { | 978 if (_instanceMembersCache == null) { |
905 _instanceMembersCache = new UnmodifiableMapView($instanceMembersString); | 979 _instanceMembersCache = new UnmodifiableMapView($instanceMembersString); |
906 } | 980 } |
907 return _instanceMembersCache; | 981 return _instanceMembersCache; |
908 }"""); | 982 }"""); |
909 if (classDomain.reflectorDomain.capabilities.supportsMetadata) { | 983 if (classDomain.reflectorDomain.capabilities.supportsMetadata) { |
910 implementedMembers | 984 implementedMembers |
911 .add("List<Object> metadata = ${classDomain.metadataString};"); | 985 .add("List<Object> metadata = ${classDomain.metadataString};"); |
912 } | 986 } |
| 987 if (!classDomain.classElement.isAbstract) { |
| 988 implementedMembers.add(classDomain.newInstanceString); |
| 989 } |
913 | 990 |
914 return """ | 991 return """ |
915 class ${classDomain.staticClassMirrorName} extends ClassMirrorUnimpl { | 992 class ${classDomain.staticClassMirrorName} extends ClassMirrorUnimpl { |
916 ${implementedMembers.join("\n\n ")} | 993 ${implementedMembers.join("\n\n ")} |
917 } | 994 } |
918 """; | 995 """; |
919 } | 996 } |
920 | 997 |
921 /// Perform some very simple steps that are consistent with Dart | 998 /// Perform some very simple steps that are consistent with Dart |
922 /// semantics for the evaluation of constant expressions, such that | 999 /// semantics for the evaluation of constant expressions, such that |
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1482 TransformLogger get logger => _aggregateTransform.logger; | 1559 TransformLogger get logger => _aggregateTransform.logger; |
1483 Future<Asset> getInput(AssetId id) => _aggregateTransform.getInput(id); | 1560 Future<Asset> getInput(AssetId id) => _aggregateTransform.getInput(id); |
1484 Future<String> readInputAsString(AssetId id, {Encoding encoding}) { | 1561 Future<String> readInputAsString(AssetId id, {Encoding encoding}) { |
1485 return _aggregateTransform.readInputAsString(id, encoding: encoding); | 1562 return _aggregateTransform.readInputAsString(id, encoding: encoding); |
1486 } | 1563 } |
1487 Stream<List<int>> readInput(AssetId id) => _aggregateTransform.readInput(id); | 1564 Stream<List<int>> readInput(AssetId id) => _aggregateTransform.readInput(id); |
1488 Future<bool> hasInput(AssetId id) => _aggregateTransform.hasInput(id); | 1565 Future<bool> hasInput(AssetId id) => _aggregateTransform.hasInput(id); |
1489 void addOutput(Asset output) => _aggregateTransform.addOutput(output); | 1566 void addOutput(Asset output) => _aggregateTransform.addOutput(output); |
1490 void consumePrimary() => _aggregateTransform.consumePrimary(primaryInput.id); | 1567 void consumePrimary() => _aggregateTransform.consumePrimary(primaryInput.id); |
1491 } | 1568 } |
OLD | NEW |