'How to read the Annotation fields and their values (Code Generation)
i have been struggling to get the fields from an annotation.
I am using the source code generator to generate my widget from my annotation but cant seem to use the annotation fields, how can i access the fields and the values.
My Annotation:
class CoreEntity {
final String label;
const CoreEntity({
this.label,
});
}
Using the annotation:
@CoreEntity(
label: 'User',
)
class User {
String email;
}
My Widget Generator:
class CoreWidgetGenerator extends GeneratorForAnnotation<CoreEntity> {
@override
FutureOr<String> generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) {
return _generateWidgetSource(element);
}
String _generateWidgetSource(Element element) {
final anotData = element.metadata;
for (ElementAnnotation el in anotData) {
el.computeConstantValue();
var elVisitor = ModelVisitor();
el.element.visitChildren(elVisitor);
print("1 ${elVisitor.className}"); // this prints out null
print("2 ${elVisitor.fields}"); // this prints out empty list {}
}
}
class ModelVisitor extends SimpleElementVisitor {
DartType className;
Map<String, DartType> fields = Map();
@override
visitConstructorElement(ConstructorElement element) {
className = element.type.returnType;
return super.visitConstructorElement(element);
}
@override
visitFieldElement(FieldElement element) {
fields[element.name] = element.type;
return super.visitFieldElement(element);
}
}
Packages in pubspec.yaml
dependencies:
build: ^1.1.6
source_gen: ^0.9.4+4
core_widget:
path: ../core_widgets
Build Script (build.yaml)
targets:
$default:
builders:
core_gen|core_widget:
enabled: true
builders:
core_widget:
target: ":core_gen"
import: "package:core_gen/builder.dart"
builder_factories: ["coreWidget"]
build_extensions: {".dart":[".core_widget.g.part"]}
auto_apply: dependents
build_to: cache
applies_builders: ["source_gen|combining_builder"]
References|Research i have done but with no luck.
Solution 1:[1]
You already have access to the annotation properties via the ConstantReader
class CoreWidgetGenerator extends GeneratorForAnnotation<CoreEntity> {
@override
FutureOr<String> generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) {
return _generateWidgetSource(element, annotation);
}
String _generateWidgetSource(Element element, ConstantReader annotation) {
print(annotation.read('label').stringValue);
}
}
However if you want to retrieve annotation information for a field of a ClassElement
you can use a TypeChecker
Annotation
class CoreProperty {
final String label;
const CoreProperty({ this.label});
}
Usage
@CoreEntity(label: 'User')
class User {
@CoreProperty(label: 'Email')
String email;
}
final _coreChecker = const TypeChecker.fromRuntime(CoreProperty);
class CoreWidgetGenerator extends GeneratorForAnnotation<CoreEntity> {
@override
FutureOr<String> generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) {
return _generateWidgetSource(element as ClassElement, annotation);
}
String _generateWidgetSource(ClassElement element, ConstantReader annotation) {
for (var f in element.fields) {
if (_coreChecker.hasAnnotationOfExact(f)) {
print(_coreChecker
.firstAnnotationOfExact(f)
.getField('label')
.toStringValue()
);
}
}
}
}
Solution 2:[2]
Based on Dan's answer, to get the value of an enum field:
final _coreChecker = const TypeChecker.fromRuntime(CoreProperty);
class CoreWidgetGenerator extends GeneratorForAnnotation<CoreEntity> {
@override
FutureOr<String> generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) {
return _generateWidgetSource(element as ClassElement, annotation);
}
String _generateWidgetSource(ClassElement element, ConstantReader annotation) {
for (var f in element.fields) {
if (_coreChecker.hasAnnotationOfExact(f)) {
print(_coreChecker
.firstAnnotationOfExact(f)
.getField('label')
.toStringValue()
// for enum field named myEnum with an Enum type called MyEnumType
int? myEnumIndex = _coreChecker.firstAnnotationOfExact(f)?.getField('myEnum')?.getField("index")?.toIntValue();
MyEnumType myEnumValue = MyEnumType.values[myEnumIndex!];
print(myEnumValue)
);
}
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Dan |
Solution 2 | Ethan |