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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | test_reflectable/.status » ('j') | test_reflectable/.status » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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}') {"
« 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