google / reflectable.dart

Reflectable is a Dart library that allows programmers to eliminate certain usages of dynamic reflection by specialization of reflective code to an equivalent implementation using only static techniques. The use of dynamic reflection is constrained in order to ensure that the specialized code can be generated and will have a reasonable size.
https://pub.dev/packages/reflectable
BSD 3-Clause "New" or "Revised" License
381 stars 57 forks source link

Severe error during build with @reflector and @JsonKey on the same class. #319

Closed binzheng closed 8 months ago

binzheng commented 1 year ago

When using both @reflector and @JsonKey annotations on the same class, the flutter pub run build_runner build command produces a severe error.

Here is the code snippet causing the issue:

part 'sample_item.g.dart';

@JsonSerializable()
@reflector
class SampleItem {
  final int id;
  @JsonKey(includeFromJson: true, toJson: _decodeString)
  String? descriptionActivity;
  SampleItem(this.id, {this.descriptionActivity});
  static String? _decodeString(String? image) => image;

  factory SampleItem.fromJson(Map<String, dynamic> json) => _$SampleItemFromJson(json);
  Map<String, dynamic> toJson() => _$SampleItemToJson(this);
}

The error messages are:

[SEVERE] reflectable on lib/main.dart (cached): Cannot handle private identifier _decodeString [SEVERE] reflectable on lib/main.dart (cached): Could not format because the source could not be parsed: ... Expected an identifier.

I believe this issue lies within the reflector package's handling of @JsonKey annotations. More specifically, it appears to struggle with parsing the toJson attribute when it refers to a private method, like _decodeString in my example.

Any guidance or fixes would be greatly appreciated.

eernstg commented 1 year ago

Reflectable cannot generate code that accesses private members, so we can't reflect on those members in any way.

You should be able to use something like the capability instanceInvokeCapability('^[^_]') to avoid attempting to include support for any members with a private name. The string '^[^_]' is a regular expression, and it just says that the member name doesn't start with an underscore.

Check out https://github.com/google/reflectable.dart/blob/master/test_reflectable/test/member_capability_test.dart for an example where members are included in / excluded from reflective support by means of this mechanism.