Index: reflectable/lib/src/transformer_implementation.dart |
diff --git a/reflectable/lib/src/transformer_implementation.dart b/reflectable/lib/src/transformer_implementation.dart |
index d7709061f90ca8f8b9a6f98ec3f5362c2ccea25b..7d64e2427fb004be10f11eb18f0febe44d3a208c 100644 |
--- a/reflectable/lib/src/transformer_implementation.dart |
+++ b/reflectable/lib/src/transformer_implementation.dart |
@@ -82,14 +82,14 @@ class ClassDomain { |
ReflectorDomain reflectorDomain; |
Iterable<MethodElement> get invokableMethods => instanceMembers |
- .where((ExecutableElement element) => element is MethodElement); |
+ .where((ExecutableElement element) => element is MethodElement); |
String staticClassMirrorName; |
String staticInstanceMirrorName; |
String get baseName => classElement.name; |
- ClassDomain(this.classElement, this.declaredMethods, |
- this.declaredAccessors, this.constructors, this.reflectorDomain); |
+ ClassDomain(this.classElement, this.declaredMethods, this.declaredAccessors, |
+ this.constructors, this.reflectorDomain); |
Iterable<ExecutableElement> get declarations { |
// TODO(sigurdm): Include fields. |
@@ -99,7 +99,6 @@ class ClassDomain { |
/// Finds all instance members by going through the class hierarchy. |
Iterable<ExecutableElement> get instanceMembers { |
- |
Map<String, ExecutableElement> helper(ClassElement classElement) { |
if (reflectorDomain._instanceMemberCache[classElement] != null) { |
return reflectorDomain._instanceMemberCache[classElement]; |
@@ -203,14 +202,86 @@ class ClassDomain { |
String get instanceMembersString { |
// TODO(sigurdm): Find out how to set the right owner. |
Iterable<String> instanceMemberParts = instanceMembers.map( |
- (ExecutableElement declaration) { |
- return '"${nameOfDeclaration(declaration)}": ' |
+ (ExecutableElement declaration) { |
+ return '"${nameOfDeclaration(declaration)}": ' |
'new MethodMirrorImpl("${declaration.name}", ' |
'${_declarationDescriptor(declaration)}, null)'; |
- }); |
+ }); |
return "{${instanceMemberParts.join(", ")}}"; |
} |
+ 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
|
+ // TODO(eernst, sigurdm, #8): Recreate the default values faithfully. |
+ List<String> constructorLines = new List<String>(); |
+ |
+ String name(int i) { |
+ String alphabet = "abcdefghijklmnopqrstuvwxyz"; |
+ int alphabetLength = alphabet.length; |
+ if (i < alphabetLength) { |
+ return "_${alphabet[i]}"; |
+ } |
+ return "_${alphabet[i % alphabetLength]}${i ~/ alphabetLength}"; |
+ } |
+ for (ConstructorElement constructor in constructors) { |
+ FunctionType type = constructor.type; |
+ int positionalCount = type.normalParameterTypes.length; |
+ int optionalCount = type.optionalParameterTypes.length; |
+ List<String> argumentNames = type.namedParameterTypes.keys.toList(); |
+ String positionals = new Iterable.generate( |
+ positionalCount, (int i) => name(i)).join(", "); |
+ String optionalsWithDefaults = new Iterable.generate(optionalCount, |
+ (int i) { |
+ String defaultValueCode = |
+ constructor.parameters[positionalCount + i].defaultValueCode; |
+ String defaultValueString = |
+ defaultValueCode == null ? "" : " = $defaultValueCode"; |
+ return "${name(i + positionalCount)}$defaultValueString"; |
+ }).join(", "); |
eernst
2015/06/18 13:35:41
Maybe
we can sell this style of
indentation to
sigurdm
2015/06/19 07:50:54
?
|
+ String namedWithDefaults = new Iterable.generate(argumentNames.length, |
+ (int i) { |
+ String defaultValueCode = |
+ constructor.parameters[positionalCount + i].defaultValueCode; |
+ String defaultValueString = |
+ defaultValueCode == null ? "" : ": $defaultValueCode"; |
+ return "${argumentNames[i]}$defaultValueString"; |
+ }).join(", "); |
+ |
+ String optionalArguments = new Iterable.generate( |
+ optionalCount, (int i) => name(i + positionalCount)).join(", "); |
+ String namedArguments = |
+ argumentNames.map((String name) => "$name: $name").join(", "); |
+ List<String> parameterParts = new List<String>(); |
+ List<String> argumentParts = new List<String>(); |
+ if (positionalCount != 0) { |
+ parameterParts.add(positionals); |
+ argumentParts.add(positionals); |
+ } |
+ if (optionalCount != 0) { |
+ parameterParts.add("[$optionalsWithDefaults]"); |
+ argumentParts.add(optionalArguments); |
+ } |
+ if (argumentNames.isNotEmpty) { |
+ parameterParts.add("{${namedWithDefaults}}"); |
+ argumentParts.add(namedArguments); |
+ } |
+ constructorLines.add('case "${constructor.name}": ' |
+ 'c = (${parameterParts.join(', ')}) => ' |
+ 'new ${nameOfDeclaration(constructor)}' |
+ '(${argumentParts.join(", ")});'); |
+ constructorLines.add(' break;'); |
+ } |
+ return """newInstance(String constructorName, List positionalArguments, |
+ [Map<Symbol, dynamic> namedArguments]) { |
+ Function c; |
+ switch (constructorName) { |
+ ${constructorLines.join("\n ")} |
+ default: throw new NoSuchInvokeCapabilityError(${classElement.name}, |
+ constructorName, positionalArguments, namedArguments); |
+ } |
+ return Function.apply(c, positionalArguments, namedArguments); |
+ }"""; |
+ } |
+ |
void computeNames(Namer namer) { |
staticClassMirrorName = namer.freshName("Static_${baseName}_ClassMirror"); |
staticInstanceMirrorName = |
@@ -855,8 +926,13 @@ class TransformerImplementation { |
/// [ClassMirror] which is specialized for a `reflectedType` which |
/// is the class modeled by [classElement]. |
String _staticClassMirrorCode(ClassDomain classDomain) { |
+ |
String declarationsString = classDomain.declarationsString; |
String instanceMembersString = classDomain.instanceMembersString; |
+ List<String> memberStrings = new List<String>(); |
+ if (!classDomain.classElement.isAbstract) { |
+ memberStrings.add(classDomain.newInstanceString); |
+ } |
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,
|
return """ |
class ${classDomain.staticClassMirrorName} extends ClassMirrorUnimpl { |
final String simpleName = "${classDomain.classElement.name}"; |
@@ -879,6 +955,7 @@ class ${classDomain.staticClassMirrorName} extends ClassMirrorUnimpl { |
return _instanceMembersCache; |
} |
+ ${memberStrings.join("\n\n ")} |
} |
"""; |
} |
@@ -976,6 +1053,8 @@ class ${classDomain.staticClassMirrorName} extends ClassMirrorUnimpl { |
throw new UnimplementedError("$classElement not yet supported"); |
case "InvokeStaticMemberCapability": |
throw new UnimplementedError("$classElement not yet supported"); |
+ case "_InvokeConstructorsCapability": |
+ 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
|
default: |
throw new UnimplementedError("Unexpected capability $classElement"); |
} |
@@ -1041,7 +1120,6 @@ class ${classDomain.staticClassMirrorName} extends ClassMirrorUnimpl { |
/// the given [classElement], bounded by the permissions given |
/// in [capabilities]. |
String _staticInstanceMirrorInvokeCode(ClassDomain classDomain) { |
- |
String tearOff(MethodElement methodElement) { |
if (!methodElement.isOperator) return "reflectee.${methodElement.name}"; |
if (methodElement.name == "[]=") return "(x, v) => reflectee[x] = v"; |
@@ -1049,7 +1127,6 @@ class ${classDomain.staticClassMirrorName} extends ClassMirrorUnimpl { |
return "(x) => reflectee ${methodElement.name} x"; |
} |
- |
List<String> methodCases = new List<String>(); |
for (MethodElement methodElement in classDomain.invokableMethods) { |
methodCases.add("if (memberName == '${methodElement.name}') {" |