platform/angel_container/lib/src/mirrors/reflector.dart
2019-10-12 09:34:15 -04:00

253 lines
7.2 KiB
Dart

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));
}
}