253 lines
7.2 KiB
Dart
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));
|
|
}
|
|
}
|