writeGeneratedBuilder static method

void writeGeneratedBuilder(
  1. ClassElement2 element,
  2. StructurizeResult structurized,
  3. String constructorName,
  4. SubjectCodeContext codeContext,
  5. DogsGeneratorSettings settings,
)

Implementation

static void writeGeneratedBuilder(ClassElement2 element, StructurizeResult structurized,
    String constructorName, SubjectCodeContext codeContext, DogsGeneratorSettings settings) {
  var emitter = DartEmitter();
  var copyWithFrontendName = "${element.displayName}\$Copy";
  var copyClazz = Class((builder) {
    builder.name = copyWithFrontendName;
    builder.abstract = true;

    // Call method base
    builder.methods.add(Method((builder) {
      builder.name = "call";

      builder.returns = Reference(codeContext.className(element));
      for (var field in structurized.structure.fields) {
        builder.optionalParameters.add(Parameter((param) {
          param.name = field.accessor;
          param.named = true;
          param.type = Reference("${field.type}?");
        }));
      }
    }));
  });

  var builderName = "${element.displayName}Builder";
  var clazz = Class((builder) {
    builder.name = builderName;
    builder.implements.add(Reference(copyWithFrontendName));

    builder.fields.add(Field((builder) => builder
      ..name = "\$values"
      ..type = Reference("late List<dynamic>")));

    builder.fields.add(Field((builder) => builder
      ..name = "\$src"
      ..type = Reference("${codeContext.className(element)}?")));

    builder.constructors.add(Constructor((builder) => builder
      ..optionalParameters.add(Parameter((builder) => builder
        ..type = Reference("${codeContext.className(element)}?")
        ..name = "\$src"))
      ..body = Code(
          "if (\$src == null) {\$values = List.filled(${structurized.fieldNames.length},null);} else {\$values = ${element.displayName}Converter._values(\$src);this.\$src=\$src;}")));

    for (var element in structurized.structure.fields) {
      var index = structurized.structure.fields.indexOf(element);
      builder.methods.add(Method((builder) => builder
        ..name = element.accessor
        ..type = MethodType.setter
        ..requiredParameters.add(Parameter((builder) => builder
          ..name = "value"
          ..type = Reference(
              element.type + ((element.optional || settings.nullableAccessors) ? "?" : ""))))
        ..body = Code("\$values[$index] = value;")));

      builder.methods.add(Method((builder) => builder
        ..name = element.accessor
        ..type = MethodType.getter
        ..returns = Reference(
            element.type + ((element.optional || settings.nullableAccessors) ? "?" : ""))
        ..lambda = true
        ..body = Code("\$values[$index]")));
    }

    builder.methods.add(Method((builder) {
      builder.name = "call";
      builder.annotations.add(CodeExpression(Code("override")));

      var bodyBuilder = StringBuffer();
      builder.returns = Reference(codeContext.className(element));
      for (var field in structurized.structure.fields) {
        builder.optionalParameters.add(Parameter((param) {
          param.name = field.accessor;
          param.named = true;
          param.type = Reference("Object?");
          param.defaultTo = Code("#sentinel");
        }));

        bodyBuilder.write("""
        if (${field.accessor} != #sentinel) {
          this.${field.accessor} = ${field.accessor} as ${field.type + (field.optional ? "?" : "")};
        }
        """);
      }

      bodyBuilder.writeln("return build();");
      builder.body = Code(bodyBuilder.toString());
    }));

    var hasRebuildHook =
        TypeChecker.typeNamed(PostRebuildHook).isAssignableFromType(element.thisType);

    builder.methods.add(Method((builder) => builder
      ..name = "build"
      ..returns = Reference(codeContext.className(element))
      ..body = Code("""
var instance = ${element.displayName}Converter._activator(\$values);
${!hasRebuildHook ? "" : """if (\$src != null) {
// ignore: invalid_use_of_internal_member
instance.postRebuild(\$src!, instance);
}"""}
return instance;""")));
  });

  codeContext.codeBuffer.writeln(copyClazz.accept(emitter));
  codeContext.codeBuffer.writeln(clazz.accept(emitter));
}