generate method

  1. @override
String generate(
  1. List<ClassMember> members
)

Implementation

@override
String generate(List<ClassMember> members) {
  var toMap = '';
  var patcher = '';

  var usingToDouble = false;
  var usingToDecimal = false;
  final toDouble =
      'final toDouble = (val) => val == null ? null : val * 1.0;\n';
  final toDecimal =
      'final toDecimal = (val) => val == null ? null : Decimal.parse(val.toString());\n';

  for (var member in members) {
    if (!(member is FieldDeclaration)) continue;
    if (!getTag(member).contains('json')) continue;

    final key = getTag(member).split(':')[1].replaceAll('"', '');
    final isNullable = member.fields.type?.question != null;
    final dot = isNullable ? '?.' : '.';
    final typeName = (member.fields.type as NamedType).name.toString();
    final typeArgs =
        (member.fields.type as NamedType).typeArguments?.arguments;
    final leftType = (typeArgs?.elementAtOrNull(0) as NamedType?);
    final leftName = leftType?.name.toString() ?? 'dynamic';
    final leftDot = (leftType?.question?.toString() ?? '') + '.';
    final leftExcl = leftType?.question == null ? '!' : '';
    final rightType = (typeArgs?.elementAtOrNull(1) as NamedType?);
    final rightName = rightType?.name.toString() ?? 'dynamic';
    final rightDot = (rightType?.question?.toString() ?? '') + '.';
    final rightExcl = rightType?.question == null ? '!' : '';

    final type = member.fields.type
        .toString()
        .replaceAll('\$', '')
        .replaceAll('?', '');
    final name = member.fields.variables.first.name.lexeme;
    final initializer = member.fields.variables.first.initializer;

    if ([
      'String',
      'num',
      'bool',
      'int',
      'dynamic',
      'Map<String, dynamic>',
      'List<dynamic>'
    ].contains(type)) {
      toMap += "'$key': $name,\n";
      patcher += "$name = _data['$key']";
    } else if (type == 'double') {
      toMap += "'$key': $name,\n";
      patcher += "$name = toDouble(_data['$key'])";
      usingToDouble = true;
    } else if (type == 'Decimal') {
      toMap += "'$key': $name${dot}toDouble(),\n";
      patcher += "$name = toDecimal(_data['$key'])";
      usingToDecimal = true;
    } else if (enums.contains(type)) {
      toMap += "'$key': $name${dot}value,\n";
      patcher += "$name = $type.parse(_data['$key'])";
    } else if (typeName == 'Map') {
      if (['String', 'num', 'bool', 'dynamic'].contains(rightName)) {
        toMap += "'$key': $name,\n";
        patcher +=
            "$name = (_data['$key'] as Map?)?.map<$leftName, $rightName>((k, v) => MapEntry(k as $leftName, v as $rightName))";
      } else if (rightName == 'int') {
        toMap += "'$key': $name,\n";
        patcher +=
            "$name = (_data['$key'] as Map?)?.map<$leftName, $rightName>((k, v) => MapEntry(k as $leftName, v ~/ 1))";
      } else if (rightName == 'double') {
        toMap += "'$key': $name,\n";
        patcher +=
            "$name = (_data['$key'] as Map?)?.map<$leftName, $rightName>((k, v) => MapEntry(k as $leftName, v * 1.0))";
      } else if (enums.contains(rightName)) {
        toMap +=
            "'$key': $name${dot}map<String, dynamic>((k,v) => MapEntry(k, v${rightDot}value)),\n";
        patcher +=
            "$name = (_data['$key'] as Map?)?.map<$leftName, $rightName>((k, v) => MapEntry(k as $leftName, $rightName.parse(v)$rightExcl))";
      } else {
        toMap +=
            "'$key': $name${dot}map<String, dynamic>((k,v) => MapEntry(k, v${rightDot}toMap())),\n";
        patcher +=
            "$name = (_data['$key'] as Map?)?.map<$leftName, $rightName>((k, v) => MapEntry(k as $leftName, $rightName.fromMap(v)$rightExcl))";
      }
    } else if (typeName == 'List') {
      if (['String', 'num', 'bool', 'dynamic'].contains(leftName)) {
        toMap += "'$key': $name,\n";
        patcher += "$name = _data['$key']?.cast<$leftName>()";
      } else if (leftName == 'int') {
        toMap += "'$key': $name,\n";
        patcher +=
            "$name = _data['$key']?.map((i) => i ~/ 1).toList().cast<int>()";
      } else if (leftName == 'double') {
        toMap += "'$key': $name,\n";
        patcher +=
            "$name = _data['$key']?.map((i) => i * 1.0).toList().cast<double>()";
      } else if (enums.contains(leftName)) {
        toMap +=
            "'$key': $name${dot}map((i) => i${leftDot}value).toList(),\n";
        patcher +=
            "$name = _data['$key']?.map((i) => $leftName.parse(i)$leftExcl).toList().cast<$leftName>()";
      } else {
        toMap +=
            "'$key': $name${dot}map((i) => i${leftDot}toMap()).toList(),\n";
        patcher +=
            "$name = _data['$key']?.map((i) => $leftName.fromMap(i)$leftExcl).toList().cast<$leftName>()";
      }
    } else {
      toMap += "'$key': $name${dot}toMap(),";
      patcher += "$name = $type.fromMap(_data['$key'])";
    }

    patcher += ' ?? ${initializer ?? name};\n';
  }

  return '''
  void patch(Map? _data) { if(_data == null) return;
    ${usingToDouble ? toDouble : ''}
    ${usingToDecimal ? toDecimal : ''}
    $patcher
  }

  static $className? fromMap(Map? data) { if(data == null) return null; return $className()..patch(data); }

  Map<String, dynamic> toMap() => {
    $toMap
  };
  ''';
}