build method

  1. @override
  2. @mustCallSuper
FutureOr<void> build([
  1. BuildStep? buildStep
])

Generate fileMap from files under importPath.

Loads .json and .yaml files and skips others.

Implementation

@override
@mustCallSuper
FutureOr<void> build([final BuildStep? buildStep]) async {
  await super.build(buildStep);
  models.clear();

  /// Generate models from dictionaries.
  for (final MapEntry<String, Map<String, Object?>> entry in fileMap.values
      .toMap<String>()
      .cast<String, Map<String, Object?>>()
      .entries) {
    /// Process class fields.
    final List<FieldModel> fields = <FieldModel>[];
    for (final MapEntry<String, Map<String, Object?>> fieldEntry
        in (entry.value['fields'] as Map<String, Object?>? ??
                const <String, Object?>{})
            .cast<String, Map<String, Object?>>()
            .entries) {
      final Object? type = fieldEntry.value['type'];
      final Object? name = fieldEntry.value['name'];
      final Object? doc = fieldEntry.value['doc'];
      final Object? $default = fieldEntry.value['default'];
      final Object? compare = fieldEntry.value['compare'];
      final Object? nullable = fieldEntry.value['nullable'];
      final Object? required = fieldEntry.value['required'];
      final Object? copy = fieldEntry.value['copy'];
      final Object? serialize = fieldEntry.value['serialize'];
      final Object? deserialize = fieldEntry.value['deserialize'];
      final Object? equality = fieldEntry.value['equality'];
      final Object? toString = fieldEntry.value['to_string'];
      final Object? checkType = fieldEntry.value['check_type'];
      final Object? checkTypeDefault = fieldEntry.value['check_type_default'];
      final Object? castIterable = fieldEntry.value['cast_iterable'];
      fields.add(
        FieldModel(
          fieldEntry.key,
          type is String
              ? FieldType.fromString(type)
              : assignFieldTypes && $default != null
                  ? FieldType.fromObject($default)
                  : FieldType.$object,
          dartName:
              name is String && name.isNotEmpty ? name.normalize() : null,
          reference: type is String ? type : null,
          doc: doc is String ? doc : null,
          $default: $default,
          compare: compare is bool ? compare : null,
          nullable: nullable is bool ? nullable : null,
          required: required is bool ? required : null,
          copy: copy is bool ? copy : null,
          serialize: serialize is bool
              ? serialize
                  ? includeNullFields
                      ? FieldSerialization.all
                      : FieldSerialization.nonNull
                  : FieldSerialization.none
              : serialize is String
                  ? FieldSerialization.values.firstWhereOrNull(
                      (final FieldSerialization $serialize) =>
                          $serialize.name == serialize.trim(),
                    )
                  : !includeNullFields
                      ? FieldSerialization.nonNull
                      : null,
          deserialize: deserialize is bool ? deserialize : null,
          equality: equality is bool
              ? (equality ? FieldEquality.ordered : FieldEquality.none)
              : equality is String
                  ? FieldEquality.values.firstWhereOrNull(
                      (final FieldEquality $equality) =>
                          $equality.name == equality.trim(),
                    )
                  : null,
          toString: toString is bool ? toString : null,
          convert: convertFieldNames,
          checkType: checkType is bool ? checkType : null,
          checkTypeDefault: checkTypeDefault ??
              (!fieldEntry.value.containsKey('check_type_default')
                  ? Object
                  : null),
          castIterable: castIterable is bool ? castIterable : null,
        ),
      );
    }

    final List<InstanceModel> $instances = <InstanceModel>[];
    final Object? instances = entry.value['instances'];
    if (instances != null) {
      if (instances is! Map<String, Object?> ||
          instances.values.any((final _) => _ is! Map<String, Object?>)) {
        throw Exception(
          'Class ${entry.key} instances field is of the wrong type.'
          '\n\nShould be a Map with keys as instances names.',
        );
      }
      for (final MapEntry<String, Map<String, Object?>> instanceEntry
          in instances.cast<String, Map<String, Object?>>().entries) {
        final Map<String, Object?> instance = instanceEntry.value;
        final Object? name = instance['name'];
        final Object? doc = instance['doc'];
        final Object? instanceFields = instance['fields'];
        if (instanceFields is! Iterable<Object?> &&
            instanceFields is! Map<String, Object?>) {
          throw Exception(
            'Class "${entry.key}" instance "${instanceEntry.key}" is of the '
            'wrong type.\n\n$instance\n\nShould be Iterable or Map.',
          );
        } else if (instanceFields is Iterable<Object?> &&
            instanceFields.length != fields.length) {
          throw Exception(
            'Class "${entry.key}" instance "${instanceEntry.key}" has '
            'invalid number of values.\n\n$instance\n\n'
            'Should be exactly ${fields.length} values.',
          );
        } else if (instanceFields is Map<String, Object?>) {
          final Set<String> instanceKeys = instanceFields.keys.toSet();
          final Set<String> fieldKeys =
              fields.map((final _) => _.key).toSet();
          for (final String fieldKey in fieldKeys) {
            if (!instanceKeys.contains(fieldKey)) {
              throw Exception(
                'Class "${entry.key}" instance "${instanceEntry.key}" does '
                'not contain "$fieldKey" key.\n\n$instance',
              );
            }
          }
          for (final String instanceKey in instanceKeys) {
            if (!fieldKeys.contains(instanceKey)) {
              throw Exception(
                'Class "${entry.key}" does not contain "$instanceKey" key of '
                'instance "${instanceEntry.key}".\n\n$instance',
              );
            }
          }
        }
        $instances.add(
          InstanceModel(
            entry.key,
            dartName:
                name is String && name.isNotEmpty ? name.normalize() : null,
            doc: doc is String ? doc : null,
            fields: instanceFields,
            convert: convertInstanceNames,
          ),
        );
      }
    }

    final Object? name = entry.value['name'];
    final Object? doc = entry.value['doc'];
    final Object? toJson = entry.value['to_json'];
    models.add(
      ClassModel(
        entry.key.split('.').last.normalize(),
        reference: entry.key,
        dartName: name is String && name.isNotEmpty ? name : null,
        doc: doc is String && doc.isNotEmpty ? doc : null,
        toJson: toJson is bool ? toJson : null,
        convert: convertClassNames,
        fields: fields,
        instances: $instances,
      ),
    );
  }
}