generateForAnnotatedElement method

  1. @override
FutureOr<String> generateForAnnotatedElement(
  1. Element element,
  2. ConstantReader annotation,
  3. 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
FutureOr<String> generateForAnnotatedElement(Element element, ConstantReader annotation, BuildStep buildStep) async {
  GeneratorLog.info(title: 'Annotation Found', data: annotation.getName);
  GeneratorLog.info(title: 'Code Generation for Annotation Started');

  String code = '';

  GeneratorLog.info(title: 'Main Code Generation Started...');
  String className = element.name ?? 'UnnamedClass';
  List<Variable> variablesList = List<Variable>.empty(growable: true);
  ElementVisitor visitor = ElementVisitor();
  element.visitChildren(visitor);
  List<Element> fields = element.children.where((child) => child.kind == ElementKind.FIELD).toList();
  List<Element> constructors = element.children.where((child) => child.kind == ElementKind.CONSTRUCTOR).toList();

  GeneratorLog.info(title: 'Generating Variables and Checking DartTypes...');
  for (var item in fields) {
    DartType? selectedVisitorField = visitor.fieldElements[item.name];
    // code += selectedVisitorField == null ? '' : Prints.dartTypeInfo(selectedVisitorField);

    Variable variable = Variable(
      name: item.name ?? Strings.unnamedVariable,
      type: selectedVisitorField,
      typeString: selectedVisitorField?.toString(),
      isCoreType: selectedVisitorField?.isDartCoreList == true ? selectedVisitorField?.isCoreTypeFromList : selectedVisitorField?.isCoreType,
      isFinal: item.declaration.toString().contains('final'),
      hasRequired: constructors.first.children.isEmpty ? null : constructors.first.children.firstWhere((e) => e.name == item.name).declaration.toString().contains('required '),
      isNullable: item.declaration?.toString().split(' ').first.contains('?'),
      isEnum: selectedVisitorField?.isEnum,
      isList: selectedVisitorField?.isDartCoreList,
    );
    variablesList.add(variable);
  }

  GeneratorLog.info(title: 'Commenting Started');
  code += AddCode.addCommentLine('  This File is Generated by ${PackageAuthorInfo.packageNameDescription}');
  code += AddCode.addCommentLine('  [$className] Annotated with [${PackageAuthorInfo.annotationName}] with [${annotation.getName}] mode');
  code += AddCode.addCommentLine('  Including:');
  code += AddCode.addCommentLine('    Model Class, Entity Class and Mapper Class,');
  code += AddCode.addCommentLine('    Model Classes includes [toJson] and [fromJson] functions, and Entity Classes are not!');
  code += AddCode.addCommentLine('    Mappers will convert every filed in the class including [SubClasses], they should be annotated as well.');
  code += AddCode.addCommentLine(
      '    [${PackageAuthorInfo.annotationName}] Annotation will generate all these fields for all Classes, so all subclasses should decorated with annotation to generate model, entity and mapper to use them here');
  code += AddCode.addCommentLine('    [Enums] also supported and they will be detected and count into account for mappers and also json conversion');
  annotation.getFreezed == true ? code += AddCode.addCommentLine('    Classes are decorated with [Freezed], other functions will generate with [Freezed]') : null;
  code += AddCode.addSpace();
  code += AddCode.addCommentLine('  Details:');
  code += AddCode.addCommentLine('    Class: ${annotation.getAs ?? className}');
  code += AddCode.addCommentLine('    Constructors Count: ${constructors.length}');
  code += AddCode.addCommentLine('    Variables Count: ${variablesList.length}');
  code += AddCode.addSpace();

  GeneratorLog.info(title: 'Generating Classes (Model and Entity) for', data: className);
  code += AddCode.addCommentLine('  ==> Model Class:');
  GeneratorData generatorData = GeneratorData(
    className: annotation.getAs ?? className,
    variablesList: variablesList,
    isFreezed: annotation.getFreezed,
    extended: annotation.getIsExtended,
  );

  code += AddClass().generate(generatorData.copyWith(annotationType: AnnotationTypes.model));
  code += AddCode.addCommentLine('  ==> Entity Class:');
  code += AddClass().generate(generatorData.copyWith(annotationType: AnnotationTypes.entity));
  GeneratorLog.info(title: 'Generating Mapper Class for', data: className);
  code += AddCode.addCommentLine('  ==> Mapper Classes:');
  code += AddMapper().generate(generatorData);

  GeneratorLog.info(title: 'Completing Code Generation and Preparing Files...');
  return code;
}