google/built_value.dart

Classes not being generated with new Dart 3 classes modifiers

yisusparkr opened this issue · 2 comments

Hi @davidmorgan, hope you are doing pretty well!

The generated code is not respecting the classes modifiers in case we mark our class with one, example:

Entity

abstract interface class CreateVehiclePayload {
  int get year;
  String get make;
  String get model;
  double get initialMileage;
  String? get plate;
  String? get plateState;
  String? get vin;

  String toJson();
}

Model

library create_vehicle_payload_model;

part 'create_vehicle_payload_model.g.dart';

abstract final class CreateVehiclePayloadModel
    implements CreateVehiclePayload, Built<CreateVehiclePayloadModel, CreateVehiclePayloadModelBuilder> {
  const CreateVehiclePayloadModel._();

  factory CreateVehiclePayloadModel({
    required int year,
    required String model,
    required String make,
    required double initialMileage,
    String? plate,
    String? plateState,
    String? vin,
  }) =>
      _$CreateVehiclePayloadModel(
        (b) => b
          ..year = year
          ..model = model
          ..make = make
          ..initialMileage = initialMileage
          ..plate = plate
          ..vin = vin
          ..plateState = plateState,
      );

  @override
  String toJson() {
    return jsonEncode(coreSerializers.serializeWith(CreateVehiclePayloadModel.serializer, this));
  }

  static Serializer<CreateVehiclePayloadModel> get serializer => _$createVehiclePayloadModelSerializer;
}

Then, if I run the command flutter pub run build_runner build --delete-conflicting-outputs, I get the following generated file:

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'create_vehicle_payload_model.dart';

// **************************************************************************
// BuiltValueGenerator
// **************************************************************************

Serializer<CreateVehiclePayloadModel> _$createVehiclePayloadModelSerializer =
    new _$CreateVehiclePayloadModelSerializer();

class _$CreateVehiclePayloadModelSerializer
    implements StructuredSerializer<CreateVehiclePayloadModel> {
  @override
  final Iterable<Type> types = const [
    CreateVehiclePayloadModel,
    _$CreateVehiclePayloadModel
  ];
  @override
  final String wireName = 'CreateVehiclePayloadModel';

  @override
  Iterable<Object?> serialize(
      Serializers serializers, CreateVehiclePayloadModel object,
      {FullType specifiedType = FullType.unspecified}) {
    final result = <Object?>[
      'year',
      serializers.serialize(object.year, specifiedType: const FullType(int)),
      'make',
      serializers.serialize(object.make, specifiedType: const FullType(String)),
      'model',
      serializers.serialize(object.model,
          specifiedType: const FullType(String)),
      'initialMileage',
      serializers.serialize(object.initialMileage,
          specifiedType: const FullType(double)),
    ];
    Object? value;
    value = object.plate;
    if (value != null) {
      result
        ..add('plate')
        ..add(serializers.serialize(value,
            specifiedType: const FullType(String)));
    }
    value = object.plateState;
    if (value != null) {
      result
        ..add('plateState')
        ..add(serializers.serialize(value,
            specifiedType: const FullType(String)));
    }
    value = object.vin;
    if (value != null) {
      result
        ..add('vin')
        ..add(serializers.serialize(value,
            specifiedType: const FullType(String)));
    }
    return result;
  }

  @override
  CreateVehiclePayloadModel deserialize(
      Serializers serializers, Iterable<Object?> serialized,
      {FullType specifiedType = FullType.unspecified}) {
    final result = new CreateVehiclePayloadModelBuilder();

    final iterator = serialized.iterator;
    while (iterator.moveNext()) {
      final key = iterator.current! as String;
      iterator.moveNext();
      final Object? value = iterator.current;
      switch (key) {
        case 'year':
          result.year = serializers.deserialize(value,
              specifiedType: const FullType(int))! as int;
          break;
        case 'make':
          result.make = serializers.deserialize(value,
              specifiedType: const FullType(String))! as String;
          break;
        case 'model':
          result.model = serializers.deserialize(value,
              specifiedType: const FullType(String))! as String;
          break;
        case 'initialMileage':
          result.initialMileage = serializers.deserialize(value,
              specifiedType: const FullType(double))! as double;
          break;
        case 'plate':
          result.plate = serializers.deserialize(value,
              specifiedType: const FullType(String)) as String?;
          break;
        case 'plateState':
          result.plateState = serializers.deserialize(value,
              specifiedType: const FullType(String)) as String?;
          break;
        case 'vin':
          result.vin = serializers.deserialize(value,
              specifiedType: const FullType(String)) as String?;
          break;
      }
    }

    return result.build();
  }
}

class _$CreateVehiclePayloadModel extends CreateVehiclePayloadModel {
  @override
  final int year;
  @override
  final String make;
  @override
  final String model;
  @override
  final double initialMileage;
  @override
  final String? plate;
  @override
  final String? plateState;
  @override
  final String? vin;

  factory _$CreateVehiclePayloadModel(
          [void Function(CreateVehiclePayloadModelBuilder)? updates]) =>
      (new CreateVehiclePayloadModelBuilder()..update(updates))._build();

  _$CreateVehiclePayloadModel._(
      {required this.year,
      required this.make,
      required this.model,
      required this.initialMileage,
      this.plate,
      this.plateState,
      this.vin})
      : super._() {
    BuiltValueNullFieldError.checkNotNull(
        year, r'CreateVehiclePayloadModel', 'year');
    BuiltValueNullFieldError.checkNotNull(
        make, r'CreateVehiclePayloadModel', 'make');
    BuiltValueNullFieldError.checkNotNull(
        model, r'CreateVehiclePayloadModel', 'model');
    BuiltValueNullFieldError.checkNotNull(
        initialMileage, r'CreateVehiclePayloadModel', 'initialMileage');
  }

  @override
  CreateVehiclePayloadModel rebuild(
          void Function(CreateVehiclePayloadModelBuilder) updates) =>
      (toBuilder()..update(updates)).build();

  @override
  CreateVehiclePayloadModelBuilder toBuilder() =>
      new CreateVehiclePayloadModelBuilder()..replace(this);

  @override
  bool operator ==(Object other) {
    if (identical(other, this)) return true;
    return other is CreateVehiclePayloadModel &&
        year == other.year &&
        make == other.make &&
        model == other.model &&
        initialMileage == other.initialMileage &&
        plate == other.plate &&
        plateState == other.plateState &&
        vin == other.vin;
  }

  @override
  int get hashCode {
    var _$hash = 0;
    _$hash = $jc(_$hash, year.hashCode);
    _$hash = $jc(_$hash, make.hashCode);
    _$hash = $jc(_$hash, model.hashCode);
    _$hash = $jc(_$hash, initialMileage.hashCode);
    _$hash = $jc(_$hash, plate.hashCode);
    _$hash = $jc(_$hash, plateState.hashCode);
    _$hash = $jc(_$hash, vin.hashCode);
    _$hash = $jf(_$hash);
    return _$hash;
  }

  @override
  String toString() {
    return (newBuiltValueToStringHelper(r'CreateVehiclePayloadModel')
          ..add('year', year)
          ..add('make', make)
          ..add('model', model)
          ..add('initialMileage', initialMileage)
          ..add('plate', plate)
          ..add('plateState', plateState)
          ..add('vin', vin))
        .toString();
  }
}

class CreateVehiclePayloadModelBuilder
    implements
        Builder<CreateVehiclePayloadModel, CreateVehiclePayloadModelBuilder> {
  _$CreateVehiclePayloadModel? _$v;

  int? _year;
  int? get year => _$this._year;
  set year(int? year) => _$this._year = year;

  String? _make;
  String? get make => _$this._make;
  set make(String? make) => _$this._make = make;

  String? _model;
  String? get model => _$this._model;
  set model(String? model) => _$this._model = model;

  double? _initialMileage;
  double? get initialMileage => _$this._initialMileage;
  set initialMileage(double? initialMileage) =>
      _$this._initialMileage = initialMileage;

  String? _plate;
  String? get plate => _$this._plate;
  set plate(String? plate) => _$this._plate = plate;

  String? _plateState;
  String? get plateState => _$this._plateState;
  set plateState(String? plateState) => _$this._plateState = plateState;

  String? _vin;
  String? get vin => _$this._vin;
  set vin(String? vin) => _$this._vin = vin;

  CreateVehiclePayloadModelBuilder();

  CreateVehiclePayloadModelBuilder get _$this {
    final $v = _$v;
    if ($v != null) {
      _year = $v.year;
      _make = $v.make;
      _model = $v.model;
      _initialMileage = $v.initialMileage;
      _plate = $v.plate;
      _plateState = $v.plateState;
      _vin = $v.vin;
      _$v = null;
    }
    return this;
  }

  @override
  void replace(CreateVehiclePayloadModel other) {
    ArgumentError.checkNotNull(other, 'other');
    _$v = other as _$CreateVehiclePayloadModel;
  }

  @override
  void update(void Function(CreateVehiclePayloadModelBuilder)? updates) {
    if (updates != null) updates(this);
  }

  @override
  CreateVehiclePayloadModel build() => _build();

  _$CreateVehiclePayloadModel _build() {
    final _$result = _$v ??
        new _$CreateVehiclePayloadModel._(
            year: BuiltValueNullFieldError.checkNotNull(
                year, r'CreateVehiclePayloadModel', 'year'),
            make: BuiltValueNullFieldError.checkNotNull(
                make, r'CreateVehiclePayloadModel', 'make'),
            model: BuiltValueNullFieldError.checkNotNull(
                model, r'CreateVehiclePayloadModel', 'model'),
            initialMileage: BuiltValueNullFieldError.checkNotNull(
                initialMileage, r'CreateVehiclePayloadModel', 'initialMileage'),
            plate: plate,
            plateState: plateState,
            vin: vin);
    replace(_$result);
    return _$result;
  }
}

// ignore_for_file: deprecated_member_use_from_same_package,type=lint

Then I get the following error -> The type '_$CreateVehiclePayloadModel' must be 'base', 'final' or 'sealed' because the supertype 'CreateVehiclePayloadModel' is 'final'.. In order to make it work, I have to manually add any of the mentioned modifiers, but I think it is not ideal, adding modifiers manually for each generated class is painful.

Thanks!

Yes, I didn't add any support for the new modifiers yet.

What modifiers are interesting for built_value classes?

I was mostly thinking "final" to prevent subclassing so the compiler knows the generate implementation is the only one.

I agree, I think final modifier would be great to have due to the benefits it provides, like preventing subclassing.

I think creating a built_value class with sealed modifier would not provide much value, at the end of the day if I will use that modifier I have to create its own subclass abstract interface class extending from the sealed class and then the abstract final built_value class implementing the created subclass, so there is no need of having the generated class marked as sealed. For the base modifier I have a similar thought.

This is just my POV and just providing the example following the good practices, also taking into account some complex models with generic types, but I don't know if someone could fall in the need of generating a built_value class with the sealed, base or another modifier.