google/built_value.dart

problem with generated Builder code for un-instantiable classes

ahmednfwela opened this issue ยท 6 comments

related to: OpenAPITools/openapi-generator#12295

consider this example:

script_payload_correct.dart:

import 'package:built_value/built_value.dart';

part 'script_payload_correct.g.dart';

@BuiltValue(instantiable: true)
abstract class ScriptPayloadCorrect
    implements Built<ScriptPayloadCorrect, ScriptPayloadCorrectBuilder> {
  ScriptPayloadCorrect._();

  @BuiltValueField(wireName: r'code')
  String get code;

  @BuiltValueHook(initializeBuilder: true)
  static void _defaults(ScriptPayloadCorrectBuilder b) => b;

  factory ScriptPayloadCorrect(
          [void Function(ScriptPayloadCorrectBuilder)? updates]) =
      _$ScriptPayloadCorrect;
}

script_payload_wrong.dart:

@BuiltValue(instantiable: false)
abstract class ScriptPayloadWrong {
  @BuiltValueField(wireName: r'code')
  String get code;
}

script_write_set.dart:

import 'package:built_value/built_value.dart';
import 'script_payload_wrong.dart';

import 'script_payload_correct.dart';

part 'script_write_set.g.dart';

@BuiltValue(instantiable: false)
abstract class ScriptWriteSet {
  @BuiltValueField(wireName: r'execute_as')
  String get executeAs;
  @BuiltValueField(wireName: r'script_correct')
  ScriptPayloadCorrect get scriptCorrect;
  @BuiltValueField(wireName: r'script_wrong')
  ScriptPayloadWrong get scriptWrong;
}

the faulty generated file script_write_set.g.dart is:

abstract class ScriptWriteSetBuilder {
  void replace(ScriptWriteSet other);
  void update(void Function(ScriptWriteSetBuilder) updates);
  String? get executeAs;
  set executeAs(String? executeAs);

  ScriptPayloadCorrectBuilder get scriptCorrect;
  set scriptCorrect(ScriptPayloadCorrectBuilder? scriptCorrect);

  ScriptPayloadWrong? get scriptWrong;
  set scriptWrong(ScriptPayloadWrong? scriptWrong);
}

you can see here that it treats the two variables differently, where it uses a builder for scriptCorrect, but uses raw value for scriptWrong, even though both should use the builder

For more context (correct me if I'm wrong @ahmednfwela), I believe the versions we're using are:

dependencies:
  built_value: '>=8.1.0 <9.0.0'
  built_collection: '>=5.1.0 <6.0.0'

dev_dependencies:
  built_value_generator: '>=8.1.0 <9.0.0'

I tried with latest version as well, same problem

@davidmorgan what do you think about this ?

On vacation this week and Monday, I'll take a look next week if I can. Thanks for your patience :)

Hmmmm I think this is working as intended, although I agree it's confusing.

ScriptPayloadWrongBuilder is, like ScriptPayloadWrong, not instantiable. So the generated ScriptWriteSetBuilder can't use it, because it doesn't know how to instantiate it. It could add it to the API, but it wouldn't know how to actually implement the API.

What you can do is provide your own implementation of ScriptWriteSetBuilder. Your implementation can use ScriptPayloadWrongBuilder, because you know about the concrete (instantiable) subclasses and can instantiate one, or even switch between them.

Please let me know if that helps :)

@dave26199 I see your point, I think it would be good to document this somewhere
I am closing this for now