From d0efa81089b667d21bd1f05b5a869c73f01ad216 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Fri, 30 Nov 2018 01:09:18 -0500 Subject: [PATCH] tad wonky, but generator works --- .../lib/angel_container_generator.dart | 96 ++++- angel_container_generator/pubspec.yaml | 1 + .../test/reflector_test.dart | 35 +- .../test/reflector_test.reflectable.dart | 338 ++++++++++++++++-- 4 files changed, 416 insertions(+), 54 deletions(-) diff --git a/angel_container_generator/lib/angel_container_generator.dart b/angel_container_generator/lib/angel_container_generator.dart index ff1cfcfb..eb34f2af 100644 --- a/angel_container_generator/lib/angel_container_generator.dart +++ b/angel_container_generator/lib/angel_container_generator.dart @@ -4,6 +4,7 @@ import 'package:reflectable/reflectable.dart'; /// A [Reflectable] instance that can be used as an annotation on types to generate metadata for them. const Reflectable contained = const ContainedReflectable(); +@contained class ContainedReflectable extends Reflectable { const ContainedReflectable() : super( @@ -13,7 +14,8 @@ class ContainedReflectable extends Reflectable { metadataCapability, newInstanceCapability, reflectedTypeCapability, - typeRelationsCapability); + typeRelationsCapability, + typeCapability); } /// A [Reflector] instance that uses a [Reflectable] to reflect upon data. @@ -24,8 +26,7 @@ class GeneratedReflector implements Reflector { @override String getName(Symbol symbol) { - // TODO: implement getName - throw new UnimplementedError(); + return symbol.toString().substring(7); } @override @@ -35,8 +36,17 @@ class GeneratedReflector implements Reflector { @override ReflectedFunction reflectFunction(Function function) { - // TODO: implement reflectFunction - throw new UnimplementedError(); + if (!reflectable.canReflect(function)) { + throw new UnsupportedError('Cannot reflect $function.'); + } + + var mirror = reflectable.reflect(function); + + if (mirror is ClosureMirror) { + return new _GeneratedReflectedFunction(mirror.function, this, mirror); + } else { + throw new ArgumentError('$function is not a Function.'); + } } @override @@ -44,7 +54,8 @@ class GeneratedReflector implements Reflector { if (!reflectable.canReflect(object)) { throw new UnsupportedError('Cannot reflect $object.'); } else { - return new _GeneratedReflectedInstance(reflectable.reflect(object), this); + var mirror = reflectable.reflect(object); + return new _GeneratedReflectedInstance(mirror, this); } } @@ -109,8 +120,9 @@ class _GeneratedReflectedClass extends ReflectedClass { ReflectedInstance newInstance( String constructorName, List positionalArguments, [Map namedArguments, List typeArguments]) { - return mirror.newInstance(constructorName, positionalArguments, + var result = mirror.newInstance(constructorName, positionalArguments, namedArguments.map((k, v) => new MapEntry(new Symbol(k), v))); + return reflector.reflectInstance(result); } } @@ -143,24 +155,82 @@ class _GeneratedReflectedType extends ReflectedType { } } -// TODO: Reflect functions? +class _GeneratedReflectedFunction extends ReflectedFunction { + final MethodMirror mirror; + final Reflector reflector; + final ClosureMirror closure; + + _GeneratedReflectedFunction(this.mirror, this.reflector, [this.closure]) + : super( + mirror.simpleName, + [], + null, + !mirror.isRegularMethod + ? null + : new _GeneratedReflectedType(mirror.returnType), + mirror.parameters + .map((p) => _convertParameter(p, reflector)) + .toList(), + mirror.isGetter, + mirror.isSetter); + + @override + List get annotations => + mirror.metadata.map(reflector.reflectInstance).toList(); + + @override + ReflectedInstance invoke(Invocation invocation) { + if (closure != null) { + throw new UnsupportedError('Only closures can be invoked directly.'); + } else { + var result = closure.delegate(invocation); + return reflector.reflectInstance(result); + } + } +} + List _constructorsOf( Map map, Reflector reflector) { - print(map); return map.entries.fold>([], (out, entry) { - var k = entry.key, v = entry.value; - return out; + var v = entry.value; + + if (v is MethodMirror && v.isConstructor) { + return out..add(new _GeneratedReflectedFunction(v, reflector)); + } else { + return out; + } }); } List _declarationsOf( Map map, Reflector reflector) { - print(map); return map.entries.fold>([], (out, entry) { - var k = entry.key, v = entry.value; + var v = entry.value; + + if (v is VariableMirror) { + var decl = new ReflectedDeclaration(v.simpleName, v.isStatic, null); + return out..add(decl); + } + if (v is MethodMirror) { + var decl = new ReflectedDeclaration(v.simpleName, v.isStatic, + new _GeneratedReflectedFunction(v, reflector)); + return out..add(decl); + } else { + return out; + } }); } ReflectedTypeParameter _convertTypeVariable(TypeVariableMirror mirror) { return new ReflectedTypeParameter(mirror.simpleName); } + +ReflectedParameter _convertParameter( + ParameterMirror mirror, Reflector reflector) { + return new ReflectedParameter( + mirror.simpleName, + mirror.metadata.map(reflector.reflectInstance).toList(), + reflector.reflectType(mirror.type.reflectedType), + !mirror.isOptional, + mirror.isNamed); +} diff --git a/angel_container_generator/pubspec.yaml b/angel_container_generator/pubspec.yaml index 435a2301..26876cb8 100644 --- a/angel_container_generator/pubspec.yaml +++ b/angel_container_generator/pubspec.yaml @@ -10,4 +10,5 @@ dependencies: reflectable: ^2.0.0 dev_dependencies: build_runner: ^1.0.0 + build_test: test: ^1.0.0 \ No newline at end of file diff --git a/angel_container_generator/test/reflector_test.dart b/angel_container_generator/test/reflector_test.dart index 1f73caaf..c594db8e 100644 --- a/angel_container_generator/test/reflector_test.dart +++ b/angel_container_generator/test/reflector_test.dart @@ -1,10 +1,19 @@ +import 'package:angel_container/angel_container.dart'; import 'package:angel_container_generator/angel_container_generator.dart'; import 'package:test/test.dart'; import 'reflector_test.reflectable.dart'; void main() { - var reflector = const GeneratedReflector(); initializeReflectable(); + var artist = new Artist(); + var reflector = const GeneratedReflector(); + Container container; + + setUp(() { + container = new Container(reflector); + container.registerSingleton(artist); + //container.registerSingleton(new Artist(name: 'Tobe Osakwe')); + }); group('reflectClass', () { var mirror = reflector.reflectClass(Artist); @@ -13,9 +22,31 @@ void main() { expect(mirror.name, 'Artist'); }); }); + + test('inject constructor parameters', () { + var album = container.make(); + print(album.title); + expect(album.title, 'flowers by ${artist.lowerName}'); + }); } @contained class Artist { - String name; + //final String name; + + //Artist({this.name}); + + String get lowerName { + //return name.toLowerCase(); + return hashCode.toString().toLowerCase(); + } +} + +@contained +class Album { + final Artist artist; + + Album(this.artist); + + String get title => 'flowers by ${artist.lowerName}'; } diff --git a/angel_container_generator/test/reflector_test.reflectable.dart b/angel_container_generator/test/reflector_test.reflectable.dart index d2aeb204..65e8dac0 100644 --- a/angel_container_generator/test/reflector_test.reflectable.dart +++ b/angel_container_generator/test/reflector_test.reflectable.dart @@ -4,6 +4,8 @@ import "dart:core"; import 'package:angel_container_generator/angel_container_generator.dart' as prefix0; +import 'package:reflectable/capability.dart' as prefix2; +import 'package:reflectable/mirrors.dart' as prefix3; import 'reflector_test.dart' as prefix1; // ignore:unused_import @@ -22,8 +24,8 @@ final _data = { 7, 0, const prefix0.ContainedReflectable(), - const [0, 3], - const [4, 5, 6, 7, 8, 1, 2], + const [1, 2], + const [3, 4, 5, 6, 7, 1], const [], -1, {}, @@ -33,21 +35,64 @@ final _data = { 0, const [], const [prefix0.contained], + null), + new r.NonGenericClassMirrorImpl( + r"Album", + r".Album", + 7, + 1, + const prefix0.ContainedReflectable(), + const [0, 9, 10], + const [3, 4, 5, 6, 7, 8, 9], + const [], + -1, + {}, + {}, + {r"": (b) => (artist) => b ? new prefix1.Album(artist) : null}, + -1, + 1, + const [], + const [prefix0.contained], + null), + new r.NonGenericClassMirrorImpl( + r"ContainedReflectable", + r".ContainedReflectable", + 7, + 2, + const prefix0.ContainedReflectable(), + const [11], + const [3, 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 18, 19], + const [], + -1, + {}, + {}, + {r"": (b) => () => b ? new prefix0.ContainedReflectable() : null}, + -1, + 2, + const [], + const [prefix0.contained], null) ], [ new r.VariableMirrorImpl( - r"name", - 32773, - 0, - const prefix0.ContainedReflectable(), - -1, + r"artist", + 33797, 1, - 1, const [], const []), - new r.ImplicitGetterMirrorImpl( - const prefix0.ContainedReflectable(), 0, 1, 1, 1), - new r.ImplicitSetterMirrorImpl( - const prefix0.ContainedReflectable(), 0, 1, 1, 2), + const prefix0.ContainedReflectable(), + 0, + 0, + 0, const [], const []), + new r.MethodMirrorImpl( + r"lowerName", + 131075, + 0, + -1, + 3, + 3, + const [], + const [], + const prefix0.ContainedReflectable(), + const []), new r.MethodMirrorImpl(r"", 64, 0, -1, 0, 0, const [], const [], const prefix0.ContainedReflectable(), const []), new r.MethodMirrorImpl( @@ -55,10 +100,10 @@ final _data = { 131074, null, -1, - 2, - 2, + 4, + 4, const [], - const [1], + const [0], const prefix0.ContainedReflectable(), const []), new r.MethodMirrorImpl( @@ -66,8 +111,8 @@ final _data = { 131074, null, -1, - 1, - 1, + 3, + 3, const [], const [], const prefix0.ContainedReflectable(), @@ -80,7 +125,7 @@ final _data = { null, null, const [], - const [2], + const [1], const prefix0.ContainedReflectable(), const [const pragma("vm:entry-point")]), new r.MethodMirrorImpl( @@ -88,8 +133,8 @@ final _data = { 131075, null, -1, - 3, - 3, + 5, + 5, const [], const [], const prefix0.ContainedReflectable(), @@ -99,30 +144,141 @@ final _data = { 131075, null, -1, - 4, - 4, + 6, + 6, const [], const [], const prefix0.ContainedReflectable(), - const []) - ], - [ - new r.ParameterMirrorImpl( - r"_name", - 32870, - 2, + const []), + new r.ImplicitGetterMirrorImpl( + const prefix0.ContainedReflectable(), 0, 0, 0, 8), + new r.MethodMirrorImpl( + r"title", + 131075, + 1, + -1, + 3, + 3, + const [], + const [], const prefix0.ContainedReflectable(), + const []), + new r.MethodMirrorImpl( + r"", + 0, + 1, -1, 1, 1, const [], - const [], + const [2], + const prefix0.ContainedReflectable(), + const []), + new r.MethodMirrorImpl( + r"", + 128, + 2, + -1, + 2, + 2, + const [], + const [], + const prefix0.ContainedReflectable(), + const []), + new r.MethodMirrorImpl( + r"capabilities", + 4325379, null, - null), + -1, + 8, + 9, + const [7], + const [], + const prefix0.ContainedReflectable(), + const []), + new r.MethodMirrorImpl( + r"canReflect", + 131074, + null, + -1, + 4, + 4, + const [], + const [3], + const prefix0.ContainedReflectable(), + const [override]), + new r.MethodMirrorImpl( + r"reflect", + 131074, + null, + -1, + 10, + 10, + const [], + const [4], + const prefix0.ContainedReflectable(), + const [override]), + new r.MethodMirrorImpl( + r"canReflectType", + 131074, + null, + -1, + 4, + 4, + const [], + const [5], + const prefix0.ContainedReflectable(), + const [override]), + new r.MethodMirrorImpl( + r"reflectType", + 131074, + null, + -1, + 11, + 11, + const [], + const [6], + const prefix0.ContainedReflectable(), + const [override]), + new r.MethodMirrorImpl( + r"findLibrary", + 131074, + null, + -1, + 12, + 12, + const [], + const [7], + const prefix0.ContainedReflectable(), + const [override]), + new r.MethodMirrorImpl( + r"libraries", + 4325379, + null, + -1, + 14, + 15, + const [13, 12], + const [], + const prefix0.ContainedReflectable(), + const [override]), + new r.MethodMirrorImpl( + r"annotatedClasses", + 4325379, + null, + -1, + 17, + 18, + const [16], + const [], + const prefix0.ContainedReflectable(), + const [override]) + ], + [ new r.ParameterMirrorImpl( r"other", 16390, - 4, + 3, const prefix0.ContainedReflectable(), null, null, @@ -134,27 +290,131 @@ final _data = { new r.ParameterMirrorImpl( r"invocation", 32774, - 6, + 5, const prefix0.ContainedReflectable(), -1, - 5, - 5, + 19, + 19, + const [], + const [], + null, + null), + new r.ParameterMirrorImpl( + r"artist", + 32774, + 10, + const prefix0.ContainedReflectable(), + 0, + 0, + 0, + const [], + const [], + null, + null), + new r.ParameterMirrorImpl( + r"reflectee", + 32774, + 13, + const prefix0.ContainedReflectable(), + -1, + 20, + 20, + const [], + const [], + null, + null), + new r.ParameterMirrorImpl( + r"reflectee", + 32774, + 14, + const prefix0.ContainedReflectable(), + -1, + 20, + 20, + const [], + const [], + null, + null), + new r.ParameterMirrorImpl( + r"type", + 32774, + 15, + const prefix0.ContainedReflectable(), + -1, + 6, + 6, + const [], + const [], + null, + null), + new r.ParameterMirrorImpl( + r"type", + 32774, + 16, + const prefix0.ContainedReflectable(), + -1, + 6, + 6, + const [], + const [], + null, + null), + new r.ParameterMirrorImpl( + r"libraryName", + 32774, + 17, + const prefix0.ContainedReflectable(), + -1, + 3, + 3, const [], const [], null, null) ], - [prefix1.Artist, String, bool, int, Type, Invocation], - 1, + [ + prefix1.Artist, + prefix1.Album, + prefix0.ContainedReflectable, + String, + bool, + int, + Type, + prefix2.ReflectCapability, + const m.TypeValue>().type, + List, + prefix3.InstanceMirror, + prefix3.TypeMirror, + prefix3.LibraryMirror, + Uri, + const m.TypeValue>().type, + Map, + prefix3.ClassMirror, + const m.TypeValue>().type, + Iterable, + Invocation, + Object + ], + 3, { r"==": (dynamic instance) => (x) => instance == x, r"toString": (dynamic instance) => instance.toString, r"noSuchMethod": (dynamic instance) => instance.noSuchMethod, r"hashCode": (dynamic instance) => instance.hashCode, r"runtimeType": (dynamic instance) => instance.runtimeType, - r"name": (dynamic instance) => instance.name + r"lowerName": (dynamic instance) => instance.lowerName, + r"artist": (dynamic instance) => instance.artist, + r"title": (dynamic instance) => instance.title, + r"capabilities": (dynamic instance) => instance.capabilities, + r"canReflect": (dynamic instance) => instance.canReflect, + r"reflect": (dynamic instance) => instance.reflect, + r"canReflectType": (dynamic instance) => instance.canReflectType, + r"reflectType": (dynamic instance) => instance.reflectType, + r"findLibrary": (dynamic instance) => instance.findLibrary, + r"libraries": (dynamic instance) => instance.libraries, + r"annotatedClasses": (dynamic instance) => instance.annotatedClasses }, - {r"name=": (dynamic instance, value) => instance.name = value}, + {}, null, []) };