instantiateAnnotation function
dynamic
instantiateAnnotation(
- AnnotatedNode member,
- Type annotationType, {
- dynamic onUnsupportedArgument(
- Expression argument
Uses reflection to instantiate and returns the first annotation on member
of type
annotationType
, or null if no matching annotations are found.
Annotation constructors are currently limited to the values supported by getValue
.
Naively assumes that the name of the annotationType
class is canonical.
Implementation
dynamic instantiateAnnotation(AnnotatedNode member, Type annotationType,
{dynamic onUnsupportedArgument(Expression argument)?}) {
final matchingAnnotation = getMatchingAnnotation(member, annotationType);
// If no annotation is found, return null.
if (matchingAnnotation == null) {
return null;
}
final matchingAnnotationArgs = matchingAnnotation.arguments;
if (matchingAnnotationArgs == null) {
throw 'Annotation not invocation of constructor: `$matchingAnnotation`. '
'This is likely due to invalid usage of the annotation class, but could'
'also be a name conflict with the specified type `$annotationType`';
}
// Get the parameters from the annotation's AST.
Map<Symbol, dynamic> namedParameters = {};
List positionalParameters = [];
matchingAnnotationArgs.arguments.forEach((argument) {
var onUnsupportedExpression = onUnsupportedArgument == null
? null
: (_) => onUnsupportedArgument(argument);
if (argument is NamedExpression) {
var name = argument.name.label.name;
var value = getValue(argument.expression,
onUnsupportedExpression: onUnsupportedExpression);
namedParameters[Symbol(name)] = value;
} else {
var value =
getValue(argument, onUnsupportedExpression: onUnsupportedExpression);
positionalParameters.add(value);
}
});
// Instantiate and return an instance of the annotation using reflection.
String constructorName = _getConstructorName(matchingAnnotation) ?? '';
// Be sure to use `originalDeclaration` so that generic parameters work.
final classMirror = mirrors.reflectClass(annotationType).originalDeclaration
as mirrors.ClassMirror;
try {
var instanceMirror = classMirror.newInstance(
Symbol(constructorName), positionalParameters, namedParameters);
return instanceMirror.reflectee;
} catch (e, stacktrace) {
throw 'Unable to instantiate annotation: $matchingAnnotation. This is '
'likely due to improper usage, or a naming conflict with '
'annotationType $annotationType. Original error: $e. Stacktrace: $stacktrace';
}
}