generateFromConstructors function

Future<Library> generateFromConstructors(
  1. InterfaceElement clazz,
  2. GeneratorCtx ctx
)

Implementation

Future<Library> generateFromConstructors(
  InterfaceElement clazz,
  GeneratorCtx ctx,
) async {
  final inputConfig = inputTypeAnnotation(clazz);
  final hasFrezzed = freezedTypeChecker.hasAnnotationOfExact(clazz);
  final _annot =
      const TypeChecker.fromRuntime(GraphQLUnion).firstAnnotationOfExact(clazz);
  final classAnnot = getClassConfig(ctx, clazz);

  final annot = _annot == null
      ? null
      : GraphQLUnion(
          name: _annot.getField('name')?.toStringValue(),
          unnestIfEqual: _annot.getField('unnestIfEqual')?.toBoolValue(),
        );
  final variants = await freezedVariants(
    clazz,
    ctx,
    isInput: inputConfig != null,
  );
  if (inputConfig != null &&
      (inputConfig.constructor != null || variants.length > 1)) {
    final constructor = inputConfig.constructor ?? '';
    variants.removeWhere((v) => v.constructorName != constructor);
  }

  if (inputConfig != null && variants.length != 1) {
    if (inputConfig.constructor == null) {
      throw Exception(
        'A class annotated with @GraphQLInput should only have one constructor'
        ' or the `GraphQLInput.constructor` parameter should be set.',
      );
    } else {
      throw Exception(
        'Could not find constructor "${inputConfig.constructor}" for'
        ' @GraphQLInput annotated class "${clazz.name}".'
        ' Available constructors: ${variants.map((v) => v.constructorName).join(', ')}',
      );
    }
  }

  final _classLib = classAnnot != null && inputConfig != null
      ? await generateObjectFromFields(ctx, clazz)
      : null;

  return Library((l) {
    // l.directives.addAll(
    //   ctx.config.customTypes.map((e) => Directive.import(e.import)),
    // );
    if (_classLib != null) {
      l.replace(_classLib);
    }
    if (hasFrezzed || inputConfig != null) {
      /// We need to generate each Object variant for freezed annotated classes
      for (final variant in variants) {
        if (_classLib == null) {
          // `variant.serializer()` is already present in _classLib for inputs
          l.body.add(variant.serializer());
        }
        l.body.add(Code(variant.typeDefinitionCode()));
      }
    }
    if (variants.length == 1 && annot == null) {
      /// if it's a single freezed constructor, don't generate the union
      return;
    }

    final className = clazz.name;
    final fieldName = '${ReCase(className).camelCase}$graphqlTypeSuffix';
    final description = getDescription(clazz, clazz.documentationComment);
    final attachments = getAttachments(clazz);

    l.body.add(Code('''
${hasFromJson(clazz) ? serializerDefinitionCode(className, hasFrezzed: false) : ''}

/// Generated from [$className]
GraphQLUnionType<$className> get $fieldName => _$fieldName.value;

final _$fieldName = HotReloadableDefinition<GraphQLUnionType<$className>>((setValue) {
  final type = GraphQLUnionType<$className>(
    '${annot?.name ?? className}',
    const [],
    ${description == null ? '' : "description: '$description',"}
    ${attachments == null ? '' : 'extra: GraphQLTypeDefinitionExtra.attach($attachments),'}
  );
  setValue(type);
  type.possibleTypes.addAll([
      ${variants.map((e) => e.fieldName).join(',')},
  ]);
  return type;
});
'''));

    // Map<String, Object?> _\$${typeName}ToJson($typeName instance) => instance.toJson();

    // GraphQLObjectField<String, String, P>
    // $fieldName$unionKeySuffix<P extends $typeName>()
    //    => field(
    //   'runtimeType',
    //   enumTypeFromStrings('${typeName}Type', [
    //     ${variants.map((e) => '"${e.constructorName}"').join(',')}
    //   ]),
    // );
  });
}