generateEnum function

Library generateEnum(
  1. InterfaceElement clazz,
  2. GeneratorCtx ctx,
  3. DartObject enumAnnotation
)

Implementation

Library generateEnum(
  InterfaceElement clazz,
  GeneratorCtx ctx,
  DartObject enumAnnotation,
) {
  final index =
      enumAnnotation.getField('valuesCase')?.getField('index')?.toIntValue() ??
          ctx.config.enumValuesCase?.index;
  final valuesCase = index == null ? null : EnumNameCase.values[index];
  final annot = GraphQLEnum(
    valuesCase: valuesCase,
    name: enumAnnotation.getField('name')?.toStringValue(),
  );

  String _mapVariantName(String name) {
    if (valuesCase == null) return name;
    final _recase = ReCase(name);
    switch (valuesCase) {
      case EnumNameCase.CONSTANT_CASE:
        return _recase.constantCase;
      case EnumNameCase.PascalCase:
        return _recase.pascalCase;
      case EnumNameCase.Pascal_Underscore_Case:
        return _recase.titleCase.replaceAll(' ', '_');
      case EnumNameCase.camelCase:
        return _recase.camelCase;
      case EnumNameCase.snake_case:
        return _recase.snakeCase;
      case EnumNameCase.none:
        return name;
    }
  }

  final allNames = <String>{};

  const _variantChecker = TypeChecker.fromRuntime(GraphQLEnumVariant);
  final variants = List.of(
    clazz.fields
        .where(
            (f) => f.isEnumConstant || _variantChecker.hasAnnotationOfExact(f))
        .map(
      (variant) {
        final String name;
        if (!variant.isEnumConstant) {
          if (!variant.isStatic) {
            throw Exception(
              'A $GraphQLEnumVariant should be a static field.'
              ' In ${clazz.name}.${variant.name}.',
            );
          } else if (variant.type.element != clazz) {
            throw Exception(
              'All $GraphQLEnumVariant should be a instances'
              ' of the $GraphQLEnum annotated class.'
              ' In ${clazz.name}.${variant.name}.',
            );
          }

          name = _variantChecker
                  .firstAnnotationOfExact(variant)!
                  .getField('name')!
                  .toStringValue() ??
              _mapVariantName(variant.name);
        } else {
          name = _mapVariantName(variant.name);
        }
        allNames.add(name);

        final description =
            getDescription(variant, variant.documentationComment);
        final deprecationReason = getDeprecationReason(variant);
        final attachments = getAttachments(variant);

        return refer('GraphQLEnumValue').call([
          literalString(name),
          refer('${clazz.name}.${variant.name}'),
        ], {
          if (description != null && description.isNotEmpty)
            'description': refer("'$description'"),
          if (deprecationReason != null)
            'deprecationReason': literalString(deprecationReason),
          if (attachments != null) 'attachments': refer(attachments),
        });
      },
    ),
  );
  if (variants.isEmpty) {
    throw Exception(
      'Enum "${clazz.name}" should have at least one'
      ' $GraphQLEnumVariant annotated static field.',
    );
  } else if (allNames.length != variants.length) {
    throw Exception(
      'All enum variant names should be unique: $allNames. In ${clazz.name}.',
    );
  } else if (const ['true', 'false', 'null'].any(allNames.contains)) {
    throw Exception(
      "Can't have any of 'true', 'false' or 'null' as names"
      ' of variants in enums: $allNames. In ${clazz.name}.',
    );
  }
  return Library((b) {
    b.body.add(Field((b) {
      final args = <Expression>[
        literalString(annot.name ?? clazz.name),
        literalList(variants),
      ];
      final description = getDescription(clazz, clazz.documentationComment);
      final attachments = getAttachments(clazz);
      b
        ..name = '${ReCase(clazz.name).camelCase}$graphqlTypeSuffix'
        ..docs.add('/// Auto-generated from [${clazz.name}].')
        ..type = TypeReference((b) => b
          ..symbol = 'GraphQLEnumType'
          ..types.add(refer(clazz.name)))
        ..modifier = FieldModifier.final$
        ..assignment = refer('GraphQLEnumType').call(
          args,
          {
            if (description != null) 'description': refer("'$description'"),
            if (attachments != null)
              'extra': refer('GraphQLTypeDefinitionExtra.attach').call([
                refer(attachments),
              ])
          },
        ).code;
    }));
  });
}