import 'dart:async'; import 'dart:mirrors' as dart; import 'package:angel_container/angel_container.dart'; import 'package:angel_container/src/reflector.dart'; /// A [Reflector] implementation that forwards to `dart:mirrors`. /// /// Useful on the server, where reflection is supported. class MirrorsReflector extends Reflector { const MirrorsReflector(); @override String getName(Symbol symbol) => dart.MirrorSystem.getName(symbol); @override ReflectedClass reflectClass(Type clazz) { var mirror = dart.reflectType(clazz); if (mirror is dart.ClassMirror) { return _ReflectedClassMirror(mirror); } else { throw ArgumentError('$clazz is not a class.'); } } @override ReflectedFunction reflectFunction(Function function) { var closure = dart.reflect(function) as dart.ClosureMirror; return _ReflectedMethodMirror(closure.function, closure); } @override ReflectedType reflectType(Type type) { var mirror = dart.reflectType(type); if (!mirror.hasReflectedType) { return reflectType(dynamic); } else { if (mirror is dart.ClassMirror) { return _ReflectedClassMirror(mirror); } else { return _ReflectedTypeMirror(mirror); } } } @override ReflectedType reflectFutureOf(Type type) { var inner = reflectType(type); dart.TypeMirror _mirror; if (inner is _ReflectedClassMirror) { _mirror = inner.mirror; } else if (inner is _ReflectedTypeMirror) { _mirror = inner.mirror; } else { throw ArgumentError('$type is not a class or type.'); } var future = dart.reflectType(Future, [_mirror.reflectedType]); return _ReflectedClassMirror(future as dart.ClassMirror); } @override ReflectedInstance reflectInstance(Object object) { return _ReflectedInstanceMirror(dart.reflect(object)); } } class _ReflectedTypeParameter extends ReflectedTypeParameter { final dart.TypeVariableMirror mirror; _ReflectedTypeParameter(this.mirror) : super(dart.MirrorSystem.getName(mirror.simpleName)); } class _ReflectedTypeMirror extends ReflectedType { final dart.TypeMirror mirror; _ReflectedTypeMirror(this.mirror) : super( dart.MirrorSystem.getName(mirror.simpleName), mirror.typeVariables .map((m) => _ReflectedTypeParameter(m)) .toList(), mirror.reflectedType, ); @override bool isAssignableTo(ReflectedType other) { if (other is _ReflectedClassMirror) { return mirror.isAssignableTo(other.mirror); } else if (other is _ReflectedTypeMirror) { return mirror.isAssignableTo(other.mirror); } else { return false; } } @override ReflectedInstance newInstance( String constructorName, List positionalArguments, [Map<String, dynamic> namedArguments, List<Type> typeArguments]) { throw ReflectionException( '$name is not a class, and therefore cannot be instantiated.'); } } class _ReflectedClassMirror extends ReflectedClass { final dart.ClassMirror mirror; _ReflectedClassMirror(this.mirror) : super( dart.MirrorSystem.getName(mirror.simpleName), mirror.typeVariables .map((m) => _ReflectedTypeParameter(m)) .toList(), [], [], _declarationsOf(mirror), mirror.reflectedType, ); static List<ReflectedFunction> _constructorsOf(dart.ClassMirror mirror) { var out = <ReflectedFunction>[]; for (var key in mirror.declarations.keys) { var value = mirror.declarations[key]; if (value is dart.MethodMirror && value.isConstructor) { out.add(_ReflectedMethodMirror(value)); } } return out; } static List<ReflectedDeclaration> _declarationsOf(dart.ClassMirror mirror) { var out = <ReflectedDeclaration>[]; for (var key in mirror.declarations.keys) { var value = mirror.declarations[key]; if (value is dart.MethodMirror && !value.isConstructor) { out.add(_ReflectedDeclarationMirror( dart.MirrorSystem.getName(key), value)); } } return out; } @override List<ReflectedInstance> get annotations => mirror.metadata.map((m) => _ReflectedInstanceMirror(m)).toList(); @override List<ReflectedFunction> get constructors => _constructorsOf(mirror); @override bool isAssignableTo(ReflectedType other) { if (other is _ReflectedClassMirror) { return mirror.isAssignableTo(other.mirror); } else if (other is _ReflectedTypeMirror) { return mirror.isAssignableTo(other.mirror); } else { return false; } } @override ReflectedInstance newInstance( String constructorName, List positionalArguments, [Map<String, dynamic> namedArguments, List<Type> typeArguments]) { return _ReflectedInstanceMirror( mirror.newInstance(Symbol(constructorName), positionalArguments)); } @override bool operator ==(other) { return other is _ReflectedClassMirror && other.mirror == mirror; } } class _ReflectedDeclarationMirror extends ReflectedDeclaration { final String name; final dart.MethodMirror mirror; _ReflectedDeclarationMirror(this.name, this.mirror) : super(name, mirror.isStatic, null); @override bool get isStatic => mirror.isStatic; @override ReflectedFunction get function => _ReflectedMethodMirror(mirror); } class _ReflectedInstanceMirror extends ReflectedInstance { final dart.InstanceMirror mirror; _ReflectedInstanceMirror(this.mirror) : super(_ReflectedClassMirror(mirror.type), _ReflectedClassMirror(mirror.type), mirror.reflectee); @override ReflectedInstance getField(String name) { return _ReflectedInstanceMirror(mirror.getField(Symbol(name))); } } class _ReflectedMethodMirror extends ReflectedFunction { final dart.MethodMirror mirror; final dart.ClosureMirror closureMirror; _ReflectedMethodMirror(this.mirror, [this.closureMirror]) : super( dart.MirrorSystem.getName(mirror.simpleName), <ReflectedTypeParameter>[], mirror.metadata .map((mirror) => _ReflectedInstanceMirror(mirror)) .toList(), !mirror.returnType.hasReflectedType ? const MirrorsReflector().reflectType(dynamic) : const MirrorsReflector() .reflectType(mirror.returnType.reflectedType), mirror.parameters.map(_reflectParameter).toList(), mirror.isGetter, mirror.isSetter); static ReflectedParameter _reflectParameter(dart.ParameterMirror mirror) { return ReflectedParameter( dart.MirrorSystem.getName(mirror.simpleName), mirror.metadata .map((mirror) => _ReflectedInstanceMirror(mirror)) .toList(), const MirrorsReflector().reflectType(mirror.type.reflectedType), !mirror.isOptional, mirror.isNamed); } @override ReflectedInstance invoke(Invocation invocation) { if (closureMirror == null) { throw StateError( 'This object was reflected without a ClosureMirror, and therefore cannot be directly invoked.'); } return _ReflectedInstanceMirror(closureMirror.invoke( invocation.memberName, invocation.positionalArguments, invocation.namedArguments)); } }