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 // TODO(eernst, sigurdm): Perhaps reconsider what the best strategy for |
| 72 // caching is. |
| 73 Map<ClassElement, Map<String, ExecutableElement>> _instanceMemberCache = |
| 74 new Map<ClassElement, Map<String, ExecutableElement>>(); |
64 } | 75 } |
65 | 76 |
66 /// Information about reflectability for a given class. | 77 /// Information about reflectability for a given class. |
67 class ClassDomain { | 78 class ClassDomain { |
68 final ClassElement classElement; | 79 final ClassElement classElement; |
69 final Iterable<MethodElement> invokableMethods; | |
70 final Iterable<MethodElement> declaredMethods; | 80 final Iterable<MethodElement> declaredMethods; |
71 final Iterable<PropertyAccessorElement> declaredAccessors; | 81 final Iterable<PropertyAccessorElement> declaredAccessors; |
72 final Iterable<ConstructorElement> constructors; | 82 final Iterable<ConstructorElement> constructors; |
73 | 83 |
74 ReflectorDomain reflectorDomain; | 84 ReflectorDomain reflectorDomain; |
| 85 |
| 86 Iterable<MethodElement> get invokableMethods => instanceMembers |
| 87 .where((ExecutableElement element) => element is MethodElement); |
| 88 |
75 String staticClassMirrorName; | 89 String staticClassMirrorName; |
76 String staticInstanceMirrorName; | 90 String staticInstanceMirrorName; |
77 String get baseName => classElement.name; | 91 String get baseName => classElement.name; |
78 | 92 |
79 ClassDomain(this.classElement, this.invokableMethods, this.declaredMethods, | 93 ClassDomain(this.classElement, this.declaredMethods, this.declaredAccessors, |
80 this.declaredAccessors, this.constructors, this.reflectorDomain); | 94 this.constructors, this.reflectorDomain); |
81 | 95 |
82 Iterable<ExecutableElement> get declarations { | 96 Iterable<ExecutableElement> get declarations { |
83 // TODO(sigurdm): Include fields. | 97 // TODO(sigurdm): Include fields. |
84 // TODO(sigurdm): Include type variables (if we decide to keep them). | 98 // TODO(sigurdm): Include type variables (if we decide to keep them). |
85 return [declaredMethods, declaredAccessors, constructors].expand((x) => x); | 99 return [declaredMethods, declaredAccessors, constructors].expand((x) => x); |
86 } | 100 } |
87 | 101 |
| 102 /// Finds all instance members by going through the class hierarchy. |
| 103 Iterable<ExecutableElement> get instanceMembers { |
| 104 Map<String, ExecutableElement> helper(ClassElement classElement) { |
| 105 if (reflectorDomain._instanceMemberCache[classElement] != null) { |
| 106 return reflectorDomain._instanceMemberCache[classElement]; |
| 107 } |
| 108 Map<String, ExecutableElement> result = |
| 109 new Map<String, ExecutableElement>(); |
| 110 |
| 111 void addIfCapable(ExecutableElement member) { |
| 112 if (reflectorDomain.capabilities.supportsInstanceInvoke(member.name)) { |
| 113 result[member.name] = member; |
| 114 } |
| 115 } |
| 116 if (classElement.supertype != null) { |
| 117 helper(classElement.supertype.element) |
| 118 .forEach((String name, ExecutableElement member) { |
| 119 addIfCapable(member); |
| 120 }); |
| 121 } |
| 122 for (InterfaceType mixin in classElement.mixins) { |
| 123 helper(mixin.element).forEach((String name, ExecutableElement member) { |
| 124 addIfCapable(member); |
| 125 }); |
| 126 } |
| 127 for (MethodElement member in classElement.methods) { |
| 128 if (member.isAbstract || member.isStatic) continue; |
| 129 addIfCapable(member); |
| 130 } |
| 131 for (PropertyAccessorElement member in classElement.accessors) { |
| 132 if (member.isAbstract || member.isStatic) continue; |
| 133 addIfCapable(member); |
| 134 } |
| 135 for (FieldElement field in classElement.fields) { |
| 136 if (field.isStatic) continue; |
| 137 if (field.isSynthetic) continue; |
| 138 addIfCapable(field.getter); |
| 139 if (!field.isFinal) { |
| 140 addIfCapable(field.setter); |
| 141 } |
| 142 } |
| 143 return result; |
| 144 } |
| 145 return helper(classElement).values; |
| 146 } |
| 147 |
88 /// Returns an integer encoding the kind and attributes of the given | 148 /// Returns an integer encoding the kind and attributes of the given |
89 /// method/constructor/getter/setter. | 149 /// method/constructor/getter/setter. |
90 int _declarationDescriptor(ExecutableElement element) { | 150 int _declarationDescriptor(ExecutableElement element) { |
91 int result; | 151 int result; |
92 if (element is PropertyAccessorElement) { | 152 if (element is PropertyAccessorElement) { |
93 result = element.isGetter ? constants.getter : constants.setter; | 153 result = element.isGetter ? constants.getter : constants.setter; |
94 } else if (element is ConstructorElement) { | 154 } else if (element is ConstructorElement) { |
95 if (element.isFactory) { | 155 if (element.isFactory) { |
96 result = constants.factoryConstructor; | 156 result = constants.factoryConstructor; |
97 } else { | 157 } else { |
98 result = constants.generativeConstructor; | 158 result = constants.generativeConstructor; |
99 } | 159 } |
100 if (element.isConst) { | 160 if (element.isConst) { |
101 result += constants.constAttribute; | 161 result += constants.constAttribute; |
102 } | 162 } |
103 if (element.redirectedConstructor != null) { | 163 if (element.redirectedConstructor != null) { |
104 result += constants.redirectingConstructor; | 164 result += constants.redirectingConstructor; |
105 } | 165 } |
106 } else { | 166 } else { |
107 result = constants.method; | 167 result = constants.method; |
108 } | 168 } |
109 if (element.isPrivate) { | 169 if (element.isPrivate) { |
110 result += constants.privateAttribute; | 170 result += constants.privateAttribute; |
111 } | 171 } |
| 172 if (element.isStatic) { |
| 173 result += constants.staticAttribute; |
| 174 } |
| 175 if (element.isSynthetic) { |
| 176 result += constants.syntheticAttribute; |
| 177 } |
112 if (element.isAbstract) { | 178 if (element.isAbstract) { |
113 result += constants.abstractAttribute; | 179 result += constants.abstractAttribute; |
114 } | 180 } |
115 if (element.isStatic) { | |
116 result += constants.staticAttribute; | |
117 } | |
118 return result; | 181 return result; |
119 } | 182 } |
120 | 183 |
121 String nameOfDeclaration(ExecutableElement element) { | 184 String nameOfDeclaration(ExecutableElement element) { |
122 if (element is ConstructorElement) { | 185 if (element is ConstructorElement) { |
123 return element.name == "" | 186 return element.name == "" |
124 ? classElement.name | 187 ? classElement.name |
125 : "${classElement.name}.${element.name}"; | 188 : "${classElement.name}.${element.name}"; |
126 } | 189 } |
127 return element.name; | 190 return element.name; |
128 } | 191 } |
129 | 192 |
130 /// Returns a String with the textual representation of the declarations-map. | 193 /// Returns a String with the textual representation of the declarations-map. |
131 String get declarationsString { | 194 String get declarationsString { |
132 Iterable<String> declarationParts = declarations | 195 Iterable<String> declarationParts = declarations |
133 .map((ExecutableElement declaration) { | 196 .map((ExecutableElement declaration) { |
134 return '"${nameOfDeclaration(declaration)}": ' | 197 return '"${nameOfDeclaration(declaration)}": ' |
135 'new MethodMirrorImpl("${declaration.name}", ' | 198 'new MethodMirrorImpl("${declaration.name}", ' |
136 '${_declarationDescriptor(declaration)}, this)'; | 199 '${_declarationDescriptor(declaration)}, this)'; |
137 }); | 200 }); |
138 return "{${declarationParts.join(", ")}}"; | 201 return "{${declarationParts.join(", ")}}"; |
139 } | 202 } |
140 | 203 |
| 204 /// Returns a String with the textual representation of the |
| 205 /// instanceMembers-map. |
| 206 String get instanceMembersString { |
| 207 // TODO(sigurdm): Find out how to set the right owner. |
| 208 Iterable<String> instanceMemberParts = instanceMembers |
| 209 .map((ExecutableElement declaration) { |
| 210 return '"${nameOfDeclaration(declaration)}": ' |
| 211 'new MethodMirrorImpl("${declaration.name}", ' |
| 212 '${_declarationDescriptor(declaration)}, null)'; |
| 213 }); |
| 214 return "{${instanceMemberParts.join(", ")}}"; |
| 215 } |
| 216 |
141 /// Returns a String with the textual representations of the metadata list. | 217 /// Returns a String with the textual representations of the metadata list. |
142 // TODO(sigurdm, 17307): Make this less fragile when the analyzer's | 218 // TODO(sigurdm, 17307): Make this less fragile when the analyzer's |
143 // element-model exposes the metadata in a more friendly way. | 219 // element-model exposes the metadata in a more friendly way. |
144 String get metadataString { | 220 String get metadataString { |
145 List<String> metadataParts = new List<String>(); | 221 List<String> metadataParts = new List<String>(); |
146 Iterator<Annotation> nodeIterator = classElement.node.metadata.iterator; | 222 Iterator<Annotation> nodeIterator = classElement.node.metadata.iterator; |
147 Iterator<ElementAnnotation> elementIterator = | 223 Iterator<ElementAnnotation> elementIterator = |
148 classElement.metadata.iterator; | 224 classElement.metadata.iterator; |
149 while (nodeIterator.moveNext()) { | 225 while (nodeIterator.moveNext()) { |
150 bool r = elementIterator.moveNext(); | 226 bool r = elementIterator.moveNext(); |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 // have no effect; it might be better to emit a diagnostic message (a | 485 // have no effect; it might be better to emit a diagnostic message (a |
410 // hint?) in order to notify the programmer that "it does not work". | 486 // hint?) in order to notify the programmer that "it does not work". |
411 // The trade-off is that such constructs may have been written by | 487 // The trade-off is that such constructs may have been written by |
412 // programmers who are doing something else, intentionally. To emit a | 488 // programmers who are doing something else, intentionally. To emit a |
413 // diagnostic message, we must check whether there is a Reflectable | 489 // diagnostic message, we must check whether there is a Reflectable |
414 // somewhere inside this syntactic construct, and then emit the message | 490 // somewhere inside this syntactic construct, and then emit the message |
415 // in cases that we "consider likely to be misunderstood". | 491 // in cases that we "consider likely to be misunderstood". |
416 return null; | 492 return null; |
417 } | 493 } |
418 | 494 |
419 /// Finds all the methods in the class and all super-classes. | |
420 Iterable<MethodElement> allMethods(ClassElement classElement) { | |
421 List<MethodElement> result = new List<MethodElement>(); | |
422 result.addAll(classElement.methods); | |
423 classElement.allSupertypes.forEach((InterfaceType superType) { | |
424 result.addAll(superType.methods); | |
425 }); | |
426 return result; | |
427 } | |
428 | |
429 Iterable<MethodElement> declaredMethods( | 495 Iterable<MethodElement> declaredMethods( |
430 ClassElement classElement, Capabilities capabilities) { | 496 ClassElement classElement, Capabilities capabilities) { |
431 return classElement.methods.where((MethodElement method) { | 497 return classElement.methods.where((MethodElement method) { |
432 if (method.isAbstract) return false; | |
433 if (method.isStatic) { | 498 if (method.isStatic) { |
434 // TODO(sigurdm): Ask capabilities about support. | 499 // TODO(sigurdm): Ask capabilities about support. |
435 return true; | 500 return true; |
436 } else { | 501 } else { |
437 return capabilities.supportsInstanceInvoke(method.name); | 502 return capabilities.supportsInstanceInvoke(method.name); |
438 } | 503 } |
439 }); | 504 }); |
440 } | 505 } |
441 | 506 |
442 Iterable<PropertyAccessorElement> declaredAccessors( | 507 Iterable<PropertyAccessorElement> declaredAccessors( |
443 ClassElement classElement, Capabilities capabilities) { | 508 ClassElement classElement, Capabilities capabilities) { |
444 return classElement.accessors.where((PropertyAccessorElement accessor) { | 509 return classElement.accessors.where((PropertyAccessorElement accessor) { |
445 if (accessor.isStatic) { | 510 if (accessor.isStatic) { |
446 // TODO(sigurdm): Ask capabilities about support. | 511 // TODO(sigurdm): Ask capabilities about support. |
447 return true; | 512 return true; |
448 } else { | 513 } else { |
449 return capabilities.supportsInstanceInvoke(accessor.name); | 514 return capabilities.supportsInstanceInvoke(accessor.name); |
450 } | 515 } |
451 }); | 516 }); |
452 } | 517 } |
453 | 518 |
454 Iterable<ConstructorElement> declaredConstructors( | 519 Iterable<ConstructorElement> declaredConstructors( |
455 ClassElement classElement, Capabilities capabilities) { | 520 ClassElement classElement, Capabilities capabilities) { |
456 return classElement.constructors.where((ConstructorElement constructor) { | 521 return classElement.constructors.where((ConstructorElement constructor) { |
457 // TODO(sigurdm): Ask capabilities about support. | 522 // TODO(sigurdm): Ask capabilities about support. |
458 return true; | 523 return true; |
459 }); | 524 }); |
460 } | 525 } |
461 | 526 |
462 Iterable<MethodElement> invocableInstanceMethods( | |
463 ClassElement classElement, Capabilities capabilities) { | |
464 return allMethods(classElement).where((MethodElement method) { | |
465 MethodDeclaration methodDeclaration = method.node; | |
466 // TODO(eernst): We currently ignore method declarations when | |
467 // they are operators. One issue is generation of code (which | |
468 // does not work if we go ahead naively). | |
469 if (methodDeclaration.isOperator) return false; | |
470 String methodName = methodDeclaration.name.name; | |
471 return capabilities.supportsInstanceInvoke(methodName); | |
472 }); | |
473 } | |
474 | |
475 /// Returns a [ReflectionWorld] instantiated with all the reflectors seen by | 527 /// Returns a [ReflectionWorld] instantiated with all the reflectors seen by |
476 /// [resolver] and all classes annotated by them. | 528 /// [resolver] and all classes annotated by them. |
477 /// | 529 /// |
478 /// TODO(eernst): Make sure it works also when other packages are being | 530 /// TODO(eernst): Make sure it works also when other packages are being |
479 /// used by the target program which have already been transformed by | 531 /// used by the target program which have already been transformed by |
480 /// this transformer (e.g., there would be a clash on the use of | 532 /// this transformer (e.g., there would be a clash on the use of |
481 /// reflectableClassId with values near 1000 for more than one class). | 533 /// reflectableClassId with values near 1000 for more than one class). |
482 ReflectionWorld _computeWorld(LibraryElement reflectableLibrary) { | 534 ReflectionWorld _computeWorld(LibraryElement reflectableLibrary) { |
483 ReflectionWorld world = new ReflectionWorld(reflectableLibrary); | 535 ReflectionWorld world = new ReflectionWorld(reflectableLibrary); |
484 Map<ClassElement, ReflectorDomain> domains = | 536 Map<ClassElement, ReflectorDomain> domains = |
(...skipping 29 matching lines...) Expand all Loading... |
514 for (ElementAnnotation metadatum in type.metadata) { | 566 for (ElementAnnotation metadatum in type.metadata) { |
515 ClassElement reflector = | 567 ClassElement reflector = |
516 _getReflectableAnnotation(metadatum, focusClass); | 568 _getReflectableAnnotation(metadatum, focusClass); |
517 if (reflector == null) continue; | 569 if (reflector == null) continue; |
518 ReflectorDomain domain = domains.putIfAbsent(reflector, () { | 570 ReflectorDomain domain = domains.putIfAbsent(reflector, () { |
519 Capabilities capabilities = | 571 Capabilities capabilities = |
520 _capabilitiesOf(capabilityLibrary, reflector); | 572 _capabilitiesOf(capabilityLibrary, reflector); |
521 return new ReflectorDomain( | 573 return new ReflectorDomain( |
522 reflector, new List<ClassDomain>(), capabilities); | 574 reflector, new List<ClassDomain>(), capabilities); |
523 }); | 575 }); |
524 List<MethodElement> instanceMethods = | |
525 invocableInstanceMethods(type, domain.capabilities).toList(); | |
526 List<MethodElement> declaredMethodsOfClass = | 576 List<MethodElement> declaredMethodsOfClass = |
527 declaredMethods(type, domain.capabilities).toList(); | 577 declaredMethods(type, domain.capabilities).toList(); |
528 List<PropertyAccessorElement> declaredAccessorsOfClass = | 578 List<PropertyAccessorElement> declaredAccessorsOfClass = |
529 declaredAccessors(type, domain.capabilities).toList(); | 579 declaredAccessors(type, domain.capabilities).toList(); |
530 List<ConstructorElement> declaredConstructorsOfClass = | 580 List<ConstructorElement> declaredConstructorsOfClass = |
531 declaredConstructors(type, domain.capabilities).toList(); | 581 declaredConstructors(type, domain.capabilities).toList(); |
532 domain.annotatedClasses.add(new ClassDomain(type, instanceMethods, | 582 domain.annotatedClasses.add(new ClassDomain(type, |
533 declaredMethodsOfClass, declaredAccessorsOfClass, | 583 declaredMethodsOfClass, declaredAccessorsOfClass, |
534 declaredConstructorsOfClass, domain)); | 584 declaredConstructorsOfClass, domain)); |
535 } | 585 } |
536 } | 586 } |
537 } | 587 } |
538 } | 588 } |
539 domains.values.forEach(_collectMissingImports); | 589 domains.values.forEach(_collectMissingImports); |
540 | 590 |
541 world.reflectors.addAll(domains.values.toList()); | 591 world.reflectors.addAll(domains.values.toList()); |
542 world.computeNames(namer); | 592 world.computeNames(namer); |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
824 return [${annotatedClassesStrings.join(", ")}]; | 874 return [${annotatedClassesStrings.join(", ")}]; |
825 }"""); | 875 }"""); |
826 } | 876 } |
827 | 877 |
828 /// Returns the source code for the reflection free subclass of | 878 /// Returns the source code for the reflection free subclass of |
829 /// [ClassMirror] which is specialized for a `reflectedType` which | 879 /// [ClassMirror] which is specialized for a `reflectedType` which |
830 /// is the class modeled by [classElement]. | 880 /// is the class modeled by [classElement]. |
831 String _staticClassMirrorCode(ClassDomain classDomain) { | 881 String _staticClassMirrorCode(ClassDomain classDomain) { |
832 List<String> implementedMembers = new List<String>(); | 882 List<String> implementedMembers = new List<String>(); |
833 String simpleName = classDomain.classElement.name; | 883 String simpleName = classDomain.classElement.name; |
834 implementedMembers | 884 implementedMembers.add('final String simpleName = "$simpleName";'); |
835 .add('final String simpleName = "$simpleName";'); | |
836 // When/if we have library-mirrors there could be a generic implementation: | 885 // When/if we have library-mirrors there could be a generic implementation: |
837 // String get qualifiedName => "${owner.qualifiedName}.${simpleName}"; | 886 // String get qualifiedName => "${owner.qualifiedName}.${simpleName}"; |
838 String qualifiedName = | 887 String qualifiedName = |
839 "${classDomain.classElement.library.name}.$simpleName"; | 888 "${classDomain.classElement.library.name}.$simpleName"; |
840 implementedMembers.add('final String qualifiedName = "$qualifiedName";'); | 889 implementedMembers.add('final String qualifiedName = "$qualifiedName";'); |
841 String declarationsString = classDomain.declarationsString; | 890 String declarationsString = classDomain.declarationsString; |
842 implementedMembers.add(""" | 891 implementedMembers.add(""" |
843 Map<String, MethodMirror> _declarationsCache; | 892 Map<String, MethodMirror> _declarationsCache; |
844 Map<String, MethodMirror> get declarations { | 893 Map<String, MethodMirror> get declarations { |
845 if (_declarationsCache == null) { | 894 if (_declarationsCache == null) { |
846 _declarationsCache = new UnmodifiableMapView($declarationsString); | 895 _declarationsCache = new UnmodifiableMapView($declarationsString); |
847 } | 896 } |
848 return _declarationsCache; | 897 return _declarationsCache; |
849 }"""); | 898 }"""); |
| 899 String instanceMembersString = classDomain.instanceMembersString; |
| 900 implementedMembers.add(""" |
| 901 Map<String, MethodMirror> _instanceMembersCache; |
| 902 |
| 903 Map<String, MethodMirror> get instanceMembers { |
| 904 if (_instanceMembersCache == null) { |
| 905 _instanceMembersCache = new UnmodifiableMapView($instanceMembersString); |
| 906 } |
| 907 return _instanceMembersCache; |
| 908 }"""); |
850 if (classDomain.reflectorDomain.capabilities.supportsMetadata) { | 909 if (classDomain.reflectorDomain.capabilities.supportsMetadata) { |
851 implementedMembers | 910 implementedMembers |
852 .add("List<Object> metadata = ${classDomain.metadataString};"); | 911 .add("List<Object> metadata = ${classDomain.metadataString};"); |
853 } | 912 } |
854 | 913 |
855 return """ | 914 return """ |
856 class ${classDomain.staticClassMirrorName} extends ClassMirrorUnimpl { | 915 class ${classDomain.staticClassMirrorName} extends ClassMirrorUnimpl { |
857 ${implementedMembers.join("\n\n ")} | 916 ${implementedMembers.join("\n\n ")} |
858 } | 917 } |
859 """; | 918 """; |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1135 ListLiteral listLiteral = arguments[0]; | 1194 ListLiteral listLiteral = arguments[0]; |
1136 NodeList<Expression> expressions = listLiteral.elements; | 1195 NodeList<Expression> expressions = listLiteral.elements; |
1137 return new Capabilities(expressions.map(capabilityOfExpression).toList()); | 1196 return new Capabilities(expressions.map(capabilityOfExpression).toList()); |
1138 } | 1197 } |
1139 | 1198 |
1140 /// Returns a [String] containing generated code for the `invoke` | 1199 /// Returns a [String] containing generated code for the `invoke` |
1141 /// method of the static `InstanceMirror` class corresponding to | 1200 /// method of the static `InstanceMirror` class corresponding to |
1142 /// the given [classElement], bounded by the permissions given | 1201 /// the given [classElement], bounded by the permissions given |
1143 /// in [capabilities]. | 1202 /// in [capabilities]. |
1144 String _staticInstanceMirrorInvokeCode(ClassDomain classDomain) { | 1203 String _staticInstanceMirrorInvokeCode(ClassDomain classDomain) { |
| 1204 String tearOff(MethodElement methodElement) { |
| 1205 if (!methodElement.isOperator) return "reflectee.${methodElement.name}"; |
| 1206 if (methodElement.name == "[]=") return "(x, v) => reflectee[x] = v"; |
| 1207 if (methodElement.name == "[]") return "(x) => reflectee[x]"; |
| 1208 return "(x) => reflectee ${methodElement.name} x"; |
| 1209 } |
| 1210 |
1145 List<String> methodCases = new List<String>(); | 1211 List<String> methodCases = new List<String>(); |
1146 for (MethodElement methodElement in classDomain.invokableMethods) { | 1212 for (MethodElement methodElement in classDomain.invokableMethods) { |
1147 String methodName = methodElement.name; | 1213 methodCases.add("if (memberName == '${methodElement.name}') {" |
1148 methodCases.add("if (memberName == '$methodName') {" | 1214 "method = ${tearOff(methodElement)}; }"); |
1149 "method = reflectee.$methodName; }"); | |
1150 } | 1215 } |
1151 // TODO(eernst, sigurdm): Create an instance of [Invocation] in user code. | 1216 // TODO(eernst, sigurdm): Create an instance of [Invocation] in user code. |
1152 methodCases.add("if (instanceMethodFilter.hasMatch(memberName)) {" | 1217 methodCases.add("if (instanceMethodFilter.hasMatch(memberName)) {" |
1153 "throw new UnimplementedError('Should call noSuchMethod'); }"); | 1218 "throw new UnimplementedError('Should call noSuchMethod'); }"); |
1154 methodCases.add("{ throw new NoSuchInvokeCapabilityError(" | 1219 methodCases.add("{ throw new NoSuchInvokeCapabilityError(" |
1155 "reflectee, memberName, positionalArguments, namedArguments); }"); | 1220 "reflectee, memberName, positionalArguments, namedArguments); }"); |
1156 // Handle the cases where permission is given even though there is | 1221 // Handle the cases where permission is given even though there is |
1157 // no corresponding method. One case is where _all_ methods can be | 1222 // no corresponding method. One case is where _all_ methods can be |
1158 // invoked. Another case is when the user has specified a name | 1223 // invoked. Another case is when the user has specified a name |
1159 // `"foo"` and a reflector `@reflector` allowing for invocation | 1224 // `"foo"` and a reflector `@reflector` allowing for invocation |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1417 TransformLogger get logger => _aggregateTransform.logger; | 1482 TransformLogger get logger => _aggregateTransform.logger; |
1418 Future<Asset> getInput(AssetId id) => _aggregateTransform.getInput(id); | 1483 Future<Asset> getInput(AssetId id) => _aggregateTransform.getInput(id); |
1419 Future<String> readInputAsString(AssetId id, {Encoding encoding}) { | 1484 Future<String> readInputAsString(AssetId id, {Encoding encoding}) { |
1420 return _aggregateTransform.readInputAsString(id, encoding: encoding); | 1485 return _aggregateTransform.readInputAsString(id, encoding: encoding); |
1421 } | 1486 } |
1422 Stream<List<int>> readInput(AssetId id) => _aggregateTransform.readInput(id); | 1487 Stream<List<int>> readInput(AssetId id) => _aggregateTransform.readInput(id); |
1423 Future<bool> hasInput(AssetId id) => _aggregateTransform.hasInput(id); | 1488 Future<bool> hasInput(AssetId id) => _aggregateTransform.hasInput(id); |
1424 void addOutput(Asset output) => _aggregateTransform.addOutput(output); | 1489 void addOutput(Asset output) => _aggregateTransform.addOutput(output); |
1425 void consumePrimary() => _aggregateTransform.consumePrimary(primaryInput.id); | 1490 void consumePrimary() => _aggregateTransform.consumePrimary(primaryInput.id); |
1426 } | 1491 } |
OLD | NEW |