255 lines
7.5 KiB
Dart
255 lines
7.5 KiB
Dart
import 'package:platform_container/container.dart';
|
|
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 = ContainedReflectable();
|
|
|
|
@contained
|
|
class ContainedReflectable extends Reflectable {
|
|
const ContainedReflectable()
|
|
: super(
|
|
topLevelInvokeCapability,
|
|
typeAnnotationQuantifyCapability,
|
|
superclassQuantifyCapability,
|
|
libraryCapability,
|
|
invokingCapability,
|
|
metadataCapability,
|
|
reflectedTypeCapability,
|
|
typeCapability,
|
|
typingCapability);
|
|
}
|
|
|
|
/// A [Reflector] instance that uses a [Reflectable] to reflect upon data.
|
|
class GeneratedReflector extends Reflector {
|
|
final Reflectable reflectable;
|
|
|
|
const GeneratedReflector([this.reflectable = contained]);
|
|
|
|
@override
|
|
String getName(Symbol symbol) {
|
|
return symbol.toString().substring(7);
|
|
}
|
|
|
|
@override
|
|
ReflectedClass reflectClass(Type clazz) {
|
|
return reflectType(clazz) as ReflectedClass;
|
|
}
|
|
|
|
@override
|
|
ReflectedFunction reflectFunction(Function function) {
|
|
if (!reflectable.canReflect(function)) {
|
|
throw UnsupportedError('Cannot reflect $function.');
|
|
}
|
|
|
|
var mirror = reflectable.reflect(function);
|
|
|
|
if (mirror is ClosureMirror) {
|
|
return _GeneratedReflectedFunction(mirror.function, this, mirror);
|
|
} else {
|
|
throw ArgumentError('$function is not a Function.');
|
|
}
|
|
}
|
|
|
|
@override
|
|
ReflectedInstance reflectInstance(Object object) {
|
|
if (!reflectable.canReflect(object)) {
|
|
throw UnsupportedError('Cannot reflect $object.');
|
|
} else {
|
|
var mirror = reflectable.reflect(object);
|
|
return _GeneratedReflectedInstance(mirror, this);
|
|
}
|
|
}
|
|
|
|
@override
|
|
ReflectedType reflectType(Type type) {
|
|
if (!reflectable.canReflectType(type)) {
|
|
throw UnsupportedError('Cannot reflect $type.');
|
|
} else {
|
|
var mirror = reflectable.reflectType(type);
|
|
return mirror is ClassMirror
|
|
? _GeneratedReflectedClass(mirror, this)
|
|
: _GeneratedReflectedType(mirror);
|
|
}
|
|
}
|
|
}
|
|
|
|
class _GeneratedReflectedInstance extends ReflectedInstance {
|
|
final InstanceMirror mirror;
|
|
final GeneratedReflector reflector;
|
|
|
|
_GeneratedReflectedInstance(this.mirror, this.reflector)
|
|
: super(_GeneratedReflectedType(mirror.type),
|
|
_GeneratedReflectedClass(mirror.type, reflector), mirror.reflectee);
|
|
|
|
@override
|
|
ReflectedType get type => clazz;
|
|
|
|
@override
|
|
ReflectedInstance getField(String name) {
|
|
var result = mirror.invokeGetter(name)!;
|
|
var instance = reflector.reflectable.reflect(result);
|
|
return _GeneratedReflectedInstance(instance, reflector);
|
|
}
|
|
}
|
|
|
|
class _GeneratedReflectedClass extends ReflectedClass {
|
|
final ClassMirror mirror;
|
|
final Reflector reflector;
|
|
|
|
_GeneratedReflectedClass(this.mirror, this.reflector)
|
|
: super(mirror.simpleName, [], [], [], [], mirror.reflectedType);
|
|
|
|
@override
|
|
List<ReflectedTypeParameter> get typeParameters =>
|
|
mirror.typeVariables.map(_convertTypeVariable).toList();
|
|
|
|
@override
|
|
List<ReflectedFunction> get constructors =>
|
|
_constructorsOf(mirror.declarations, reflector);
|
|
|
|
@override
|
|
List<ReflectedDeclaration> get declarations =>
|
|
_declarationsOf(mirror.declarations, reflector);
|
|
|
|
@override
|
|
List<ReflectedInstance> get annotations => mirror.metadata
|
|
.map(reflector.reflectInstance)
|
|
.whereType<ReflectedInstance>()
|
|
.toList();
|
|
|
|
@override
|
|
bool isAssignableTo(ReflectedType? other) {
|
|
if (other is _GeneratedReflectedClass) {
|
|
return mirror.isAssignableTo(other.mirror);
|
|
} else if (other is _GeneratedReflectedType) {
|
|
return mirror.isAssignableTo(other.mirror);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@override
|
|
ReflectedInstance newInstance(
|
|
String constructorName, List positionalArguments,
|
|
[Map<String, dynamic>? namedArguments, List<Type>? typeArguments]) {
|
|
namedArguments ??= {};
|
|
var result = mirror.newInstance(constructorName, positionalArguments,
|
|
namedArguments.map((k, v) => MapEntry(Symbol(k), v)));
|
|
return reflector.reflectInstance(result)!;
|
|
}
|
|
}
|
|
|
|
class _GeneratedReflectedType extends ReflectedType {
|
|
final TypeMirror mirror;
|
|
|
|
_GeneratedReflectedType(this.mirror)
|
|
: super(mirror.simpleName, [], mirror.reflectedType);
|
|
|
|
@override
|
|
List<ReflectedTypeParameter> get typeParameters =>
|
|
mirror.typeVariables.map(_convertTypeVariable).toList();
|
|
|
|
@override
|
|
bool isAssignableTo(ReflectedType? other) {
|
|
if (other is _GeneratedReflectedClass) {
|
|
return mirror.isAssignableTo(other.mirror);
|
|
} else if (other is _GeneratedReflectedType) {
|
|
return mirror.isAssignableTo(other.mirror);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@override
|
|
ReflectedInstance newInstance(
|
|
String constructorName, List positionalArguments,
|
|
[Map<String, dynamic> namedArguments = const {},
|
|
List<Type> typeArguments = const []]) {
|
|
throw UnsupportedError('Cannot create a new instance of $reflectedType.');
|
|
}
|
|
}
|
|
|
|
class _GeneratedReflectedFunction extends ReflectedFunction {
|
|
final MethodMirror mirror;
|
|
final Reflector reflector;
|
|
final ClosureMirror? closure;
|
|
|
|
_GeneratedReflectedFunction(this.mirror, this.reflector, [this.closure])
|
|
: super(
|
|
mirror.simpleName,
|
|
[],
|
|
[],
|
|
mirror.parameters
|
|
.map((p) => _convertParameter(p, reflector))
|
|
.toList(),
|
|
mirror.isGetter,
|
|
mirror.isSetter,
|
|
returnType: !mirror.isRegularMethod
|
|
? null
|
|
: _GeneratedReflectedType(mirror.returnType));
|
|
|
|
@override
|
|
List<ReflectedInstance> get annotations => mirror.metadata
|
|
.map(reflector.reflectInstance)
|
|
.whereType<ReflectedInstance>()
|
|
.toList();
|
|
|
|
@override
|
|
ReflectedInstance invoke(Invocation invocation) {
|
|
if (closure != null) {
|
|
throw UnsupportedError('Only closures can be invoked directly.');
|
|
} else {
|
|
var result = closure!.delegate(invocation)!;
|
|
return reflector.reflectInstance(result)!;
|
|
}
|
|
}
|
|
}
|
|
|
|
List<ReflectedFunction> _constructorsOf(
|
|
Map<String, DeclarationMirror> map, Reflector reflector) {
|
|
return map.entries.fold<List<ReflectedFunction>>([], (out, entry) {
|
|
var v = entry.value;
|
|
|
|
if (v is MethodMirror && v.isConstructor) {
|
|
return out..add(_GeneratedReflectedFunction(v, reflector));
|
|
} else {
|
|
return out;
|
|
}
|
|
});
|
|
}
|
|
|
|
List<ReflectedDeclaration> _declarationsOf(
|
|
Map<String, DeclarationMirror> map, Reflector reflector) {
|
|
return map.entries.fold<List<ReflectedDeclaration>>([], (out, entry) {
|
|
var v = entry.value;
|
|
|
|
if (v is VariableMirror) {
|
|
var decl = ReflectedDeclaration(v.simpleName, v.isStatic, null);
|
|
return out..add(decl);
|
|
}
|
|
if (v is MethodMirror) {
|
|
var decl = ReflectedDeclaration(
|
|
v.simpleName, v.isStatic, _GeneratedReflectedFunction(v, reflector));
|
|
return out..add(decl);
|
|
} else {
|
|
return out;
|
|
}
|
|
});
|
|
}
|
|
|
|
ReflectedTypeParameter _convertTypeVariable(TypeVariableMirror mirror) {
|
|
return ReflectedTypeParameter(mirror.simpleName);
|
|
}
|
|
|
|
ReflectedParameter _convertParameter(
|
|
ParameterMirror mirror, Reflector reflector) {
|
|
return ReflectedParameter(
|
|
mirror.simpleName,
|
|
mirror.metadata
|
|
.map(reflector.reflectInstance)
|
|
.whereType<ReflectedInstance>()
|
|
.toList(),
|
|
reflector.reflectType(mirror.type.reflectedType)!,
|
|
!mirror.isOptional,
|
|
mirror.isNamed);
|
|
}
|