Chromium Code Reviews| 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 43 reflectors | 43 reflectors |
| 44 .forEach((ReflectorDomain reflector) => reflector.computeNames(namer)); | 44 .forEach((ReflectorDomain reflector) => reflector.computeNames(namer)); |
| 45 } | 45 } |
| 46 } | 46 } |
| 47 | 47 |
| 48 /// Information about the program parts that can be reflected by a given | 48 /// Information about the program parts that can be reflected by a given |
| 49 /// Reflector. | 49 /// Reflector. |
| 50 class ReflectorDomain { | 50 class ReflectorDomain { |
| 51 final ClassElement reflector; | 51 final ClassElement reflector; |
| 52 final List<ClassDomain> annotatedClasses; | 52 final List<ClassDomain> annotatedClasses; |
| 53 final Map<ClassElement, ClassDomain> classMap = | |
| 54 new Map<ClassElement, ClassDomain>(); | |
| 53 final Capabilities capabilities; | 55 final Capabilities capabilities; |
| 54 | 56 |
| 55 /// Libraries that must be imported to `reflector.library`. | 57 /// Libraries that must be imported to `reflector.library`. |
| 56 final Set<LibraryElement> missingImports = new Set<LibraryElement>(); | 58 final Set<LibraryElement> missingImports = new Set<LibraryElement>(); |
| 57 | 59 |
| 58 ReflectorDomain(this.reflector, this.annotatedClasses, this.capabilities); | 60 ReflectorDomain(this.reflector, this.annotatedClasses, this.capabilities) { |
| 61 for (ClassDomain classDomain in annotatedClasses) { | |
| 62 classMap[classDomain.classElement] = classDomain; | |
| 63 } | |
| 64 } | |
| 59 | 65 |
| 60 void computeNames(Namer namer) { | 66 void computeNames(Namer namer) { |
| 61 annotatedClasses | 67 annotatedClasses |
| 62 .forEach((ClassDomain classDomain) => classDomain.computeNames(namer)); | 68 .forEach((ClassDomain classDomain) => classDomain.computeNames(namer)); |
| 63 } | 69 } |
| 70 | |
| 71 Map<ClassElement, Map<String, ExecutableElement>> _instanceMemberCache = | |
| 72 new Map<ClassElement, Map<String, ExecutableElement>>(); | |
|
eernst
2015/06/18 12:21:12
Do we need an more global mechanism to guide the e
sigurdm
2015/06/18 14:22:27
I am not sure - will leave a todo.
| |
| 64 } | 73 } |
| 65 | 74 |
| 66 /// Information about reflectability for a given class. | 75 /// Information about reflectability for a given class. |
| 67 class ClassDomain { | 76 class ClassDomain { |
| 68 final ClassElement classElement; | 77 final ClassElement classElement; |
| 69 final Iterable<MethodElement> invokableMethods; | |
| 70 final Iterable<MethodElement> declaredMethods; | 78 final Iterable<MethodElement> declaredMethods; |
| 79 final Iterable<PropertyAccessorElement> declaredAccessors; | |
| 80 final Iterable<ConstructorElement> constructors; | |
| 71 | 81 |
| 72 ReflectorDomain reflectorDomain; | 82 ReflectorDomain reflectorDomain; |
| 83 | |
| 84 Iterable<MethodElement> get invokableMethods => instanceMembers | |
| 85 .where((ExecutableElement element) => element is MethodElement); | |
| 86 | |
| 73 String staticClassMirrorName; | 87 String staticClassMirrorName; |
| 74 String staticInstanceMirrorName; | 88 String staticInstanceMirrorName; |
| 75 String get baseName => classElement.name; | 89 String get baseName => classElement.name; |
| 76 | 90 |
| 77 ClassDomain(this.classElement, this.invokableMethods, this.declaredMethods, | 91 ClassDomain(this.classElement, this.declaredMethods, |
| 78 this.reflectorDomain); | 92 this.declaredAccessors, this.constructors, this.reflectorDomain); |
| 79 | 93 |
| 80 Iterable<ExecutableElement> get declarations { | 94 Iterable<ExecutableElement> get declarations { |
| 81 // TODO(sigurdm): Include constructors. | |
| 82 // TODO(sigurdm): Include fields. | 95 // TODO(sigurdm): Include fields. |
| 83 // TODO(sigurdm): Include getters and setters. | |
| 84 // TODO(sigurdm): Include type variables (if we decide to keep them). | 96 // TODO(sigurdm): Include type variables (if we decide to keep them). |
| 85 return [declaredMethods].expand((x) => x); | 97 return [declaredMethods, declaredAccessors, constructors].expand((x) => x); |
| 98 } | |
| 99 | |
| 100 /// Finds all instance members by going through the class hierarchy. | |
| 101 Iterable<ExecutableElement> get instanceMembers { | |
| 102 | |
| 103 Map<String, ExecutableElement> helper(ClassElement classElement) { | |
| 104 if (reflectorDomain._instanceMemberCache[classElement] != null) { | |
| 105 return reflectorDomain._instanceMemberCache[classElement]; | |
| 106 } | |
| 107 Map<String, ExecutableElement> result = | |
| 108 new Map<String, ExecutableElement>(); | |
| 109 | |
| 110 void addIfCapable(ExecutableElement member) { | |
| 111 if (reflectorDomain.capabilities.supportsInstanceInvoke(member.name)) { | |
| 112 result[member.name] = member; | |
| 113 } | |
| 114 } | |
| 115 if (classElement.supertype != null) { | |
| 116 helper(classElement.supertype.element).forEach( | |
| 117 (String name, ExecutableElement member) { | |
| 118 addIfCapable(member); | |
| 119 }); | |
| 120 } | |
| 121 for (InterfaceType mixin in classElement.mixins) { | |
| 122 helper(mixin.element).forEach((String name, ExecutableElement member) { | |
| 123 addIfCapable(member); | |
| 124 }); | |
| 125 } | |
| 126 for (MethodElement member in classElement.methods) { | |
| 127 if (member.isAbstract || member.isStatic) continue; | |
| 128 addIfCapable(member); | |
| 129 } | |
| 130 for (PropertyAccessorElement member in classElement.accessors) { | |
| 131 if (member.isAbstract || member.isStatic) continue; | |
| 132 addIfCapable(member); | |
| 133 } | |
| 134 for (FieldElement field in classElement.fields) { | |
| 135 if (field.isStatic) continue; | |
| 136 if (field.isSynthetic) continue; | |
| 137 addIfCapable(field.getter); | |
| 138 if (!field.isFinal) { | |
| 139 addIfCapable(field.setter); | |
| 140 } | |
| 141 } | |
| 142 return result; | |
| 143 } | |
| 144 return helper(classElement).values; | |
| 86 } | 145 } |
| 87 | 146 |
| 88 /// Returns an integer encoding the kind and attributes of the given | 147 /// Returns an integer encoding the kind and attributes of the given |
| 89 /// method/constructor/getter/setter. | 148 /// method/constructor/getter/setter. |
| 90 int _declarationDescriptor(ExecutableElement element) { | 149 int _declarationDescriptor(ExecutableElement element) { |
| 91 int result; | 150 int result; |
| 92 if (element is PropertyAccessorElement) { | 151 if (element is PropertyAccessorElement) { |
| 93 result = element.isGetter ? constants.getter : constants.setter; | 152 result = element.isGetter ? constants.getter : constants.setter; |
| 94 } else if (element is ConstructorElement) { | 153 } else if (element is ConstructorElement) { |
| 95 if (element.isFactory) { | 154 if (element.isFactory) { |
| 96 result = constants.factoryConstructor; | 155 result = constants.factoryConstructor; |
| 97 } else if (element.redirectedConstructor != null) { | |
| 98 result = constants.redirectingConstructor; | |
| 99 } else { | 156 } else { |
| 100 result = constants.generativeConstructor; | 157 result = constants.generativeConstructor; |
| 101 } | 158 } |
| 102 if (element.isConst) { | 159 if (element.isConst) { |
| 103 result += constants.constAttribute; | 160 result += constants.constAttribute; |
| 104 } | 161 } |
| 162 if (element.redirectedConstructor != null) { | |
| 163 result += constants.redirectingConstructor; | |
| 164 } | |
| 105 } else { | 165 } else { |
| 106 result = constants.method; | 166 result = constants.method; |
| 107 } | 167 } |
| 108 if (element.isPrivate) { | 168 if (element.isPrivate) { |
| 109 result += constants.privateAttribute; | 169 result += constants.privateAttribute; |
| 110 } | 170 } |
| 111 if (element.isAbstract) { | 171 assert(!element.isAbstract); |
| 112 result += constants.abstractAttribute; | |
| 113 } | |
| 114 if (element.isStatic) { | 172 if (element.isStatic) { |
| 115 result += constants.staticAttribute; | 173 result += constants.staticAttribute; |
| 116 } | 174 } |
| 175 if (element.isSynthetic) { | |
| 176 result += constants.syntheticAttribute; | |
| 177 } | |
| 117 return result; | 178 return result; |
| 118 } | 179 } |
| 119 | 180 |
| 181 String nameOfDeclaration(ExecutableElement element) { | |
| 182 if (element is ConstructorElement) { | |
| 183 return element.name == "" | |
| 184 ? classElement.name | |
| 185 : "${classElement.name}.${element.name}"; | |
| 186 } | |
| 187 return element.name; | |
| 188 } | |
| 189 | |
| 120 /// Returns a String with the textual representation of the declarations-map. | 190 /// Returns a String with the textual representation of the declarations-map. |
| 121 String get declarationsString { | 191 String get declarationsString { |
| 122 Iterable<String> declarationParts = declarations.map( | 192 Iterable<String> declarationParts = declarations.map( |
| 123 (ExecutableElement instanceMember) { | 193 (ExecutableElement declaration) { |
| 124 return '"${instanceMember.name}": ' | 194 return '"${nameOfDeclaration(declaration)}": ' |
| 125 'new MethodMirrorImpl("${instanceMember.name}", ' | 195 'new MethodMirrorImpl("${declaration.name}", ' |
| 126 '${_declarationDescriptor(instanceMember)}, this)'; | 196 '${_declarationDescriptor(declaration)}, this)'; |
| 127 }); | 197 }); |
| 128 return "{${declarationParts.join(", ")}}"; | 198 return "{${declarationParts.join(", ")}}"; |
| 129 } | 199 } |
| 130 | 200 |
| 201 /// Returns a String with the textual representation of the | |
| 202 /// instanceMembers-map. | |
| 203 String get instanceMembersString { | |
| 204 // TODO(sigurdm): Find out how to set the right owner. | |
| 205 Iterable<String> instanceMemberParts = instanceMembers.map( | |
| 206 (ExecutableElement declaration) { | |
| 207 return '"${nameOfDeclaration(declaration)}": ' | |
| 208 'new MethodMirrorImpl("${declaration.name}", ' | |
| 209 '${_declarationDescriptor(declaration)}, null)'; | |
| 210 }); | |
| 211 return "{${instanceMemberParts.join(", ")}}"; | |
| 212 } | |
| 213 | |
| 131 void computeNames(Namer namer) { | 214 void computeNames(Namer namer) { |
| 132 staticClassMirrorName = namer.freshName("Static_${baseName}_ClassMirror"); | 215 staticClassMirrorName = namer.freshName("Static_${baseName}_ClassMirror"); |
| 133 staticInstanceMirrorName = | 216 staticInstanceMirrorName = |
| 134 namer.freshName("Static_${baseName}_InstanceMirror"); | 217 namer.freshName("Static_${baseName}_InstanceMirror"); |
| 135 } | 218 } |
| 136 } | 219 } |
| 137 | 220 |
| 138 /// A wrapper around a list of Capabilities. | 221 /// A wrapper around a list of Capabilities. |
| 139 /// Supports queries about the methods supported by the set of capabilities. | 222 /// Supports queries about the methods supported by the set of capabilities. |
| 140 class Capabilities { | 223 class Capabilities { |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 376 // have no effect; it might be better to emit a diagnostic message (a | 459 // have no effect; it might be better to emit a diagnostic message (a |
| 377 // hint?) in order to notify the programmer that "it does not work". | 460 // hint?) in order to notify the programmer that "it does not work". |
| 378 // The trade-off is that such constructs may have been written by | 461 // The trade-off is that such constructs may have been written by |
| 379 // programmers who are doing something else, intentionally. To emit a | 462 // programmers who are doing something else, intentionally. To emit a |
| 380 // diagnostic message, we must check whether there is a Reflectable | 463 // diagnostic message, we must check whether there is a Reflectable |
| 381 // somewhere inside this syntactic construct, and then emit the message | 464 // somewhere inside this syntactic construct, and then emit the message |
| 382 // in cases that we "consider likely to be misunderstood". | 465 // in cases that we "consider likely to be misunderstood". |
| 383 return null; | 466 return null; |
| 384 } | 467 } |
| 385 | 468 |
| 386 /// Finds all the methods in the class and all super-classes. | |
| 387 Iterable<MethodElement> allMethods(ClassElement classElement) { | |
| 388 List<MethodElement> result = new List<MethodElement>(); | |
| 389 result.addAll(classElement.methods); | |
| 390 classElement.allSupertypes.forEach((InterfaceType superType) { | |
| 391 result.addAll(superType.methods); | |
| 392 }); | |
| 393 return result; | |
| 394 } | |
| 395 | |
| 396 Iterable<MethodElement> declaredMethods( | 469 Iterable<MethodElement> declaredMethods( |
| 397 ClassElement classElement, Capabilities capabilities) { | 470 ClassElement classElement, Capabilities capabilities) { |
| 398 return classElement.methods.where((MethodElement method) { | 471 return classElement.methods.where((MethodElement method) { |
| 472 if (method.isAbstract) return false; | |
| 399 if (method.isStatic) { | 473 if (method.isStatic) { |
| 400 // TODO(sigurdm): Ask capability about support. | 474 // TODO(sigurdm): Ask capabilities about support. |
| 401 return true; | 475 return true; |
| 402 } else { | 476 } else { |
| 403 return capabilities.supportsInstanceInvoke(method.name); | 477 return capabilities.supportsInstanceInvoke(method.name); |
| 404 } | 478 } |
| 405 }); | 479 }); |
| 406 } | 480 } |
| 407 | 481 |
| 408 Iterable<MethodElement> invocableInstanceMethods( | 482 Iterable<PropertyAccessorElement> declaredAccessors( |
| 409 ClassElement classElement, Capabilities capabilities) { | 483 ClassElement classElement, Capabilities capabilities) { |
| 410 return allMethods(classElement).where((MethodElement method) { | 484 return classElement.accessors.where((PropertyAccessorElement accessor) { |
| 411 MethodDeclaration methodDeclaration = method.node; | 485 if (accessor.isAbstract) return false; |
| 412 // TODO(eernst): We currently ignore method declarations when | 486 if (accessor.isStatic) { |
| 413 // they are operators. One issue is generation of code (which | 487 // TODO(sigurdm): Ask capabilities about support. |
| 414 // does not work if we go ahead naively). | 488 return true; |
| 415 if (methodDeclaration.isOperator) return false; | 489 } else { |
| 416 String methodName = methodDeclaration.name.name; | 490 return capabilities.supportsInstanceInvoke(accessor.name); |
| 417 return capabilities.supportsInstanceInvoke(methodName); | 491 } |
| 418 }); | 492 }); |
| 419 } | 493 } |
| 420 | 494 |
| 495 Iterable<ConstructorElement> declaredConstructors( | |
| 496 ClassElement classElement, Capabilities capabilities) { | |
| 497 return classElement.constructors.where((ConstructorElement constructor) { | |
| 498 // TODO(sigurdm): Ask capabilities about support. | |
| 499 return true; | |
| 500 }); | |
| 501 } | |
| 502 | |
| 421 /// Returns a [ReflectionWorld] instantiated with all the reflectors seen by | 503 /// Returns a [ReflectionWorld] instantiated with all the reflectors seen by |
| 422 /// [resolver] and all classes annotated by them. | 504 /// [resolver] and all classes annotated by them. |
| 423 /// | 505 /// |
| 424 /// TODO(eernst): Make sure it works also when other packages are being | 506 /// TODO(eernst): Make sure it works also when other packages are being |
| 425 /// used by the target program which have already been transformed by | 507 /// used by the target program which have already been transformed by |
| 426 /// this transformer (e.g., there would be a clash on the use of | 508 /// this transformer (e.g., there would be a clash on the use of |
| 427 /// reflectableClassId with values near 1000 for more than one class). | 509 /// reflectableClassId with values near 1000 for more than one class). |
| 428 ReflectionWorld _computeWorld(LibraryElement reflectableLibrary) { | 510 ReflectionWorld _computeWorld(LibraryElement reflectableLibrary) { |
| 429 ReflectionWorld world = new ReflectionWorld(reflectableLibrary); | 511 ReflectionWorld world = new ReflectionWorld(reflectableLibrary); |
| 430 Map<ClassElement, ReflectorDomain> domains = | 512 Map<ClassElement, ReflectorDomain> domains = |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 460 for (ElementAnnotation metadatum in type.metadata) { | 542 for (ElementAnnotation metadatum in type.metadata) { |
| 461 ClassElement reflector = | 543 ClassElement reflector = |
| 462 _getReflectableAnnotation(metadatum, focusClass); | 544 _getReflectableAnnotation(metadatum, focusClass); |
| 463 if (reflector == null) continue; | 545 if (reflector == null) continue; |
| 464 ReflectorDomain domain = domains.putIfAbsent(reflector, () { | 546 ReflectorDomain domain = domains.putIfAbsent(reflector, () { |
| 465 Capabilities capabilities = | 547 Capabilities capabilities = |
| 466 _capabilitiesOf(capabilityLibrary, reflector); | 548 _capabilitiesOf(capabilityLibrary, reflector); |
| 467 return new ReflectorDomain( | 549 return new ReflectorDomain( |
| 468 reflector, new List<ClassDomain>(), capabilities); | 550 reflector, new List<ClassDomain>(), capabilities); |
| 469 }); | 551 }); |
| 470 List<MethodElement> instanceMethods = | |
| 471 invocableInstanceMethods(type, domain.capabilities).toList(); | |
| 472 List<MethodElement> declaredMethodsOfClass = | 552 List<MethodElement> declaredMethodsOfClass = |
| 473 declaredMethods(type, domain.capabilities).toList(); | 553 declaredMethods(type, domain.capabilities).toList(); |
| 474 domain.annotatedClasses.add(new ClassDomain( | 554 List<PropertyAccessorElement> declaredAccessorsOfClass = |
| 475 type, instanceMethods, declaredMethodsOfClass, domain)); | 555 declaredAccessors(type, domain.capabilities).toList(); |
| 556 List<ConstructorElement> declaredConstructorsOfClass = | |
| 557 declaredConstructors(type, domain.capabilities).toList(); | |
| 558 domain.annotatedClasses.add(new ClassDomain(type, | |
| 559 declaredMethodsOfClass, declaredAccessorsOfClass, | |
| 560 declaredConstructorsOfClass, domain)); | |
| 476 } | 561 } |
| 477 } | 562 } |
| 478 } | 563 } |
| 479 } | 564 } |
| 480 domains.values.forEach(_collectMissingImports); | 565 domains.values.forEach(_collectMissingImports); |
| 481 | 566 |
| 482 world.reflectors.addAll(domains.values.toList()); | 567 world.reflectors.addAll(domains.values.toList()); |
| 483 world.computeNames(namer); | 568 world.computeNames(namer); |
| 484 return world; | 569 return world; |
| 485 } | 570 } |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 764 Iterable<${prefix}ClassMirror> get annotatedClasses { | 849 Iterable<${prefix}ClassMirror> get annotatedClasses { |
| 765 return [${annotatedClassesStrings.join(", ")}]; | 850 return [${annotatedClassesStrings.join(", ")}]; |
| 766 }"""); | 851 }"""); |
| 767 } | 852 } |
| 768 | 853 |
| 769 /// Returns the source code for the reflection free subclass of | 854 /// Returns the source code for the reflection free subclass of |
| 770 /// [ClassMirror] which is specialized for a `reflectedType` which | 855 /// [ClassMirror] which is specialized for a `reflectedType` which |
| 771 /// is the class modeled by [classElement]. | 856 /// is the class modeled by [classElement]. |
| 772 String _staticClassMirrorCode(ClassDomain classDomain) { | 857 String _staticClassMirrorCode(ClassDomain classDomain) { |
| 773 String declarationsString = classDomain.declarationsString; | 858 String declarationsString = classDomain.declarationsString; |
| 859 String instanceMembersString = classDomain.instanceMembersString; | |
| 774 return """ | 860 return """ |
| 775 class ${classDomain.staticClassMirrorName} extends ClassMirrorUnimpl { | 861 class ${classDomain.staticClassMirrorName} extends ClassMirrorUnimpl { |
| 776 final String simpleName = "${classDomain.classElement.name}"; | 862 final String simpleName = "${classDomain.classElement.name}"; |
| 777 | 863 |
| 778 Map<String, MethodMirror> _declarationsCache; | 864 Map<String, MethodMirror> _declarationsCache; |
| 779 | 865 |
| 780 Map<String, MethodMirror> get declarations { | 866 Map<String, MethodMirror> get declarations { |
| 781 if (_declarationsCache == null) { | 867 if (_declarationsCache == null) { |
| 782 _declarationsCache = new UnmodifiableMapView($declarationsString); | 868 _declarationsCache = new UnmodifiableMapView($declarationsString); |
| 783 } | 869 } |
| 784 return _declarationsCache; | 870 return _declarationsCache; |
| 785 } | 871 } |
| 872 | |
| 873 Map<String, MethodMirror> _instanceMembersCache; | |
| 874 | |
| 875 Map<String, MethodMirror> get instanceMembers { | |
| 876 if (_instanceMembersCache == null) { | |
| 877 _instanceMembersCache = new UnmodifiableMapView($instanceMembersString); | |
| 878 } | |
| 879 return _instanceMembersCache; | |
| 880 } | |
| 881 | |
| 786 } | 882 } |
| 787 """; | 883 """; |
| 788 } | 884 } |
| 789 | 885 |
| 790 /// Perform some very simple steps that are consistent with Dart | 886 /// Perform some very simple steps that are consistent with Dart |
| 791 /// semantics for the evaluation of constant expressions, such that | 887 /// semantics for the evaluation of constant expressions, such that |
| 792 /// information about the value of a given `const` variable can be | 888 /// information about the value of a given `const` variable can be |
| 793 /// obtained. It is intended to help recognizing values of type | 889 /// obtained. It is intended to help recognizing values of type |
| 794 /// [ReflectCapability], so we only cover cases needed for that. | 890 /// [ReflectCapability], so we only cover cases needed for that. |
| 795 /// In particular, we cover lookup (e.g., with `const x = e` we can | 891 /// In particular, we cover lookup (e.g., with `const x = e` we can |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 938 ListLiteral listLiteral = arguments[0]; | 1034 ListLiteral listLiteral = arguments[0]; |
| 939 NodeList<Expression> expressions = listLiteral.elements; | 1035 NodeList<Expression> expressions = listLiteral.elements; |
| 940 return new Capabilities(expressions.map(capabilityOfExpression).toList()); | 1036 return new Capabilities(expressions.map(capabilityOfExpression).toList()); |
| 941 } | 1037 } |
| 942 | 1038 |
| 943 /// Returns a [String] containing generated code for the `invoke` | 1039 /// Returns a [String] containing generated code for the `invoke` |
| 944 /// method of the static `InstanceMirror` class corresponding to | 1040 /// method of the static `InstanceMirror` class corresponding to |
| 945 /// the given [classElement], bounded by the permissions given | 1041 /// the given [classElement], bounded by the permissions given |
| 946 /// in [capabilities]. | 1042 /// in [capabilities]. |
| 947 String _staticInstanceMirrorInvokeCode(ClassDomain classDomain) { | 1043 String _staticInstanceMirrorInvokeCode(ClassDomain classDomain) { |
| 1044 | |
| 1045 String tearOff(MethodElement methodElement) { | |
| 1046 if (!methodElement.isOperator) return "reflectee.${methodElement.name}"; | |
| 1047 if (methodElement.name == "[]=") return "(x, v) => reflectee[x] = v"; | |
| 1048 if (methodElement.name == "[]") return "(x) => reflectee[x]"; | |
| 1049 return "(x) => reflectee ${methodElement.name} x"; | |
| 1050 } | |
| 1051 | |
| 1052 | |
| 948 List<String> methodCases = new List<String>(); | 1053 List<String> methodCases = new List<String>(); |
| 949 for (MethodElement methodElement in classDomain.invokableMethods) { | 1054 for (MethodElement methodElement in classDomain.invokableMethods) { |
| 950 String methodName = methodElement.name; | 1055 methodCases.add("if (memberName == '${methodElement.name}') {" |
| 951 methodCases.add("if (memberName == '$methodName') {" | 1056 "method = ${tearOff(methodElement)}; }"); |
| 952 "method = reflectee.$methodName; }"); | |
| 953 } | 1057 } |
| 954 // TODO(eernst, sigurdm): Create an instance of [Invocation] in user code. | 1058 // TODO(eernst, sigurdm): Create an instance of [Invocation] in user code. |
| 955 methodCases.add("if (instanceMethodFilter.hasMatch(memberName)) {" | 1059 methodCases.add("if (instanceMethodFilter.hasMatch(memberName)) {" |
| 956 "throw new UnimplementedError('Should call noSuchMethod'); }"); | 1060 "throw new UnimplementedError('Should call noSuchMethod'); }"); |
| 957 methodCases.add("{ throw new NoSuchInvokeCapabilityError(" | 1061 methodCases.add("{ throw new NoSuchInvokeCapabilityError(" |
| 958 "reflectee, memberName, positionalArguments, namedArguments); }"); | 1062 "reflectee, memberName, positionalArguments, namedArguments); }"); |
| 959 // Handle the cases where permission is given even though there is | 1063 // Handle the cases where permission is given even though there is |
| 960 // no corresponding method. One case is where _all_ methods can be | 1064 // no corresponding method. One case is where _all_ methods can be |
| 961 // invoked. Another case is when the user has specified a name | 1065 // invoked. Another case is when the user has specified a name |
| 962 // `"foo"` and a reflector `@reflector` allowing for invocation | 1066 // `"foo"` and a reflector `@reflector` allowing for invocation |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1218 TransformLogger get logger => _aggregateTransform.logger; | 1322 TransformLogger get logger => _aggregateTransform.logger; |
| 1219 Future<Asset> getInput(AssetId id) => _aggregateTransform.getInput(id); | 1323 Future<Asset> getInput(AssetId id) => _aggregateTransform.getInput(id); |
| 1220 Future<String> readInputAsString(AssetId id, {Encoding encoding}) { | 1324 Future<String> readInputAsString(AssetId id, {Encoding encoding}) { |
| 1221 return _aggregateTransform.readInputAsString(id, encoding: encoding); | 1325 return _aggregateTransform.readInputAsString(id, encoding: encoding); |
| 1222 } | 1326 } |
| 1223 Stream<List<int>> readInput(AssetId id) => _aggregateTransform.readInput(id); | 1327 Stream<List<int>> readInput(AssetId id) => _aggregateTransform.readInput(id); |
| 1224 Future<bool> hasInput(AssetId id) => _aggregateTransform.hasInput(id); | 1328 Future<bool> hasInput(AssetId id) => _aggregateTransform.hasInput(id); |
| 1225 void addOutput(Asset output) => _aggregateTransform.addOutput(output); | 1329 void addOutput(Asset output) => _aggregateTransform.addOutput(output); |
| 1226 void consumePrimary() => _aggregateTransform.consumePrimary(primaryInput.id); | 1330 void consumePrimary() => _aggregateTransform.consumePrimary(primaryInput.id); |
| 1227 } | 1331 } |
| OLD | NEW |