Pub Package

Uses Dart Build System builders for generating boilerplate code.

So far this generator generates code when it encounters classes annotated with adeptannotations.

Clone Generator

This generator creates a function that returns a new instance of the annotated ClassType by creating a copy of the currentData and replacing its fields with the newData

Notes:

  1. The function will use the values from newData, in case of null then currentData values will be used.
  2. If mergeParam is true then currentData will mirror the new instance returned.
  3. If @CloneKey(defaultValue: someValue) (defaults to null) annotation is used in some field, then that specific value will used for the specified field when cloning.
  4. If @CloneKey(ignore: true) (defaults to false) annotation is used in some field, then that specific field will not be taking into account when cloning.
  5. If @CloneKey(forceCurrentData: true) (defaults to false) annotation is used in some field, then currentData value will be forced for the specified field no matter it's nullability.
  6. If @CloneKey(forceNewData: true) (defaults to false) annotation is used in some field, then newData value will be forced for the specified field no matter it's nullability.
  7. If @CloneKey(considerEmptyCollectionAsNull: true) (defaults to true) annotation is used and the field is some collection type (List, Set, Iterable, Map), then newData will be considered only if is not empty.
  8. If @CloneKey(cloneFunction: someFunction) (defaults to null) annotation is used in some field, then that specific function will be used for cloning the specified field. Function must be a top-level or static function with two positional parameters, compatible with the field being cloned that returns the same type as the cloned field. e.g: Type? function({Type? currentData, Type newData})

Diff Generator

This generator creates a function that returns a new instance of the annotated ClassType with the fields that are different different between currentData and newData

Notes:

  1. Each field should implement a proper (==) function to ensure that every field is properly compared, this will be specially necessary for Object fields.
  2. newData takes precedence over currentData, this means that when comparing if a field is different then the newData field will be the one in the resulting instance.
  3. If no field are different then resulting instance will be null, this means no difference at all.
  4. If @DiffKey(defaultValue: someValue) (defaults to null) annotation is used in some field, then that specific value will used for the specified field when fields are not different.
  5. If @DiffKey(ignore: true) annotation is used in some field, then that specific field will be null in the resulting instance.
  6. If @DiffKey(forceCurrentData: true) annotation is used in some field, then currentData value will be forced for the specified field.
  7. If @DiffKey(forceNewData: true) annotation is used in some field, then newData value will be forced for the specified field.
  8. If @DiffKey(diffFunction: someFunction) (defaults to null) annotation is used in some field, then that specific function will be used for diff the specified field. Function must be a top-level or static function with two positional parameters, compatible with the field being diff that returns the same type as the diff field. e.g: Type? function({Type? currentData, Type newData})

Example:

import 'package:adeptannotations/adeptannotations.dart';

part 'sample.g.dart';

@Cloneable()
@Differentiable()
class Sample implements ICloneable<Sample>, IDifferentiable<Sample?> {
  static int aStaticMutableField = 0;
  static final int aStaticImmutableField = 0;
  static const int aConstField = 0;

  num? aPublicField;
  num? _aPrivateField;
  @CloneKey(ignore: true)
  String? aCloneIgnoreField;
  @CloneKey(forceCurrentData: true)
  String? aCloneForceCurrentDataField;
  @CloneKey(forceNewData: true)
  String? aCloneForceNewDataField;

  @DiffKey(ignore: true)
  String? aDiffIgnoreField;
  @DiffKey(forceCurrentData: true)
  String? aDiffForceCurrentDataField;
  @DiffKey(forceNewData: true)
  String? aDiffForceNewDataField;

  @CloneKey(ignore: true)
  @DiffKey(ignore: true)
  String? aCombinationIgnoreField;
  @CloneKey(forceCurrentData: true)
  @DiffKey(forceCurrentData: true)
  String? aCombinationForceCurrentDataField;
  @CloneKey(forceNewData: true)
  @DiffKey(forceNewData: true)
  String? aCombinationForceNewDataField;

  Sample(
      {this.aPublicField,
      num? aPrivateField,
      this.aCloneIgnoreField,
      this.aCloneForceCurrentDataField,
      this.aCloneForceNewDataField,
      this.aDiffIgnoreField,
      this.aDiffForceCurrentDataField,
      this.aDiffForceNewDataField,
      this.aCombinationIgnoreField,
      this.aCombinationForceCurrentDataField,
      this.aCombinationForceNewDataField})
      : this._aPrivateField = aPrivateField;

  int get aPublicGetWithoutSet => 0;

  set aPublicSetWithoutGet(double size) {}

  String get someFunctionField => "";

  set someFunctionField(String? value) {}

  @override
  Sample clone({Sample? data, bool merge = false}) =>
      $SampleClone(currentData: this, newData: data, merge: merge);

  @override
  Sample? diff({Sample? data}) => $SampleDiff(currentData: this, newData: data);
}

After running: flutter pub run build_runner build

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'sample.dart';

// **************************************************************************
// CloneGenerator
// **************************************************************************

Sample $SampleClone(
    {required Sample currentData, Sample? newData, bool merge = false}) {
  final clone = Sample()
    ..aPublicField = newData?.aPublicField ?? currentData.aPublicField
    .._aPrivateField = newData?._aPrivateField ?? currentData._aPrivateField
    ..aCloneForceCurrentDataField = currentData.aCloneForceCurrentDataField
    ..aCloneForceNewDataField = newData?.aCloneForceNewDataField
    ..aDiffIgnoreField =
        newData?.aDiffIgnoreField ?? currentData.aDiffIgnoreField
    ..aDiffForceCurrentDataField = newData?.aDiffForceCurrentDataField ??
        currentData.aDiffForceCurrentDataField
    ..aDiffForceNewDataField =
        newData?.aDiffForceNewDataField ?? currentData.aDiffForceNewDataField
    ..aCombinationForceCurrentDataField =
        currentData.aCombinationForceCurrentDataField
    ..aCombinationForceNewDataField = newData?.aCombinationForceNewDataField
    ..someFunctionField =
        newData?.someFunctionField ?? currentData.someFunctionField;

  if (merge) {
    currentData.aPublicField = clone.aPublicField;
    currentData._aPrivateField = clone._aPrivateField;
    currentData.aCloneForceCurrentDataField = clone.aCloneForceCurrentDataField;
    currentData.aCloneForceNewDataField = clone.aCloneForceNewDataField;
    currentData.aDiffIgnoreField = clone.aDiffIgnoreField;
    currentData.aDiffForceCurrentDataField = clone.aDiffForceCurrentDataField;
    currentData.aDiffForceNewDataField = clone.aDiffForceNewDataField;
    currentData.aCombinationForceCurrentDataField =
        clone.aCombinationForceCurrentDataField;
    currentData.aCombinationForceNewDataField =
        clone.aCombinationForceNewDataField;
    currentData.someFunctionField = clone.someFunctionField;
  }

  return clone;
}

// **************************************************************************
// DiffGenerator
// **************************************************************************

Sample? $SampleDiff({Sample? currentData, Sample? newData}) {
  if (newData == null) return currentData;
  if (currentData == null) return newData;

  final diff = Sample()
    ..aPublicField = newData.aPublicField != currentData.aPublicField
        ? newData.aPublicField
        : null
    .._aPrivateField = newData._aPrivateField != currentData._aPrivateField
        ? newData._aPrivateField
        : null
    ..aCloneIgnoreField =
        newData.aCloneIgnoreField != currentData.aCloneIgnoreField
            ? newData.aCloneIgnoreField
            : null
    ..aCloneForceCurrentDataField = newData.aCloneForceCurrentDataField !=
            currentData.aCloneForceCurrentDataField
        ? newData.aCloneForceCurrentDataField
        : null
    ..aCloneForceNewDataField =
        newData.aCloneForceNewDataField != currentData.aCloneForceNewDataField
            ? newData.aCloneForceNewDataField
            : null
    ..aDiffForceCurrentDataField = currentData.aDiffForceCurrentDataField
    ..aDiffForceNewDataField = newData.aDiffForceNewDataField
    ..aCombinationForceCurrentDataField =
        currentData.aCombinationForceCurrentDataField
    ..aCombinationForceNewDataField = newData.aCombinationForceNewDataField
    ..someFunctionField =
        newData.someFunctionField != currentData.someFunctionField
            ? newData.someFunctionField
            : null;

  bool isDiff = false;
  isDiff |= diff.aPublicField != null;
  isDiff |= diff._aPrivateField != null;
  isDiff |= diff.aCloneIgnoreField != null;
  isDiff |= diff.aCloneForceCurrentDataField != null;
  isDiff |= diff.aCloneForceNewDataField != null;
  isDiff |= diff.aDiffIgnoreField != null;
  isDiff |= diff.aDiffForceCurrentDataField != null;
  isDiff |= diff.aDiffForceNewDataField != null;
  isDiff |= diff.aCombinationIgnoreField != null;
  isDiff |= diff.aCombinationForceCurrentDataField != null;
  isDiff |= diff.aCombinationForceNewDataField != null;
  isDiff |= diff.someFunctionField != null;

  return isDiff ? diff : null;
}

Libraries

adeptgenerator