generateForAnnotatedElement method
Future<String?>
generateForAnnotatedElement(
- Element element,
- ConstantReader constantReader,
- BuildStep buildStep
Implement to return source code to generate for element
.
This method is invoked based on finding elements annotated with an
instance of T
. The annotation
is provided as a ConstantReader
.
Supported return values include a single String or multiple String instances within an Iterable or Stream. It is also valid to return a Future of String, Iterable, or Stream.
Implementations should return null
when no content is generated. Empty
or whitespace-only String instances are also ignored.
Implementation
@override
Future<String?> generateForAnnotatedElement(Element element,
ConstantReader constantReader, BuildStep buildStep) async {
if (element is FunctionElement) {
return 'const ${element.name}FunctionMirror = ${_renderFunction(element)};';
}
if (element is EnumElement) {
return "const ${element.name}ClassMirror = ClassMirror("
"name: '${element.name}',"
"isEnum: true,"
"values: ${element.name}.values);";
}
if (element is ClassElement) {
var superTypes =
element.allSupertypes.where((st) => !{'Object', 'SerializableMap', 'Map'}.contains(st.element.name));
var stAccessors = superTypes.expand((st) => st.accessors);
var stMethods = superTypes.expand((st) => st.methods);
var stFields = superTypes.expand((st) => st.element.fields);
var constructors = element.constructors;
var className = element.name;
var elementFields = <FieldElement>[]
..addAll(element.fields.toList())
..addAll(stFields);
var fields = _distinctByName(elementFields);
var accessors = _distinctByName([...element.accessors, ...stAccessors]);
var getters =
_distinctByName(accessors.where((a) => a.kind == ElementKind.GETTER));
var setters =
_distinctByName(accessors.where((a) => a.kind == ElementKind.SETTER));
var methods = _distinctByName([...element.methods, ...stMethods]);
return '''${element.isAbstract ? '' : constructors.map((c) => '_${className}_${c.name}_Constructor([positionalParams, namedParams]) =>'
'${className}${c.name.isEmpty ? '' : '.${c.name}'}(${_renderConstructorParametersCall(c)});\n').join('')}
${element.fields.map(_renderFieldsDeclarations).join('\n')}
const ${className}ClassMirror = ClassMirror(
name: '${element.name}',
${[
element.isAbstract
? ''
: '''constructors: {
${constructors.map((c) => "'${c.name}': FunctionMirror("
"name: '${c.name}',"
"${_renderPositionalParameters(c.parameters)}"
"${_renderNamedParameters(c.parameters)}"
"\$call: _${className}_${c.name}_Constructor)").join(',')}
}''',
_renderMetadata(element.metadata),
fields.where((x) => !x.isStatic).isNotEmpty
? 'fields: {${fields.where((x) => !x.isStatic).map(_renderFields).join(',')}}'
: '',
getters.where((x) => !x.isStatic).isNotEmpty
? 'getters: [${getters.where((x) => !x.isStatic).map((g) => "'${_getSerializedNameFromAccessor(g)}'").join(',')}]'
: '',
setters.where((x) => !x.isStatic).isNotEmpty
? 'setters: [${setters.where((x) => !x.isStatic).map((s) => "'${_getSerializedNameFromAccessor(s)}'").join(',')}]'
: '',
methods.where((x) => !x.isStatic).isNotEmpty
? 'methods: {${methods.where((x) => !x.isStatic).map(_renderMethods).join(',')}}'
: '',
element.isAbstract ? 'isAbstract: true' : '',
element.supertype?.getDisplayString(withNullability: false) != 'Object'
? 'superclass: ${element.supertype?.element.name}'
: '',
element.interfaces.isNotEmpty
? 'superinterfaces: [${element.interfaces.map((i) => i.element.name).join(',')}]'
: ''
].fold('', _combine)}
);''';
}
return null;
}