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.toString().contains('?');
    final dot = isNullable ? '?.' : '.';
    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 (type.contains('Map<')) {
      var types = type.substring(4, type.lastIndexOf('>')).split(',');
      toMap += "'$key': $name,\n";
      patcher +=
          "$name = _data['$key']${dot}map<${types[0]}, ${types[1]}>((k, v) => MapEntry(k as ${types[0]}, v as ${types[1]}))";
    } else if (type.contains('List<')) {
      final listPrimitive = type.replaceAll('List<', '').replaceAll('>', '');
      if (['String', 'num', 'bool', 'dynamic'].contains(listPrimitive)) {
        toMap += "'$key': $name,\n";
        patcher += "$name = _data['$key']?.cast<$listPrimitive>()";
      } else if (listPrimitive == 'int') {
        toMap += "'$key': $name,\n";
        patcher +=
            "$name = _data['$key']?.map((i) => i ~/ 1).toList().cast<int>()";
      } else if (listPrimitive == 'double') {
        toMap += "'$key': $name,\n";
        patcher +=
            "$name = _data['$key']?.map((i) => i * 1.0).toList().cast<double>()";
      } else if (enums.contains(listPrimitive)) {
        toMap += "'$key': $name${dot}map((i) => i.value).toList(),\n";
        patcher +=
            "$name = _data['$key']?.map((i) => $listPrimitive.parse(i)).toList().cast<$listPrimitive>()";
      } else {
        toMap += "'$key': $name${dot}map((i) => i.toMap()).toList(),\n";
        patcher +=
            "$name = _data['$key']?.map((i) => $listPrimitive.fromMap(i)).toList().cast<$listPrimitive>()";
      }
    } 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
  };
  ''';
}