Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Side by Side Diff: reflectable/lib/src/transformer_implementation.dart

Issue 1181413005: Implement newInstance in the transformer. (Closed) Base URL: https://github.com/dart-lang/reflectable.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test_reflectable/.status » ('j') | test_reflectable/.status » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 /// Information about reflectability for a given class. 75 /// Information about reflectability for a given class.
76 class ClassDomain { 76 class ClassDomain {
77 final ClassElement classElement; 77 final ClassElement classElement;
78 final Iterable<MethodElement> declaredMethods; 78 final Iterable<MethodElement> declaredMethods;
79 final Iterable<PropertyAccessorElement> declaredAccessors; 79 final Iterable<PropertyAccessorElement> declaredAccessors;
80 final Iterable<ConstructorElement> constructors; 80 final Iterable<ConstructorElement> constructors;
81 81
82 ReflectorDomain reflectorDomain; 82 ReflectorDomain reflectorDomain;
83 83
84 Iterable<MethodElement> get invokableMethods => instanceMembers 84 Iterable<MethodElement> get invokableMethods => instanceMembers
85 .where((ExecutableElement element) => element is MethodElement); 85 .where((ExecutableElement element) => element is MethodElement);
86 86
87 String staticClassMirrorName; 87 String staticClassMirrorName;
88 String staticInstanceMirrorName; 88 String staticInstanceMirrorName;
89 String get baseName => classElement.name; 89 String get baseName => classElement.name;
90 90
91 ClassDomain(this.classElement, this.declaredMethods, 91 ClassDomain(this.classElement, this.declaredMethods, this.declaredAccessors,
92 this.declaredAccessors, this.constructors, this.reflectorDomain); 92 this.constructors, this.reflectorDomain);
93 93
94 Iterable<ExecutableElement> get declarations { 94 Iterable<ExecutableElement> get declarations {
95 // TODO(sigurdm): Include fields. 95 // TODO(sigurdm): Include fields.
96 // TODO(sigurdm): Include type variables (if we decide to keep them). 96 // TODO(sigurdm): Include type variables (if we decide to keep them).
97 return [declaredMethods, declaredAccessors, constructors].expand((x) => x); 97 return [declaredMethods, declaredAccessors, constructors].expand((x) => x);
98 } 98 }
99 99
100 /// Finds all instance members by going through the class hierarchy. 100 /// Finds all instance members by going through the class hierarchy.
101 Iterable<ExecutableElement> get instanceMembers { 101 Iterable<ExecutableElement> get instanceMembers {
102
103 Map<String, ExecutableElement> helper(ClassElement classElement) { 102 Map<String, ExecutableElement> helper(ClassElement classElement) {
104 if (reflectorDomain._instanceMemberCache[classElement] != null) { 103 if (reflectorDomain._instanceMemberCache[classElement] != null) {
105 return reflectorDomain._instanceMemberCache[classElement]; 104 return reflectorDomain._instanceMemberCache[classElement];
106 } 105 }
107 Map<String, ExecutableElement> result = 106 Map<String, ExecutableElement> result =
108 new Map<String, ExecutableElement>(); 107 new Map<String, ExecutableElement>();
109 108
110 void addIfCapable(ExecutableElement member) { 109 void addIfCapable(ExecutableElement member) {
111 if (reflectorDomain.capabilities.supportsInstanceInvoke(member.name)) { 110 if (reflectorDomain.capabilities.supportsInstanceInvoke(member.name)) {
112 result[member.name] = member; 111 result[member.name] = member;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 '${_declarationDescriptor(declaration)}, this)'; 195 '${_declarationDescriptor(declaration)}, this)';
197 }); 196 });
198 return "{${declarationParts.join(", ")}}"; 197 return "{${declarationParts.join(", ")}}";
199 } 198 }
200 199
201 /// Returns a String with the textual representation of the 200 /// Returns a String with the textual representation of the
202 /// instanceMembers-map. 201 /// instanceMembers-map.
203 String get instanceMembersString { 202 String get instanceMembersString {
204 // TODO(sigurdm): Find out how to set the right owner. 203 // TODO(sigurdm): Find out how to set the right owner.
205 Iterable<String> instanceMemberParts = instanceMembers.map( 204 Iterable<String> instanceMemberParts = instanceMembers.map(
206 (ExecutableElement declaration) { 205 (ExecutableElement declaration) {
207 return '"${nameOfDeclaration(declaration)}": ' 206 return '"${nameOfDeclaration(declaration)}": '
208 'new MethodMirrorImpl("${declaration.name}", ' 207 'new MethodMirrorImpl("${declaration.name}", '
209 '${_declarationDescriptor(declaration)}, null)'; 208 '${_declarationDescriptor(declaration)}, null)';
210 }); 209 });
211 return "{${instanceMemberParts.join(", ")}}"; 210 return "{${instanceMemberParts.join(", ")}}";
212 } 211 }
213 212
213 String get newInstanceString {
eernst 2015/06/18 13:35:41 I've been looking for a general hint (some DartDoc
sigurdm 2015/06/19 07:50:54 Your intuition is right. There is no exact defined
214 // TODO(eernst, sigurdm, #8): Recreate the default values faithfully.
215 List<String> constructorLines = new List<String>();
216
217 String name(int i) {
218 String alphabet = "abcdefghijklmnopqrstuvwxyz";
219 int alphabetLength = alphabet.length;
220 if (i < alphabetLength) {
221 return "_${alphabet[i]}";
222 }
223 return "_${alphabet[i % alphabetLength]}${i ~/ alphabetLength}";
224 }
225 for (ConstructorElement constructor in constructors) {
226 FunctionType type = constructor.type;
227 int positionalCount = type.normalParameterTypes.length;
228 int optionalCount = type.optionalParameterTypes.length;
229 List<String> argumentNames = type.namedParameterTypes.keys.toList();
230 String positionals = new Iterable.generate(
231 positionalCount, (int i) => name(i)).join(", ");
232 String optionalsWithDefaults = new Iterable.generate(optionalCount,
233 (int i) {
234 String defaultValueCode =
235 constructor.parameters[positionalCount + i].defaultValueCode;
236 String defaultValueString =
237 defaultValueCode == null ? "" : " = $defaultValueCode";
238 return "${name(i + positionalCount)}$defaultValueString";
239 }).join(", ");
eernst 2015/06/18 13:35:41 Maybe we can sell this style of indentation to
sigurdm 2015/06/19 07:50:54 ?
240 String namedWithDefaults = new Iterable.generate(argumentNames.length,
241 (int i) {
242 String defaultValueCode =
243 constructor.parameters[positionalCount + i].defaultValueCode;
244 String defaultValueString =
245 defaultValueCode == null ? "" : ": $defaultValueCode";
246 return "${argumentNames[i]}$defaultValueString";
247 }).join(", ");
248
249 String optionalArguments = new Iterable.generate(
250 optionalCount, (int i) => name(i + positionalCount)).join(", ");
251 String namedArguments =
252 argumentNames.map((String name) => "$name: $name").join(", ");
253 List<String> parameterParts = new List<String>();
254 List<String> argumentParts = new List<String>();
255 if (positionalCount != 0) {
256 parameterParts.add(positionals);
257 argumentParts.add(positionals);
258 }
259 if (optionalCount != 0) {
260 parameterParts.add("[$optionalsWithDefaults]");
261 argumentParts.add(optionalArguments);
262 }
263 if (argumentNames.isNotEmpty) {
264 parameterParts.add("{${namedWithDefaults}}");
265 argumentParts.add(namedArguments);
266 }
267 constructorLines.add('case "${constructor.name}": '
268 'c = (${parameterParts.join(', ')}) => '
269 'new ${nameOfDeclaration(constructor)}'
270 '(${argumentParts.join(", ")});');
271 constructorLines.add(' break;');
272 }
273 return """newInstance(String constructorName, List positionalArguments,
274 [Map<Symbol, dynamic> namedArguments]) {
275 Function c;
276 switch (constructorName) {
277 ${constructorLines.join("\n ")}
278 default: throw new NoSuchInvokeCapabilityError(${classElement.name},
279 constructorName, positionalArguments, namedArguments);
280 }
281 return Function.apply(c, positionalArguments, namedArguments);
282 }""";
283 }
284
214 void computeNames(Namer namer) { 285 void computeNames(Namer namer) {
215 staticClassMirrorName = namer.freshName("Static_${baseName}_ClassMirror"); 286 staticClassMirrorName = namer.freshName("Static_${baseName}_ClassMirror");
216 staticInstanceMirrorName = 287 staticInstanceMirrorName =
217 namer.freshName("Static_${baseName}_InstanceMirror"); 288 namer.freshName("Static_${baseName}_InstanceMirror");
218 } 289 }
219 } 290 }
220 291
221 /// A wrapper around a list of Capabilities. 292 /// A wrapper around a list of Capabilities.
222 /// Supports queries about the methods supported by the set of capabilities. 293 /// Supports queries about the methods supported by the set of capabilities.
223 class Capabilities { 294 class Capabilities {
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 insert(""" 919 insert("""
849 Iterable<${prefix}ClassMirror> get annotatedClasses { 920 Iterable<${prefix}ClassMirror> get annotatedClasses {
850 return [${annotatedClassesStrings.join(", ")}]; 921 return [${annotatedClassesStrings.join(", ")}];
851 }"""); 922 }""");
852 } 923 }
853 924
854 /// Returns the source code for the reflection free subclass of 925 /// Returns the source code for the reflection free subclass of
855 /// [ClassMirror] which is specialized for a `reflectedType` which 926 /// [ClassMirror] which is specialized for a `reflectedType` which
856 /// is the class modeled by [classElement]. 927 /// is the class modeled by [classElement].
857 String _staticClassMirrorCode(ClassDomain classDomain) { 928 String _staticClassMirrorCode(ClassDomain classDomain) {
929
858 String declarationsString = classDomain.declarationsString; 930 String declarationsString = classDomain.declarationsString;
859 String instanceMembersString = classDomain.instanceMembersString; 931 String instanceMembersString = classDomain.instanceMembersString;
932 List<String> memberStrings = new List<String>();
933 if (!classDomain.classElement.isAbstract) {
934 memberStrings.add(classDomain.newInstanceString);
935 }
eernst 2015/06/18 13:35:41 This one would be new, but still related to the tr
sigurdm 2015/06/19 07:50:54 You cannot invoke abstract cosntructors directly,
860 return """ 936 return """
861 class ${classDomain.staticClassMirrorName} extends ClassMirrorUnimpl { 937 class ${classDomain.staticClassMirrorName} extends ClassMirrorUnimpl {
862 final String simpleName = "${classDomain.classElement.name}"; 938 final String simpleName = "${classDomain.classElement.name}";
863 939
864 Map<String, MethodMirror> _declarationsCache; 940 Map<String, MethodMirror> _declarationsCache;
865 941
866 Map<String, MethodMirror> get declarations { 942 Map<String, MethodMirror> get declarations {
867 if (_declarationsCache == null) { 943 if (_declarationsCache == null) {
868 _declarationsCache = new UnmodifiableMapView($declarationsString); 944 _declarationsCache = new UnmodifiableMapView($declarationsString);
869 } 945 }
870 return _declarationsCache; 946 return _declarationsCache;
871 } 947 }
872 948
873 Map<String, MethodMirror> _instanceMembersCache; 949 Map<String, MethodMirror> _instanceMembersCache;
874 950
875 Map<String, MethodMirror> get instanceMembers { 951 Map<String, MethodMirror> get instanceMembers {
876 if (_instanceMembersCache == null) { 952 if (_instanceMembersCache == null) {
877 _instanceMembersCache = new UnmodifiableMapView($instanceMembersString); 953 _instanceMembersCache = new UnmodifiableMapView($instanceMembersString);
878 } 954 }
879 return _instanceMembersCache; 955 return _instanceMembersCache;
880 } 956 }
881 957
958 ${memberStrings.join("\n\n ")}
882 } 959 }
883 """; 960 """;
884 } 961 }
885 962
886 /// Perform some very simple steps that are consistent with Dart 963 /// Perform some very simple steps that are consistent with Dart
887 /// semantics for the evaluation of constant expressions, such that 964 /// semantics for the evaluation of constant expressions, such that
888 /// information about the value of a given `const` variable can be 965 /// information about the value of a given `const` variable can be
889 /// obtained. It is intended to help recognizing values of type 966 /// obtained. It is intended to help recognizing values of type
890 /// [ReflectCapability], so we only cover cases needed for that. 967 /// [ReflectCapability], so we only cover cases needed for that.
891 /// In particular, we cover lookup (e.g., with `const x = e` we can 968 /// In particular, we cover lookup (e.g., with `const x = e` we can
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
969 case "InvokeMembersWithMetadataCapability": 1046 case "InvokeMembersWithMetadataCapability":
970 throw new UnimplementedError("$classElement not yet supported"); 1047 throw new UnimplementedError("$classElement not yet supported");
971 case "InvokeInstanceMembersUpToSuperCapability": 1048 case "InvokeInstanceMembersUpToSuperCapability":
972 throw new UnimplementedError("$classElement not yet supported"); 1049 throw new UnimplementedError("$classElement not yet supported");
973 case "_InvokeStaticMembersCapability": 1050 case "_InvokeStaticMembersCapability":
974 return invokeStaticMembersCapability; 1051 return invokeStaticMembersCapability;
975 case "InvokeInstanceMemberCapability": 1052 case "InvokeInstanceMemberCapability":
976 throw new UnimplementedError("$classElement not yet supported"); 1053 throw new UnimplementedError("$classElement not yet supported");
977 case "InvokeStaticMemberCapability": 1054 case "InvokeStaticMemberCapability":
978 throw new UnimplementedError("$classElement not yet supported"); 1055 throw new UnimplementedError("$classElement not yet supported");
1056 case "_InvokeConstructorsCapability":
1057 return invokeConstructorsCapability;
eernst 2015/06/18 13:35:41 I believe this is the same thing as the capability
sigurdm 2015/06/19 07:50:54 This was based on the previous incantation of capa
979 default: 1058 default:
980 throw new UnimplementedError("Unexpected capability $classElement"); 1059 throw new UnimplementedError("Unexpected capability $classElement");
981 } 1060 }
982 } 1061 }
983 1062
984 /// Returns the list of Capabilities given given as a superinitializer by the 1063 /// Returns the list of Capabilities given given as a superinitializer by the
985 /// reflector. 1064 /// reflector.
986 Capabilities _capabilitiesOf( 1065 Capabilities _capabilitiesOf(
987 LibraryElement capabilityLibrary, ClassElement reflector) { 1066 LibraryElement capabilityLibrary, ClassElement reflector) {
988 List<ConstructorElement> constructors = reflector.constructors; 1067 List<ConstructorElement> constructors = reflector.constructors;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1034 ListLiteral listLiteral = arguments[0]; 1113 ListLiteral listLiteral = arguments[0];
1035 NodeList<Expression> expressions = listLiteral.elements; 1114 NodeList<Expression> expressions = listLiteral.elements;
1036 return new Capabilities(expressions.map(capabilityOfExpression).toList()); 1115 return new Capabilities(expressions.map(capabilityOfExpression).toList());
1037 } 1116 }
1038 1117
1039 /// Returns a [String] containing generated code for the `invoke` 1118 /// Returns a [String] containing generated code for the `invoke`
1040 /// method of the static `InstanceMirror` class corresponding to 1119 /// method of the static `InstanceMirror` class corresponding to
1041 /// the given [classElement], bounded by the permissions given 1120 /// the given [classElement], bounded by the permissions given
1042 /// in [capabilities]. 1121 /// in [capabilities].
1043 String _staticInstanceMirrorInvokeCode(ClassDomain classDomain) { 1122 String _staticInstanceMirrorInvokeCode(ClassDomain classDomain) {
1044
1045 String tearOff(MethodElement methodElement) { 1123 String tearOff(MethodElement methodElement) {
1046 if (!methodElement.isOperator) return "reflectee.${methodElement.name}"; 1124 if (!methodElement.isOperator) return "reflectee.${methodElement.name}";
1047 if (methodElement.name == "[]=") return "(x, v) => reflectee[x] = v"; 1125 if (methodElement.name == "[]=") return "(x, v) => reflectee[x] = v";
1048 if (methodElement.name == "[]") return "(x) => reflectee[x]"; 1126 if (methodElement.name == "[]") return "(x) => reflectee[x]";
1049 return "(x) => reflectee ${methodElement.name} x"; 1127 return "(x) => reflectee ${methodElement.name} x";
1050 } 1128 }
1051 1129
1052
1053 List<String> methodCases = new List<String>(); 1130 List<String> methodCases = new List<String>();
1054 for (MethodElement methodElement in classDomain.invokableMethods) { 1131 for (MethodElement methodElement in classDomain.invokableMethods) {
1055 methodCases.add("if (memberName == '${methodElement.name}') {" 1132 methodCases.add("if (memberName == '${methodElement.name}') {"
1056 "method = ${tearOff(methodElement)}; }"); 1133 "method = ${tearOff(methodElement)}; }");
1057 } 1134 }
1058 // TODO(eernst, sigurdm): Create an instance of [Invocation] in user code. 1135 // TODO(eernst, sigurdm): Create an instance of [Invocation] in user code.
1059 methodCases.add("if (instanceMethodFilter.hasMatch(memberName)) {" 1136 methodCases.add("if (instanceMethodFilter.hasMatch(memberName)) {"
1060 "throw new UnimplementedError('Should call noSuchMethod'); }"); 1137 "throw new UnimplementedError('Should call noSuchMethod'); }");
1061 methodCases.add("{ throw new NoSuchInvokeCapabilityError(" 1138 methodCases.add("{ throw new NoSuchInvokeCapabilityError("
1062 "reflectee, memberName, positionalArguments, namedArguments); }"); 1139 "reflectee, memberName, positionalArguments, namedArguments); }");
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
1322 TransformLogger get logger => _aggregateTransform.logger; 1399 TransformLogger get logger => _aggregateTransform.logger;
1323 Future<Asset> getInput(AssetId id) => _aggregateTransform.getInput(id); 1400 Future<Asset> getInput(AssetId id) => _aggregateTransform.getInput(id);
1324 Future<String> readInputAsString(AssetId id, {Encoding encoding}) { 1401 Future<String> readInputAsString(AssetId id, {Encoding encoding}) {
1325 return _aggregateTransform.readInputAsString(id, encoding: encoding); 1402 return _aggregateTransform.readInputAsString(id, encoding: encoding);
1326 } 1403 }
1327 Stream<List<int>> readInput(AssetId id) => _aggregateTransform.readInput(id); 1404 Stream<List<int>> readInput(AssetId id) => _aggregateTransform.readInput(id);
1328 Future<bool> hasInput(AssetId id) => _aggregateTransform.hasInput(id); 1405 Future<bool> hasInput(AssetId id) => _aggregateTransform.hasInput(id);
1329 void addOutput(Asset output) => _aggregateTransform.addOutput(output); 1406 void addOutput(Asset output) => _aggregateTransform.addOutput(output);
1330 void consumePrimary() => _aggregateTransform.consumePrimary(primaryInput.id); 1407 void consumePrimary() => _aggregateTransform.consumePrimary(primaryInput.id);
1331 } 1408 }
OLDNEW
« no previous file with comments | « no previous file | test_reflectable/.status » ('j') | test_reflectable/.status » ('J')

Powered by Google App Engine
This is Rietveld 408576698