From 29820a5d87057711e15ed32d9b92cdb0e97a3141 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 25 Aug 2023 13:34:01 +0200 Subject: [PATCH 01/48] Use Dart 3 --- .../auto_mappr/lib/src/builder/methods/callable_method.dart | 4 +--- .../auto_mappr/lib/src/builder/methods/callable_property.dart | 2 +- packages/auto_mappr/pubspec.yaml | 2 +- packages/auto_mappr_annotation/lib/src/auto_mappr.dart | 4 ++-- .../auto_mappr_annotation/lib/src/auto_mappr_interface.dart | 2 +- packages/auto_mappr_annotation/lib/src/field.dart | 2 +- packages/auto_mappr_annotation/lib/src/map_type.dart | 2 +- packages/auto_mappr_annotation/pubspec.yaml | 2 +- pubspec.yaml | 2 +- 9 files changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/auto_mappr/lib/src/builder/methods/callable_method.dart b/packages/auto_mappr/lib/src/builder/methods/callable_method.dart index c482064c..22df0c3d 100644 --- a/packages/auto_mappr/lib/src/builder/methods/callable_method.dart +++ b/packages/auto_mappr/lib/src/builder/methods/callable_method.dart @@ -1,10 +1,8 @@ import 'package:code_builder/code_builder.dart'; // ignore: one_member_abstracts, it is implemented in builders -abstract class CallableMethod { +abstract interface class CallableMethod { const CallableMethod(); Expression methodCall({Map<String, Expression> namedArguments = const {}}); - - } diff --git a/packages/auto_mappr/lib/src/builder/methods/callable_property.dart b/packages/auto_mappr/lib/src/builder/methods/callable_property.dart index bd7315b9..6a260121 100644 --- a/packages/auto_mappr/lib/src/builder/methods/callable_property.dart +++ b/packages/auto_mappr/lib/src/builder/methods/callable_property.dart @@ -1,7 +1,7 @@ import 'package:code_builder/code_builder.dart'; // ignore: one_member_abstracts, it is implemented in builders -abstract class CallableProperty { +abstract interface class CallableProperty { const CallableProperty(); Expression propertyCall({ diff --git a/packages/auto_mappr/pubspec.yaml b/packages/auto_mappr/pubspec.yaml index e76e248a..e9eeb20c 100644 --- a/packages/auto_mappr/pubspec.yaml +++ b/packages/auto_mappr/pubspec.yaml @@ -8,7 +8,7 @@ screenshots: path: doc/icon.png environment: - sdk: ">=2.18.7 <4.0.0" + sdk: ^3.0.0 dependencies: # TODO: Support analyzer same way as json_serializable https://github.com/google/json_serializable.dart/pull/1333 diff --git a/packages/auto_mappr_annotation/lib/src/auto_mappr.dart b/packages/auto_mappr_annotation/lib/src/auto_mappr.dart index bd22d593..e45ea2cb 100644 --- a/packages/auto_mappr_annotation/lib/src/auto_mappr.dart +++ b/packages/auto_mappr_annotation/lib/src/auto_mappr.dart @@ -2,9 +2,9 @@ import 'package:auto_mappr_annotation/src/auto_mappr_interface.dart'; import 'package:auto_mappr_annotation/src/map_type.dart'; /// Annotates class which will be used as base for generated mappr. -class AutoMappr { +final class AutoMappr { /// List of mapprs. - final List<MapType<Object?, Object?>> mappers; + final List<MapType<Object, Object>> mappers; /// List of other AutoMappr classes to use as modules. /// diff --git a/packages/auto_mappr_annotation/lib/src/auto_mappr_interface.dart b/packages/auto_mappr_annotation/lib/src/auto_mappr_interface.dart index 3ba549a8..eef65470 100644 --- a/packages/auto_mappr_annotation/lib/src/auto_mappr_interface.dart +++ b/packages/auto_mappr_annotation/lib/src/auto_mappr_interface.dart @@ -1,7 +1,7 @@ /// AutoMappr interface for converting source objects into target objects. /// /// Users should not implement or extend this. -abstract class AutoMapprInterface { +abstract interface class AutoMapprInterface { /// const AutoMapprInterface(); diff --git a/packages/auto_mappr_annotation/lib/src/field.dart b/packages/auto_mappr_annotation/lib/src/field.dart index f2c12ae9..e7f56503 100644 --- a/packages/auto_mappr_annotation/lib/src/field.dart +++ b/packages/auto_mappr_annotation/lib/src/field.dart @@ -1,5 +1,5 @@ /// Mapping configuration of target object's field. -class Field { +final class Field { /// Which field is mapped. /// /// It should be either name of TARGET's field OR name of TARGET's constructor. diff --git a/packages/auto_mappr_annotation/lib/src/map_type.dart b/packages/auto_mappr_annotation/lib/src/map_type.dart index f8c627c7..30c5f640 100644 --- a/packages/auto_mappr_annotation/lib/src/map_type.dart +++ b/packages/auto_mappr_annotation/lib/src/map_type.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/src/field.dart'; /// Configured mapping from [SOURCE] to [TARGET]. -class MapType<SOURCE, TARGET> { +final class MapType<SOURCE, TARGET> { /// Configuration for [TARGET]'s fields. final List<Field> fields; diff --git a/packages/auto_mappr_annotation/pubspec.yaml b/packages/auto_mappr_annotation/pubspec.yaml index 8e1b4a7c..13b63e20 100644 --- a/packages/auto_mappr_annotation/pubspec.yaml +++ b/packages/auto_mappr_annotation/pubspec.yaml @@ -5,7 +5,7 @@ repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues environment: - sdk: ">=2.18.7 <4.0.0" + sdk: ^3.0.0 dev_dependencies: netglade_analysis: ^4.0.0 diff --git a/pubspec.yaml b/pubspec.yaml index d3eabbd2..b51f93a2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: auto_mappr_workspace publish_to: "none" environment: - sdk: ">=2.18.0 <4.0.0" + sdk: ^3.0.0 dev_dependencies: melos: ^3.0.0 From eb8f5d1ae6d7574105874958023b5ef7e04c0be1 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 28 Aug 2023 09:44:10 +0200 Subject: [PATCH 02/48] Fix flutter pub run reprecated message --- packages/auto_mappr/README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/auto_mappr/README.md b/packages/auto_mappr/README.md index c9ab94a5..28fb0df0 100644 --- a/packages/auto_mappr/README.md +++ b/packages/auto_mappr/README.md @@ -232,13 +232,7 @@ dart pub add --dev auto_mappr ### Run the generator -For a Flutter project: - -```shell -flutter pub run build_runner build -``` - -For a Dart project: +For Dart or Flutter projects: ```shell dart run build_runner build From 19833d144879c0a738491d0365f0bc3fe6e88ea4 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 28 Aug 2023 11:22:35 +0200 Subject: [PATCH 03/48] Add reverse mapping option --- packages/auto_mappr/CHANGELOG.md | 3 + packages/auto_mappr/README.md | 14 +++ .../src/generator/auto_mappr_generator.dart | 111 ++++++++++-------- .../test/integration/fixture/reverse.dart | 79 +++++++++++++ .../test/integration/reverse_test.dart | 96 +++++++++++++++ packages/auto_mappr_annotation/CHANGELOG.md | 5 +- .../lib/src/map_type.dart | 8 ++ 7 files changed, 266 insertions(+), 50 deletions(-) create mode 100644 packages/auto_mappr/test/integration/fixture/reverse.dart create mode 100644 packages/auto_mappr/test/integration/reverse_test.dart diff --git a/packages/auto_mappr/CHANGELOG.md b/packages/auto_mappr/CHANGELOG.md index f761e8a5..87f9aa4f 100644 --- a/packages/auto_mappr/CHANGELOG.md +++ b/packages/auto_mappr/CHANGELOG.md @@ -1,5 +1,8 @@ [//]: # (## Unreleased) +## Unreleased +- Add a `reverse` option on `MapType`, which includes the reverse mapping. [#115](https://github.com/netglade/auto_mappr/pull/115) + ## 1.7.0 - Adhere to netglade_analysis. [#94](https://github.com/netglade/auto_mappr/pull/94) - Update analyzer and mocktail packages. [#111](https://github.com/netglade/auto_mappr/pull/111) diff --git a/packages/auto_mappr/README.md b/packages/auto_mappr/README.md index c9ab94a5..d365a9d5 100644 --- a/packages/auto_mappr/README.md +++ b/packages/auto_mappr/README.md @@ -48,6 +48,7 @@ Heavily inspired by [C# AutoMapper][auto_mapper_net_link]. - [Generics](#generics) - [Library import aliases](#library-import-aliases) - [Modules](#modules) + - [Reverse mapping](#reverse-mapping) - [Works with `equatable`](#works-with-equatable) - [Works with `json_serializable`](#works-with-json_serializable) - [Works with generated source and target classes](#works-with-generated-source-and-target-classes) @@ -605,6 +606,19 @@ so you can only provide one grouping/main mappr that can handle everything. Each feature in your app can return an instance of const `AutoMapprInterface`, that each mappr internally implements. +### Reverse mapping + +When you want to create a bidirectional mapping (e.g. normal: source to target and reversed: target to source), +you can use `reverse` option on `MapType`. + +Note that it's your responsibility to make sure those objects +support normal and reverse mapping +and to keep them in sync. +Also note that reverse mapping might not work properly when additional configuration +such as [whenSourceIsNull] or [constructor] is used. + +For more complicated scenarios two separate mappings are recommended instead. + ### Works with `equatable` Mapping works with the Equatable package. diff --git a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart index 8ca35929..231c208b 100644 --- a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart +++ b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart @@ -85,55 +85,70 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { required ClassElement element, required AutoMapprConfig config, }) { - return mappers.map((mapper) { - final mapperType = mapper.type! as ParameterizedType; - - final sourceType = mapperType.typeArguments.firstOrNull; - final targetType = mapperType.typeArguments.lastOrNull; - - if (sourceType is! InterfaceType) { - throw InvalidGenerationSourceError( - '${sourceType?.getDisplayStringWithLibraryAlias(config: config, withNullability: true)} is not a class and cannot be mapped from', - element: element, - todo: 'Use a class', - ); - } - if (targetType is! InterfaceType) { - throw InvalidGenerationSourceError( - '${targetType?.getDisplayStringWithLibraryAlias(config: config, withNullability: true)} is not a class and cannot be mapped to', - element: element, - todo: 'Use a class', - ); - } - - final fields = mapper.getField('fields')?.toListValue(); - final whenSourceIsNull = mapper.getField('whenSourceIsNull')?.toCodeExpression(config: config); - final constructor = mapper.getField('constructor')?.toStringValue(); - final ignoreFieldNull = mapper.getField('ignoreFieldNull')?.toBoolValue(); - - final fieldMappings = fields - ?.map( - (fieldMapping) => FieldMapping( - field: fieldMapping.getField('field')!.toStringValue()!, - ignore: fieldMapping.getField('ignore')!.toBoolValue()!, - from: fieldMapping.getField('from')!.toStringValue(), - customExpression: - fieldMapping.getField('custom')!.toCodeExpression(passModelArgument: true, config: config), - whenNullExpression: fieldMapping.getField('whenNull')!.toCodeExpression(config: config), - ignoreNull: fieldMapping.getField('ignoreNull')?.toBoolValue(), + return mappers + .map((mapper) { + final mapperType = mapper.type! as ParameterizedType; + + final sourceType = mapperType.typeArguments.firstOrNull; + final targetType = mapperType.typeArguments.lastOrNull; + + if (sourceType is! InterfaceType) { + throw InvalidGenerationSourceError( + '${sourceType?.getDisplayStringWithLibraryAlias(config: config, withNullability: true)} is not a class and cannot be mapped from', + element: element, + todo: 'Use a class', + ); + } + if (targetType is! InterfaceType) { + throw InvalidGenerationSourceError( + '${targetType?.getDisplayStringWithLibraryAlias(config: config, withNullability: true)} is not a class and cannot be mapped to', + element: element, + todo: 'Use a class', + ); + } + + final fields = mapper.getField('fields')?.toListValue(); + final whenSourceIsNull = mapper.getField('whenSourceIsNull')?.toCodeExpression(config: config); + final constructor = mapper.getField('constructor')?.toStringValue(); + final ignoreFieldNull = mapper.getField('ignoreFieldNull')?.toBoolValue(); + final reverse = mapper.getField('reverse')?.toBoolValue(); + + final fieldMappings = fields + ?.map( + (fieldMapping) => FieldMapping( + field: fieldMapping.getField('field')!.toStringValue()!, + ignore: fieldMapping.getField('ignore')!.toBoolValue()!, + from: fieldMapping.getField('from')!.toStringValue(), + customExpression: + fieldMapping.getField('custom')!.toCodeExpression(passModelArgument: true, config: config), + whenNullExpression: fieldMapping.getField('whenNull')!.toCodeExpression(config: config), + ignoreNull: fieldMapping.getField('ignoreNull')?.toBoolValue(), + ), + ) + .toList(); + + return [ + TypeMapping( + source: sourceType, + target: targetType, + fieldMappings: fieldMappings, + whenSourceIsNullExpression: whenSourceIsNull, + constructor: constructor, + ignoreFieldNull: ignoreFieldNull, ), - ) - .toList(); - - return TypeMapping( - source: sourceType, - target: targetType, - fieldMappings: fieldMappings, - whenSourceIsNullExpression: whenSourceIsNull, - constructor: constructor, - ignoreFieldNull: ignoreFieldNull, - ); - }).toList(); + if (reverse ?? false) + TypeMapping( + source: targetType, + target: sourceType, + fieldMappings: fieldMappings, + whenSourceIsNullExpression: whenSourceIsNull, + constructor: constructor, + ignoreFieldNull: ignoreFieldNull, + ), + ]; + }) + .flattened + .toList(); } Map<String, String> _getLibraryAliases({required ClassElement element}) { diff --git a/packages/auto_mappr/test/integration/fixture/reverse.dart b/packages/auto_mappr/test/integration/fixture/reverse.dart new file mode 100644 index 00000000..c79569b0 --- /dev/null +++ b/packages/auto_mappr/test/integration/fixture/reverse.dart @@ -0,0 +1,79 @@ +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +import 'package:equatable/equatable.dart'; + +part 'reverse.g.dart'; + +@AutoMappr([ + MapType<PrimitiveDto, Primitive>(reverse: true), + MapType<UserDto, User>(reverse: true), + MapType<AddressDto, Address>(reverse: true), +]) +class Mappr extends $Mappr { + const Mappr(); +} + +// Primitive + +class Primitive extends Equatable { + final int number; + final String string; + + @override + List<Object?> get props => [number, string]; + + const Primitive({required this.number, required this.string}); +} + +class PrimitiveDto extends Equatable { + final int number; + final String string; + + @override + List<Object?> get props => [number, string]; + + const PrimitiveDto({required this.number, required this.string}); +} + +// User + +class User extends Equatable { + final int id; + final String name; + final Address address; + + @override + List<Object?> get props => [id, name, address]; + + const User({required this.id, required this.name, required this.address}); +} + +class UserDto extends Equatable { + final int id; + final String name; + final AddressDto address; + + @override + List<Object?> get props => [id, name, address]; + + const UserDto(this.id, {required this.name, required this.address}); +} + +class Address extends Equatable { + final String street; + final String city; + + @override + List<Object?> get props => [street, city]; + + const Address({required this.street, required this.city}); +} + +class AddressDto extends Equatable { + final String street; + final String city; + + @override + List<Object?> get props => [street, city]; + + const AddressDto({required this.street, required this.city}); +} diff --git a/packages/auto_mappr/test/integration/reverse_test.dart b/packages/auto_mappr/test/integration/reverse_test.dart new file mode 100644 index 00000000..05d1e643 --- /dev/null +++ b/packages/auto_mappr/test/integration/reverse_test.dart @@ -0,0 +1,96 @@ +import 'package:test/test.dart'; + +import 'fixture/reverse.dart' as fixture; + +void main() { + late final fixture.Mappr mappr; + + setUpAll(() { + mappr = const fixture.Mappr(); + }); + + group('converting primitives', () { + test('PrimitiveDto to Primitive', () { + const dto = fixture.PrimitiveDto( + number: 111, + string: 'Uzumaki Naruto', + ); + final converted = mappr.convert<fixture.PrimitiveDto, fixture.Primitive>(dto); + + expect( + converted, + equals( + const fixture.Primitive(number: 111, string: 'Uzumaki Naruto'), + ), + ); + }); + + test('Primitive to PrimitiveDto', () { + const dto = fixture.Primitive(number: 111, string: 'Uzumaki Naruto'); + final converted = mappr.convert<fixture.Primitive, fixture.PrimitiveDto>(dto); + + expect( + converted, + equals( + const fixture.PrimitiveDto(number: 111, string: 'Uzumaki Naruto'), + ), + ); + }); + }); + + group('converting nested objects', () { + test('AddressDto to Address', () { + const dto = fixture.AddressDto(street: 'Alpha', city: 'Beta'); + final converted = mappr.convert<fixture.AddressDto, fixture.Address>(dto); + + expect( + converted, + equals(const fixture.Address(street: 'Alpha', city: 'Beta')), + ); + }); + + test('Address to AddressDto', () { + const dto = fixture.Address(street: 'Gama', city: 'Delta'); + final converted = mappr.convert<fixture.Address, fixture.AddressDto>(dto); + + expect( + converted, + equals(const fixture.AddressDto(street: 'Gama', city: 'Delta')), + ); + }); + + test('UserDto to User', () { + const dto = + fixture.UserDto(1, name: 'Xxx 1', address: fixture.AddressDto(street: 'test street 1', city: 'test city 1')); + final converted = mappr.convert<fixture.UserDto, fixture.User>(dto); + + expect( + converted, + equals( + const fixture.User( + id: 1, + name: 'Xxx 1', + address: fixture.Address(street: 'test street 1', city: 'test city 1'), + ), + ), + ); + }); + + test('User to UserDto', () { + const dto = + fixture.User(id: 2, name: 'Xxx 2', address: fixture.Address(street: 'test street 2', city: 'test city 2')); + final converted = mappr.convert<fixture.User, fixture.UserDto>(dto); + + expect( + converted, + equals( + const fixture.UserDto( + 2, + name: 'Xxx 2', + address: fixture.AddressDto(street: 'test street 2', city: 'test city 2'), + ), + ), + ); + }); + }); +} diff --git a/packages/auto_mappr_annotation/CHANGELOG.md b/packages/auto_mappr_annotation/CHANGELOG.md index aaa90ecb..4fe11239 100644 --- a/packages/auto_mappr_annotation/CHANGELOG.md +++ b/packages/auto_mappr_annotation/CHANGELOG.md @@ -2,10 +2,11 @@ ## Unreleased - Adhere to netglade_analysis 4.0.0 +- Add `reverse` option to `MapType`. ## 1.2.0 -- Add `ignoreFieldNull` in MapType to force non-nullable field for when source's field is nullable -- Add `ignoreNull` in Field to force non-nullable field for when source's field is nullable +- Add `ignoreFieldNull` in `MapType` to force non-nullable field for when source's field is nullable +- Add `ignoreNull` in `Field`` to force non-nullable field for when source's field is nullable ## 1.1.1 - Adhere to netglade_analysis 2.0.0. diff --git a/packages/auto_mappr_annotation/lib/src/map_type.dart b/packages/auto_mappr_annotation/lib/src/map_type.dart index f8c627c7..95d76420 100644 --- a/packages/auto_mappr_annotation/lib/src/map_type.dart +++ b/packages/auto_mappr_annotation/lib/src/map_type.dart @@ -25,11 +25,19 @@ class MapType<SOURCE, TARGET> { /// Ignores if [SOURCE]'s field is nullable and [TARGET]'s field non-nullable. final bool? ignoreFieldNull; + /// Includes reverse mapping. + /// + /// Warning: reverse warning might be suitable only for specific objects. + /// Reverse mapping might not work properly when additional configuration + /// such as [whenSourceIsNull] or [constructor] is used. + final bool reverse; + /// Constructs mapping between [SOURCE] and [TARGET] types. const MapType({ this.fields = const [], this.whenSourceIsNull, this.constructor, this.ignoreFieldNull, + this.reverse = false, }); } From 516c422a3d6dddbef58f0342566b41836c74855f Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 28 Aug 2023 14:57:35 +0200 Subject: [PATCH 04/48] Rework value assignment so it uses small builders --- .../assignments/assignment_builder_base.dart | 20 + .../src/builder/assignments/assignments.dart | 4 + .../iterable_assignment_builder.dart | 98 +++++ .../assignments/map_assignment_builder.dart | 158 +++++++ .../nested_object_assignment_builder.dart | 39 ++ .../assignments/nested_object_mixin.dart | 135 ++++++ .../src/builder/methods/callable_method.dart | 2 - .../src/builder/value_assignment_builder.dart | 393 ++---------------- .../lib/src/models/source_assignment.dart | 4 + packages/auto_mappr/pubspec.yaml | 2 +- packages/auto_mappr_annotation/pubspec.yaml | 2 +- pubspec.yaml | 2 +- 12 files changed, 501 insertions(+), 358 deletions(-) create mode 100644 packages/auto_mappr/lib/src/builder/assignments/assignment_builder_base.dart create mode 100644 packages/auto_mappr/lib/src/builder/assignments/assignments.dart create mode 100644 packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart create mode 100644 packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart create mode 100644 packages/auto_mappr/lib/src/builder/assignments/nested_object_assignment_builder.dart create mode 100644 packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart diff --git a/packages/auto_mappr/lib/src/builder/assignments/assignment_builder_base.dart b/packages/auto_mappr/lib/src/builder/assignments/assignment_builder_base.dart new file mode 100644 index 00000000..762398e2 --- /dev/null +++ b/packages/auto_mappr/lib/src/builder/assignments/assignment_builder_base.dart @@ -0,0 +1,20 @@ +import 'package:auto_mappr/src/models/models.dart'; +import 'package:code_builder/code_builder.dart'; + +abstract class AssignmentBuilderBase { + final SourceAssignment assignment; + final AutoMapprConfig mapperConfig; + final TypeMapping mapping; + final void Function(TypeMapping? mapping)? usedNullableMethodCallback; + + const AssignmentBuilderBase({ + required this.assignment, + required this.mapperConfig, + required this.mapping, + required this.usedNullableMethodCallback, + }); + + Expression buildAssignment(); + + bool canAssign(); +} diff --git a/packages/auto_mappr/lib/src/builder/assignments/assignments.dart b/packages/auto_mappr/lib/src/builder/assignments/assignments.dart new file mode 100644 index 00000000..1ad59974 --- /dev/null +++ b/packages/auto_mappr/lib/src/builder/assignments/assignments.dart @@ -0,0 +1,4 @@ +export 'assignment_builder_base.dart'; +export 'iterable_assignment_builder.dart'; +export 'map_assignment_builder.dart'; +export 'nested_object_assignment_builder.dart'; diff --git a/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart new file mode 100644 index 00000000..4cfd51ef --- /dev/null +++ b/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart @@ -0,0 +1,98 @@ +import 'package:analyzer/dart/element/nullability_suffix.dart'; +import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; +import 'package:auto_mappr/src/builder/assignments/nested_object_mixin.dart'; +import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:auto_mappr/src/extensions/expression_extension.dart'; +import 'package:auto_mappr/src/models/models.dart'; +import 'package:code_builder/code_builder.dart'; + +class IterableAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin { + const IterableAssignmentBuilder({ + required super.assignment, + required super.mapperConfig, + required super.mapping, + required super.usedNullableMethodCallback, + }); + + @override + bool canAssign() { + return assignment.shouldAssignIterable(); + } + + @override + Expression buildAssignment() { + final sourceType = assignment.sourceType!; + final targetType = assignment.targetType; + + final sourceNullable = sourceType.nullabilitySuffix == NullabilitySuffix.question; + final targetNullable = targetType.nullabilitySuffix == NullabilitySuffix.question; + + final sourceIterableType = sourceType.genericParameterTypeOrSelf; + final targetIterableType = targetType.genericParameterTypeOrSelf; + + final shouldFilterNullInSource = sourceIterableType.nullabilitySuffix == NullabilitySuffix.question && + targetIterableType.nullabilitySuffix != NullabilitySuffix.question; + + final assignNestedObject = (!targetIterableType.isPrimitiveType && !targetIterableType.isSpecializedListType) && + (!targetIterableType.isSame(sourceIterableType)); + + // When [sourceIterableType] is nullable and [targetIterableType] is not, remove null values. + final sourceIterableExpression = refer('model').property(assignment.sourceField!.name).maybeWhereIterableNotNull( + condition: shouldFilterNullInSource, + isOnNullable: sourceNullable, + ); + + final defaultIterableValueExpression = targetType.defaultIterableExpression(config: mapperConfig); + + if (assignNestedObject) { + return sourceIterableExpression + // Map complex nested types. + .maybeNullSafeProperty('map', isOnNullable: sourceNullable) + .call( + [_nestedMapCallForIterable(assignment)], + {}, + [ + refer( + targetIterableType.getDisplayStringWithLibraryAlias( + withNullability: true, + config: mapperConfig, + ), + ), + ], + ) + // Call toList, toSet or nothing. + // isOnNullable is false, because if map() was called, the value is non-null + .maybeToIterableCall( + source: sourceType, + target: targetType, + forceCast: true, //map was used so we want force toIterable() call + isOnNullable: false, + ) + // When [sourceNullable], use default value. + .maybeIfNullThen(defaultIterableValueExpression, isOnNullable: sourceNullable && !targetNullable); + } + + return sourceIterableExpression + .maybeToIterableCall( + source: sourceType, + target: targetType, + forceCast: shouldFilterNullInSource, // if whereNotNull was used -> we want to force toIterable() call + isOnNullable: !targetNullable && sourceNullable, + ) + .maybeIfNullThen( + defaultIterableValueExpression, + isOnNullable: !targetNullable && sourceNullable, + ); + } + + Expression _nestedMapCallForIterable(SourceAssignment assignment) { + final targetListType = assignment.targetType.genericParameterTypeOrSelf; + final sourceListType = assignment.sourceType!.genericParameterTypeOrSelf; + + return assignNestedObject( + assignment: assignment, + source: sourceListType, + target: targetListType, + ); + } +} diff --git a/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart new file mode 100644 index 00000000..7b32781e --- /dev/null +++ b/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart @@ -0,0 +1,158 @@ +import 'package:analyzer/dart/element/nullability_suffix.dart'; +import 'package:analyzer/dart/element/type.dart'; +import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; +import 'package:auto_mappr/src/builder/assignments/nested_object_mixin.dart'; +import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:auto_mappr/src/extensions/expression_extension.dart'; +import 'package:auto_mappr/src/models/models.dart'; +import 'package:code_builder/code_builder.dart'; +import 'package:collection/collection.dart'; +import 'package:source_gen/source_gen.dart'; + +class MapAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin { + const MapAssignmentBuilder({ + required super.assignment, + required super.mapperConfig, + required super.mapping, + required super.usedNullableMethodCallback, + }); + + @override + bool canAssign() { + return assignment.shouldAssignMap(); + } + + @override + Expression buildAssignment() { + final sourceType = assignment.sourceType!; + final targetType = assignment.targetType; + + final sourceNullable = sourceType.nullabilitySuffix == NullabilitySuffix.question; + + final sourceKeyType = (sourceType as ParameterizedType).typeArguments.firstOrNull; + final sourceValueType = sourceType.typeArguments.lastOrNull; + + final targetKeyType = (targetType as ParameterizedType).typeArguments.firstOrNull; + final targetValueType = targetType.typeArguments.lastOrNull; + + final sourceNullableKey = sourceKeyType?.nullabilitySuffix == NullabilitySuffix.question; + final sourceNullableValue = sourceValueType?.nullabilitySuffix == NullabilitySuffix.question; + final targetNullableKey = targetKeyType?.nullabilitySuffix == NullabilitySuffix.question; + final targetNullableValue = targetValueType?.nullabilitySuffix == NullabilitySuffix.question; + + if (targetKeyType == null || targetValueType == null) { + throw InvalidGenerationSourceError( + 'Target key or value type is null for ${targetType.getDisplayStringWithLibraryAlias(config: assignment.config)}', + ); + } + + if (sourceKeyType == null || sourceValueType == null) { + throw InvalidGenerationSourceError( + 'Source key or value type is null for ${sourceType.getDisplayStringWithLibraryAlias(config: assignment.config)}', + ); + } + + final keyMapping = mapperConfig.findMapping(source: sourceKeyType, target: targetKeyType); + final valueMapping = mapperConfig.findMapping(source: sourceValueType, target: targetValueType); + + // Keys: source is null, target is not null, and default value does not exist. + final shouldRemoveNullsKey = + sourceNullableKey && !targetNullableKey && (!(keyMapping?.hasWhenNullDefault() ?? false)); + + // Value: source is null, target is not null, and default value does not exist. + final shouldRemoveNullsValue = + sourceNullableValue && !targetNullableValue && (!(valueMapping?.hasWhenNullDefault() ?? false)); + + final sourceMapExpression = refer('model').property(assignment.sourceField!.name); + + final defaultMapValueExpression = literalMap( + {}, + refer(targetKeyType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), + refer(targetValueType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), + ); + + final assignNestedObjectKey = !targetKeyType.isPrimitiveType && (targetKeyType != sourceKeyType); + final assignNestedObjectValue = !targetValueType.isPrimitiveType && (targetValueType != sourceValueType); + + final shouldDoMapCall = assignNestedObjectKey || assignNestedObjectValue; + + return sourceMapExpression + // Filter nulls when source key/value is nullable and target is not. + .maybeWhereMapNotNull( + isOnNullable: sourceNullable, + keyIsNullable: shouldRemoveNullsKey, + valueIsNullable: shouldRemoveNullsValue, + keyType: sourceKeyType, + valueType: sourceValueType, + config: mapperConfig, + ) + .maybeCall( + 'map', + isOnNullable: sourceNullable, + // Call map only when actually some mapping is required. + condition: shouldDoMapCall, + positionalArguments: [_callMapForMap(assignment)], + typeArguments: [ + refer(targetKeyType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), + refer(targetValueType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), + ], + ) + // When [sourceNullable], use default value. + .maybeIfNullThen(defaultMapValueExpression, isOnNullable: sourceNullable); + } + + Expression _callMapForMap(SourceAssignment assignment) { + final sourceKeyType = (assignment.sourceType! as ParameterizedType).typeArguments.firstOrNull; + final sourceValueType = (assignment.sourceType! as ParameterizedType).typeArguments.lastOrNull; + final targetKeyType = (assignment.targetType as ParameterizedType).typeArguments.firstOrNull; + final targetValueType = (assignment.targetType as ParameterizedType).typeArguments.lastOrNull; + + if (targetKeyType == null || targetValueType == null) { + throw InvalidGenerationSourceError( + 'Target key or value type is null for ${assignment.targetType.getDisplayStringWithLibraryAlias(config: assignment.config)}', + ); + } + + if (sourceKeyType == null || sourceValueType == null) { + throw InvalidGenerationSourceError( + 'Source key or value type is null for ${assignment.sourceType?.getDisplayStringWithLibraryAlias(config: assignment.config)}', + ); + } + + final assignNestedObjectKey = !targetKeyType.isPrimitiveType && (targetKeyType != sourceKeyType); + final assignNestedObjectValue = !targetValueType.isPrimitiveType && (targetValueType != sourceValueType); + + final keysAreSameType = sourceKeyType == targetKeyType; + final valuesAreSameType = sourceValueType == targetValueType; + + // Returns a tear off when no nested call is needed. + if (!assignNestedObjectKey && !assignNestedObjectValue) { + return refer('MapEntry.new'); + } + + final sourceMapExpression = refer('key'); + final targetMapExpression = refer('value'); + + final keyExpression = assignNestedObjectKey + ? assignNestedObject( + assignment: assignment, + source: sourceKeyType, + target: targetKeyType, + convertMethodArgument: keysAreSameType ? null : sourceMapExpression, + ) + : sourceMapExpression; + + final valueExpression = assignNestedObjectValue + ? assignNestedObject( + assignment: assignment, + source: sourceValueType, + target: targetValueType, + convertMethodArgument: valuesAreSameType ? null : targetMapExpression, + ) + : targetMapExpression; + + return refer( + '(key, value) => MapEntry(${keyExpression.accept(DartEmitter())}, ${valueExpression.accept(DartEmitter())})', + ); + } +} diff --git a/packages/auto_mappr/lib/src/builder/assignments/nested_object_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/nested_object_assignment_builder.dart new file mode 100644 index 00000000..f2ac78fa --- /dev/null +++ b/packages/auto_mappr/lib/src/builder/assignments/nested_object_assignment_builder.dart @@ -0,0 +1,39 @@ +import 'package:analyzer/dart/element/type.dart'; +import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; +import 'package:auto_mappr/src/builder/assignments/nested_object_mixin.dart'; +import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:code_builder/code_builder.dart'; + +class NestedObjectAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin { + final DartType source; + final DartType target; + final Expression? convertMethodArgument; + final bool includeGenericTypes; + + const NestedObjectAssignmentBuilder({ + required super.assignment, + required super.mapperConfig, + required super.mapping, + required super.usedNullableMethodCallback, + required this.source, + required this.target, + this.convertMethodArgument, + this.includeGenericTypes = false, + }); + + @override + bool canAssign() { + return !assignment.targetType.isPrimitiveType; + } + + @override + Expression buildAssignment() { + return assignNestedObject( + source: source, + target: target, + assignment: assignment, + convertMethodArgument: convertMethodArgument, + includeGenericTypes: includeGenericTypes, + ); + } +} diff --git a/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart b/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart new file mode 100644 index 00000000..6a83a62d --- /dev/null +++ b/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart @@ -0,0 +1,135 @@ +import 'package:analyzer/dart/element/nullability_suffix.dart'; +import 'package:analyzer/dart/element/type.dart'; +import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; +import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; +import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:auto_mappr/src/models/models.dart'; +import 'package:build/build.dart'; +import 'package:code_builder/code_builder.dart'; +import 'package:source_gen/source_gen.dart'; + +/// Separate logic as a mixin so we do not soil [AssignmentBuilderBase]. +mixin NestedObjectMixin on AssignmentBuilderBase { + /// Assigns nested object as either: + /// - default value + /// - call to already generated mapping between two types + /// + /// If [convertMethodArgument] is null, uses a tear off call instead. + Expression assignNestedObject({ + required DartType source, + required DartType target, + required SourceAssignment assignment, + Expression? convertMethodArgument, + bool includeGenericTypes = false, + }) { + if (source.isSame(target)) { + return refer('model').property(assignment.sourceField!.displayName); + } + + final nestedMapping = mapperConfig.findMapping( + source: source, + target: target, + ); + + if (nestedMapping == null) { + final targetTypeName = target.getDisplayStringWithLibraryAlias( + withNullability: true, + config: mapperConfig, + ); + final sourceName = assignment.sourceField?.getDisplayString(withNullability: true); + + if (target.nullabilitySuffix == NullabilitySuffix.question) { + log.warning("Can't find nested mapping '$assignment' but target is nullable. Setting null"); + + return literalNull; + } + + throw InvalidGenerationSourceError( + 'Trying to map nested object from "$assignment" but no mapping is configured.', + todo: 'Configure mapping from $sourceName to $targetTypeName', + ); + } + + final convertCallExpression = mappingCall( + nestedMapping: nestedMapping, + source: source, + target: target, + convertMethodArgument: convertMethodArgument, + includeGenericTypes: includeGenericTypes, + ); + + // If source == null and target not nullable -> use whenNullDefault if possible + final fieldMapping = mapping.tryGetFieldMapping(assignment.targetName); + if (source.nullabilitySuffix == NullabilitySuffix.question && (fieldMapping?.whenNullExpression != null)) { + // Generates code like: + // + // model.name == null + // ? const Nested( + // id: 123, + // name: 'test', + // ) + // : _map_NestedDto_To_Nested(model.name), + return refer('model').property(assignment.sourceField!.displayName).equalTo(literalNull).conditional( + fieldMapping!.whenNullExpression!, + convertCallExpression, + ); + } + + // Generates code like: + // + // `_map_NestedDto_To_Nested(model.name)` + return convertCallExpression; + } + + /// Generates a mapping call `_mapAlphaDto_to_Alpha(convertMethodArgument)`. + /// When [convertMethodArgument] is null, then a tear off `_mapAlphaDto_to_Alpha` is generated. + /// + /// This function also marks nullable mapping to be generated + /// using the [usedNullableMethodCallback] callback. + Expression mappingCall({ + required DartType source, + required DartType target, + required TypeMapping nestedMapping, + Expression? convertMethodArgument, + bool includeGenericTypes = false, + }) { + final targetNullable = target.nullabilitySuffix == NullabilitySuffix.question; + + final useNullableMethod = targetNullable && !mapping.hasWhenNullDefault(); + + // When target is nullable, use nullable convert method. + // But use non-nullable when the mapping has default value. + // + // Otherwise use non-nullable. + final convertMethod = refer( + useNullableMethod + ? MethodBuilderBase.constructNullableConvertMethodName( + source: source, + target: target, + config: mapperConfig, + ) + : MethodBuilderBase.constructConvertMethodName( + source: source, + target: target, + config: mapperConfig, + ), + ); + + if (useNullableMethod) { + usedNullableMethodCallback?.call(nestedMapping); + } + + return convertMethodArgument == null + ? convertMethod + : convertMethod.call( + [convertMethodArgument], + {}, + includeGenericTypes + ? [ + refer(source.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), + refer(target.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), + ] + : [], + ); + } +} diff --git a/packages/auto_mappr/lib/src/builder/methods/callable_method.dart b/packages/auto_mappr/lib/src/builder/methods/callable_method.dart index c482064c..0d0fe1f1 100644 --- a/packages/auto_mappr/lib/src/builder/methods/callable_method.dart +++ b/packages/auto_mappr/lib/src/builder/methods/callable_method.dart @@ -5,6 +5,4 @@ abstract class CallableMethod { const CallableMethod(); Expression methodCall({Map<String, Expression> namedArguments = const {}}); - - } diff --git a/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart index ffba90d2..a456b949 100644 --- a/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart @@ -1,13 +1,9 @@ import 'package:analyzer/dart/element/nullability_suffix.dart'; -import 'package:analyzer/dart/element/type.dart'; -import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; -import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; -import 'package:auto_mappr/src/extensions/expression_extension.dart'; +import 'package:auto_mappr/src/builder/assignments/iterable_assignment_builder.dart'; +import 'package:auto_mappr/src/builder/assignments/map_assignment_builder.dart'; +import 'package:auto_mappr/src/builder/assignments/nested_object_assignment_builder.dart'; import 'package:auto_mappr/src/models/models.dart'; -import 'package:build/build.dart'; import 'package:code_builder/code_builder.dart'; -import 'package:collection/collection.dart'; -import 'package:source_gen/source_gen.dart'; class ValueAssignmentBuilder { final AutoMapprConfig mapperConfig; @@ -39,26 +35,49 @@ class ValueAssignmentBuilder { return fieldMapping.apply(assignment); } - final assignNestedObject = !assignment.targetType.isPrimitiveType; - - if (assignment.shouldAssignIterable()) { - return _assignIterableValue(assignment); - } - - if (assignment.shouldAssignMap()) { - return _assignMapValue(assignment); - } - final rightSide = refer(sourceField.isStatic ? '${sourceField.enclosingElement.name}' : 'model').property(sourceField.name); - if (assignNestedObject) { - return _assignNestedObject( + final assignmentBuilders = [ + // Iterable. + IterableAssignmentBuilder( + assignment: assignment, + mapperConfig: mapperConfig, + mapping: mapping, + usedNullableMethodCallback: usedNullableMethodCallback, + ), + // Map. + MapAssignmentBuilder( + assignment: assignment, + mapperConfig: mapperConfig, + mapping: mapping, + usedNullableMethodCallback: usedNullableMethodCallback, + ), + // TODO(record): Make records assignment + // Record. + // IterableAssignmentBuilder( + // assignment: assignment, + // mapperConfig: mapperConfig, + // mapping: mapping, + // usedNullableMethodCallback: usedNullableMethodCallback, + // ), + // Nested object. + NestedObjectAssignmentBuilder( + assignment: assignment, + mapperConfig: mapperConfig, + mapping: mapping, + usedNullableMethodCallback: usedNullableMethodCallback, source: assignment.sourceType!, target: assignment.targetType, - assignment: assignment, convertMethodArgument: rightSide, - ); + ), + ]; + + // Try to assign value using one of assignment builder. + for (final builder in assignmentBuilders) { + if (builder.canAssign()) { + return builder.buildAssignment(); + } } if (fieldMapping?.whenNullExpression != null) { @@ -82,336 +101,4 @@ class ValueAssignmentBuilder { return rightSide; } - - Expression _assignIterableValue(SourceAssignment assignment) { - final sourceType = assignment.sourceType!; - final targetType = assignment.targetType; - - final sourceNullable = sourceType.nullabilitySuffix == NullabilitySuffix.question; - final targetNullable = targetType.nullabilitySuffix == NullabilitySuffix.question; - - final sourceIterableType = sourceType.genericParameterTypeOrSelf; - final targetIterableType = targetType.genericParameterTypeOrSelf; - - final shouldFilterNullInSource = sourceIterableType.nullabilitySuffix == NullabilitySuffix.question && - targetIterableType.nullabilitySuffix != NullabilitySuffix.question; - - final assignNestedObject = (!targetIterableType.isPrimitiveType && !targetIterableType.isSpecializedListType) && - (!targetIterableType.isSame(sourceIterableType)); - - // When [sourceIterableType] is nullable and [targetIterableType] is not, remove null values. - final sourceIterableExpression = refer('model').property(assignment.sourceField!.name).maybeWhereIterableNotNull( - condition: shouldFilterNullInSource, - isOnNullable: sourceNullable, - ); - - final defaultIterableValueExpression = targetType.defaultIterableExpression(config: mapperConfig); - - if (assignNestedObject) { - return sourceIterableExpression - // Map complex nested types. - .maybeNullSafeProperty('map', isOnNullable: sourceNullable) - .call( - [_nestedMapCallForIterable(assignment)], - {}, - [ - refer( - targetIterableType.getDisplayStringWithLibraryAlias( - withNullability: true, - config: mapperConfig, - ), - ), - ], - ) - // Call toList, toSet or nothing. - // isOnNullable is false, because if map() was called, the value is non-null - .maybeToIterableCall( - source: sourceType, - target: targetType, - forceCast: true, //map was used so we want force toIterable() call - isOnNullable: false, - ) - // When [sourceNullable], use default value. - .maybeIfNullThen(defaultIterableValueExpression, isOnNullable: sourceNullable && !targetNullable); - } - - return sourceIterableExpression - .maybeToIterableCall( - source: sourceType, - target: targetType, - forceCast: shouldFilterNullInSource, // if whereNotNull was used -> we want to force toIterable() call - isOnNullable: !targetNullable && sourceNullable, - ) - .maybeIfNullThen( - defaultIterableValueExpression, - isOnNullable: !targetNullable && sourceNullable, - ); - } - - Expression _assignMapValue(SourceAssignment assignment) { - final sourceType = assignment.sourceType!; - final targetType = assignment.targetType; - - final sourceNullable = sourceType.nullabilitySuffix == NullabilitySuffix.question; - - final sourceKeyType = (sourceType as ParameterizedType).typeArguments.firstOrNull; - final sourceValueType = sourceType.typeArguments.lastOrNull; - - final targetKeyType = (targetType as ParameterizedType).typeArguments.firstOrNull; - final targetValueType = targetType.typeArguments.lastOrNull; - - final sourceNullableKey = sourceKeyType?.nullabilitySuffix == NullabilitySuffix.question; - final sourceNullableValue = sourceValueType?.nullabilitySuffix == NullabilitySuffix.question; - final targetNullableKey = targetKeyType?.nullabilitySuffix == NullabilitySuffix.question; - final targetNullableValue = targetValueType?.nullabilitySuffix == NullabilitySuffix.question; - - if (targetKeyType == null || targetValueType == null) { - throw InvalidGenerationSourceError( - 'Target key or value type is null for ${targetType.getDisplayStringWithLibraryAlias(config: assignment.config)}', - ); - } - - if (sourceKeyType == null || sourceValueType == null) { - throw InvalidGenerationSourceError( - 'Source key or value type is null for ${sourceType.getDisplayStringWithLibraryAlias(config: assignment.config)}', - ); - } - - final keyMapping = mapperConfig.findMapping(source: sourceKeyType, target: targetKeyType); - final valueMapping = mapperConfig.findMapping(source: sourceValueType, target: targetValueType); - - // Keys: source is null, target is not null, and default value does not exist. - final shouldRemoveNullsKey = - sourceNullableKey && !targetNullableKey && (!(keyMapping?.hasWhenNullDefault() ?? false)); - - // Value: source is null, target is not null, and default value does not exist. - final shouldRemoveNullsValue = - sourceNullableValue && !targetNullableValue && (!(valueMapping?.hasWhenNullDefault() ?? false)); - - final sourceMapExpression = refer('model').property(assignment.sourceField!.name); - - final defaultMapValueExpression = literalMap( - {}, - refer(targetKeyType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), - refer(targetValueType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), - ); - - final assignNestedObjectKey = !targetKeyType.isPrimitiveType && (targetKeyType != sourceKeyType); - final assignNestedObjectValue = !targetValueType.isPrimitiveType && (targetValueType != sourceValueType); - - final shouldDoMapCall = assignNestedObjectKey || assignNestedObjectValue; - - return sourceMapExpression - // Filter nulls when source key/value is nullable and target is not. - .maybeWhereMapNotNull( - isOnNullable: sourceNullable, - keyIsNullable: shouldRemoveNullsKey, - valueIsNullable: shouldRemoveNullsValue, - keyType: sourceKeyType, - valueType: sourceValueType, - config: mapperConfig, - ) - .maybeCall( - 'map', - isOnNullable: sourceNullable, - // Call map only when actually some mapping is required. - condition: shouldDoMapCall, - positionalArguments: [_callMapForMap(assignment)], - typeArguments: [ - refer(targetKeyType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), - refer(targetValueType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), - ], - ) - // When [sourceNullable], use default value. - .maybeIfNullThen(defaultMapValueExpression, isOnNullable: sourceNullable); - } - - /// Assigns nested object as either: - /// - default value - /// - call to already generated mapping between two types - /// - /// If [convertMethodArgument] is null, uses a tear off call instead. - Expression _assignNestedObject({ - required DartType source, - required DartType target, - required SourceAssignment assignment, - Expression? convertMethodArgument, - bool includeGenericTypes = false, - }) { - if (source.isSame(target)) { - return refer('model').property(assignment.sourceField!.displayName); - } - - final nestedMapping = mapperConfig.findMapping( - source: source, - target: target, - ); - - if (nestedMapping == null) { - final targetTypeName = target.getDisplayStringWithLibraryAlias( - withNullability: true, - config: mapperConfig, - ); - final sourceName = assignment.sourceField?.getDisplayString(withNullability: true); - - if (target.nullabilitySuffix == NullabilitySuffix.question) { - log.warning("Can't find nested mapping '$assignment' but target is nullable. Setting null"); - - return literalNull; - } - - throw InvalidGenerationSourceError( - 'Trying to map nested object from "$assignment" but no mapping is configured.', - todo: 'Configure mapping from $sourceName to $targetTypeName', - ); - } - - final convertCallExpression = _mappingCall( - nestedMapping: nestedMapping, - source: source, - target: target, - convertMethodArgument: convertMethodArgument, - includeGenericTypes: includeGenericTypes, - ); - - // If source == null and target not nullable -> use whenNullDefault if possible - final fieldMapping = mapping.tryGetFieldMapping(assignment.targetName); - if (source.nullabilitySuffix == NullabilitySuffix.question && (fieldMapping?.whenNullExpression != null)) { - // Generates code like: - // - // model.name == null - // ? const Nested( - // id: 123, - // name: 'test', - // ) - // : _map_NestedDto_To_Nested(model.name), - return refer('model').property(assignment.sourceField!.displayName).equalTo(literalNull).conditional( - fieldMapping!.whenNullExpression!, - convertCallExpression, - ); - } - - // Generates code like: - // - // `_map_NestedDto_To_Nested(model.name)` - return convertCallExpression; - } - - /// Generates a mapping call `_mapAlphaDto_to_Alpha(convertMethodArgument)`. - /// When [convertMethodArgument] is null, then a tear off `_mapAlphaDto_to_Alpha` is generated. - /// - /// This function also marks nullable mapping to be generated - /// using the [usedNullableMethodCallback] callback. - Expression _mappingCall({ - required DartType source, - required DartType target, - required TypeMapping nestedMapping, - Expression? convertMethodArgument, - bool includeGenericTypes = false, - }) { - final targetNullable = target.nullabilitySuffix == NullabilitySuffix.question; - - final useNullableMethod = targetNullable && !mapping.hasWhenNullDefault(); - - // When target is nullable, use nullable convert method. - // But use non-nullable when the mapping has default value. - // - // Otherwise use non-nullable. - final convertMethod = refer( - useNullableMethod - ? MethodBuilderBase.constructNullableConvertMethodName( - source: source, - target: target, - config: mapperConfig, - ) - : MethodBuilderBase.constructConvertMethodName( - source: source, - target: target, - config: mapperConfig, - ), - ); - - if (useNullableMethod) { - usedNullableMethodCallback?.call(nestedMapping); - } - - return convertMethodArgument == null - ? convertMethod - : convertMethod.call( - [convertMethodArgument], - {}, - includeGenericTypes - ? [ - refer(source.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), - refer(target.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), - ] - : [], - ); - } - - Expression _nestedMapCallForIterable(SourceAssignment assignment) { - final targetListType = assignment.targetType.genericParameterTypeOrSelf; - final sourceListType = assignment.sourceType!.genericParameterTypeOrSelf; - - return _assignNestedObject( - assignment: assignment, - source: sourceListType, - target: targetListType, - ); - } - - Expression _callMapForMap(SourceAssignment assignment) { - final sourceKeyType = (assignment.sourceType! as ParameterizedType).typeArguments.firstOrNull; - final sourceValueType = (assignment.sourceType! as ParameterizedType).typeArguments.lastOrNull; - final targetKeyType = (assignment.targetType as ParameterizedType).typeArguments.firstOrNull; - final targetValueType = (assignment.targetType as ParameterizedType).typeArguments.lastOrNull; - - if (targetKeyType == null || targetValueType == null) { - throw InvalidGenerationSourceError( - 'Target key or value type is null for ${assignment.targetType.getDisplayStringWithLibraryAlias(config: assignment.config)}', - ); - } - - if (sourceKeyType == null || sourceValueType == null) { - throw InvalidGenerationSourceError( - 'Source key or value type is null for ${assignment.sourceType?.getDisplayStringWithLibraryAlias(config: assignment.config)}', - ); - } - - final assignNestedObjectKey = !targetKeyType.isPrimitiveType && (targetKeyType != sourceKeyType); - final assignNestedObjectValue = !targetValueType.isPrimitiveType && (targetValueType != sourceValueType); - - final keysAreSameType = sourceKeyType == targetKeyType; - final valuesAreSameType = sourceValueType == targetValueType; - - // Returns a tear off when no nested call is needed. - if (!assignNestedObjectKey && !assignNestedObjectValue) { - return refer('MapEntry.new'); - } - - final sourceMapExpression = refer('key'); - final targetMapExpression = refer('value'); - - final keyExpression = assignNestedObjectKey - ? _assignNestedObject( - assignment: assignment, - source: sourceKeyType, - target: targetKeyType, - convertMethodArgument: keysAreSameType ? null : sourceMapExpression, - ) - : sourceMapExpression; - - final valueExpression = assignNestedObjectValue - ? _assignNestedObject( - assignment: assignment, - source: sourceValueType, - target: targetValueType, - convertMethodArgument: valuesAreSameType ? null : targetMapExpression, - ) - : targetMapExpression; - - return refer( - '(key, value) => MapEntry(${keyExpression.accept(DartEmitter())}, ${valueExpression.accept(DartEmitter())})', - ); - } } diff --git a/packages/auto_mappr/lib/src/models/source_assignment.dart b/packages/auto_mappr/lib/src/models/source_assignment.dart index 8e12e118..e0357c54 100644 --- a/packages/auto_mappr/lib/src/models/source_assignment.dart +++ b/packages/auto_mappr/lib/src/models/source_assignment.dart @@ -62,6 +62,10 @@ class SourceAssignment { return targetType.isDartCoreMap && _isMappableMap(sourceType!); } + bool shouldAssignRecord() { + return targetType.isDartCoreRecord && sourceType!.isDartCoreRecord; + } + bool shouldAssignComplexObject() => !targetType.isPrimitiveType; @override diff --git a/packages/auto_mappr/pubspec.yaml b/packages/auto_mappr/pubspec.yaml index d02e2840..16041bce 100644 --- a/packages/auto_mappr/pubspec.yaml +++ b/packages/auto_mappr/pubspec.yaml @@ -8,7 +8,7 @@ screenshots: path: doc/icon.png environment: - sdk: ">=2.18.7 <4.0.0" + sdk: ^3.0.0 dependencies: # TODO: Support analyzer same way as json_serializable https://github.com/google/json_serializable.dart/pull/1333 diff --git a/packages/auto_mappr_annotation/pubspec.yaml b/packages/auto_mappr_annotation/pubspec.yaml index 8e1b4a7c..13b63e20 100644 --- a/packages/auto_mappr_annotation/pubspec.yaml +++ b/packages/auto_mappr_annotation/pubspec.yaml @@ -5,7 +5,7 @@ repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues environment: - sdk: ">=2.18.7 <4.0.0" + sdk: ^3.0.0 dev_dependencies: netglade_analysis: ^4.0.0 diff --git a/pubspec.yaml b/pubspec.yaml index d3eabbd2..b51f93a2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: auto_mappr_workspace publish_to: "none" environment: - sdk: ">=2.18.0 <4.0.0" + sdk: ^3.0.0 dev_dependencies: melos: ^3.0.0 From f969355b589b31984b41ab33efefb66dcb730e33 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Tue, 29 Aug 2023 12:44:35 +0200 Subject: [PATCH 05/48] Init Dart 3 records support --- melos.yaml | 6 +- packages/auto_mappr/build.yaml | 2 + packages/auto_mappr/example/lib/mappr.g.dart | 216 ----------- .../src/builder/assignments/assignments.dart | 1 + .../iterable_assignment_builder.dart | 2 +- .../assignments/map_assignment_builder.dart | 2 +- .../record_assignment_builder.dart | 130 +++++++ .../lib/src/builder/auto_mappr_builder.dart | 1 + .../map_bodies/class_body_builder.dart | 354 ++++++++++++++++++ .../enum_body_builder.dart} | 21 +- .../src/builder/map_bodies/map_bodies.dart | 2 + .../map_bodies/map_body_builder_base.dart | 22 ++ .../map_model_body_method_builder.dart | 342 +---------------- .../src/builder/value_assignment_builder.dart | 18 +- .../src/extensions/dart_type_extension.dart | 9 +- .../lib/src/models/source_assignment.dart | 8 +- packages/auto_mappr/pubspec.yaml | 2 +- .../test/integration/fixture/record.dart | 136 +++++++ .../test/integration/record_test.dart | 33 ++ 19 files changed, 735 insertions(+), 572 deletions(-) delete mode 100644 packages/auto_mappr/example/lib/mappr.g.dart create mode 100644 packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart create mode 100644 packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart rename packages/auto_mappr/lib/src/builder/{enum_assignment_builder.dart => map_bodies/enum_body_builder.dart} (85%) create mode 100644 packages/auto_mappr/lib/src/builder/map_bodies/map_bodies.dart create mode 100644 packages/auto_mappr/lib/src/builder/map_bodies/map_body_builder_base.dart create mode 100644 packages/auto_mappr/test/integration/fixture/record.dart create mode 100644 packages/auto_mappr/test/integration/record_test.dart diff --git a/melos.yaml b/melos.yaml index 0627e6ff..5dc207ae 100644 --- a/melos.yaml +++ b/melos.yaml @@ -1,9 +1,9 @@ name: auto_mappr_workspace packages: - - packages/** - - packages/**/example - - examples/** + - packages/* + - packages/*/example + # - examples/* # TODO command: bootstrap: diff --git a/packages/auto_mappr/build.yaml b/packages/auto_mappr/build.yaml index 905672fe..d7065af6 100644 --- a/packages/auto_mappr/build.yaml +++ b/packages/auto_mappr/build.yaml @@ -4,6 +4,8 @@ targets: :auto_mappr: enabled: true generate_for: + include: # TODO + - test/integration/fixture/record.dart exclude: - test/integration/error_fixture/** options: diff --git a/packages/auto_mappr/example/lib/mappr.g.dart b/packages/auto_mappr/example/lib/mappr.g.dart deleted file mode 100644 index 596834af..00000000 --- a/packages/auto_mappr/example/lib/mappr.g.dart +++ /dev/null @@ -1,216 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'mappr.dart'; - -// ************************************************************************** -// AutoMapprGenerator -// ************************************************************************** - -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings - -/// {@template asset:auto_mappr/example/lib/mappr.dart} -/// Available mappings: -/// - `UserDto` → `User`. -/// {@endtemplate} -class $Mappr implements AutoMapprInterface { - const $Mappr(); - - Type _typeOf<T>() => T; - List<AutoMapprInterface> get _modules => const []; - - /// {@macro AutoMapprInterface:canConvert} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - bool canConvert<SOURCE, TARGET>({bool recursive = true}) { - final sourceTypeOf = _typeOf<SOURCE>(); - final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { - return true; - } - if (recursive) { - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return true; - } - } - } - return false; - } - - /// {@macro AutoMapprInterface:convert} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - TARGET convert<SOURCE, TARGET>(SOURCE? model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return _convert(model)!; - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.convert(model)!; - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// {@macro AutoMapprInterface:tryConvert} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - TARGET? tryConvert<SOURCE, TARGET>(SOURCE? model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return _convert( - model, - canReturnNull: true, - ); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.tryConvert(model); - } - } - - return null; - } - - /// {@macro AutoMapprInterface:convertIterable} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - Iterable<TARGET> convertIterable<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return model.map<TARGET>((item) => _convert(item)!); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.convertIterable(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into Iterable. - /// - /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null - /// - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - Iterable<TARGET?> tryConvertIterable<SOURCE, TARGET>( - Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.tryConvertIterable(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// {@macro AutoMapprInterface:convertList} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - List<TARGET> convertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return convertIterable<SOURCE, TARGET>(model).toList(); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.convertList(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into List. - /// - /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null - /// - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - List<TARGET?> tryConvertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return tryConvertIterable<SOURCE, TARGET>(model).toList(); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.tryConvertList(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// {@macro AutoMapprInterface:convertSet} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - Set<TARGET> convertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return convertIterable<SOURCE, TARGET>(model).toSet(); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.convertSet(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into Set. - /// - /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null - /// - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - Set<TARGET?> tryConvertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return tryConvertIterable<SOURCE, TARGET>(model).toSet(); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.tryConvertSet(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - TARGET? _convert<SOURCE, TARGET>( - SOURCE? model, { - bool canReturnNull = false, - }) { - final sourceTypeOf = _typeOf<SOURCE>(); - final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { - if (canReturnNull && model == null) { - return null; - } - return (_map__UserDto__To__User((model as UserDto?)) as TARGET); - } - throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); - } - - User _map__UserDto__To__User(UserDto? input) { - final model = input; - if (model == null) { - throw Exception( - r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' - r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); - } - return User( - id: model.id, - name: model.xname, - ); - } -} diff --git a/packages/auto_mappr/lib/src/builder/assignments/assignments.dart b/packages/auto_mappr/lib/src/builder/assignments/assignments.dart index 1ad59974..5df7a1c5 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/assignments.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/assignments.dart @@ -2,3 +2,4 @@ export 'assignment_builder_base.dart'; export 'iterable_assignment_builder.dart'; export 'map_assignment_builder.dart'; export 'nested_object_assignment_builder.dart'; +export 'record_assignment_builder.dart'; diff --git a/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart index 4cfd51ef..fd01567b 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart @@ -16,7 +16,7 @@ class IterableAssignmentBuilder extends AssignmentBuilderBase with NestedObjectM @override bool canAssign() { - return assignment.shouldAssignIterable(); + return assignment.canAssignIterable(); } @override diff --git a/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart index 7b32781e..aaa0a492 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart @@ -19,7 +19,7 @@ class MapAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin @override bool canAssign() { - return assignment.shouldAssignMap(); + return assignment.canAssignMap(); } @override diff --git a/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart new file mode 100644 index 00000000..88d03437 --- /dev/null +++ b/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart @@ -0,0 +1,130 @@ +import 'package:analyzer/dart/element/nullability_suffix.dart'; +import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; +import 'package:auto_mappr/src/builder/assignments/nested_object_mixin.dart'; +import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:build/build.dart'; +import 'package:code_builder/code_builder.dart'; +import 'package:source_gen/source_gen.dart'; + +class RecordAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin { + const RecordAssignmentBuilder({ + required super.assignment, + required super.mapperConfig, + required super.mapping, + required super.usedNullableMethodCallback, + }); + + @override + bool canAssign() { + log.warning( + 'RECORD ASSIGNMENT CHECK ${assignment.targetType is RecordType} ... ${assignment.sourceType is RecordType} /// $assignment'); + return assignment.canAssignRecord(); + } + + @override + Expression buildAssignment() { + log.warning('RECORD ASSIGNMENT'); + final sourceType = assignment.sourceType!; + final targetType = assignment.targetType; + + // final sourceNullable = sourceType.nullabilitySuffix == NullabilitySuffix.question; + // final targetNullable = targetType.nullabilitySuffix == NullabilitySuffix.question; + + // ignore: avoid-unrelated-type-casts, it's ok and handled by canAssign + final sourceRecordType = sourceType as RecordType; + // ignore: avoid-unrelated-type-casts, it's ok and handled by canAssign + final targetRecordType = targetType as RecordType; + + // Positional fields check. + final sourcePositional = sourceRecordType.positionalFieldTypes; + final targetPositional = targetRecordType.positionalFieldTypes; + if (sourcePositional.length != targetPositional.length) { + throw InvalidGenerationSourceError( + 'Positional source and target fields length mismatch for source ${sourceType} and target ${targetType}', + ); + } + + // Named fields check. + final sourceNamed = sourceRecordType.namedFieldTypes; + final targetNamed = targetRecordType.namedFieldTypes; + for (final field in targetNamed.entries) { + print('!!! ${field.key} = ${field.value}'); + } + + // NAMED - check target has all source's named, if target is nullable it might not + + // --- ASSIGN MAP --- + + // -- RETURN -- + + // TODO(records): return positional and named as code + return const CodeExpression(Code('(1, 2, 3, alpha: 4, beta: 5)')); + + // ---------------- + + // final shouldFilterNullInSource = sourceRecordType.nullabilitySuffix == NullabilitySuffix.question && + // targetRecordType.nullabilitySuffix != NullabilitySuffix.question; + + // final assignNestedObject = (!targetRecordType.isPrimitiveType && !targetRecordType.isSpecializedListType) && + // (!targetRecordType.isSame(sourceRecordType)); + + // // When [sourceIterableType] is nullable and [targetIterableType] is not, remove null values. + // final sourceIterableExpression = refer('model').property(assignment.sourceField!.name).maybeWhereIterableNotNull( + // condition: shouldFilterNullInSource, + // isOnNullable: sourceNullable, + // ); + + // final defaultIterableValueExpression = targetType.defaultIterableExpression(config: mapperConfig); + + // if (assignNestedObject) { + // return sourceIterableExpression + // // Map complex nested types. + // .maybeNullSafeProperty('map', isOnNullable: sourceNullable) + // .call( + // [_nestedMapCallForIterable(assignment)], + // {}, + // [ + // refer( + // targetRecordType.getDisplayStringWithLibraryAlias( + // withNullability: true, + // config: mapperConfig, + // ), + // ), + // ], + // ) + // // Call toList, toSet or nothing. + // // isOnNullable is false, because if map() was called, the value is non-null + // .maybeToIterableCall( + // source: sourceType, + // target: targetType, + // forceCast: true, //map was used so we want force toIterable() call + // isOnNullable: false, + // ) + // // When [sourceNullable], use default value. + // .maybeIfNullThen(defaultIterableValueExpression, isOnNullable: sourceNullable && !targetNullable); + // } + + // return sourceIterableExpression + // .maybeToIterableCall( + // source: sourceType, + // target: targetType, + // forceCast: shouldFilterNullInSource, // if whereNotNull was used -> we want to force toIterable() call + // isOnNullable: !targetNullable && sourceNullable, + // ) + // .maybeIfNullThen( + // defaultIterableValueExpression, + // isOnNullable: !targetNullable && sourceNullable, + // ); + } + + // Expression _nestedMapCallForIterable(SourceAssignment assignment) { + // final targetListType = assignment.targetType.genericParameterTypeOrSelf; + // final sourceListType = assignment.sourceType!.genericParameterTypeOrSelf; + + // return assignNestedObject( + // assignment: assignment, + // source: sourceListType, + // target: targetListType, + // ); + // } +} diff --git a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart index 3f076c92..56708c05 100644 --- a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart +++ b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart @@ -9,6 +9,7 @@ import 'package:auto_mappr/src/models/type_mapping.dart'; import 'package:built_collection/built_collection.dart'; import 'package:code_builder/code_builder.dart'; +/// Entrypoint for mappr class generation. class AutoMapprBuilder { final AutoMapprConfig config; final ClassElement mapperClassElement; diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart new file mode 100644 index 00000000..d7c122ec --- /dev/null +++ b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart @@ -0,0 +1,354 @@ +import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/nullability_suffix.dart'; +import 'package:analyzer/dart/element/type.dart'; +import 'package:auto_mappr/src/builder/map_bodies/map_body_builder_base.dart'; +import 'package:auto_mappr/src/builder/value_assignment_builder.dart'; +import 'package:auto_mappr/src/extensions/element_extension.dart'; +import 'package:auto_mappr/src/extensions/interface_type_extension.dart'; +import 'package:auto_mappr/src/models/source_assignment.dart'; +import 'package:build/build.dart'; +import 'package:code_builder/code_builder.dart'; +import 'package:collection/collection.dart'; +import 'package:source_gen/source_gen.dart'; + +class ClassBodyBuilder extends MapBodyBuilderBase { + const ClassBodyBuilder({ + required super.mapperConfig, + required super.mapping, + required super.nullable, + required super.usedNullableMethodCallback, + }); + + @override + Code build() { + final sourceFields = _getAllReadableFields(classType: mapping.source); + + // Name of the source field names which can be mapped into constructor field + final mappedSourceFieldNames = <String>[]; + + // Map fields using a constructor. + // Returns an constructor call without `;`. + // + // One( + // usingConstructor1: model.usingConstructor1, + // usingConstructor2: model.usingConstructor2, + // ) + final constructorExpression = _processConstructorMapping( + mappedSourceFieldNames: mappedSourceFieldNames, + sourceFields: sourceFields, + ); + + // Map fields not mapped directly in constructor as setters if possible. + // + // Code like: + // + // <constructorExpression> + // ..withoutConstructor1 = model.withoutConstructor1 + // ..withoutConstructor2 = model.withoutConstructor2 + // ..withoutConstructor3 = model.withoutConstructor3 + final constructorWithSetters = _mapSetterFields( + alreadyMapped: mappedSourceFieldNames, + sourceFields: sourceFields, + constructorExpression: constructorExpression, + ); + + return constructorWithSetters.returned.statement; + } + + @override + bool canProcess() { + return !mapping.isEnumMapping; + } + + /// Returns all public fields (instance or static) that have a getter. + Map<String, PropertyAccessorElement> _getAllReadableFields({ + required InterfaceType classType, + }) { + final fieldsWithGetter = classType.getAllGetters(); + + return {for (final field in fieldsWithGetter) field.name: field}; + } + + Expression _processConstructorMapping({ + required List<String> mappedSourceFieldNames, + required Map<String, PropertyAccessorElement> sourceFields, + }) { + final mappedTargetConstructorParams = <SourceAssignment>[]; + final notMappedTargetParameters = <SourceAssignment>[]; + + final targetConstructor = _findBestConstructor(mapping.target, forcedConstructor: mapping.constructor); + + if (targetConstructor == null) { + throw InvalidGenerationSourceError( + 'There is no target constructor in ${mapping.target}', + ); + } + + final targetClassGetters = (mapping.target).getAllGetters(); + + // Map constructor parameters + for (var i = 0; i < targetConstructor.parameters.length; i++) { + final param = targetConstructor.parameters.elementAtOrNull(i); + + if (param == null) continue; + +// TODO +// log.warning(''' +// PARAM $param +// type.getDisplayString: ${param.type.getDisplayString(withNullability: true)} +// type.isDartCoreRecord: ${param.type.isDartCoreRecord} +// type.name: ${param.type.name} +// type.element.name: ${param.type.element?.name} +// type.element.library.isDartCore: ${param.type.element?.library?.isDartCore} +// type.element.library: ${param.type.element?.library} +// ////// +// '''); + + final paramPosition = param.isPositional ? i : null; + final constructorAssignment = ConstructorAssignment(param: param, position: paramPosition); + + final fieldMapping = mapping.tryGetFieldMapping(param.name); + + // Handles renaming. + final from = fieldMapping?.from; + final sourceFieldName = from ?? param.name; + + // Custom mapping has precedence. + if (fieldMapping?.hasCustomMapping() ?? false) { + final targetField = + targetClassGetters.firstWhereOrNull((targetField) => targetField.displayName == fieldMapping?.field); + + if (targetField == null) continue; + + if (mapping.fieldShouldBeIgnored(targetField.displayName)) { + _assertParamFieldCanBeIgnored(param, targetField); + } + + final sourceAssignment = SourceAssignment( + sourceField: null, + targetField: targetField, + targetConstructorParam: constructorAssignment, + fieldMapping: mapping.tryGetFieldMapping(targetField.displayName), + typeMapping: mapping, + config: mapperConfig, + ); + + mappedTargetConstructorParams.add(sourceAssignment); + mappedSourceFieldNames.add(param.name); + } + // Source field has the same name as target parameter or is renamed using [from]. + else if (sourceFields.containsKey(sourceFieldName)) { + final sourceField = sourceFields[sourceFieldName]!; + + final targetField = from == null + // find target field based on matching source field + ? targetClassGetters.firstWhereOrNull((field) => field.displayName == sourceField.displayName) + // support custom field rename mapping + : targetClassGetters.firstWhereOrNull((field) => field.displayName == fieldMapping?.field); + + if (targetField == null) continue; + + if (mapping.fieldShouldBeIgnored(targetField.displayName)) { + _assertParamFieldCanBeIgnored(param, sourceField); + } + + final sourceAssignment = SourceAssignment( + sourceField: sourceFields[sourceFieldName], + targetField: targetField, + targetConstructorParam: constructorAssignment, + fieldMapping: mapping.tryGetFieldMapping(targetField.displayName), + typeMapping: mapping, + config: mapperConfig, + ); + + mappedTargetConstructorParams.add(sourceAssignment); + mappedSourceFieldNames.add(param.name); + } else { + // If not mapped constructor param is optional - skip it + if (param.isOptional) continue; + + final targetField = + (mapping.target).getAllGetters().firstWhereOrNull((field) => field.displayName == param.displayName); + + final fieldMapping = mapping.tryGetFieldMapping(param.displayName); + + if (targetField == null && fieldMapping == null) { + throw InvalidGenerationSourceError( + "Can't find mapping for target's constructor parameter: ${param.displayName}. Parameter is required and no mapping or target's class field not found", + ); + } + + notMappedTargetParameters.add( + SourceAssignment( + sourceField: null, + targetField: targetField, + fieldMapping: fieldMapping, + targetConstructorParam: constructorAssignment, + typeMapping: mapping, + config: mapperConfig, + ), + ); + } + } + + _assertNotMappedConstructorParameters(notMappedTargetParameters.map((e) => e.targetConstructorParam!.param)); + + // Prepare and merge mapped and notMapped parameters into Positional and Named arrays + final mappedPositionalParameters = + mappedTargetConstructorParams.where((x) => x.targetConstructorParam?.position != null); + final notMappedPositionalParameters = + notMappedTargetParameters.where((x) => x.targetConstructorParam?.position != null); + + final positionalParameters = <SourceAssignment>[...mappedPositionalParameters, ...notMappedPositionalParameters] + ..sortByCompare((x) => x.targetConstructorParam!.position!, (a, b) => a - b); + + final namedParameters = <SourceAssignment>[ + ...mappedTargetConstructorParams.where((x) => x.targetConstructorParam?.isNamed ?? false), + ...notMappedTargetParameters.where((element) => element.targetConstructorParam?.isNamed ?? false), + ]; + + // Mapped fields into constructor - positional and named + return _mapConstructor( + targetConstructor, + positional: positionalParameters, + named: namedParameters, + ); + } + + void _assertParamFieldCanBeIgnored(ParameterElement param, PropertyAccessorElement sourceField) { + final sourceFieldName = sourceField.getDisplayString(withNullability: true); + if (param.isPositional && param.type.nullabilitySuffix != NullabilitySuffix.question) { + throw InvalidGenerationSourceError( + "Can't ignore field '$sourceFieldName' as it is positional not-nullable parameter", + ); + } + + if (param.isRequiredNamed && param.type.nullabilitySuffix != NullabilitySuffix.question) { + throw InvalidGenerationSourceError( + "Can't ignore field '$sourceFieldName' as it is required named not-nullable parameter", + ); + } + } + + Expression _mapSetterFields({ + required List<String> alreadyMapped, + required Map<String, PropertyAccessorElement> sourceFields, + required Expression constructorExpression, + }) { + final targetSetters = mapping.target.getAllSetters(); + + final potentialSetterFields = sourceFields.keys.where((field) => !alreadyMapped.contains(field)).toList(); + final fields = potentialSetterFields + .map((key) => sourceFields[key]) + .whereNotNull() + // Use only those that match. + .where((accessor) => targetSetters.any((targetAccessor) => targetAccessor.displayName == accessor.displayName)) + // Skip ignored fields. + .where((accessor) => !mapping.fieldShouldBeIgnored(accessor.displayName)) + .toList(); + + if (fields.isEmpty) { + return constructorExpression; + } + + final targetClassGetters = mapping.target.getAllGetters(); + + var cascadedAssignments = constructorExpression; + for (final sourceField in fields) { + final targetField = targetClassGetters.firstWhereOrNull((field) => field.displayName == sourceField.displayName); + + if (targetField == null) continue; + + // Assign result.X = model.X + cascadedAssignments = cascadedAssignments.cascade(sourceField.displayName).assign( + ValueAssignmentBuilder( + mapperConfig: mapperConfig, + mapping: mapping, + assignment: SourceAssignment( + sourceField: sourceField, + targetField: targetField, + typeMapping: mapping, + config: mapperConfig, + ), + usedNullableMethodCallback: usedNullableMethodCallback, + ).build(), + ); + } + + return cascadedAssignments; + } + + /// Tries to find best constructor for mapping. + /// + /// Returns a constructor with the most parameter count. + /// Prefer non factory constructors over factory ones. + ConstructorElement? _findBestConstructor(InterfaceType classType, {String? forcedConstructor}) { + if (forcedConstructor != null) { + final selectedConstructor = classType.constructors.firstWhereOrNull((c) => c.name == forcedConstructor); + if (selectedConstructor != null) return selectedConstructor; + + log.warning( + "Couldn't find constructor '$forcedConstructor', fall-backing to using the most fitted one instead.", + ); + } + + final allConstructors = classType.constructors.where((c) => !c.isPrivate); + + // Sort constructors by number of parameters, descending. + int sortConstructors(ConstructorElement a, ConstructorElement b) => + -a.parameters.length.compareTo(b.parameters.length); + + final nonFactoryConstructors = allConstructors.where((c) => !c.isFactory).sorted(sortConstructors); + final factoryConstructors = + allConstructors.where((c) => c.isFactory && c.name != 'fromJson').sorted(sortConstructors); + + // Prefers non factory constructors over factory ones. + return [...nonFactoryConstructors, ...factoryConstructors].firstOrNull; + } + + Expression _mapConstructor( + ConstructorElement targetConstructor, { + required List<SourceAssignment> positional, + required List<SourceAssignment> named, + }) { + final alias = targetConstructor.enclosingElement.getLibraryAlias(config: mapperConfig); + final constructorName = targetConstructor.displayName; + + return refer('$alias$constructorName').newInstance( + positional.map( + (assignment) => ValueAssignmentBuilder( + mapperConfig: mapperConfig, + mapping: mapping, + assignment: assignment, + usedNullableMethodCallback: usedNullableMethodCallback, + ).build(), + ), + { + for (final assignment in named) + assignment.targetConstructorParam!.param.name: ValueAssignmentBuilder( + mapperConfig: mapperConfig, + mapping: mapping, + assignment: assignment, + usedNullableMethodCallback: usedNullableMethodCallback, + ).build(), + }, + ); + } + + void _assertNotMappedConstructorParameters(Iterable<ParameterElement> notMapped) { + for (final param in notMapped) { + if (param.isPositional && param.type.nullabilitySuffix != NullabilitySuffix.question) { + throw InvalidGenerationSourceError( + "Can't generate mapping $mapping as there is non mapped not-nullable positional parameter ${param.displayName}", + ); + } + + if (param.isRequiredNamed && param.type.nullabilitySuffix != NullabilitySuffix.question) { + if (param.type.isDartCoreList) return; + throw InvalidGenerationSourceError( + "Can't generate mapping $mapping as there is non mapped not-nullable required named parameter ${param.displayName}", + ); + } + } + } +} diff --git a/packages/auto_mappr/lib/src/builder/enum_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart similarity index 85% rename from packages/auto_mappr/lib/src/builder/enum_assignment_builder.dart rename to packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart index 34318b1a..1caef1e1 100644 --- a/packages/auto_mappr/lib/src/builder/enum_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart @@ -1,18 +1,18 @@ import 'package:analyzer/dart/element/element.dart'; +import 'package:auto_mappr/src/builder/map_bodies/map_body_builder_base.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; -import 'package:auto_mappr/src/models/models.dart'; import 'package:code_builder/code_builder.dart'; import 'package:source_gen/source_gen.dart'; -class EnumAssignmentBuilder { - final AutoMapprConfig mapperConfig; - final TypeMapping mapping; - - const EnumAssignmentBuilder({ - required this.mapperConfig, - required this.mapping, +class EnumBodyBuilder extends MapBodyBuilderBase { + const EnumBodyBuilder({ + required super.mapperConfig, + required super.mapping, + required super.nullable, + required super.usedNullableMethodCallback, }); + @override Code build() { final isSourceEnum = mapping.source.element is EnumElement; final isTargetEnum = mapping.target.element is EnumElement; @@ -64,4 +64,9 @@ class EnumAssignmentBuilder { .returned .statement; } + + @override + bool canProcess() { + return mapping.isEnumMapping; + } } diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/map_bodies.dart b/packages/auto_mappr/lib/src/builder/map_bodies/map_bodies.dart new file mode 100644 index 00000000..3978c068 --- /dev/null +++ b/packages/auto_mappr/lib/src/builder/map_bodies/map_bodies.dart @@ -0,0 +1,2 @@ +export 'class_body_builder.dart'; +export 'enum_body_builder.dart'; diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/map_body_builder_base.dart b/packages/auto_mappr/lib/src/builder/map_bodies/map_body_builder_base.dart new file mode 100644 index 00000000..d90dff23 --- /dev/null +++ b/packages/auto_mappr/lib/src/builder/map_bodies/map_body_builder_base.dart @@ -0,0 +1,22 @@ +import 'package:auto_mappr/src/models/auto_mappr_config.dart'; +import 'package:auto_mappr/src/models/type_mapping.dart'; +import 'package:code_builder/code_builder.dart'; + +abstract class MapBodyBuilderBase { + final AutoMapprConfig mapperConfig; + final TypeMapping mapping; + + final bool nullable; + final void Function(TypeMapping? mapping)? usedNullableMethodCallback; + + const MapBodyBuilderBase({ + required this.mapperConfig, + required this.mapping, + required this.nullable, + required this.usedNullableMethodCallback, + }); + + Code build(); + + bool canProcess(); +} diff --git a/packages/auto_mappr/lib/src/builder/map_model_body_method_builder.dart b/packages/auto_mappr/lib/src/builder/map_model_body_method_builder.dart index 27c1f96f..687d0fd4 100644 --- a/packages/auto_mappr/lib/src/builder/map_model_body_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/map_model_body_method_builder.dart @@ -1,17 +1,9 @@ -import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/dart/element/nullability_suffix.dart'; -import 'package:analyzer/dart/element/type.dart'; -import 'package:auto_mappr/src/builder/enum_assignment_builder.dart'; -import 'package:auto_mappr/src/builder/value_assignment_builder.dart'; -import 'package:auto_mappr/src/extensions/element_extension.dart'; +import 'package:auto_mappr/src/builder/map_bodies/map_bodies.dart'; import 'package:auto_mappr/src/extensions/expression_extension.dart'; -import 'package:auto_mappr/src/extensions/interface_type_extension.dart'; import 'package:auto_mappr/src/models/models.dart'; -import 'package:build/build.dart'; import 'package:code_builder/code_builder.dart'; -import 'package:collection/collection.dart'; -import 'package:source_gen/source_gen.dart'; +/// Creates mapping body. class MapModelBodyMethodBuilder { final AutoMapprConfig mapperConfig; final TypeMapping mapping; @@ -28,340 +20,38 @@ class MapModelBodyMethodBuilder { Code build() { final block = BlockBuilder(); - final sourceFields = _getAllReadableFields(classType: mapping.source); - - // Name of the source field names which can be mapped into constructor field - final mappedSourceFieldNames = <String>[]; - // Input as local model. block.statements.add(declareFinal('model').assign(refer('input')).statement); // Add handling of whenSourceIsNull. block.statements.add(_whenModelIsNullHandling()); // Is there an enum involved in the mapping? - if (mapping.isEnumMapping) { - final enumBuilder = EnumAssignmentBuilder(mapperConfig: mapperConfig, mapping: mapping); - - final assignment = enumBuilder.build(); - - block.statements.add(assignment); + final enumMapBodyBuilder = EnumBodyBuilder( + mapperConfig: mapperConfig, + mapping: mapping, + nullable: nullable, + usedNullableMethodCallback: usedNullableMethodCallback, + ); + if (enumMapBodyBuilder.canProcess()) { + block.statements.add(enumMapBodyBuilder.build()); return block.build(); } - // Map fields using a constructor. - // Returns an constructor call without `;`. - // - // One( - // usingConstructor1: model.usingConstructor1, - // usingConstructor2: model.usingConstructor2, - // ) - final constructorExpression = _processConstructorMapping( - mappedSourceFieldNames: mappedSourceFieldNames, - sourceFields: sourceFields, - ); - - // Map fields not mapped directly in constructor as setters if possible. - // - // Code like: - // - // <constructorExpression> - // ..withoutConstructor1 = model.withoutConstructor1 - // ..withoutConstructor2 = model.withoutConstructor2 - // ..withoutConstructor3 = model.withoutConstructor3 - final constructorWithSetters = _mapSetterFields( - alreadyMapped: mappedSourceFieldNames, - sourceFields: sourceFields, - constructorExpression: constructorExpression, + final classMapBodyBuilder = ClassBodyBuilder( + mapperConfig: mapperConfig, + mapping: mapping, + nullable: nullable, + usedNullableMethodCallback: usedNullableMethodCallback, ); // Return a constructor call // optionally with cascaded setter assignments. - block.statements.add(constructorWithSetters.returned.statement); + block.statements.add(classMapBodyBuilder.build()); return block.build(); } - void _assertParamFieldCanBeIgnored(ParameterElement param, PropertyAccessorElement sourceField) { - final sourceFieldName = sourceField.getDisplayString(withNullability: true); - if (param.isPositional && param.type.nullabilitySuffix != NullabilitySuffix.question) { - throw InvalidGenerationSourceError( - "Can't ignore field '$sourceFieldName' as it is positional not-nullable parameter", - ); - } - - if (param.isRequiredNamed && param.type.nullabilitySuffix != NullabilitySuffix.question) { - throw InvalidGenerationSourceError( - "Can't ignore field '$sourceFieldName' as it is required named not-nullable parameter", - ); - } - } - - void _assertNotMappedConstructorParameters(Iterable<ParameterElement> notMapped) { - for (final param in notMapped) { - if (param.isPositional && param.type.nullabilitySuffix != NullabilitySuffix.question) { - throw InvalidGenerationSourceError( - "Can't generate mapping $mapping as there is non mapped not-nullable positional parameter ${param.displayName}", - ); - } - - if (param.isRequiredNamed && param.type.nullabilitySuffix != NullabilitySuffix.question) { - if (param.type.isDartCoreList) return; - throw InvalidGenerationSourceError( - "Can't generate mapping $mapping as there is non mapped not-nullable required named parameter ${param.displayName}", - ); - } - } - } - - Expression _processConstructorMapping({ - required List<String> mappedSourceFieldNames, - required Map<String, PropertyAccessorElement> sourceFields, - }) { - final mappedTargetConstructorParams = <SourceAssignment>[]; - final notMappedTargetParameters = <SourceAssignment>[]; - - final targetConstructor = _findBestConstructor(mapping.target, forcedConstructor: mapping.constructor); - - if (targetConstructor == null) { - throw InvalidGenerationSourceError( - 'There is no target constructor in ${mapping.target}', - ); - } - - final targetClassGetters = (mapping.target).getAllGetters(); - - // Map constructor parameters - for (var i = 0; i < targetConstructor.parameters.length; i++) { - final param = targetConstructor.parameters.elementAtOrNull(i); - - if (param == null) continue; - - final paramPosition = param.isPositional ? i : null; - final constructorAssignment = ConstructorAssignment(param: param, position: paramPosition); - - final fieldMapping = mapping.tryGetFieldMapping(param.name); - - // Handles renaming. - final from = fieldMapping?.from; - final sourceFieldName = from ?? param.name; - - // Custom mapping has precedence. - if (fieldMapping?.hasCustomMapping() ?? false) { - final targetField = - targetClassGetters.firstWhereOrNull((targetField) => targetField.displayName == fieldMapping?.field); - - if (targetField == null) continue; - - if (mapping.fieldShouldBeIgnored(targetField.displayName)) { - _assertParamFieldCanBeIgnored(param, targetField); - } - - final sourceAssignment = SourceAssignment( - sourceField: null, - targetField: targetField, - targetConstructorParam: constructorAssignment, - fieldMapping: mapping.tryGetFieldMapping(targetField.displayName), - typeMapping: mapping, - config: mapperConfig, - ); - - mappedTargetConstructorParams.add(sourceAssignment); - mappedSourceFieldNames.add(param.name); - } - // Source field has the same name as target parameter or is renamed using [from]. - else if (sourceFields.containsKey(sourceFieldName)) { - final sourceField = sourceFields[sourceFieldName]!; - - final targetField = from == null - // find target field based on matching source field - ? targetClassGetters.firstWhereOrNull((field) => field.displayName == sourceField.displayName) - // support custom field rename mapping - : targetClassGetters.firstWhereOrNull((field) => field.displayName == fieldMapping?.field); - - if (targetField == null) continue; - - if (mapping.fieldShouldBeIgnored(targetField.displayName)) { - _assertParamFieldCanBeIgnored(param, sourceField); - } - - final sourceAssignment = SourceAssignment( - sourceField: sourceFields[sourceFieldName], - targetField: targetField, - targetConstructorParam: constructorAssignment, - fieldMapping: mapping.tryGetFieldMapping(targetField.displayName), - typeMapping: mapping, - config: mapperConfig, - ); - - mappedTargetConstructorParams.add(sourceAssignment); - mappedSourceFieldNames.add(param.name); - } else { - // If not mapped constructor param is optional - skip it - if (param.isOptional) continue; - - final targetField = - (mapping.target).getAllGetters().firstWhereOrNull((field) => field.displayName == param.displayName); - - final fieldMapping = mapping.tryGetFieldMapping(param.displayName); - - if (targetField == null && fieldMapping == null) { - throw InvalidGenerationSourceError( - "Can't find mapping for target's constructor parameter: ${param.displayName}. Parameter is required and no mapping or target's class field not found", - ); - } - - notMappedTargetParameters.add( - SourceAssignment( - sourceField: null, - targetField: targetField, - fieldMapping: fieldMapping, - targetConstructorParam: constructorAssignment, - typeMapping: mapping, - config: mapperConfig, - ), - ); - } - } - - _assertNotMappedConstructorParameters(notMappedTargetParameters.map((e) => e.targetConstructorParam!.param)); - - // Prepare and merge mapped and notMapped parameters into Positional and Named arrays - final mappedPositionalParameters = - mappedTargetConstructorParams.where((x) => x.targetConstructorParam?.position != null); - final notMappedPositionalParameters = - notMappedTargetParameters.where((x) => x.targetConstructorParam?.position != null); - - final positionalParameters = <SourceAssignment>[...mappedPositionalParameters, ...notMappedPositionalParameters] - ..sortByCompare((x) => x.targetConstructorParam!.position!, (a, b) => a - b); - - final namedParameters = <SourceAssignment>[ - ...mappedTargetConstructorParams.where((x) => x.targetConstructorParam?.isNamed ?? false), - ...notMappedTargetParameters.where((element) => element.targetConstructorParam?.isNamed ?? false), - ]; - - // Mapped fields into constructor - positional and named - return _mapConstructor( - targetConstructor, - positional: positionalParameters, - named: namedParameters, - ); - } - - Expression _mapConstructor( - ConstructorElement targetConstructor, { - required List<SourceAssignment> positional, - required List<SourceAssignment> named, - }) { - final alias = targetConstructor.enclosingElement.getLibraryAlias(config: mapperConfig); - final constructorName = targetConstructor.displayName; - - return refer('$alias$constructorName').newInstance( - positional.map( - (assignment) => ValueAssignmentBuilder( - mapperConfig: mapperConfig, - mapping: mapping, - assignment: assignment, - usedNullableMethodCallback: usedNullableMethodCallback, - ).build(), - ), - { - for (final assignment in named) - assignment.targetConstructorParam!.param.name: ValueAssignmentBuilder( - mapperConfig: mapperConfig, - mapping: mapping, - assignment: assignment, - usedNullableMethodCallback: usedNullableMethodCallback, - ).build(), - }, - ); - } - - Expression _mapSetterFields({ - required List<String> alreadyMapped, - required Map<String, PropertyAccessorElement> sourceFields, - required Expression constructorExpression, - }) { - final targetSetters = mapping.target.getAllSetters(); - - final potentialSetterFields = sourceFields.keys.where((field) => !alreadyMapped.contains(field)).toList(); - final fields = potentialSetterFields - .map((key) => sourceFields[key]) - .whereNotNull() - // Use only those that match. - .where((accessor) => targetSetters.any((targetAccessor) => targetAccessor.displayName == accessor.displayName)) - // Skip ignored fields. - .where((accessor) => !mapping.fieldShouldBeIgnored(accessor.displayName)) - .toList(); - - if (fields.isEmpty) { - return constructorExpression; - } - - final targetClassGetters = mapping.target.getAllGetters(); - - var cascadedAssignments = constructorExpression; - for (final sourceField in fields) { - final targetField = targetClassGetters.firstWhereOrNull((field) => field.displayName == sourceField.displayName); - - if (targetField == null) continue; - - // Assign result.X = model.X - cascadedAssignments = cascadedAssignments.cascade(sourceField.displayName).assign( - ValueAssignmentBuilder( - mapperConfig: mapperConfig, - mapping: mapping, - assignment: SourceAssignment( - sourceField: sourceField, - targetField: targetField, - typeMapping: mapping, - config: mapperConfig, - ), - usedNullableMethodCallback: usedNullableMethodCallback, - ).build(), - ); - } - - return cascadedAssignments; - } - - /// Returns all public fields (instance or static) that have a getter. - Map<String, PropertyAccessorElement> _getAllReadableFields({ - required InterfaceType classType, - }) { - final fieldsWithGetter = classType.getAllGetters(); - - return {for (final field in fieldsWithGetter) field.name: field}; - } - - /// Tries to find best constructor for mapping. - /// - /// Returns a constructor with the most parameter count. - /// Prefer non factory constructors over factory ones. - ConstructorElement? _findBestConstructor(InterfaceType classType, {String? forcedConstructor}) { - if (forcedConstructor != null) { - final selectedConstructor = classType.constructors.firstWhereOrNull((c) => c.name == forcedConstructor); - if (selectedConstructor != null) return selectedConstructor; - - log.warning( - "Couldn't find constructor '$forcedConstructor', fall-backing to using the most fitted one instead.", - ); - } - - final allConstructors = classType.constructors.where((c) => !c.isPrivate); - - // Sort constructors by number of parameters, descending. - int sortConstructors(ConstructorElement a, ConstructorElement b) => - -a.parameters.length.compareTo(b.parameters.length); - - final nonFactoryConstructors = allConstructors.where((c) => !c.isFactory).sorted(sortConstructors); - final factoryConstructors = - allConstructors.where((c) => c.isFactory && c.name != 'fromJson').sorted(sortConstructors); - - // Prefers non factory constructors over factory ones. - return [...nonFactoryConstructors, ...factoryConstructors].firstOrNull; - } - Code _whenModelIsNullHandling() { final ifConditionExpression = refer('model').equalTo(literalNull); diff --git a/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart index a456b949..8a3c411e 100644 --- a/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart @@ -1,10 +1,9 @@ import 'package:analyzer/dart/element/nullability_suffix.dart'; -import 'package:auto_mappr/src/builder/assignments/iterable_assignment_builder.dart'; -import 'package:auto_mappr/src/builder/assignments/map_assignment_builder.dart'; -import 'package:auto_mappr/src/builder/assignments/nested_object_assignment_builder.dart'; +import 'package:auto_mappr/src/builder/assignments/assignments.dart'; import 'package:auto_mappr/src/models/models.dart'; import 'package:code_builder/code_builder.dart'; +/// Decides how values are assigned. class ValueAssignmentBuilder { final AutoMapprConfig mapperConfig; final TypeMapping mapping; @@ -53,14 +52,13 @@ class ValueAssignmentBuilder { mapping: mapping, usedNullableMethodCallback: usedNullableMethodCallback, ), - // TODO(record): Make records assignment // Record. - // IterableAssignmentBuilder( - // assignment: assignment, - // mapperConfig: mapperConfig, - // mapping: mapping, - // usedNullableMethodCallback: usedNullableMethodCallback, - // ), + RecordAssignmentBuilder( + assignment: assignment, + mapperConfig: mapperConfig, + mapping: mapping, + usedNullableMethodCallback: usedNullableMethodCallback, + ), // Nested object. NestedObjectAssignmentBuilder( assignment: assignment, diff --git a/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart b/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart index a2f8fc50..f0a1ac63 100644 --- a/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart +++ b/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart @@ -95,8 +95,13 @@ extension DartTypeExtension on DartType { required AutoMapprConfig config, bool withNullability = false, }) { - final alias = element!.getLibraryAlias(config: config); - final typeName = element!.name; + final alias = element?.getLibraryAlias(config: config); + final typeName = element?.name; + + if (alias == null || typeName == null) { + return '??'; + } + final buffer = StringBuffer('$alias$typeName'); if (this is ParameterizedType && (this as ParameterizedType).typeArguments.isNotEmpty) { diff --git a/packages/auto_mappr/lib/src/models/source_assignment.dart b/packages/auto_mappr/lib/src/models/source_assignment.dart index e0357c54..730bd474 100644 --- a/packages/auto_mappr/lib/src/models/source_assignment.dart +++ b/packages/auto_mappr/lib/src/models/source_assignment.dart @@ -52,21 +52,21 @@ class SourceAssignment { this.fieldMapping, }); - bool shouldAssignIterable() { + bool canAssignIterable() { // The source can be mapped to the target, if the source is mappable object and the target is an iterable. return (_isCoreIterable(targetType) || targetType.isSpecializedListType) && _isMappableIterable(sourceType!); } - bool shouldAssignMap() { + bool canAssignMap() { // The source can be mapped to the target, if the source is mappable object and the target is map. return targetType.isDartCoreMap && _isMappableMap(sourceType!); } - bool shouldAssignRecord() { + bool canAssignRecord() { return targetType.isDartCoreRecord && sourceType!.isDartCoreRecord; } - bool shouldAssignComplexObject() => !targetType.isPrimitiveType; + bool canAssignComplexObject() => !targetType.isPrimitiveType; @override String toString() { diff --git a/packages/auto_mappr/pubspec.yaml b/packages/auto_mappr/pubspec.yaml index 16041bce..c566b693 100644 --- a/packages/auto_mappr/pubspec.yaml +++ b/packages/auto_mappr/pubspec.yaml @@ -12,7 +12,7 @@ environment: dependencies: # TODO: Support analyzer same way as json_serializable https://github.com/google/json_serializable.dart/pull/1333 - analyzer: ">=5.4.0 <7.0.0" + analyzer: ^6.0.0 auto_mappr_annotation: ^1.2.0 build: ^2.3.1 built_collection: ^5.1.1 diff --git a/packages/auto_mappr/test/integration/fixture/record.dart b/packages/auto_mappr/test/integration/fixture/record.dart new file mode 100644 index 00000000..02540841 --- /dev/null +++ b/packages/auto_mappr/test/integration/fixture/record.dart @@ -0,0 +1,136 @@ +// ignore_for_file: move-records-to-typedefs + +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +import 'package:equatable/equatable.dart'; + +part 'record.g.dart'; + +// TODO(records) +// @AutoMappr([ +// // simple +// MapType<PositionalDto, Positional>(), +// MapType<PositionalNullableDto, PositionalNullable>(), +// MapType<PositionalDto, PositionalNullable>(), +// // MapType<PositionalNullableDto, Positional>(), // TODO +// MapType<NamedDto, Named>(), +// // complex +// // MapType<ComplexDto, Complex>(), +// // MapType<ComplexNullableDto, Complex>(), +// ]) +// class Mappr extends $Mappr { +// const Mappr(); +// } + +// positional + +class Positional extends Equatable { + final (int, bool, String) value; + + @override + List<Object?> get props => [value]; + + const Positional(this.value); +} + +class PositionalDto extends Equatable { + final (int, bool, String) value; + + @override + List<Object?> get props => [value]; + + const PositionalDto(this.value); +} + +class PositionalNullable extends Equatable { + final (int?, bool?, String?) value; + + @override + List<Object?> get props => [value]; + + const PositionalNullable(this.value); +} + +class PositionalNullableDto extends Equatable { + final (int?, bool?, String?) value; + + @override + List<Object?> get props => [value]; + + const PositionalNullableDto(this.value); +} + +class Named extends Equatable { + final ({int alpha, bool beta, String gama}) value; + + @override + List<Object?> get props => [value]; + + const Named(this.value); +} + +class NamedDto extends Equatable { + final ({int alpha, bool beta, String gama}) value; + + @override + List<Object?> get props => [value]; + + const NamedDto(this.value); +} + +// complex + +// class Complex extends Equatable { +// final Iterable<Nested> value; + +// @override +// List<Object?> get props => [value]; + +// const Complex(this.value); +// } + +// class ComplexDto extends Equatable { +// final Iterable<NestedDto> value; + +// @override +// List<Object?> get props => [value]; + +// const ComplexDto(this.value); +// } + +// class ComplexNullableDto extends Equatable { +// final Iterable<NestedDto?> value; + +// @override +// List<Object?> get props => [value]; + +// const ComplexNullableDto(this.value); +// } + +// // List, Set, Iterable + +// class ListHolder extends Equatable { +// final List<int> value; + +// @override +// List<Object?> get props => [value]; + +// const ListHolder(this.value); +// } + +// class SetHolder extends Equatable { +// final Set<int> value; + +// @override +// List<Object?> get props => [value]; + +// const SetHolder(this.value); +// } + +// class IterableHolder extends Equatable { +// final Iterable<int> value; + +// @override +// List<Object?> get props => [value]; + +// const IterableHolder(this.value); +// } diff --git a/packages/auto_mappr/test/integration/record_test.dart b/packages/auto_mappr/test/integration/record_test.dart new file mode 100644 index 00000000..630547d2 --- /dev/null +++ b/packages/auto_mappr/test/integration/record_test.dart @@ -0,0 +1,33 @@ +import 'package:test/test.dart'; + +import 'fixture/record.dart' as fixture; + +void main() { + late final fixture.Mappr mappr; + + setUpAll(() { + mappr = const fixture.Mappr(); + }); + + group('primitive', () { + test('non nullable to non nullable', () { + // const dto = fixture.PositionalDto([1, 2, 3, 4, 5]); + // final converted = mappr.convert<fixture.PositionalDto, fixture.Positional>(dto); + + // expect( + // converted, + // equals(fixture.Positional([1, 2, 3, 4, 5].where((_) => true))), + // ); + }); + + test('nullable to non nullable', () { + // const dto = fixture.PrimitiveNullableDto([1, 2, 3, null, 4, 5, null]); + // final converted = mappr.convert<fixture.PrimitiveNullableDto, fixture.Positional>(dto); + + // expect( + // converted, + // equals(fixture.Positional([1, 2, 3, 4, 5].where((_) => true))), + // ); + }); + }); +} From 8e8dabedf90c55641591d701617ca5b948370cc3 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Tue, 29 Aug 2023 12:51:22 +0200 Subject: [PATCH 06/48] Add record test --- .../test/integration/record_test.dart | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/packages/auto_mappr/test/integration/record_test.dart b/packages/auto_mappr/test/integration/record_test.dart index 630547d2..8e258941 100644 --- a/packages/auto_mappr/test/integration/record_test.dart +++ b/packages/auto_mappr/test/integration/record_test.dart @@ -10,24 +10,39 @@ void main() { }); group('primitive', () { - test('non nullable to non nullable', () { - // const dto = fixture.PositionalDto([1, 2, 3, 4, 5]); - // final converted = mappr.convert<fixture.PositionalDto, fixture.Positional>(dto); - - // expect( - // converted, - // equals(fixture.Positional([1, 2, 3, 4, 5].where((_) => true))), - // ); + test('positional', () { + const dto = fixture.PositionalDto((1, true, 'Brasil')); + final converted = mappr.convert<fixture.PositionalDto, fixture.Positional>(dto); + + expect(converted, equals(const fixture.Positional((1, true, 'yolo')))); + }); + + test('positional nullable', () { + const dto = fixture.PositionalNullableDto((2, false, 'New York')); + final converted = mappr.convert<fixture.PositionalNullableDto, fixture.PositionalNullable>(dto); + + expect(converted, equals(const fixture.PositionalNullable((2, false, 'New York')))); + }); + + test('positional to positional nullable', () { + const dto = fixture.PositionalDto((3, false, 'Prague')); + final converted = mappr.convert<fixture.PositionalDto, fixture.PositionalNullable>(dto); + + expect(converted, equals(const fixture.PositionalNullable((3, false, 'Prague')))); + }); + + test('positional nullable to positional', () { + const dto = fixture.PositionalNullableDto((4, true, 'Rome')); + final converted = mappr.convert<fixture.PositionalNullableDto, fixture.Positional>(dto); + + expect(converted, equals(const fixture.PositionalNullable((4, true, 'Rome')))); }); - test('nullable to non nullable', () { - // const dto = fixture.PrimitiveNullableDto([1, 2, 3, null, 4, 5, null]); - // final converted = mappr.convert<fixture.PrimitiveNullableDto, fixture.Positional>(dto); + test('named', () { + const dto = fixture.NamedDto((alpha: 5, beta: true, gama: 'Paris')); + final converted = mappr.convert<fixture.NamedDto, fixture.Named>(dto); - // expect( - // converted, - // equals(fixture.Positional([1, 2, 3, 4, 5].where((_) => true))), - // ); + expect(converted, equals(const fixture.Named((alpha: 5, beta: true, gama: 'Paris')))); }); }); } From 96590dc48febd270af592d1c69a9a304cf3ddd58 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Wed, 30 Aug 2023 14:36:55 +0200 Subject: [PATCH 07/48] Add records named support --- .../test/fixture/json_serializable.g.dart | 267 ------------------ melos.yaml | 4 +- packages/auto_mappr/build.yaml | 4 +- .../auto_mappr/example/lib/mappr.g.dart | 77 +---- .../iterable_assignment_builder.dart | 4 +- .../assignments/map_assignment_builder.dart | 4 +- .../record_assignment_builder.dart | 157 +++++----- .../map_bodies/class_body_builder.dart | 14 +- .../lib/src/models/source_assignment.dart | 7 +- packages/auto_mappr/pubspec.yaml | 2 +- .../test/integration/fixture/record.dart | 39 ++- 11 files changed, 122 insertions(+), 457 deletions(-) delete mode 100644 examples/json_serializable/test/fixture/json_serializable.g.dart rename examples/json_serializable/lib/serializable.g.dart => packages/auto_mappr/example/lib/mappr.g.dart (70%) diff --git a/examples/json_serializable/test/fixture/json_serializable.g.dart b/examples/json_serializable/test/fixture/json_serializable.g.dart deleted file mode 100644 index 174c21ee..00000000 --- a/examples/json_serializable/test/fixture/json_serializable.g.dart +++ /dev/null @@ -1,267 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'json_serializable.dart'; - -// ************************************************************************** -// AutoMapprGenerator -// ************************************************************************** - -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings - -/// {@template asset:examples_json_serializable/test/fixture/json_serializable.dart} -/// Available mappings: -/// - `UserDto` → `User`. -/// - `ValueHolderDto` → `ValueHolder`. -/// {@endtemplate} -class $Mappr implements AutoMapprInterface { - const $Mappr(); - - Type _typeOf<T>() => T; - List<AutoMapprInterface> get _modules => const []; - - /// {@macro AutoMapprInterface:canConvert} - /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} - @override - bool canConvert<SOURCE, TARGET>({bool recursive = true}) { - final sourceTypeOf = _typeOf<SOURCE>(); - final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { - return true; - } - if ((sourceTypeOf == _typeOf<ValueHolderDto>() || - sourceTypeOf == _typeOf<ValueHolderDto?>()) && - (targetTypeOf == _typeOf<ValueHolder>() || - targetTypeOf == _typeOf<ValueHolder?>())) { - return true; - } - if (recursive) { - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return true; - } - } - } - return false; - } - - /// {@macro AutoMapprInterface:convert} - /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} - @override - TARGET convert<SOURCE, TARGET>(SOURCE? model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return _convert(model)!; - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.convert(model)!; - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// {@macro AutoMapprInterface:tryConvert} - /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} - @override - TARGET? tryConvert<SOURCE, TARGET>(SOURCE? model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return _convert( - model, - canReturnNull: true, - ); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.tryConvert(model); - } - } - - return null; - } - - /// {@macro AutoMapprInterface:convertIterable} - /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} - @override - Iterable<TARGET> convertIterable<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return model.map<TARGET>((item) => _convert(item)!); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.convertIterable(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into Iterable. - /// - /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null - /// - /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} - @override - Iterable<TARGET?> tryConvertIterable<SOURCE, TARGET>( - Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.tryConvertIterable(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// {@macro AutoMapprInterface:convertList} - /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} - @override - List<TARGET> convertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return convertIterable<SOURCE, TARGET>(model).toList(); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.convertList(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into List. - /// - /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null - /// - /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} - @override - List<TARGET?> tryConvertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return tryConvertIterable<SOURCE, TARGET>(model).toList(); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.tryConvertList(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// {@macro AutoMapprInterface:convertSet} - /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} - @override - Set<TARGET> convertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return convertIterable<SOURCE, TARGET>(model).toSet(); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.convertSet(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into Set. - /// - /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null - /// - /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} - @override - Set<TARGET?> tryConvertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return tryConvertIterable<SOURCE, TARGET>(model).toSet(); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.tryConvertSet(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - TARGET? _convert<SOURCE, TARGET>( - SOURCE? model, { - bool canReturnNull = false, - }) { - final sourceTypeOf = _typeOf<SOURCE>(); - final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { - if (canReturnNull && model == null) { - return null; - } - return (_map__UserDto__To__User((model as UserDto?)) as TARGET); - } - if ((sourceTypeOf == _typeOf<ValueHolderDto>() || - sourceTypeOf == _typeOf<ValueHolderDto?>()) && - (targetTypeOf == _typeOf<ValueHolder>() || - targetTypeOf == _typeOf<ValueHolder?>())) { - if (canReturnNull && model == null) { - return null; - } - return (_map__ValueHolderDto__To__ValueHolder((model as ValueHolderDto?)) - as TARGET); - } - throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); - } - - User _map__UserDto__To__User(UserDto? input) { - final model = input; - if (model == null) { - throw Exception( - r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' - r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); - } - return User( - firstName: model.firstName, - lastName: model.lastName, - ); - } - - ValueHolder _map__ValueHolderDto__To__ValueHolder(ValueHolderDto? input) { - final model = input; - if (model == null) { - throw Exception( - r'Mapping ValueHolderDto → ValueHolder failed because ValueHolderDto was null, and no default value was provided. ' - r'Consider setting the whenSourceIsNull parameter on the MapType<ValueHolderDto, ValueHolder> to handle null values during mapping.'); - } - return ValueHolder(model.json); - } -} - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -UserDto _$UserDtoFromJson(Map<String, dynamic> json) => UserDto( - firstName: json['firstName'] as String, - lastName: json['lastName'] as String, - ); - -Map<String, dynamic> _$UserDtoToJson(UserDto instance) => <String, dynamic>{ - 'firstName': instance.firstName, - 'lastName': instance.lastName, - }; - -ValueHolderDto _$ValueHolderDtoFromJson(Map<String, dynamic> json) => - ValueHolderDto( - json['json'] as Map<String, dynamic>, - ); - -Map<String, dynamic> _$ValueHolderDtoToJson(ValueHolderDto instance) => - <String, dynamic>{ - 'json': instance.json, - }; diff --git a/melos.yaml b/melos.yaml index 5dc207ae..38263093 100644 --- a/melos.yaml +++ b/melos.yaml @@ -2,8 +2,8 @@ name: auto_mappr_workspace packages: - packages/* - - packages/*/example - # - examples/* # TODO + # - packages/*/example + # - examples/* command: bootstrap: diff --git a/packages/auto_mappr/build.yaml b/packages/auto_mappr/build.yaml index d7065af6..edb1520d 100644 --- a/packages/auto_mappr/build.yaml +++ b/packages/auto_mappr/build.yaml @@ -4,8 +4,8 @@ targets: :auto_mappr: enabled: true generate_for: - include: # TODO - - test/integration/fixture/record.dart + # include: # TODO + # - test/integration/fixture/record.dart exclude: - test/integration/error_fixture/** options: diff --git a/examples/json_serializable/lib/serializable.g.dart b/packages/auto_mappr/example/lib/mappr.g.dart similarity index 70% rename from examples/json_serializable/lib/serializable.g.dart rename to packages/auto_mappr/example/lib/mappr.g.dart index 69c429dc..596834af 100644 --- a/examples/json_serializable/lib/serializable.g.dart +++ b/packages/auto_mappr/example/lib/mappr.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'serializable.dart'; +part of 'mappr.dart'; // ************************************************************************** // AutoMapprGenerator @@ -12,10 +12,9 @@ part of 'serializable.dart'; // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings -/// {@template package:examples_json_serializable/serializable.dart} +/// {@template asset:auto_mappr/example/lib/mappr.dart} /// Available mappings: /// - `UserDto` → `User`. -/// - `ValueHolderDto` → `ValueHolder`. /// {@endtemplate} class $Mappr implements AutoMapprInterface { const $Mappr(); @@ -24,7 +23,7 @@ class $Mappr implements AutoMapprInterface { List<AutoMapprInterface> get _modules => const []; /// {@macro AutoMapprInterface:canConvert} - /// {@macro package:examples_json_serializable/serializable.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); @@ -34,12 +33,6 @@ class $Mappr implements AutoMapprInterface { (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { return true; } - if ((sourceTypeOf == _typeOf<ValueHolderDto>() || - sourceTypeOf == _typeOf<ValueHolderDto?>()) && - (targetTypeOf == _typeOf<ValueHolder>() || - targetTypeOf == _typeOf<ValueHolder?>())) { - return true; - } if (recursive) { for (final mappr in _modules) { if (mappr.canConvert<SOURCE, TARGET>()) { @@ -51,7 +44,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:convert} - /// {@macro package:examples_json_serializable/serializable.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override TARGET convert<SOURCE, TARGET>(SOURCE? model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -67,7 +60,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:tryConvert} - /// {@macro package:examples_json_serializable/serializable.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override TARGET? tryConvert<SOURCE, TARGET>(SOURCE? model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -86,7 +79,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:convertIterable} - /// {@macro package:examples_json_serializable/serializable.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override Iterable<TARGET> convertIterable<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -105,7 +98,7 @@ class $Mappr implements AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro package:examples_json_serializable/serializable.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override Iterable<TARGET?> tryConvertIterable<SOURCE, TARGET>( Iterable<SOURCE?> model) { @@ -122,7 +115,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:convertList} - /// {@macro package:examples_json_serializable/serializable.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override List<TARGET> convertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -141,7 +134,7 @@ class $Mappr implements AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro package:examples_json_serializable/serializable.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override List<TARGET?> tryConvertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -157,7 +150,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:convertSet} - /// {@macro package:examples_json_serializable/serializable.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override Set<TARGET> convertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -176,7 +169,7 @@ class $Mappr implements AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro package:examples_json_serializable/serializable.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override Set<TARGET?> tryConvertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -205,16 +198,6 @@ class $Mappr implements AutoMapprInterface { } return (_map__UserDto__To__User((model as UserDto?)) as TARGET); } - if ((sourceTypeOf == _typeOf<ValueHolderDto>() || - sourceTypeOf == _typeOf<ValueHolderDto?>()) && - (targetTypeOf == _typeOf<ValueHolder>() || - targetTypeOf == _typeOf<ValueHolder?>())) { - if (canReturnNull && model == null) { - return null; - } - return (_map__ValueHolderDto__To__ValueHolder((model as ValueHolderDto?)) - as TARGET); - } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } @@ -226,42 +209,8 @@ class $Mappr implements AutoMapprInterface { r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } return User( - firstName: model.firstName, - lastName: model.lastName, + id: model.id, + name: model.xname, ); } - - ValueHolder _map__ValueHolderDto__To__ValueHolder(ValueHolderDto? input) { - final model = input; - if (model == null) { - throw Exception( - r'Mapping ValueHolderDto → ValueHolder failed because ValueHolderDto was null, and no default value was provided. ' - r'Consider setting the whenSourceIsNull parameter on the MapType<ValueHolderDto, ValueHolder> to handle null values during mapping.'); - } - return ValueHolder(model.json); - } } - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -UserDto _$UserDtoFromJson(Map<String, dynamic> json) => UserDto( - firstName: json['firstName'] as String, - lastName: json['lastName'] as String, - ); - -Map<String, dynamic> _$UserDtoToJson(UserDto instance) => <String, dynamic>{ - 'firstName': instance.firstName, - 'lastName': instance.lastName, - }; - -ValueHolderDto _$ValueHolderDtoFromJson(Map<String, dynamic> json) => - ValueHolderDto( - json['json'] as Map<String, dynamic>, - ); - -Map<String, dynamic> _$ValueHolderDtoToJson(ValueHolderDto instance) => - <String, dynamic>{ - 'json': instance.json, - }; diff --git a/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart index fd01567b..ca7ccf8f 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart @@ -49,7 +49,7 @@ class IterableAssignmentBuilder extends AssignmentBuilderBase with NestedObjectM // Map complex nested types. .maybeNullSafeProperty('map', isOnNullable: sourceNullable) .call( - [_nestedMapCallForIterable(assignment)], + [_map(assignment)], {}, [ refer( @@ -85,7 +85,7 @@ class IterableAssignmentBuilder extends AssignmentBuilderBase with NestedObjectM ); } - Expression _nestedMapCallForIterable(SourceAssignment assignment) { + Expression _map(SourceAssignment assignment) { final targetListType = assignment.targetType.genericParameterTypeOrSelf; final sourceListType = assignment.sourceType!.genericParameterTypeOrSelf; diff --git a/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart index aaa0a492..a387e675 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart @@ -91,7 +91,7 @@ class MapAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin isOnNullable: sourceNullable, // Call map only when actually some mapping is required. condition: shouldDoMapCall, - positionalArguments: [_callMapForMap(assignment)], + positionalArguments: [_map(assignment)], typeArguments: [ refer(targetKeyType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), refer(targetValueType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), @@ -101,7 +101,7 @@ class MapAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin .maybeIfNullThen(defaultMapValueExpression, isOnNullable: sourceNullable); } - Expression _callMapForMap(SourceAssignment assignment) { + Expression _map(SourceAssignment assignment) { final sourceKeyType = (assignment.sourceType! as ParameterizedType).typeArguments.firstOrNull; final sourceValueType = (assignment.sourceType! as ParameterizedType).typeArguments.lastOrNull; final targetKeyType = (assignment.targetType as ParameterizedType).typeArguments.firstOrNull; diff --git a/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart index 88d03437..6be67932 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart @@ -1,9 +1,12 @@ import 'package:analyzer/dart/element/nullability_suffix.dart'; +import 'package:analyzer/dart/element/type.dart' as type; import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; import 'package:auto_mappr/src/builder/assignments/nested_object_mixin.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:auto_mappr/src/models/source_assignment.dart'; import 'package:build/build.dart'; import 'package:code_builder/code_builder.dart'; +import 'package:collection/collection.dart'; import 'package:source_gen/source_gen.dart'; class RecordAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin { @@ -16,115 +19,93 @@ class RecordAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMix @override bool canAssign() { - log.warning( - 'RECORD ASSIGNMENT CHECK ${assignment.targetType is RecordType} ... ${assignment.sourceType is RecordType} /// $assignment'); return assignment.canAssignRecord(); } @override Expression buildAssignment() { - log.warning('RECORD ASSIGNMENT'); + // TODO(records): assignment.fieldMapping handle -> whenNullExpression, custom final sourceType = assignment.sourceType!; final targetType = assignment.targetType; - // final sourceNullable = sourceType.nullabilitySuffix == NullabilitySuffix.question; - // final targetNullable = targetType.nullabilitySuffix == NullabilitySuffix.question; + final sourceRecordType = sourceType as type.RecordType; + final targetRecordType = targetType as type.RecordType; - // ignore: avoid-unrelated-type-casts, it's ok and handled by canAssign - final sourceRecordType = sourceType as RecordType; - // ignore: avoid-unrelated-type-casts, it's ok and handled by canAssign - final targetRecordType = targetType as RecordType; + log.warning(''' +-- RECORDS -- +${sourceRecordType.positionalFields.map((e) => '${e.type}')} +${sourceRecordType.namedFields.map((e) => '${e.type} ${e.name}')} +'''); // Positional fields check. - final sourcePositional = sourceRecordType.positionalFieldTypes; - final targetPositional = targetRecordType.positionalFieldTypes; + final sourcePositional = sourceRecordType.positionalFields; + final targetPositional = targetRecordType.positionalFields; if (sourcePositional.length != targetPositional.length) { throw InvalidGenerationSourceError( - 'Positional source and target fields length mismatch for source ${sourceType} and target ${targetType}', + 'Positional source and target fields length mismatch for source $sourceType and target $targetType', ); } // Named fields check. - final sourceNamed = sourceRecordType.namedFieldTypes; - final targetNamed = targetRecordType.namedFieldTypes; - for (final field in targetNamed.entries) { - print('!!! ${field.key} = ${field.value}'); + final sourceNamed = sourceRecordType.namedFields; + final targetNamed = targetRecordType.namedFields; + for (final targetField in targetNamed) { + if (!sourceNamed.any((sourceField) => sourceField.name == targetField.name) && + targetField.type.nullabilitySuffix == NullabilitySuffix.none) { + throw InvalidGenerationSourceError( + "Cannot find mapping to non-nullable target record's named field $targetField", + ); + } } - // NAMED - check target has all source's named, if target is nullable it might not - - // --- ASSIGN MAP --- - - // -- RETURN -- - - // TODO(records): return positional and named as code - return const CodeExpression(Code('(1, 2, 3, alpha: 4, beta: 5)')); - - // ---------------- - - // final shouldFilterNullInSource = sourceRecordType.nullabilitySuffix == NullabilitySuffix.question && - // targetRecordType.nullabilitySuffix != NullabilitySuffix.question; - - // final assignNestedObject = (!targetRecordType.isPrimitiveType && !targetRecordType.isSpecializedListType) && - // (!targetRecordType.isSame(sourceRecordType)); - - // // When [sourceIterableType] is nullable and [targetIterableType] is not, remove null values. - // final sourceIterableExpression = refer('model').property(assignment.sourceField!.name).maybeWhereIterableNotNull( - // condition: shouldFilterNullInSource, - // isOnNullable: sourceNullable, - // ); + final namedFields = <({String key, String value})>[ + for (final targetField in targetNamed) + ( + key: targetField.name, + value: _mapNamedField( + assignment: assignment, + source: sourceNamed.firstWhereOrNull((sourceField) => sourceField.name == targetField.name), + target: targetField, + ).accept(DartEmitter()).toString(), + ), + ]; + + return CodeExpression( + Code( + '(${namedFields.map((field) => '${field.key}: ${field.value}')})', + ), + ); + } - // final defaultIterableValueExpression = targetType.defaultIterableExpression(config: mapperConfig); + // Handles mapping of only one named field. + // + // Generates + // - mapping for primitives: `model.alpha` + // - mapping for complex types: `_map_NestedDto_To_Nested(model.alpha)` + // - and when nullable and if `whenNullExpression` defined, uses that as a fallback + Expression _mapNamedField({ + required SourceAssignment assignment, + required type.RecordTypeNamedField? source, + required type.RecordTypeNamedField target, + }) { + if (source == null) return literalNull; + + final valuesAreSameType = source.type == target.type; + final shouldAssignNestedObject = !target.type.isPrimitiveType && !valuesAreSameType; + + final targetRecordExpression = refer(assignment.sourceField!.name); + + if (!shouldAssignNestedObject) { + return refer('model.${targetRecordExpression.accept(DartEmitter())}.${source.name}'); + } - // if (assignNestedObject) { - // return sourceIterableExpression - // // Map complex nested types. - // .maybeNullSafeProperty('map', isOnNullable: sourceNullable) - // .call( - // [_nestedMapCallForIterable(assignment)], - // {}, - // [ - // refer( - // targetRecordType.getDisplayStringWithLibraryAlias( - // withNullability: true, - // config: mapperConfig, - // ), - // ), - // ], - // ) - // // Call toList, toSet or nothing. - // // isOnNullable is false, because if map() was called, the value is non-null - // .maybeToIterableCall( - // source: sourceType, - // target: targetType, - // forceCast: true, //map was used so we want force toIterable() call - // isOnNullable: false, - // ) - // // When [sourceNullable], use default value. - // .maybeIfNullThen(defaultIterableValueExpression, isOnNullable: sourceNullable && !targetNullable); - // } + final valueExpression = assignNestedObject( + assignment: assignment, + source: source.type, + target: target.type, + convertMethodArgument: valuesAreSameType ? null : targetRecordExpression, + ); - // return sourceIterableExpression - // .maybeToIterableCall( - // source: sourceType, - // target: targetType, - // forceCast: shouldFilterNullInSource, // if whereNotNull was used -> we want to force toIterable() call - // isOnNullable: !targetNullable && sourceNullable, - // ) - // .maybeIfNullThen( - // defaultIterableValueExpression, - // isOnNullable: !targetNullable && sourceNullable, - // ); + return refer('${valueExpression.accept(DartEmitter())})'); } - - // Expression _nestedMapCallForIterable(SourceAssignment assignment) { - // final targetListType = assignment.targetType.genericParameterTypeOrSelf; - // final sourceListType = assignment.sourceType!.genericParameterTypeOrSelf; - - // return assignNestedObject( - // assignment: assignment, - // source: sourceListType, - // target: targetListType, - // ); - // } } diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart index d7c122ec..91c8685f 100644 --- a/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart +++ b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart @@ -7,7 +7,7 @@ import 'package:auto_mappr/src/extensions/element_extension.dart'; import 'package:auto_mappr/src/extensions/interface_type_extension.dart'; import 'package:auto_mappr/src/models/source_assignment.dart'; import 'package:build/build.dart'; -import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/code_builder.dart' show Code, Expression, refer; import 'package:collection/collection.dart'; import 'package:source_gen/source_gen.dart'; @@ -92,18 +92,6 @@ class ClassBodyBuilder extends MapBodyBuilderBase { if (param == null) continue; -// TODO -// log.warning(''' -// PARAM $param -// type.getDisplayString: ${param.type.getDisplayString(withNullability: true)} -// type.isDartCoreRecord: ${param.type.isDartCoreRecord} -// type.name: ${param.type.name} -// type.element.name: ${param.type.element?.name} -// type.element.library.isDartCore: ${param.type.element?.library?.isDartCore} -// type.element.library: ${param.type.element?.library} -// ////// -// '''); - final paramPosition = param.isPositional ? i : null; final constructorAssignment = ConstructorAssignment(param: param, position: paramPosition); diff --git a/packages/auto_mappr/lib/src/models/source_assignment.dart b/packages/auto_mappr/lib/src/models/source_assignment.dart index 730bd474..455520f8 100644 --- a/packages/auto_mappr/lib/src/models/source_assignment.dart +++ b/packages/auto_mappr/lib/src/models/source_assignment.dart @@ -4,7 +4,7 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/models/models.dart'; -import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/code_builder.dart' show Expression, literalList, literalMap, literalNull, literalSet; class ConstructorAssignment { final ParameterElement param; @@ -63,7 +63,10 @@ class SourceAssignment { } bool canAssignRecord() { - return targetType.isDartCoreRecord && sourceType!.isDartCoreRecord; + final isSourceRecord = sourceType is RecordType; + final isTargetRecord = targetType is RecordType; + + return isSourceRecord && isTargetRecord; } bool canAssignComplexObject() => !targetType.isPrimitiveType; diff --git a/packages/auto_mappr/pubspec.yaml b/packages/auto_mappr/pubspec.yaml index c566b693..16041bce 100644 --- a/packages/auto_mappr/pubspec.yaml +++ b/packages/auto_mappr/pubspec.yaml @@ -12,7 +12,7 @@ environment: dependencies: # TODO: Support analyzer same way as json_serializable https://github.com/google/json_serializable.dart/pull/1333 - analyzer: ^6.0.0 + analyzer: ">=5.4.0 <7.0.0" auto_mappr_annotation: ^1.2.0 build: ^2.3.1 built_collection: ^5.1.1 diff --git a/packages/auto_mappr/test/integration/fixture/record.dart b/packages/auto_mappr/test/integration/fixture/record.dart index 02540841..9e9b4cbe 100644 --- a/packages/auto_mappr/test/integration/fixture/record.dart +++ b/packages/auto_mappr/test/integration/fixture/record.dart @@ -1,25 +1,27 @@ // ignore_for_file: move-records-to-typedefs +import 'package:analyzer/dart/ast/visitor.dart'; import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; part 'record.g.dart'; // TODO(records) -// @AutoMappr([ -// // simple -// MapType<PositionalDto, Positional>(), -// MapType<PositionalNullableDto, PositionalNullable>(), -// MapType<PositionalDto, PositionalNullable>(), -// // MapType<PositionalNullableDto, Positional>(), // TODO -// MapType<NamedDto, Named>(), -// // complex -// // MapType<ComplexDto, Complex>(), -// // MapType<ComplexNullableDto, Complex>(), -// ]) -// class Mappr extends $Mappr { -// const Mappr(); -// } +@AutoMappr([ + // simple + // MapType<PositionalDto, Positional>(), + // MapType<PositionalNullableDto, PositionalNullable>(), + // MapType<PositionalDto, PositionalNullable>(), + // MapType<PositionalNullableDto, Positional>(), // TODO + MapType<NamedDto, Named>(), + MapType<NamedDto, NamedNullable>(), + // complex + // MapType<ComplexDto, Complex>(), + // MapType<ComplexNullableDto, Complex>(), +]) +class Mappr extends $Mappr { + const Mappr(); +} // positional @@ -68,6 +70,15 @@ class Named extends Equatable { const Named(this.value); } +class NamedNullable extends Equatable { + final ({int alpha, bool beta, String gama, int? delta, bool? epsilon}) value; + + @override + List<Object?> get props => [value]; + + const NamedNullable(this.value); +} + class NamedDto extends Equatable { final ({int alpha, bool beta, String gama}) value; From 7f5dce53a23701a8196a8b54dad65cc9d241772d Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 4 Sep 2023 08:13:35 +0200 Subject: [PATCH 08/48] Finish records --- .../json_serializable/lib/serializable.g.dart | 267 ++++++++++++++++++ .../test/fixture/json_serializable.g.dart | 267 ++++++++++++++++++ melos.yaml | 4 +- packages/auto_mappr/CHANGELOG.md | 1 + packages/auto_mappr/README.md | 15 + packages/auto_mappr/build.yaml | 2 +- packages/auto_mappr/example/lib/mappr.g.dart | 20 +- .../record_assignment_builder.dart | 66 ++++- .../test/integration/fixture/record.dart | 85 +++--- .../test/integration/record_test.dart | 55 +++- 10 files changed, 700 insertions(+), 82 deletions(-) create mode 100644 examples/json_serializable/lib/serializable.g.dart create mode 100644 examples/json_serializable/test/fixture/json_serializable.g.dart diff --git a/examples/json_serializable/lib/serializable.g.dart b/examples/json_serializable/lib/serializable.g.dart new file mode 100644 index 00000000..69c429dc --- /dev/null +++ b/examples/json_serializable/lib/serializable.g.dart @@ -0,0 +1,267 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'serializable.dart'; + +// ************************************************************************** +// AutoMapprGenerator +// ************************************************************************** + +// ignore_for_file: non_constant_identifier_names, prefer_const_constructors +// ignore_for_file: prefer_const_literals_to_create_immutables +// ignore_for_file: require_trailing_commas, unnecessary_const +// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis +// ignore_for_file: unnecessary_raw_strings + +/// {@template package:examples_json_serializable/serializable.dart} +/// Available mappings: +/// - `UserDto` → `User`. +/// - `ValueHolderDto` → `ValueHolder`. +/// {@endtemplate} +class $Mappr implements AutoMapprInterface { + const $Mappr(); + + Type _typeOf<T>() => T; + List<AutoMapprInterface> get _modules => const []; + + /// {@macro AutoMapprInterface:canConvert} + /// {@macro package:examples_json_serializable/serializable.dart} + @override + bool canConvert<SOURCE, TARGET>({bool recursive = true}) { + final sourceTypeOf = _typeOf<SOURCE>(); + final targetTypeOf = _typeOf<TARGET>(); + if ((sourceTypeOf == _typeOf<UserDto>() || + sourceTypeOf == _typeOf<UserDto?>()) && + (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + return true; + } + if ((sourceTypeOf == _typeOf<ValueHolderDto>() || + sourceTypeOf == _typeOf<ValueHolderDto?>()) && + (targetTypeOf == _typeOf<ValueHolder>() || + targetTypeOf == _typeOf<ValueHolder?>())) { + return true; + } + if (recursive) { + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return true; + } + } + } + return false; + } + + /// {@macro AutoMapprInterface:convert} + /// {@macro package:examples_json_serializable/serializable.dart} + @override + TARGET convert<SOURCE, TARGET>(SOURCE? model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return _convert(model)!; + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.convert(model)!; + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// {@macro AutoMapprInterface:tryConvert} + /// {@macro package:examples_json_serializable/serializable.dart} + @override + TARGET? tryConvert<SOURCE, TARGET>(SOURCE? model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return _convert( + model, + canReturnNull: true, + ); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.tryConvert(model); + } + } + + return null; + } + + /// {@macro AutoMapprInterface:convertIterable} + /// {@macro package:examples_json_serializable/serializable.dart} + @override + Iterable<TARGET> convertIterable<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return model.map<TARGET>((item) => _convert(item)!); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.convertIterable(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into Iterable. + /// + /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null + /// + /// {@macro package:examples_json_serializable/serializable.dart} + @override + Iterable<TARGET?> tryConvertIterable<SOURCE, TARGET>( + Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.tryConvertIterable(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// {@macro AutoMapprInterface:convertList} + /// {@macro package:examples_json_serializable/serializable.dart} + @override + List<TARGET> convertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return convertIterable<SOURCE, TARGET>(model).toList(); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.convertList(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into List. + /// + /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null + /// + /// {@macro package:examples_json_serializable/serializable.dart} + @override + List<TARGET?> tryConvertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return tryConvertIterable<SOURCE, TARGET>(model).toList(); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.tryConvertList(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// {@macro AutoMapprInterface:convertSet} + /// {@macro package:examples_json_serializable/serializable.dart} + @override + Set<TARGET> convertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return convertIterable<SOURCE, TARGET>(model).toSet(); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.convertSet(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into Set. + /// + /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null + /// + /// {@macro package:examples_json_serializable/serializable.dart} + @override + Set<TARGET?> tryConvertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return tryConvertIterable<SOURCE, TARGET>(model).toSet(); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.tryConvertSet(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + TARGET? _convert<SOURCE, TARGET>( + SOURCE? model, { + bool canReturnNull = false, + }) { + final sourceTypeOf = _typeOf<SOURCE>(); + final targetTypeOf = _typeOf<TARGET>(); + if ((sourceTypeOf == _typeOf<UserDto>() || + sourceTypeOf == _typeOf<UserDto?>()) && + (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if (canReturnNull && model == null) { + return null; + } + return (_map__UserDto__To__User((model as UserDto?)) as TARGET); + } + if ((sourceTypeOf == _typeOf<ValueHolderDto>() || + sourceTypeOf == _typeOf<ValueHolderDto?>()) && + (targetTypeOf == _typeOf<ValueHolder>() || + targetTypeOf == _typeOf<ValueHolder?>())) { + if (canReturnNull && model == null) { + return null; + } + return (_map__ValueHolderDto__To__ValueHolder((model as ValueHolderDto?)) + as TARGET); + } + throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); + } + + User _map__UserDto__To__User(UserDto? input) { + final model = input; + if (model == null) { + throw Exception( + r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' + r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); + } + return User( + firstName: model.firstName, + lastName: model.lastName, + ); + } + + ValueHolder _map__ValueHolderDto__To__ValueHolder(ValueHolderDto? input) { + final model = input; + if (model == null) { + throw Exception( + r'Mapping ValueHolderDto → ValueHolder failed because ValueHolderDto was null, and no default value was provided. ' + r'Consider setting the whenSourceIsNull parameter on the MapType<ValueHolderDto, ValueHolder> to handle null values during mapping.'); + } + return ValueHolder(model.json); + } +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserDto _$UserDtoFromJson(Map<String, dynamic> json) => UserDto( + firstName: json['firstName'] as String, + lastName: json['lastName'] as String, + ); + +Map<String, dynamic> _$UserDtoToJson(UserDto instance) => <String, dynamic>{ + 'firstName': instance.firstName, + 'lastName': instance.lastName, + }; + +ValueHolderDto _$ValueHolderDtoFromJson(Map<String, dynamic> json) => + ValueHolderDto( + json['json'] as Map<String, dynamic>, + ); + +Map<String, dynamic> _$ValueHolderDtoToJson(ValueHolderDto instance) => + <String, dynamic>{ + 'json': instance.json, + }; diff --git a/examples/json_serializable/test/fixture/json_serializable.g.dart b/examples/json_serializable/test/fixture/json_serializable.g.dart new file mode 100644 index 00000000..174c21ee --- /dev/null +++ b/examples/json_serializable/test/fixture/json_serializable.g.dart @@ -0,0 +1,267 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'json_serializable.dart'; + +// ************************************************************************** +// AutoMapprGenerator +// ************************************************************************** + +// ignore_for_file: non_constant_identifier_names, prefer_const_constructors +// ignore_for_file: prefer_const_literals_to_create_immutables +// ignore_for_file: require_trailing_commas, unnecessary_const +// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis +// ignore_for_file: unnecessary_raw_strings + +/// {@template asset:examples_json_serializable/test/fixture/json_serializable.dart} +/// Available mappings: +/// - `UserDto` → `User`. +/// - `ValueHolderDto` → `ValueHolder`. +/// {@endtemplate} +class $Mappr implements AutoMapprInterface { + const $Mappr(); + + Type _typeOf<T>() => T; + List<AutoMapprInterface> get _modules => const []; + + /// {@macro AutoMapprInterface:canConvert} + /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} + @override + bool canConvert<SOURCE, TARGET>({bool recursive = true}) { + final sourceTypeOf = _typeOf<SOURCE>(); + final targetTypeOf = _typeOf<TARGET>(); + if ((sourceTypeOf == _typeOf<UserDto>() || + sourceTypeOf == _typeOf<UserDto?>()) && + (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + return true; + } + if ((sourceTypeOf == _typeOf<ValueHolderDto>() || + sourceTypeOf == _typeOf<ValueHolderDto?>()) && + (targetTypeOf == _typeOf<ValueHolder>() || + targetTypeOf == _typeOf<ValueHolder?>())) { + return true; + } + if (recursive) { + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return true; + } + } + } + return false; + } + + /// {@macro AutoMapprInterface:convert} + /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} + @override + TARGET convert<SOURCE, TARGET>(SOURCE? model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return _convert(model)!; + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.convert(model)!; + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// {@macro AutoMapprInterface:tryConvert} + /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} + @override + TARGET? tryConvert<SOURCE, TARGET>(SOURCE? model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return _convert( + model, + canReturnNull: true, + ); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.tryConvert(model); + } + } + + return null; + } + + /// {@macro AutoMapprInterface:convertIterable} + /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} + @override + Iterable<TARGET> convertIterable<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return model.map<TARGET>((item) => _convert(item)!); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.convertIterable(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into Iterable. + /// + /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null + /// + /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} + @override + Iterable<TARGET?> tryConvertIterable<SOURCE, TARGET>( + Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.tryConvertIterable(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// {@macro AutoMapprInterface:convertList} + /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} + @override + List<TARGET> convertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return convertIterable<SOURCE, TARGET>(model).toList(); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.convertList(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into List. + /// + /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null + /// + /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} + @override + List<TARGET?> tryConvertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return tryConvertIterable<SOURCE, TARGET>(model).toList(); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.tryConvertList(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// {@macro AutoMapprInterface:convertSet} + /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} + @override + Set<TARGET> convertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return convertIterable<SOURCE, TARGET>(model).toSet(); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.convertSet(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into Set. + /// + /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null + /// + /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} + @override + Set<TARGET?> tryConvertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return tryConvertIterable<SOURCE, TARGET>(model).toSet(); + } + for (final mappr in _modules) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.tryConvertSet(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + TARGET? _convert<SOURCE, TARGET>( + SOURCE? model, { + bool canReturnNull = false, + }) { + final sourceTypeOf = _typeOf<SOURCE>(); + final targetTypeOf = _typeOf<TARGET>(); + if ((sourceTypeOf == _typeOf<UserDto>() || + sourceTypeOf == _typeOf<UserDto?>()) && + (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if (canReturnNull && model == null) { + return null; + } + return (_map__UserDto__To__User((model as UserDto?)) as TARGET); + } + if ((sourceTypeOf == _typeOf<ValueHolderDto>() || + sourceTypeOf == _typeOf<ValueHolderDto?>()) && + (targetTypeOf == _typeOf<ValueHolder>() || + targetTypeOf == _typeOf<ValueHolder?>())) { + if (canReturnNull && model == null) { + return null; + } + return (_map__ValueHolderDto__To__ValueHolder((model as ValueHolderDto?)) + as TARGET); + } + throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); + } + + User _map__UserDto__To__User(UserDto? input) { + final model = input; + if (model == null) { + throw Exception( + r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' + r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); + } + return User( + firstName: model.firstName, + lastName: model.lastName, + ); + } + + ValueHolder _map__ValueHolderDto__To__ValueHolder(ValueHolderDto? input) { + final model = input; + if (model == null) { + throw Exception( + r'Mapping ValueHolderDto → ValueHolder failed because ValueHolderDto was null, and no default value was provided. ' + r'Consider setting the whenSourceIsNull parameter on the MapType<ValueHolderDto, ValueHolder> to handle null values during mapping.'); + } + return ValueHolder(model.json); + } +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserDto _$UserDtoFromJson(Map<String, dynamic> json) => UserDto( + firstName: json['firstName'] as String, + lastName: json['lastName'] as String, + ); + +Map<String, dynamic> _$UserDtoToJson(UserDto instance) => <String, dynamic>{ + 'firstName': instance.firstName, + 'lastName': instance.lastName, + }; + +ValueHolderDto _$ValueHolderDtoFromJson(Map<String, dynamic> json) => + ValueHolderDto( + json['json'] as Map<String, dynamic>, + ); + +Map<String, dynamic> _$ValueHolderDtoToJson(ValueHolderDto instance) => + <String, dynamic>{ + 'json': instance.json, + }; diff --git a/melos.yaml b/melos.yaml index 38263093..db661e5d 100644 --- a/melos.yaml +++ b/melos.yaml @@ -2,8 +2,8 @@ name: auto_mappr_workspace packages: - packages/* - # - packages/*/example - # - examples/* + - packages/*/example + - examples/* command: bootstrap: diff --git a/packages/auto_mappr/CHANGELOG.md b/packages/auto_mappr/CHANGELOG.md index 87f9aa4f..41d3d72b 100644 --- a/packages/auto_mappr/CHANGELOG.md +++ b/packages/auto_mappr/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased - Add a `reverse` option on `MapType`, which includes the reverse mapping. [#115](https://github.com/netglade/auto_mappr/pull/115) +- Add a support for Dart 3 and Records feature. [#116](https://github.com/netglade/auto_mappr/pull/116) ## 1.7.0 - Adhere to netglade_analysis. [#94](https://github.com/netglade/auto_mappr/pull/94) diff --git a/packages/auto_mappr/README.md b/packages/auto_mappr/README.md index b450568c..f319ef5c 100644 --- a/packages/auto_mappr/README.md +++ b/packages/auto_mappr/README.md @@ -49,6 +49,7 @@ Heavily inspired by [C# AutoMapper][auto_mapper_net_link]. - [Library import aliases](#library-import-aliases) - [Modules](#modules) - [Reverse mapping](#reverse-mapping) + - [Records](#records) - [Works with `equatable`](#works-with-equatable) - [Works with `json_serializable`](#works-with-json_serializable) - [Works with generated source and target classes](#works-with-generated-source-and-target-classes) @@ -613,6 +614,20 @@ such as [whenSourceIsNull] or [constructor] is used. For more complicated scenarios two separate mappings are recommended instead. +### Records + +Converting records is supported for both positional and named record's fields. + +Target positional fields must have their source field equivalent. +Target named fields must have their source field equivalent determined by name. +Bot positional and named target fields without source equivalent must be nullable in order +for mapping to be created successfully +and then thier value will be `null`. + +Note that we do not have a function similar to `convertList` for records +due to Dart 3 "limitation" +as we cannot iterate throught it's positional or named fields on the fly. + ### Works with `equatable` Mapping works with the Equatable package. diff --git a/packages/auto_mappr/build.yaml b/packages/auto_mappr/build.yaml index edb1520d..4ab62f38 100644 --- a/packages/auto_mappr/build.yaml +++ b/packages/auto_mappr/build.yaml @@ -4,7 +4,7 @@ targets: :auto_mappr: enabled: true generate_for: - # include: # TODO + # include: # - test/integration/fixture/record.dart exclude: - test/integration/error_fixture/** diff --git a/packages/auto_mappr/example/lib/mappr.g.dart b/packages/auto_mappr/example/lib/mappr.g.dart index 596834af..364cd655 100644 --- a/packages/auto_mappr/example/lib/mappr.g.dart +++ b/packages/auto_mappr/example/lib/mappr.g.dart @@ -12,7 +12,7 @@ part of 'mappr.dart'; // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings -/// {@template asset:auto_mappr/example/lib/mappr.dart} +/// {@template package:auto_mappr_example/mappr.dart} /// Available mappings: /// - `UserDto` → `User`. /// {@endtemplate} @@ -23,7 +23,7 @@ class $Mappr implements AutoMapprInterface { List<AutoMapprInterface> get _modules => const []; /// {@macro AutoMapprInterface:canConvert} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); @@ -44,7 +44,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:convert} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override TARGET convert<SOURCE, TARGET>(SOURCE? model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -60,7 +60,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:tryConvert} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override TARGET? tryConvert<SOURCE, TARGET>(SOURCE? model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -79,7 +79,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:convertIterable} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override Iterable<TARGET> convertIterable<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -98,7 +98,7 @@ class $Mappr implements AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override Iterable<TARGET?> tryConvertIterable<SOURCE, TARGET>( Iterable<SOURCE?> model) { @@ -115,7 +115,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:convertList} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override List<TARGET> convertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -134,7 +134,7 @@ class $Mappr implements AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override List<TARGET?> tryConvertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -150,7 +150,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:convertSet} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override Set<TARGET> convertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -169,7 +169,7 @@ class $Mappr implements AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override Set<TARGET?> tryConvertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { diff --git a/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart index 6be67932..ada2d394 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid-shadowing + import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart' as type; import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; @@ -37,13 +39,22 @@ ${sourceRecordType.positionalFields.map((e) => '${e.type}')} ${sourceRecordType.namedFields.map((e) => '${e.type} ${e.name}')} '''); - // Positional fields check. final sourcePositional = sourceRecordType.positionalFields; final targetPositional = targetRecordType.positionalFields; - if (sourcePositional.length != targetPositional.length) { - throw InvalidGenerationSourceError( - 'Positional source and target fields length mismatch for source $sourceType and target $targetType', - ); + // if (sourcePositional.length != targetPositional.length) { + // throw InvalidGenerationSourceError( + // 'Positional source and target fields length mismatch for source $sourceType and target $targetType', + // ); + // } + + // Positional fields check. + for (final (index, targetField) in targetPositional.indexed) { + final sourceField = sourcePositional.elementAtOrNull(index); + if (sourceField == null && targetField.type.nullabilitySuffix == NullabilitySuffix.none) { + throw InvalidGenerationSourceError( + 'Cannot map source field to non-nullable target field for source $sourceType and target $targetType', + ); + } } // Named fields check. @@ -58,6 +69,16 @@ ${sourceRecordType.namedFields.map((e) => '${e.type} ${e.name}')} } } + final positionalFields = <String>[ + for (final (index, targetField) in targetPositional.indexed) + _mapPositionalField( + assignment: assignment, + source: sourcePositional.elementAtOrNull(index), + target: targetField, + index: index + 1, + ).accept(DartEmitter()).toString(), + ]; + final namedFields = <({String key, String value})>[ for (final targetField in targetNamed) ( @@ -72,7 +93,7 @@ ${sourceRecordType.namedFields.map((e) => '${e.type} ${e.name}')} return CodeExpression( Code( - '(${namedFields.map((field) => '${field.key}: ${field.value}')})', + '(${positionalFields.join(',')} ${positionalFields.isNotEmpty ? ',' : ''} ${namedFields.map((field) => '${field.key}: ${field.value}').join(',')})', ), ); } @@ -108,4 +129,37 @@ ${sourceRecordType.namedFields.map((e) => '${e.type} ${e.name}')} return refer('${valueExpression.accept(DartEmitter())})'); } + + // Handles mapping of only one positional field. + // + // Generates + // - mapping for primitives: `model.$1` + // - mapping for complex types: `_map_NestedDto_To_Nested(model.$1)` + // - and when nullable and if `whenNullExpression` defined, uses that as a fallback + Expression _mapPositionalField({ + required SourceAssignment assignment, + required type.RecordTypePositionalField? source, + required type.RecordTypePositionalField target, + required int index, + }) { + if (source == null) return literalNull; + + final valuesAreSameType = source.type == target.type; + final shouldAssignNestedObject = !target.type.isPrimitiveType && !valuesAreSameType; + + final targetRecordExpression = refer(assignment.sourceField!.name); + + if (!shouldAssignNestedObject) { + return refer('model.${targetRecordExpression.accept(DartEmitter())}.\$$index'); + } + + final valueExpression = assignNestedObject( + assignment: assignment, + source: source.type, + target: target.type, + convertMethodArgument: valuesAreSameType ? null : targetRecordExpression, + ); + + return refer('${valueExpression.accept(DartEmitter())})'); + } } diff --git a/packages/auto_mappr/test/integration/fixture/record.dart b/packages/auto_mappr/test/integration/fixture/record.dart index 9e9b4cbe..74454579 100644 --- a/packages/auto_mappr/test/integration/fixture/record.dart +++ b/packages/auto_mappr/test/integration/fixture/record.dart @@ -1,23 +1,20 @@ // ignore_for_file: move-records-to-typedefs -import 'package:analyzer/dart/ast/visitor.dart'; import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; part 'record.g.dart'; -// TODO(records) @AutoMappr([ // simple - // MapType<PositionalDto, Positional>(), - // MapType<PositionalNullableDto, PositionalNullable>(), - // MapType<PositionalDto, PositionalNullable>(), - // MapType<PositionalNullableDto, Positional>(), // TODO + MapType<PositionalDto, Positional>(), + MapType<PositionalNullableDto, PositionalNullable>(), + MapType<PositionalDto, PositionalNullable>(), MapType<NamedDto, Named>(), MapType<NamedDto, NamedNullable>(), // complex - // MapType<ComplexDto, Complex>(), - // MapType<ComplexNullableDto, Complex>(), + MapType<ComplexPositionalDto, ComplexPositional>(), + MapType<ComplexNamedDto, ComplexNamed>(), ]) class Mappr extends $Mappr { const Mappr(); @@ -44,7 +41,8 @@ class PositionalDto extends Equatable { } class PositionalNullable extends Equatable { - final (int?, bool?, String?) value; + // ignore: prefer-trailing-comma, false positive + final (int?, bool?, String?, int?, bool?) value; @override List<Object?> get props => [value]; @@ -71,6 +69,7 @@ class Named extends Equatable { } class NamedNullable extends Equatable { + // ignore: prefer-trailing-comma, dcm has to fix this final ({int alpha, bool beta, String gama, int? delta, bool? epsilon}) value; @override @@ -90,58 +89,38 @@ class NamedDto extends Equatable { // complex -// class Complex extends Equatable { -// final Iterable<Nested> value; - -// @override -// List<Object?> get props => [value]; - -// const Complex(this.value); -// } - -// class ComplexDto extends Equatable { -// final Iterable<NestedDto> value; - -// @override -// List<Object?> get props => [value]; +class ComplexPositional extends Equatable { + final List<Positional> value; -// const ComplexDto(this.value); -// } - -// class ComplexNullableDto extends Equatable { -// final Iterable<NestedDto?> value; - -// @override -// List<Object?> get props => [value]; - -// const ComplexNullableDto(this.value); -// } + @override + List<Object?> get props => [value]; -// // List, Set, Iterable + const ComplexPositional(this.value); +} -// class ListHolder extends Equatable { -// final List<int> value; +class ComplexPositionalDto extends Equatable { + final List<PositionalDto> value; -// @override -// List<Object?> get props => [value]; + @override + List<Object?> get props => [value]; -// const ListHolder(this.value); -// } + const ComplexPositionalDto(this.value); +} -// class SetHolder extends Equatable { -// final Set<int> value; +class ComplexNamed extends Equatable { + final List<Named> value; -// @override -// List<Object?> get props => [value]; + @override + List<Object?> get props => [value]; -// const SetHolder(this.value); -// } + const ComplexNamed(this.value); +} -// class IterableHolder extends Equatable { -// final Iterable<int> value; +class ComplexNamedDto extends Equatable { + final List<NamedDto> value; -// @override -// List<Object?> get props => [value]; + @override + List<Object?> get props => [value]; -// const IterableHolder(this.value); -// } + const ComplexNamedDto(this.value); +} diff --git a/packages/auto_mappr/test/integration/record_test.dart b/packages/auto_mappr/test/integration/record_test.dart index 8e258941..9df9caac 100644 --- a/packages/auto_mappr/test/integration/record_test.dart +++ b/packages/auto_mappr/test/integration/record_test.dart @@ -14,28 +14,21 @@ void main() { const dto = fixture.PositionalDto((1, true, 'Brasil')); final converted = mappr.convert<fixture.PositionalDto, fixture.Positional>(dto); - expect(converted, equals(const fixture.Positional((1, true, 'yolo')))); + expect(converted, equals(const fixture.Positional((1, true, 'Brasil')))); }); test('positional nullable', () { const dto = fixture.PositionalNullableDto((2, false, 'New York')); final converted = mappr.convert<fixture.PositionalNullableDto, fixture.PositionalNullable>(dto); - expect(converted, equals(const fixture.PositionalNullable((2, false, 'New York')))); + expect(converted, equals(const fixture.PositionalNullable((2, false, 'New York', null, null)))); }); test('positional to positional nullable', () { const dto = fixture.PositionalDto((3, false, 'Prague')); final converted = mappr.convert<fixture.PositionalDto, fixture.PositionalNullable>(dto); - expect(converted, equals(const fixture.PositionalNullable((3, false, 'Prague')))); - }); - - test('positional nullable to positional', () { - const dto = fixture.PositionalNullableDto((4, true, 'Rome')); - final converted = mappr.convert<fixture.PositionalNullableDto, fixture.Positional>(dto); - - expect(converted, equals(const fixture.PositionalNullable((4, true, 'Rome')))); + expect(converted, equals(const fixture.PositionalNullable((3, false, 'Prague', null, null)))); }); test('named', () { @@ -45,4 +38,46 @@ void main() { expect(converted, equals(const fixture.Named((alpha: 5, beta: true, gama: 'Paris')))); }); }); + + group('complex', () { + test('positional', () { + const dto = fixture.ComplexPositionalDto([ + fixture.PositionalDto((33, true, 'qwerty')), + fixture.PositionalDto((123, true, 'qwertz')), + fixture.PositionalDto((999, true, 'dvorak')), + ]); + final converted = mappr.convert<fixture.ComplexPositionalDto, fixture.ComplexPositional>(dto); + + expect( + converted, + equals( + const fixture.ComplexPositional([ + fixture.Positional((33, true, 'qwerty')), + fixture.Positional((123, true, 'qwertz')), + fixture.Positional((999, true, 'dvorak')), + ]), + ), + ); + }); + + test('named', () { + const dto = fixture.ComplexNamedDto([ + fixture.NamedDto((alpha: 12333, beta: true, gama: 'qwerty')), + fixture.NamedDto((alpha: 123123, beta: true, gama: 'qwertz')), + fixture.NamedDto((alpha: 123999, beta: true, gama: 'dvorak')), + ]); + final converted = mappr.convert<fixture.ComplexNamedDto, fixture.ComplexNamed>(dto); + + expect( + converted, + equals( + const fixture.ComplexNamed([ + fixture.Named((alpha: 12333, beta: true, gama: 'qwerty')), + fixture.Named((alpha: 123123, beta: true, gama: 'qwertz')), + fixture.Named((alpha: 123999, beta: true, gama: 'dvorak')), + ]), + ), + ); + }); + }); } From 6210a9f0c51dfde3c3b8534554ad02aa02400ecb Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 4 Sep 2023 08:24:24 +0200 Subject: [PATCH 09/48] Cleanup --- .../assignments/record_assignment_builder.dart | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart index ada2d394..39ab0bb7 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart @@ -6,7 +6,6 @@ import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart' import 'package:auto_mappr/src/builder/assignments/nested_object_mixin.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/models/source_assignment.dart'; -import 'package:build/build.dart'; import 'package:code_builder/code_builder.dart'; import 'package:collection/collection.dart'; import 'package:source_gen/source_gen.dart'; @@ -26,33 +25,21 @@ class RecordAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMix @override Expression buildAssignment() { - // TODO(records): assignment.fieldMapping handle -> whenNullExpression, custom final sourceType = assignment.sourceType!; final targetType = assignment.targetType; final sourceRecordType = sourceType as type.RecordType; final targetRecordType = targetType as type.RecordType; - log.warning(''' --- RECORDS -- -${sourceRecordType.positionalFields.map((e) => '${e.type}')} -${sourceRecordType.namedFields.map((e) => '${e.type} ${e.name}')} -'''); - final sourcePositional = sourceRecordType.positionalFields; final targetPositional = targetRecordType.positionalFields; - // if (sourcePositional.length != targetPositional.length) { - // throw InvalidGenerationSourceError( - // 'Positional source and target fields length mismatch for source $sourceType and target $targetType', - // ); - // } // Positional fields check. for (final (index, targetField) in targetPositional.indexed) { final sourceField = sourcePositional.elementAtOrNull(index); if (sourceField == null && targetField.type.nullabilitySuffix == NullabilitySuffix.none) { throw InvalidGenerationSourceError( - 'Cannot map source field to non-nullable target field for source $sourceType and target $targetType', + 'Cannot map positional source field to non-nullable target field for source $sourceType and target $targetType', ); } } From 6b5220d59af7c5416f469ab5dcb266f8e213b721 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 4 Sep 2023 12:52:07 +0200 Subject: [PATCH 10/48] Update modules README --- packages/auto_mappr/README.md | 106 ++++++++++++++++++++++++---------- 1 file changed, 75 insertions(+), 31 deletions(-) diff --git a/packages/auto_mappr/README.md b/packages/auto_mappr/README.md index b450568c..b2292879 100644 --- a/packages/auto_mappr/README.md +++ b/packages/auto_mappr/README.md @@ -542,48 +542,94 @@ while using shared part builder. ### Modules Each AutoMappr class can be used as a **module**. -That means a mappr used inside of another mappr. -Each AutoMappr class can include a list of modules -that can be used to nest modules -and use all of its underlying mappings. +The only rule is that the mappr must be constant, +and that most of the time means you have to add an `const` constructor to be able to use it. +Other modules (AutoMappr classes) can then use it in two ways. -Note that modules work as disjunctive units -and their mappings cannot be internally used by by mappr that imported it. -They only work for grouping at the moment. +#### Importing -Applications are often split into independent parts (we will call them **features**). -Each feature should probably have its own independent mappr, -that is used as a module. +Note: Feature TBA -Imagine that in a feature you have a local mappr `UserMappr`. +Importing a module means that you want to "absorb" it's mappings +and use them later anywhere **inside** any mapped object. +Basically imagine copy-pasting definitions from imported module to yours. + +That can be handy when you have a common/shared mappr with mappings between objects shared across the app. +Since you want to use these common/shared mappings, +you **include** them in your mappr. ```dart -// file: user_mappr.dart -@AutoMappr([ - MapType<UserDto, User>(), -]) -class UserMappr extends $UserMappr { - const UserMappr(); // must implement const constructor +// file: shared_mappr.dart +@AutoMappr( + [ + MapType<AddressDto, Address>(), + ], +) +class SharedMappr extends $SharedMappr { + const SharedMappr(); // must be const! } + +// file: user_mappr.dart +@AutoMappr( + [ + MapType<UserDto, User>(), // UserDto uses AddressDto inside + ], + includes: [SharedMappr()], // include shared mappr +) +class UserMappr extends $UserMappr {} + +// file: settings_mappr.dart +@AutoMappr( + [ + MapType<ProfileDto, Profile>(), // ProfileDto uses AddressDto inside + ], + includes: [SharedMappr()], // include shared mappr +) +class SettingsMappr extends $SettingsMappr {} ``` -And in some global place, -you can have a main mappr that unifies all smaller mapprs -(`UserMappr` in this case). -As usual, it can also set it's own mappings -(`MapType<GroupDto, Group>()`). +#### Delegating + +Delegating to a module is a bit different from including them. +A mappr **delegates** to a **standalone** module. +When your mappr does not know how to convert the **top level object** (the object you put inside `mappr.convert()` method), +it asks delegates to do it. +So you can think of them as disjunctive units that are **grouped** together. + +This is usefull when you have an app with a mappr for each feature +and you want to create one main mappr using other feature mapprs. +The main mappr may not have any mapping at all +and it delegates everything to feature mapprs. ```dart // file: main_mappr.dart +@AutoMappr( + [], + delegates: [ + UserFeatureMappr(), + SettingsFeatureMappr(), + // other features + ], +) +class MainMappr extends $MainMappr {} + +// file: user_feature_mappr.dart @AutoMappr( [ - MapType<GroupDto, Group>(), + MapType<UserDto, User>(), + MapType<AddressDto, Address>(), ], - modules: [ - UserMappr(), // use module +) +class UserFeatureMappr extends $UserFeatureMappr {} + +// file: settings_feature_mappr.dart +@AutoMappr( + [ + MapType<UserDto, User>(), + MapType<AddressDto, Address>(), ], ) -class MainMappr extends $MainMappr {} +class SettingsFeatureMappr extends $SettingsFeatureMappr {} ``` Then you can use this main mappr to map between objects specified from every included mappr. @@ -591,14 +637,12 @@ Then you can use this main mappr to map between objects specified from every inc ```dart final mappr = MainMappr(); -final Group user = mappr.convert(GroupDto(...)); // from this mappr -final User user = mappr.convert(UserDto(...)); // from included mappr +final Settings settings = mappr.convert(SettingsDto(...)); // delegates to settings feature mappr +final User user = mappr.convert(UserDto(...)); // delegates to user feature mappr ``` That can be handy for example with dependency injection, -so you can only provide one grouping/main mappr that can handle everything. -Each feature in your app can return an instance of const `AutoMapprInterface`, -that each mappr internally implements. +so you can only provide one main mappr that can handle everything by delegating to other mapprs. ### Reverse mapping From 221c43f23ed06c4921cfa56fd538515f39a6d66e Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 4 Sep 2023 14:46:04 +0200 Subject: [PATCH 11/48] Update --- melos.yaml | 7 +- packages/auto_mappr/README.md | 2 +- packages/auto_mappr/build.yaml | 3 + packages/auto_mappr/example/lib/mappr.g.dart | 216 ------------------ .../methods/can_convert_method_builder.dart | 2 +- .../convert_iterable_method_builder.dart | 2 +- .../methods/convert_method_builder.dart | 2 +- .../builder/methods/method_builder_base.dart | 2 + .../private_modules_method_builder.dart | 2 +- .../try_convert_iterable_method_builder.dart | 2 +- .../methods/try_convert_method_builder.dart | 2 +- .../src/generator/auto_mappr_generator.dart | 78 +++++-- ...{modules_test.dart => delegates_test.dart} | 2 +- .../fixture/{modules.dart => delegates.dart} | 4 +- .../fixture/delegates/module_alpha.dart | 26 +++ .../fixture/delegates/module_beta.dart | 26 +++ .../{modules => delegates}/module_gama.dart | 0 .../integration/fixture/import_alias.dart | 2 +- .../test/integration/fixture/includes.dart | 31 +++ .../{modules => includes}/module_alpha.dart | 2 +- .../{modules => includes}/module_beta.dart | 2 +- .../fixture/includes/module_gama.dart | 24 ++ .../lib/src/auto_mappr.dart | 11 +- 23 files changed, 196 insertions(+), 254 deletions(-) delete mode 100644 packages/auto_mappr/example/lib/mappr.g.dart rename packages/auto_mappr/test/integration/{modules_test.dart => delegates_test.dart} (99%) rename packages/auto_mappr/test/integration/fixture/{modules.dart => delegates.dart} (81%) create mode 100644 packages/auto_mappr/test/integration/fixture/delegates/module_alpha.dart create mode 100644 packages/auto_mappr/test/integration/fixture/delegates/module_beta.dart rename packages/auto_mappr/test/integration/fixture/{modules => delegates}/module_gama.dart (100%) create mode 100644 packages/auto_mappr/test/integration/fixture/includes.dart rename packages/auto_mappr/test/integration/fixture/{modules => includes}/module_alpha.dart (86%) rename packages/auto_mappr/test/integration/fixture/{modules => includes}/module_beta.dart (86%) create mode 100644 packages/auto_mappr/test/integration/fixture/includes/module_gama.dart diff --git a/melos.yaml b/melos.yaml index 0627e6ff..c6879b29 100644 --- a/melos.yaml +++ b/melos.yaml @@ -1,9 +1,10 @@ name: auto_mappr_workspace packages: - - packages/** - - packages/**/example - - examples/** + - packages/auto_mappr + # - packages/** + # - packages/**/example + # - examples/** command: bootstrap: diff --git a/packages/auto_mappr/README.md b/packages/auto_mappr/README.md index b2292879..5a0586eb 100644 --- a/packages/auto_mappr/README.md +++ b/packages/auto_mappr/README.md @@ -541,7 +541,7 @@ while using shared part builder. ### Modules -Each AutoMappr class can be used as a **module**. +Each AutoMappr can be considered as a **module**. The only rule is that the mappr must be constant, and that most of the time means you have to add an `const` constructor to be able to use it. Other modules (AutoMappr classes) can then use it in two ways. diff --git a/packages/auto_mappr/build.yaml b/packages/auto_mappr/build.yaml index 905672fe..1ee463a8 100644 --- a/packages/auto_mappr/build.yaml +++ b/packages/auto_mappr/build.yaml @@ -4,6 +4,9 @@ targets: :auto_mappr: enabled: true generate_for: + include: + - test/integration/fixture/includes.dart + - test/integration/fixture/includes/** exclude: - test/integration/error_fixture/** options: diff --git a/packages/auto_mappr/example/lib/mappr.g.dart b/packages/auto_mappr/example/lib/mappr.g.dart deleted file mode 100644 index 596834af..00000000 --- a/packages/auto_mappr/example/lib/mappr.g.dart +++ /dev/null @@ -1,216 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'mappr.dart'; - -// ************************************************************************** -// AutoMapprGenerator -// ************************************************************************** - -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings - -/// {@template asset:auto_mappr/example/lib/mappr.dart} -/// Available mappings: -/// - `UserDto` → `User`. -/// {@endtemplate} -class $Mappr implements AutoMapprInterface { - const $Mappr(); - - Type _typeOf<T>() => T; - List<AutoMapprInterface> get _modules => const []; - - /// {@macro AutoMapprInterface:canConvert} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - bool canConvert<SOURCE, TARGET>({bool recursive = true}) { - final sourceTypeOf = _typeOf<SOURCE>(); - final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { - return true; - } - if (recursive) { - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return true; - } - } - } - return false; - } - - /// {@macro AutoMapprInterface:convert} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - TARGET convert<SOURCE, TARGET>(SOURCE? model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return _convert(model)!; - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.convert(model)!; - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// {@macro AutoMapprInterface:tryConvert} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - TARGET? tryConvert<SOURCE, TARGET>(SOURCE? model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return _convert( - model, - canReturnNull: true, - ); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.tryConvert(model); - } - } - - return null; - } - - /// {@macro AutoMapprInterface:convertIterable} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - Iterable<TARGET> convertIterable<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return model.map<TARGET>((item) => _convert(item)!); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.convertIterable(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into Iterable. - /// - /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null - /// - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - Iterable<TARGET?> tryConvertIterable<SOURCE, TARGET>( - Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.tryConvertIterable(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// {@macro AutoMapprInterface:convertList} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - List<TARGET> convertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return convertIterable<SOURCE, TARGET>(model).toList(); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.convertList(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into List. - /// - /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null - /// - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - List<TARGET?> tryConvertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return tryConvertIterable<SOURCE, TARGET>(model).toList(); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.tryConvertList(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// {@macro AutoMapprInterface:convertSet} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - Set<TARGET> convertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return convertIterable<SOURCE, TARGET>(model).toSet(); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.convertSet(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into Set. - /// - /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null - /// - /// {@macro asset:auto_mappr/example/lib/mappr.dart} - @override - Set<TARGET?> tryConvertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { - if (canConvert<SOURCE, TARGET>(recursive: false)) { - return tryConvertIterable<SOURCE, TARGET>(model).toSet(); - } - for (final mappr in _modules) { - if (mappr.canConvert<SOURCE, TARGET>()) { - return mappr.tryConvertSet(model); - } - } - - throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); - } - - TARGET? _convert<SOURCE, TARGET>( - SOURCE? model, { - bool canReturnNull = false, - }) { - final sourceTypeOf = _typeOf<SOURCE>(); - final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { - if (canReturnNull && model == null) { - return null; - } - return (_map__UserDto__To__User((model as UserDto?)) as TARGET); - } - throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); - } - - User _map__UserDto__To__User(UserDto? input) { - final model = input; - if (model == null) { - throw Exception( - r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' - r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); - } - return User( - id: model.id, - name: model.xname, - ); - } -} diff --git a/packages/auto_mappr/lib/src/builder/methods/can_convert_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/can_convert_method_builder.dart index 82c404df..7c78a90c 100644 --- a/packages/auto_mappr/lib/src/builder/methods/can_convert_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/can_convert_method_builder.dart @@ -63,7 +63,7 @@ class CanConvertMethodBuilder extends MethodBuilderBase implements CallableMetho condition: refer('recursive'), ifBody: ExpressionExtension.forStatement( item: refer('mappr'), - iterable: refer('_modules'), + iterable: refer(MethodBuilderBase.delegatesField), body: ExpressionExtension.ifStatement( condition: CanConvertMethodBuilder(config).propertyCall(on: refer('mappr')), ifBody: literalTrue.returned.statement, diff --git a/packages/auto_mappr/lib/src/builder/methods/convert_iterable_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/convert_iterable_method_builder.dart index 19c38ca2..6fcc683b 100644 --- a/packages/auto_mappr/lib/src/builder/methods/convert_iterable_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/convert_iterable_method_builder.dart @@ -81,7 +81,7 @@ class ConvertIterableMethodBuilder extends MethodBuilderBase { block.statements.add( ExpressionExtension.forStatement( item: refer('mappr'), - iterable: refer('_modules'), + iterable: refer(MethodBuilderBase.delegatesField), body: ExpressionExtension.ifStatement( condition: CanConvertMethodBuilder(config).propertyCall(on: refer('mappr')), ifBody: refer('mappr').property('convert$wrapper').call([refer('model')], {}, []).returned.statement, diff --git a/packages/auto_mappr/lib/src/builder/methods/convert_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/convert_method_builder.dart index 8b59ff69..ebf16562 100644 --- a/packages/auto_mappr/lib/src/builder/methods/convert_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/convert_method_builder.dart @@ -56,7 +56,7 @@ class ConvertMethodBuilder extends MethodBuilderBase { block.statements.add( ExpressionExtension.forStatement( item: refer('mappr'), - iterable: refer('_modules'), + iterable: refer(MethodBuilderBase.delegatesField), body: ExpressionExtension.ifStatement( condition: CanConvertMethodBuilder(config).propertyCall(on: refer('mappr')), ifBody: refer('mappr').property('convert').call([refer('model')], {}, []).nullChecked.returned.statement, diff --git a/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart b/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart index f61d9240..9e015227 100644 --- a/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart +++ b/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart @@ -9,6 +9,8 @@ import 'package:meta/meta.dart'; /// Base class for method builders. abstract class MethodBuilderBase { + static const delegatesField = '_delegates'; + static const sourceKey = 'SOURCE'; static const sourceTypeReference = Reference(sourceKey); static const nullableSourceTypeReference = Reference('$sourceKey?'); diff --git a/packages/auto_mappr/lib/src/builder/methods/private_modules_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/private_modules_method_builder.dart index a01ad827..406498b6 100644 --- a/packages/auto_mappr/lib/src/builder/methods/private_modules_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/private_modules_method_builder.dart @@ -8,7 +8,7 @@ class PrivateModulesMethodBuilder extends MethodBuilderBase { Method buildMethod() { return Method( (builder) => builder - ..name = '_modules' + ..name = MethodBuilderBase.delegatesField ..returns = refer('List<AutoMapprInterface>') ..lambda = true ..type = MethodType.getter diff --git a/packages/auto_mappr/lib/src/builder/methods/try_convert_iterable_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/try_convert_iterable_method_builder.dart index 90d72efe..cba40c6a 100644 --- a/packages/auto_mappr/lib/src/builder/methods/try_convert_iterable_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/try_convert_iterable_method_builder.dart @@ -90,7 +90,7 @@ class TryConvertIterableMethodBuilder extends MethodBuilderBase { block.statements.add( ExpressionExtension.forStatement( item: refer('mappr'), - iterable: refer('_modules'), + iterable: refer(MethodBuilderBase.delegatesField), body: ExpressionExtension.ifStatement( condition: CanConvertMethodBuilder(config).propertyCall(on: refer('mappr')), ifBody: refer('mappr').property('tryConvert$wrapper').call([refer('model')], {}, []).returned.statement, diff --git a/packages/auto_mappr/lib/src/builder/methods/try_convert_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/try_convert_method_builder.dart index 71809d4a..65bead72 100644 --- a/packages/auto_mappr/lib/src/builder/methods/try_convert_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/try_convert_method_builder.dart @@ -58,7 +58,7 @@ class TryConvertMethodBuilder extends MethodBuilderBase { block.statements.add( ExpressionExtension.forStatement( item: refer('mappr'), - iterable: refer('_modules'), + iterable: refer(MethodBuilderBase.delegatesField), body: ExpressionExtension.ifStatement( condition: CanConvertMethodBuilder(config).propertyCall(on: refer('mappr')), ifBody: refer('mappr').property('tryConvert').call([refer('model')], {}, []).returned.statement, diff --git a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart index 231c208b..9ff7243e 100644 --- a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart +++ b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart @@ -19,6 +19,27 @@ import 'package:source_gen/source_gen.dart'; class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { final BuilderOptions builderOptions; + // Constants for AutoMappr. + static const String annotationName = 'AutoMappr'; + static const String annotationFieldDelegates = 'delegates'; + static const String annotationFieldMappers = 'mappers'; + static const String annotationFieldIncludes = 'includes'; + + // Constants for MapType. + static const String mapTypeFieldFields = 'fields'; + static const String mapTypeFieldWhenSourceIsNull = 'whenSourceIsNull'; + static const String mapTypeFieldConstructor = 'constructor'; + static const String mapTypeFieldIgnoreFieldNull = 'ignoreFieldNull'; + static const String mapTypeFieldReverse = 'reverse'; + + // Constants for Field. + static const String fieldFieldField = 'field'; + static const String fieldFieldIgnore = 'ignore'; + static const String fieldFieldFrom = 'from'; + static const String fieldFieldCustom = 'custom'; + static const String fieldFieldWhenNull = 'whenNull'; + static const String fieldFieldIgnoreNull = 'ignoreNull'; + const AutoMapprGenerator({required this.builderOptions}); @override @@ -43,13 +64,31 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { ); final constant = annotation.objectValue; - final mappersField = constant.getField('mappers')!; - final mappersList = mappersField.toListValue()!; - final modulesExpression = constant.getField('modules')!.toCodeExpression(config: tmpConfig); - final modulesList = constant.getField('modules')!.toListValue(); + final mappersList = constant.getField(annotationFieldMappers)!.toListValue()!; + final delegatesExpression = constant.getField(annotationFieldDelegates)!.toCodeExpression(config: tmpConfig); + final delegatesList = constant.getField(annotationFieldDelegates)!.toListValue(); + final includesList = constant.getField(annotationFieldIncludes)!.toListValue(); + + final allMappers = [...mappersList]; + + for (final include in includesList ?? <DartObject>[]) { + if (include.type?.element?.metadata + .firstWhereOrNull((data) => data.element?.displayName == annotationName) + ?.computeConstantValue() + case final includeConstant?) { + final mappersList2 = includeConstant.getField(annotationFieldMappers)!.toListValue()!; + // final delegatesExpression2 = includeConstant.getField(fieldDelegates)!.toCodeExpression(config: tmpConfig); + // final delegatesList2 = includeConstant.getField(fieldDelegates)!.toListValue(); + // final includesList2 = includeConstant.getField(fieldIncludes)!.toListValue(); + + allMappers.addAll(mappersList2); + } + } + + log.warning('all mappings = ${allMappers.join(',\n')} ...'); final mappers = _processMappers( - mappers: mappersList, + mappers: allMappers, element: element, config: tmpConfig, ); @@ -67,8 +106,8 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { mappers: mappers, availableMappingsMacroId: element.library.identifier, libraryUriToAlias: libraryUriToAlias, - modulesCode: modulesExpression, - modulesList: modulesList ?? [], + modulesCode: delegatesExpression, + modulesList: delegatesList ?? [], mapprOptions: mapprOptions, ); @@ -107,22 +146,23 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { ); } - final fields = mapper.getField('fields')?.toListValue(); - final whenSourceIsNull = mapper.getField('whenSourceIsNull')?.toCodeExpression(config: config); - final constructor = mapper.getField('constructor')?.toStringValue(); - final ignoreFieldNull = mapper.getField('ignoreFieldNull')?.toBoolValue(); - final reverse = mapper.getField('reverse')?.toBoolValue(); + final fields = mapper.getField(mapTypeFieldFields)?.toListValue(); + final whenSourceIsNull = mapper.getField(mapTypeFieldWhenSourceIsNull)?.toCodeExpression(config: config); + final constructor = mapper.getField(mapTypeFieldConstructor)?.toStringValue(); + final ignoreFieldNull = mapper.getField(mapTypeFieldIgnoreFieldNull)?.toBoolValue(); + final reverse = mapper.getField(mapTypeFieldReverse)?.toBoolValue(); final fieldMappings = fields ?.map( (fieldMapping) => FieldMapping( - field: fieldMapping.getField('field')!.toStringValue()!, - ignore: fieldMapping.getField('ignore')!.toBoolValue()!, - from: fieldMapping.getField('from')!.toStringValue(), - customExpression: - fieldMapping.getField('custom')!.toCodeExpression(passModelArgument: true, config: config), - whenNullExpression: fieldMapping.getField('whenNull')!.toCodeExpression(config: config), - ignoreNull: fieldMapping.getField('ignoreNull')?.toBoolValue(), + field: fieldMapping.getField(fieldFieldField)!.toStringValue()!, + ignore: fieldMapping.getField(fieldFieldIgnore)!.toBoolValue()!, + from: fieldMapping.getField(fieldFieldFrom)!.toStringValue(), + customExpression: fieldMapping + .getField(fieldFieldCustom)! + .toCodeExpression(passModelArgument: true, config: config), + whenNullExpression: fieldMapping.getField(fieldFieldWhenNull)!.toCodeExpression(config: config), + ignoreNull: fieldMapping.getField(fieldFieldIgnoreNull)?.toBoolValue(), ), ) .toList(); diff --git a/packages/auto_mappr/test/integration/modules_test.dart b/packages/auto_mappr/test/integration/delegates_test.dart similarity index 99% rename from packages/auto_mappr/test/integration/modules_test.dart rename to packages/auto_mappr/test/integration/delegates_test.dart index 639bb87f..5d6f64b0 100644 --- a/packages/auto_mappr/test/integration/modules_test.dart +++ b/packages/auto_mappr/test/integration/delegates_test.dart @@ -1,6 +1,6 @@ import 'package:test/test.dart'; -import 'fixture/modules.dart' as fixture_group; +import 'fixture/delegates.dart' as fixture_group; import 'fixture/modules/module_alpha.dart' as fixture_alpha; import 'fixture/modules/module_beta.dart' as fixture_beta; import 'fixture/modules/module_gama.dart' as fixture_gama; diff --git a/packages/auto_mappr/test/integration/fixture/modules.dart b/packages/auto_mappr/test/integration/fixture/delegates.dart similarity index 81% rename from packages/auto_mappr/test/integration/fixture/modules.dart rename to packages/auto_mappr/test/integration/fixture/delegates.dart index da0df0ba..b5f873ca 100644 --- a/packages/auto_mappr/test/integration/fixture/modules.dart +++ b/packages/auto_mappr/test/integration/fixture/delegates.dart @@ -3,9 +3,9 @@ import 'package:equatable/equatable.dart'; import 'modules/module_alpha.dart'; -part 'modules.g.dart'; +part 'delegates.g.dart'; -@AutoMappr([MapType<GroupDto, Group>()], modules: [MapprAlpha()]) +@AutoMappr([MapType<GroupDto, Group>()], delegates: [MapprAlpha()]) class MapprGroup extends $MapprGroup { const MapprGroup(); } diff --git a/packages/auto_mappr/test/integration/fixture/delegates/module_alpha.dart b/packages/auto_mappr/test/integration/fixture/delegates/module_alpha.dart new file mode 100644 index 00000000..c9ca910e --- /dev/null +++ b/packages/auto_mappr/test/integration/fixture/delegates/module_alpha.dart @@ -0,0 +1,26 @@ +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +import 'package:equatable/equatable.dart'; + +import 'module_beta.dart'; + +part 'module_alpha.g.dart'; + +@AutoMappr([MapType<AlphaDto, Alpha>()], delegates: [MapprBeta()]) +class MapprAlpha extends $MapprAlpha { + const MapprAlpha(); +} + +class AlphaDto { + final int value; + + const AlphaDto(this.value); +} + +class Alpha with EquatableMixin { + final int value; + + @override + List<Object?> get props => [value]; + + const Alpha(this.value); +} diff --git a/packages/auto_mappr/test/integration/fixture/delegates/module_beta.dart b/packages/auto_mappr/test/integration/fixture/delegates/module_beta.dart new file mode 100644 index 00000000..17e1b0d1 --- /dev/null +++ b/packages/auto_mappr/test/integration/fixture/delegates/module_beta.dart @@ -0,0 +1,26 @@ +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +import 'package:equatable/equatable.dart'; + +import 'module_gama.dart'; + +part 'module_beta.g.dart'; + +@AutoMappr([MapType<BetaDto, Beta>()], delegates: [MapprGama()]) +class MapprBeta extends $MapprBeta { + const MapprBeta(); +} + +class BetaDto { + final int value; + + const BetaDto(this.value); +} + +class Beta with EquatableMixin { + final int value; + + @override + List<Object?> get props => [value]; + + const Beta(this.value); +} diff --git a/packages/auto_mappr/test/integration/fixture/modules/module_gama.dart b/packages/auto_mappr/test/integration/fixture/delegates/module_gama.dart similarity index 100% rename from packages/auto_mappr/test/integration/fixture/modules/module_gama.dart rename to packages/auto_mappr/test/integration/fixture/delegates/module_gama.dart diff --git a/packages/auto_mappr/test/integration/fixture/import_alias.dart b/packages/auto_mappr/test/integration/fixture/import_alias.dart index 84308046..4bb75de6 100644 --- a/packages/auto_mappr/test/integration/fixture/import_alias.dart +++ b/packages/auto_mappr/test/integration/fixture/import_alias.dart @@ -27,7 +27,7 @@ part 'import_alias.g.dart'; MapType<ListHolder<UserDto>, ListHolder<a1.User>>(), MapType<MapHolder<UserDto>, MapHolder<a2.User>>(), ], - modules: [module.ImportAliasModule()], + delegates: [module.ImportAliasModule()], ) class Mappr extends $Mappr { const Mappr(); diff --git a/packages/auto_mappr/test/integration/fixture/includes.dart b/packages/auto_mappr/test/integration/fixture/includes.dart new file mode 100644 index 00000000..338f3120 --- /dev/null +++ b/packages/auto_mappr/test/integration/fixture/includes.dart @@ -0,0 +1,31 @@ +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +import 'package:equatable/equatable.dart'; + +import 'includes/module_gama.dart'; +// import 'includes/module_alpha.dart' as alpha_feature; + +part 'includes.g.dart'; + +@AutoMappr([MapType<GroupDto, Group>()], includes: [MapprGama()]) +class MapprGroup extends $MapprGroup { + const MapprGroup(); +} + +class GroupDto { + // final AlphaDto alpha; + // final BetaDto beta; + final GamaDto gama; + + const GroupDto(this.gama); +} + +class Group with EquatableMixin { + // final Alpha alpha; + // final Beta beta; + final Gama gama; + + @override + List<Object?> get props => [gama]; + + const Group(this.gama); +} diff --git a/packages/auto_mappr/test/integration/fixture/modules/module_alpha.dart b/packages/auto_mappr/test/integration/fixture/includes/module_alpha.dart similarity index 86% rename from packages/auto_mappr/test/integration/fixture/modules/module_alpha.dart rename to packages/auto_mappr/test/integration/fixture/includes/module_alpha.dart index d4ab7cb9..ec313d6e 100644 --- a/packages/auto_mappr/test/integration/fixture/modules/module_alpha.dart +++ b/packages/auto_mappr/test/integration/fixture/includes/module_alpha.dart @@ -5,7 +5,7 @@ import 'module_beta.dart'; part 'module_alpha.g.dart'; -@AutoMappr([MapType<AlphaDto, Alpha>()], modules: [MapprBeta()]) +@AutoMappr([MapType<AlphaDto, Alpha>()], includes: [MapprBeta()]) class MapprAlpha extends $MapprAlpha { const MapprAlpha(); } diff --git a/packages/auto_mappr/test/integration/fixture/modules/module_beta.dart b/packages/auto_mappr/test/integration/fixture/includes/module_beta.dart similarity index 86% rename from packages/auto_mappr/test/integration/fixture/modules/module_beta.dart rename to packages/auto_mappr/test/integration/fixture/includes/module_beta.dart index 95f5d516..78bfc57d 100644 --- a/packages/auto_mappr/test/integration/fixture/modules/module_beta.dart +++ b/packages/auto_mappr/test/integration/fixture/includes/module_beta.dart @@ -5,7 +5,7 @@ import 'module_gama.dart'; part 'module_beta.g.dart'; -@AutoMappr([MapType<BetaDto, Beta>()], modules: [MapprGama()]) +@AutoMappr([MapType<BetaDto, Beta>()], includes: [MapprGama()]) class MapprBeta extends $MapprBeta { const MapprBeta(); } diff --git a/packages/auto_mappr/test/integration/fixture/includes/module_gama.dart b/packages/auto_mappr/test/integration/fixture/includes/module_gama.dart new file mode 100644 index 00000000..fee4a6d6 --- /dev/null +++ b/packages/auto_mappr/test/integration/fixture/includes/module_gama.dart @@ -0,0 +1,24 @@ +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +import 'package:equatable/equatable.dart'; + +part 'module_gama.g.dart'; + +@AutoMappr([MapType<GamaDto, Gama>()]) +class MapprGama extends $MapprGama { + const MapprGama(); +} + +class GamaDto { + final int value; + + const GamaDto(this.value); +} + +class Gama with EquatableMixin { + final int value; + + @override + List<Object?> get props => [value]; + + const Gama(this.value); +} diff --git a/packages/auto_mappr_annotation/lib/src/auto_mappr.dart b/packages/auto_mappr_annotation/lib/src/auto_mappr.dart index e45ea2cb..cac577f1 100644 --- a/packages/auto_mappr_annotation/lib/src/auto_mappr.dart +++ b/packages/auto_mappr_annotation/lib/src/auto_mappr.dart @@ -6,12 +6,17 @@ final class AutoMappr { /// List of mapprs. final List<MapType<Object, Object>> mappers; - /// List of other AutoMappr classes to use as modules. + /// List of mapprs that should be included to this mappr. + /// + /// Imagine copy-pasting mappings from included mappr to this one. + final List<AutoMapprInterface>? includes; + + /// List of mapprs used as delegates. /// /// When current mappr cannot convert source to target, /// it lets modules in order try to convert it instead. - final List<AutoMapprInterface>? modules; + final List<AutoMapprInterface>? delegates; /// Constructs AutoMappr. - const AutoMappr(this.mappers, {this.modules}); + const AutoMappr(this.mappers, {this.includes, this.delegates}); } From 5ed883e8c90582adbc386d0508771860df2f0f9b Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 4 Sep 2023 14:47:09 +0200 Subject: [PATCH 12/48] Fix issues --- packages/auto_mappr/README.md | 2 +- packages/auto_mappr/build.yaml | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/auto_mappr/README.md b/packages/auto_mappr/README.md index f319ef5c..30f819a8 100644 --- a/packages/auto_mappr/README.md +++ b/packages/auto_mappr/README.md @@ -620,7 +620,7 @@ Converting records is supported for both positional and named record's fields. Target positional fields must have their source field equivalent. Target named fields must have their source field equivalent determined by name. -Bot positional and named target fields without source equivalent must be nullable in order +Both positional and named target fields without source equivalent must be nullable in order for mapping to be created successfully and then thier value will be `null`. diff --git a/packages/auto_mappr/build.yaml b/packages/auto_mappr/build.yaml index 4ab62f38..905672fe 100644 --- a/packages/auto_mappr/build.yaml +++ b/packages/auto_mappr/build.yaml @@ -4,8 +4,6 @@ targets: :auto_mappr: enabled: true generate_for: - # include: - # - test/integration/fixture/record.dart exclude: - test/integration/error_fixture/** options: From 6d8d8039f7c2d2a1036603b3e1d28284d8c3d382 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 4 Sep 2023 15:32:51 +0200 Subject: [PATCH 13/48] Add includes test --- examples/drift/lib/mappr.g.dart | 20 +- examples/example/lib/enum.g.dart | 20 +- examples/example/lib/equatable.g.dart | 20 +- examples/example/lib/nested.g.dart | 20 +- examples/example/lib/nullable.g.dart | 20 +- examples/example/lib/rename.g.dart | 20 +- examples/freezed/lib/freezed_example.g.dart | 20 +- examples/injectable/lib/mappr.g.dart | 20 +- .../json_serializable/lib/serializable.g.dart | 20 +- .../test/fixture/json_serializable.g.dart | 20 +- melos.yaml | 7 +- packages/auto_mappr/build.yaml | 3 - packages/auto_mappr/example/lib/mappr.g.dart | 216 ++++++ .../src/generator/auto_mappr_generator.dart | 48 +- .../test/integration/delegates_test.dart | 6 +- .../test/integration/fixture/includes.dart | 19 +- .../test/integration/includes_test.dart | 660 ++++++++++++++++++ 17 files changed, 1020 insertions(+), 139 deletions(-) create mode 100644 packages/auto_mappr/example/lib/mappr.g.dart create mode 100644 packages/auto_mappr/test/integration/includes_test.dart diff --git a/examples/drift/lib/mappr.g.dart b/examples/drift/lib/mappr.g.dart index 5b8a0208..717d0c4c 100644 --- a/examples/drift/lib/mappr.g.dart +++ b/examples/drift/lib/mappr.g.dart @@ -20,7 +20,7 @@ class $Mappr implements AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _modules => const []; + List<AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_drift/mappr.dart} @@ -34,7 +34,7 @@ class $Mappr implements AutoMapprInterface { return true; } if (recursive) { - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return true; } @@ -50,7 +50,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return _convert(model)!; } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convert(model)!; } @@ -69,7 +69,7 @@ class $Mappr implements AutoMapprInterface { canReturnNull: true, ); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvert(model); } @@ -85,7 +85,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET>((item) => _convert(item)!); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertIterable(model); } @@ -105,7 +105,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertIterable(model); } @@ -121,7 +121,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertList(model); } @@ -140,7 +140,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertList(model); } @@ -156,7 +156,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertSet(model); } @@ -175,7 +175,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertSet(model); } diff --git a/examples/example/lib/enum.g.dart b/examples/example/lib/enum.g.dart index 6cdd3e9e..7e05cc9d 100644 --- a/examples/example/lib/enum.g.dart +++ b/examples/example/lib/enum.g.dart @@ -22,7 +22,7 @@ class $Mappr implements AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _modules => const []; + List<AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_example/enum.dart} @@ -49,7 +49,7 @@ class $Mappr implements AutoMapprInterface { return true; } if (recursive) { - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return true; } @@ -65,7 +65,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return _convert(model)!; } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convert(model)!; } @@ -84,7 +84,7 @@ class $Mappr implements AutoMapprInterface { canReturnNull: true, ); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvert(model); } @@ -100,7 +100,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET>((item) => _convert(item)!); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertIterable(model); } @@ -120,7 +120,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertIterable(model); } @@ -136,7 +136,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertList(model); } @@ -155,7 +155,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertList(model); } @@ -171,7 +171,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertSet(model); } @@ -190,7 +190,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertSet(model); } diff --git a/examples/example/lib/equatable.g.dart b/examples/example/lib/equatable.g.dart index d4ce6859..3ac31a03 100644 --- a/examples/example/lib/equatable.g.dart +++ b/examples/example/lib/equatable.g.dart @@ -20,7 +20,7 @@ class $Mappr implements AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _modules => const []; + List<AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_example/equatable.dart} @@ -34,7 +34,7 @@ class $Mappr implements AutoMapprInterface { return true; } if (recursive) { - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return true; } @@ -50,7 +50,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return _convert(model)!; } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convert(model)!; } @@ -69,7 +69,7 @@ class $Mappr implements AutoMapprInterface { canReturnNull: true, ); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvert(model); } @@ -85,7 +85,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET>((item) => _convert(item)!); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertIterable(model); } @@ -105,7 +105,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertIterable(model); } @@ -121,7 +121,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertList(model); } @@ -140,7 +140,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertList(model); } @@ -156,7 +156,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertSet(model); } @@ -175,7 +175,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertSet(model); } diff --git a/examples/example/lib/nested.g.dart b/examples/example/lib/nested.g.dart index f50fa375..cace55e7 100644 --- a/examples/example/lib/nested.g.dart +++ b/examples/example/lib/nested.g.dart @@ -22,7 +22,7 @@ class $Mappr implements AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _modules => const []; + List<AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_example/nested.dart} @@ -48,7 +48,7 @@ class $Mappr implements AutoMapprInterface { return true; } if (recursive) { - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return true; } @@ -64,7 +64,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return _convert(model)!; } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convert(model)!; } @@ -83,7 +83,7 @@ class $Mappr implements AutoMapprInterface { canReturnNull: true, ); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvert(model); } @@ -99,7 +99,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET>((item) => _convert(item)!); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertIterable(model); } @@ -119,7 +119,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertIterable(model); } @@ -135,7 +135,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertList(model); } @@ -154,7 +154,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertList(model); } @@ -170,7 +170,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertSet(model); } @@ -189,7 +189,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertSet(model); } diff --git a/examples/example/lib/nullable.g.dart b/examples/example/lib/nullable.g.dart index e2c9cf1f..ed59201b 100644 --- a/examples/example/lib/nullable.g.dart +++ b/examples/example/lib/nullable.g.dart @@ -21,7 +21,7 @@ class $Mappr implements AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _modules => const []; + List<AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_example/nullable.dart} @@ -41,7 +41,7 @@ class $Mappr implements AutoMapprInterface { return true; } if (recursive) { - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return true; } @@ -57,7 +57,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return _convert(model)!; } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convert(model)!; } @@ -76,7 +76,7 @@ class $Mappr implements AutoMapprInterface { canReturnNull: true, ); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvert(model); } @@ -92,7 +92,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET>((item) => _convert(item)!); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertIterable(model); } @@ -112,7 +112,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertIterable(model); } @@ -128,7 +128,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertList(model); } @@ -147,7 +147,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertList(model); } @@ -163,7 +163,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertSet(model); } @@ -182,7 +182,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertSet(model); } diff --git a/examples/example/lib/rename.g.dart b/examples/example/lib/rename.g.dart index 89de1b19..2a8a4626 100644 --- a/examples/example/lib/rename.g.dart +++ b/examples/example/lib/rename.g.dart @@ -20,7 +20,7 @@ class $Mappr implements AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _modules => const []; + List<AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_example/rename.dart} @@ -34,7 +34,7 @@ class $Mappr implements AutoMapprInterface { return true; } if (recursive) { - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return true; } @@ -50,7 +50,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return _convert(model)!; } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convert(model)!; } @@ -69,7 +69,7 @@ class $Mappr implements AutoMapprInterface { canReturnNull: true, ); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvert(model); } @@ -85,7 +85,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET>((item) => _convert(item)!); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertIterable(model); } @@ -105,7 +105,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertIterable(model); } @@ -121,7 +121,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertList(model); } @@ -140,7 +140,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertList(model); } @@ -156,7 +156,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertSet(model); } @@ -175,7 +175,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertSet(model); } diff --git a/examples/freezed/lib/freezed_example.g.dart b/examples/freezed/lib/freezed_example.g.dart index 625fc49e..c7964b8e 100644 --- a/examples/freezed/lib/freezed_example.g.dart +++ b/examples/freezed/lib/freezed_example.g.dart @@ -20,7 +20,7 @@ class $Mappr implements AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _modules => const []; + List<AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_freezed/freezed_example.dart} @@ -35,7 +35,7 @@ class $Mappr implements AutoMapprInterface { return true; } if (recursive) { - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return true; } @@ -51,7 +51,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return _convert(model)!; } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convert(model)!; } @@ -70,7 +70,7 @@ class $Mappr implements AutoMapprInterface { canReturnNull: true, ); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvert(model); } @@ -86,7 +86,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET>((item) => _convert(item)!); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertIterable(model); } @@ -106,7 +106,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertIterable(model); } @@ -122,7 +122,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertList(model); } @@ -141,7 +141,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertList(model); } @@ -157,7 +157,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertSet(model); } @@ -176,7 +176,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertSet(model); } diff --git a/examples/injectable/lib/mappr.g.dart b/examples/injectable/lib/mappr.g.dart index 3cdd617f..bb04a465 100644 --- a/examples/injectable/lib/mappr.g.dart +++ b/examples/injectable/lib/mappr.g.dart @@ -20,7 +20,7 @@ class $Mappr implements AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _modules => const []; + List<AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_injectable/mappr.dart} @@ -34,7 +34,7 @@ class $Mappr implements AutoMapprInterface { return true; } if (recursive) { - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return true; } @@ -50,7 +50,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return _convert(model)!; } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convert(model)!; } @@ -69,7 +69,7 @@ class $Mappr implements AutoMapprInterface { canReturnNull: true, ); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvert(model); } @@ -85,7 +85,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET>((item) => _convert(item)!); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertIterable(model); } @@ -105,7 +105,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertIterable(model); } @@ -121,7 +121,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertList(model); } @@ -140,7 +140,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertList(model); } @@ -156,7 +156,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertSet(model); } @@ -175,7 +175,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertSet(model); } diff --git a/examples/json_serializable/lib/serializable.g.dart b/examples/json_serializable/lib/serializable.g.dart index 69c429dc..3a92c1ba 100644 --- a/examples/json_serializable/lib/serializable.g.dart +++ b/examples/json_serializable/lib/serializable.g.dart @@ -21,7 +21,7 @@ class $Mappr implements AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _modules => const []; + List<AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_json_serializable/serializable.dart} @@ -41,7 +41,7 @@ class $Mappr implements AutoMapprInterface { return true; } if (recursive) { - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return true; } @@ -57,7 +57,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return _convert(model)!; } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convert(model)!; } @@ -76,7 +76,7 @@ class $Mappr implements AutoMapprInterface { canReturnNull: true, ); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvert(model); } @@ -92,7 +92,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET>((item) => _convert(item)!); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertIterable(model); } @@ -112,7 +112,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertIterable(model); } @@ -128,7 +128,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertList(model); } @@ -147,7 +147,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertList(model); } @@ -163,7 +163,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertSet(model); } @@ -182,7 +182,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertSet(model); } diff --git a/examples/json_serializable/test/fixture/json_serializable.g.dart b/examples/json_serializable/test/fixture/json_serializable.g.dart index 174c21ee..4293c37b 100644 --- a/examples/json_serializable/test/fixture/json_serializable.g.dart +++ b/examples/json_serializable/test/fixture/json_serializable.g.dart @@ -21,7 +21,7 @@ class $Mappr implements AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _modules => const []; + List<AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} @@ -41,7 +41,7 @@ class $Mappr implements AutoMapprInterface { return true; } if (recursive) { - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return true; } @@ -57,7 +57,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return _convert(model)!; } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convert(model)!; } @@ -76,7 +76,7 @@ class $Mappr implements AutoMapprInterface { canReturnNull: true, ); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvert(model); } @@ -92,7 +92,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET>((item) => _convert(item)!); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertIterable(model); } @@ -112,7 +112,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertIterable(model); } @@ -128,7 +128,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertList(model); } @@ -147,7 +147,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toList(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertList(model); } @@ -163,7 +163,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return convertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.convertSet(model); } @@ -182,7 +182,7 @@ class $Mappr implements AutoMapprInterface { if (canConvert<SOURCE, TARGET>(recursive: false)) { return tryConvertIterable<SOURCE, TARGET>(model).toSet(); } - for (final mappr in _modules) { + for (final mappr in _delegates) { if (mappr.canConvert<SOURCE, TARGET>()) { return mappr.tryConvertSet(model); } diff --git a/melos.yaml b/melos.yaml index c6879b29..0627e6ff 100644 --- a/melos.yaml +++ b/melos.yaml @@ -1,10 +1,9 @@ name: auto_mappr_workspace packages: - - packages/auto_mappr - # - packages/** - # - packages/**/example - # - examples/** + - packages/** + - packages/**/example + - examples/** command: bootstrap: diff --git a/packages/auto_mappr/build.yaml b/packages/auto_mappr/build.yaml index 1ee463a8..905672fe 100644 --- a/packages/auto_mappr/build.yaml +++ b/packages/auto_mappr/build.yaml @@ -4,9 +4,6 @@ targets: :auto_mappr: enabled: true generate_for: - include: - - test/integration/fixture/includes.dart - - test/integration/fixture/includes/** exclude: - test/integration/error_fixture/** options: diff --git a/packages/auto_mappr/example/lib/mappr.g.dart b/packages/auto_mappr/example/lib/mappr.g.dart new file mode 100644 index 00000000..c290fb31 --- /dev/null +++ b/packages/auto_mappr/example/lib/mappr.g.dart @@ -0,0 +1,216 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'mappr.dart'; + +// ************************************************************************** +// AutoMapprGenerator +// ************************************************************************** + +// ignore_for_file: non_constant_identifier_names, prefer_const_constructors +// ignore_for_file: prefer_const_literals_to_create_immutables +// ignore_for_file: require_trailing_commas, unnecessary_const +// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis +// ignore_for_file: unnecessary_raw_strings + +/// {@template asset:auto_mappr/example/lib/mappr.dart} +/// Available mappings: +/// - `UserDto` → `User`. +/// {@endtemplate} +class $Mappr implements AutoMapprInterface { + const $Mappr(); + + Type _typeOf<T>() => T; + List<AutoMapprInterface> get _delegates => const []; + + /// {@macro AutoMapprInterface:canConvert} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} + @override + bool canConvert<SOURCE, TARGET>({bool recursive = true}) { + final sourceTypeOf = _typeOf<SOURCE>(); + final targetTypeOf = _typeOf<TARGET>(); + if ((sourceTypeOf == _typeOf<UserDto>() || + sourceTypeOf == _typeOf<UserDto?>()) && + (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + return true; + } + if (recursive) { + for (final mappr in _delegates) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return true; + } + } + } + return false; + } + + /// {@macro AutoMapprInterface:convert} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} + @override + TARGET convert<SOURCE, TARGET>(SOURCE? model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return _convert(model)!; + } + for (final mappr in _delegates) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.convert(model)!; + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// {@macro AutoMapprInterface:tryConvert} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} + @override + TARGET? tryConvert<SOURCE, TARGET>(SOURCE? model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return _convert( + model, + canReturnNull: true, + ); + } + for (final mappr in _delegates) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.tryConvert(model); + } + } + + return null; + } + + /// {@macro AutoMapprInterface:convertIterable} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} + @override + Iterable<TARGET> convertIterable<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return model.map<TARGET>((item) => _convert(item)!); + } + for (final mappr in _delegates) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.convertIterable(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into Iterable. + /// + /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null + /// + /// {@macro asset:auto_mappr/example/lib/mappr.dart} + @override + Iterable<TARGET?> tryConvertIterable<SOURCE, TARGET>( + Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return model.map<TARGET?>((item) => _convert(item, canReturnNull: true)); + } + for (final mappr in _delegates) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.tryConvertIterable(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// {@macro AutoMapprInterface:convertList} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} + @override + List<TARGET> convertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return convertIterable<SOURCE, TARGET>(model).toList(); + } + for (final mappr in _delegates) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.convertList(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into List. + /// + /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null + /// + /// {@macro asset:auto_mappr/example/lib/mappr.dart} + @override + List<TARGET?> tryConvertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return tryConvertIterable<SOURCE, TARGET>(model).toList(); + } + for (final mappr in _delegates) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.tryConvertList(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// {@macro AutoMapprInterface:convertSet} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} + @override + Set<TARGET> convertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return convertIterable<SOURCE, TARGET>(model).toSet(); + } + for (final mappr in _delegates) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.convertSet(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + /// For iterable items, converts from SOURCE to TARGET if such mapping is configured, into Set. + /// + /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null + /// + /// {@macro asset:auto_mappr/example/lib/mappr.dart} + @override + Set<TARGET?> tryConvertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { + if (canConvert<SOURCE, TARGET>(recursive: false)) { + return tryConvertIterable<SOURCE, TARGET>(model).toSet(); + } + for (final mappr in _delegates) { + if (mappr.canConvert<SOURCE, TARGET>()) { + return mappr.tryConvertSet(model); + } + } + + throw Exception('No ${_typeOf<SOURCE>()} -> ${_typeOf<TARGET>()} mapping.'); + } + + TARGET? _convert<SOURCE, TARGET>( + SOURCE? model, { + bool canReturnNull = false, + }) { + final sourceTypeOf = _typeOf<SOURCE>(); + final targetTypeOf = _typeOf<TARGET>(); + if ((sourceTypeOf == _typeOf<UserDto>() || + sourceTypeOf == _typeOf<UserDto?>()) && + (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if (canReturnNull && model == null) { + return null; + } + return (_map__UserDto__To__User((model as UserDto?)) as TARGET); + } + throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); + } + + User _map__UserDto__To__User(UserDto? input) { + final model = input; + if (model == null) { + throw Exception( + r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' + r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); + } + return User( + id: model.id, + name: model.xname, + ); + } +} diff --git a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart index 9ff7243e..b235a0cb 100644 --- a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart +++ b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart @@ -20,7 +20,7 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { final BuilderOptions builderOptions; // Constants for AutoMappr. - static const String annotationName = 'AutoMappr'; + static const String annotationAutoMappr = 'AutoMappr'; static const String annotationFieldDelegates = 'delegates'; static const String annotationFieldMappers = 'mappers'; static const String annotationFieldIncludes = 'includes'; @@ -69,24 +69,7 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { final delegatesList = constant.getField(annotationFieldDelegates)!.toListValue(); final includesList = constant.getField(annotationFieldIncludes)!.toListValue(); - final allMappers = [...mappersList]; - - for (final include in includesList ?? <DartObject>[]) { - if (include.type?.element?.metadata - .firstWhereOrNull((data) => data.element?.displayName == annotationName) - ?.computeConstantValue() - case final includeConstant?) { - final mappersList2 = includeConstant.getField(annotationFieldMappers)!.toListValue()!; - // final delegatesExpression2 = includeConstant.getField(fieldDelegates)!.toCodeExpression(config: tmpConfig); - // final delegatesList2 = includeConstant.getField(fieldDelegates)!.toListValue(); - // final includesList2 = includeConstant.getField(fieldIncludes)!.toListValue(); - - allMappers.addAll(mappersList2); - } - } - - log.warning('all mappings = ${allMappers.join(',\n')} ...'); - + final allMappers = [...mappersList, ..._mappersFromRecursiveIncludes(includesList: includesList ?? [])]; final mappers = _processMappers( mappers: allMappers, element: element, @@ -228,4 +211,31 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { ...exports.map((e) => _getRecursiveLibraryExports(e.exportedLibrary!)).flattened, ]; } + + /// Recursively returns all mappings from includes. + Iterable<DartObject> _mappersFromRecursiveIncludes({required List<DartObject> includesList}) { + final mappings = <DartObject>[]; + + for (final include in includesList) { + // For each include locate AutoMappr annotation. + if (include.type?.element?.metadata + .firstWhereOrNull((data) => data.element?.displayName == annotationAutoMappr) + ?.computeConstantValue() + case final includeConstant?) { + // This -- mappers. + final mappers = includeConstant.getField(annotationFieldMappers)?.toListValue(); + if (mappers != null) { + mappings.addAll(mappers); + } + + // Bellow -- recursive includes. + final includes = includeConstant.getField(annotationFieldIncludes)?.toListValue(); + if (includes != null) { + mappings.addAll(_mappersFromRecursiveIncludes(includesList: includes)); + } + } + } + + return mappings; + } } diff --git a/packages/auto_mappr/test/integration/delegates_test.dart b/packages/auto_mappr/test/integration/delegates_test.dart index 5d6f64b0..93116737 100644 --- a/packages/auto_mappr/test/integration/delegates_test.dart +++ b/packages/auto_mappr/test/integration/delegates_test.dart @@ -1,9 +1,9 @@ import 'package:test/test.dart'; import 'fixture/delegates.dart' as fixture_group; -import 'fixture/modules/module_alpha.dart' as fixture_alpha; -import 'fixture/modules/module_beta.dart' as fixture_beta; -import 'fixture/modules/module_gama.dart' as fixture_gama; +import 'fixture/delegates/module_alpha.dart' as fixture_alpha; +import 'fixture/delegates/module_beta.dart' as fixture_beta; +import 'fixture/delegates/module_gama.dart' as fixture_gama; // modules hierarchy: // diff --git a/packages/auto_mappr/test/integration/fixture/includes.dart b/packages/auto_mappr/test/integration/fixture/includes.dart index 338f3120..36162185 100644 --- a/packages/auto_mappr/test/integration/fixture/includes.dart +++ b/packages/auto_mappr/test/integration/fixture/includes.dart @@ -1,31 +1,30 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -import 'includes/module_gama.dart'; -// import 'includes/module_alpha.dart' as alpha_feature; +import 'includes/module_alpha.dart' as alpha_feature; part 'includes.g.dart'; -@AutoMappr([MapType<GroupDto, Group>()], includes: [MapprGama()]) +@AutoMappr([MapType<GroupDto, Group>()], includes: [alpha_feature.MapprAlpha()]) class MapprGroup extends $MapprGroup { const MapprGroup(); } class GroupDto { - // final AlphaDto alpha; + final alpha_feature.AlphaDto alpha; // final BetaDto beta; - final GamaDto gama; + // final GamaDto gama; - const GroupDto(this.gama); + const GroupDto(this.alpha); } class Group with EquatableMixin { - // final Alpha alpha; + final alpha_feature.Alpha alpha; // final Beta beta; - final Gama gama; + // final Gama gama; @override - List<Object?> get props => [gama]; + List<Object?> get props => [alpha]; - const Group(this.gama); + const Group(this.alpha); } diff --git a/packages/auto_mappr/test/integration/includes_test.dart b/packages/auto_mappr/test/integration/includes_test.dart new file mode 100644 index 00000000..a2e27960 --- /dev/null +++ b/packages/auto_mappr/test/integration/includes_test.dart @@ -0,0 +1,660 @@ +import 'package:test/test.dart'; + +import 'fixture/includes.dart' as fixture_group; +import 'fixture/includes/module_alpha.dart' as fixture_alpha; +import 'fixture/includes/module_beta.dart' as fixture_beta; +import 'fixture/includes/module_gama.dart' as fixture_gama; + +// includes hierarchy: +// +// - Group (this one) +// - Alpha +// - Beta +// - Gama +void main() { + late final fixture_group.MapprGroup mappr; + + setUpAll(() { + mappr = const fixture_group.MapprGroup(); + }); + + group('convert', () { + test('group', () { + const dto = fixture_group.GroupDto(fixture_alpha.AlphaDto(1), fixture_beta.BetaDto(2), fixture_gama.GamaDto(3)); + final converted = mappr.convert<fixture_group.GroupDto, fixture_group.Group>(dto); + + expect( + converted, + equals(const fixture_group.Group(fixture_alpha.Alpha(1), fixture_beta.Beta(2), fixture_gama.Gama(3))), + ); + }); + + test('alpha', () { + const dto = fixture_alpha.AlphaDto(4); + final converted = mappr.convert<fixture_alpha.AlphaDto, fixture_alpha.Alpha>(dto); + + expect(converted, equals(const fixture_alpha.Alpha(4))); + }); + + test('beta', () { + const dto = fixture_beta.BetaDto(5); + final converted = mappr.convert<fixture_beta.BetaDto, fixture_beta.Beta>(dto); + + expect(converted, equals(const fixture_beta.Beta(5))); + }); + + test('gama', () { + const dto = fixture_gama.GamaDto(6); + final converted = mappr.convert<fixture_gama.GamaDto, fixture_gama.Gama>(dto); + + expect(converted, equals(const fixture_gama.Gama(6))); + }); + }); + + group('tryConvert', () { + test('group', () { + const dto = fixture_group.GroupDto(fixture_alpha.AlphaDto(1), fixture_beta.BetaDto(2), fixture_gama.GamaDto(3)); + final converted = mappr.tryConvert<fixture_group.GroupDto, fixture_group.Group>(dto); + + expect( + converted, + equals(const fixture_group.Group(fixture_alpha.Alpha(1), fixture_beta.Beta(2), fixture_gama.Gama(3))), + ); + }); + + test('group w/ null', () { + const fixture_group.GroupDto? dto = null; + final converted = mappr.tryConvert<fixture_group.GroupDto, fixture_group.Group>(dto); + + expect(converted, isNull); + }); + + test('alpha', () { + const dto = fixture_alpha.AlphaDto(2); + final converted = mappr.tryConvert<fixture_alpha.AlphaDto, fixture_alpha.Alpha>(dto); + + expect(converted, equals(const fixture_alpha.Alpha(2))); + }); + + test('alpha w/ null', () { + const fixture_alpha.AlphaDto? dto = null; + final converted = mappr.tryConvert<fixture_alpha.AlphaDto, fixture_alpha.Alpha>(dto); + + expect(converted, isNull); + }); + + test('beta', () { + const dto = fixture_beta.BetaDto(3); + final converted = mappr.tryConvert<fixture_beta.BetaDto, fixture_beta.Beta>(dto); + + expect(converted, equals(const fixture_beta.Beta(3))); + }); + + test('beta w/ null', () { + const fixture_beta.BetaDto? dto = null; + final converted = mappr.tryConvert<fixture_beta.BetaDto, fixture_beta.Beta>(dto); + + expect(converted, isNull); + }); + + test('gama', () { + const dto = fixture_gama.GamaDto(4); + final converted = mappr.tryConvert<fixture_gama.GamaDto, fixture_gama.Gama>(dto); + + expect(converted, equals(const fixture_gama.Gama(4))); + }); + + test('gama w/ null', () { + const fixture_gama.GamaDto? dto = null; + final converted = mappr.tryConvert<fixture_gama.GamaDto, fixture_gama.Gama>(dto); + + expect(converted, isNull); + }); + }); + + group('convertIterable', () { + test('group', () { + final dto = [ + const fixture_group.GroupDto(fixture_alpha.AlphaDto(1), fixture_beta.BetaDto(2), fixture_gama.GamaDto(3)), + const fixture_group.GroupDto(fixture_alpha.AlphaDto(4), fixture_beta.BetaDto(5), fixture_gama.GamaDto(6)), + const fixture_group.GroupDto(fixture_alpha.AlphaDto(7), fixture_beta.BetaDto(8), fixture_gama.GamaDto(9)), + ].map((e) => e); + final converted = mappr.convertIterable<fixture_group.GroupDto, fixture_group.Group>(dto); + + expect( + converted, + equals(const [ + fixture_group.Group(fixture_alpha.Alpha(1), fixture_beta.Beta(2), fixture_gama.Gama(3)), + fixture_group.Group(fixture_alpha.Alpha(4), fixture_beta.Beta(5), fixture_gama.Gama(6)), + fixture_group.Group(fixture_alpha.Alpha(7), fixture_beta.Beta(8), fixture_gama.Gama(9)), + ]), + ); + }); + + test('alpha', () { + final dto = [ + const fixture_alpha.AlphaDto(4), + const fixture_alpha.AlphaDto(5), + ].map((e) => e); + final converted = mappr.convertIterable<fixture_alpha.AlphaDto, fixture_alpha.Alpha>(dto); + + expect( + converted, + equals(const [fixture_alpha.Alpha(4), fixture_alpha.Alpha(5)]), + ); + }); + + test('beta', () { + final dto = [ + const fixture_beta.BetaDto(6), + const fixture_beta.BetaDto(7), + const fixture_beta.BetaDto(8), + ].map((e) => e); + final converted = mappr.convertIterable<fixture_beta.BetaDto, fixture_beta.Beta>(dto); + + expect( + converted, + equals(const [ + fixture_beta.Beta(6), + fixture_beta.Beta(7), + fixture_beta.Beta(8), + ]), + ); + }); + + test('gama', () { + final dto = [ + const fixture_gama.GamaDto(9), + const fixture_gama.GamaDto(10), + ].map((e) => e); + final converted = mappr.convertIterable<fixture_gama.GamaDto, fixture_gama.Gama>(dto); + + expect(converted, equals(const [fixture_gama.Gama(9), fixture_gama.Gama(10)])); + }); + }); + + group('tryConvertIterable', () { + test('group', () { + final dto = const [ + fixture_group.GroupDto(fixture_alpha.AlphaDto(11), fixture_beta.BetaDto(12), fixture_gama.GamaDto(13)), + fixture_group.GroupDto(fixture_alpha.AlphaDto(14), fixture_beta.BetaDto(15), fixture_gama.GamaDto(16)), + fixture_group.GroupDto(fixture_alpha.AlphaDto(17), fixture_beta.BetaDto(18), fixture_gama.GamaDto(19)), + ].map((e) => e); + final converted = mappr.tryConvertIterable<fixture_group.GroupDto, fixture_group.Group>(dto); + + expect( + converted, + equals(const [ + fixture_group.Group(fixture_alpha.Alpha(11), fixture_beta.Beta(12), fixture_gama.Gama(13)), + fixture_group.Group(fixture_alpha.Alpha(14), fixture_beta.Beta(15), fixture_gama.Gama(16)), + fixture_group.Group(fixture_alpha.Alpha(17), fixture_beta.Beta(18), fixture_gama.Gama(19)), + ]), + ); + }); + + test('group w/ null', () { + final dto = [ + const fixture_group.GroupDto(fixture_alpha.AlphaDto(101), fixture_beta.BetaDto(102), fixture_gama.GamaDto(103)), + null, + const fixture_group.GroupDto(fixture_alpha.AlphaDto(201), fixture_beta.BetaDto(202), fixture_gama.GamaDto(203)), + ].map((e) => e); + final converted = mappr.tryConvertIterable<fixture_group.GroupDto, fixture_group.Group>(dto); + + expect( + converted, + equals(const [ + fixture_group.Group(fixture_alpha.Alpha(101), fixture_beta.Beta(102), fixture_gama.Gama(103)), + null, + fixture_group.Group(fixture_alpha.Alpha(201), fixture_beta.Beta(202), fixture_gama.Gama(203)), + ]), + ); + }); + + test('alpha', () { + final dto = [ + const fixture_alpha.AlphaDto(4), + const fixture_alpha.AlphaDto(5), + ].map((e) => e); + final converted = mappr.tryConvertIterable<fixture_alpha.AlphaDto, fixture_alpha.Alpha>(dto); + + expect( + converted, + equals(const [fixture_alpha.Alpha(4), fixture_alpha.Alpha(5)]), + ); + }); + + test('alpha w/ null', () { + final dto = [ + const fixture_alpha.AlphaDto(4), + const fixture_alpha.AlphaDto(5), + null, + ].map((e) => e); + final converted = mappr.tryConvertIterable<fixture_alpha.AlphaDto, fixture_alpha.Alpha>(dto); + + expect( + converted, + equals(const [fixture_alpha.Alpha(4), fixture_alpha.Alpha(5), null]), + ); + }); + + test('beta', () { + final dto = [ + const fixture_beta.BetaDto(6), + const fixture_beta.BetaDto(7), + const fixture_beta.BetaDto(8), + ].map((e) => e); + final converted = mappr.tryConvertIterable<fixture_beta.BetaDto, fixture_beta.Beta>(dto); + + expect( + converted, + equals(const [ + fixture_beta.Beta(6), + fixture_beta.Beta(7), + fixture_beta.Beta(8), + ]), + ); + }); + + test('beta w/ null', () { + final dto = [ + null, + const fixture_beta.BetaDto(7), + const fixture_beta.BetaDto(8), + ].map((e) => e); + final converted = mappr.tryConvertIterable<fixture_beta.BetaDto, fixture_beta.Beta>(dto); + + expect( + converted, + equals(const [null, fixture_beta.Beta(7), fixture_beta.Beta(8)]), + ); + }); + + test('gama', () { + final dto = [ + const fixture_gama.GamaDto(9), + const fixture_gama.GamaDto(10), + ].map((e) => e); + final converted = mappr.tryConvertIterable<fixture_gama.GamaDto, fixture_gama.Gama>(dto); + + expect(converted, equals(const [fixture_gama.Gama(9), fixture_gama.Gama(10)])); + }); + + test('gama w/ null', () { + final dto = [ + null, + const fixture_gama.GamaDto(9), + const fixture_gama.GamaDto(10), + ].map((e) => e); + final converted = mappr.tryConvertIterable<fixture_gama.GamaDto, fixture_gama.Gama>(dto); + + expect( + converted, + equals(const [null, fixture_gama.Gama(9), fixture_gama.Gama(10)]), + ); + }); + }); + + group('convertList', () { + test('group', () { + const dto = <fixture_group.GroupDto>[ + fixture_group.GroupDto(fixture_alpha.AlphaDto(21), fixture_beta.BetaDto(22), fixture_gama.GamaDto(23)), + fixture_group.GroupDto(fixture_alpha.AlphaDto(24), fixture_beta.BetaDto(25), fixture_gama.GamaDto(26)), + fixture_group.GroupDto(fixture_alpha.AlphaDto(27), fixture_beta.BetaDto(28), fixture_gama.GamaDto(29)), + ]; + final converted = mappr.convertList<fixture_group.GroupDto, fixture_group.Group>(dto); + + expect( + converted, + equals(const [ + fixture_group.Group(fixture_alpha.Alpha(21), fixture_beta.Beta(22), fixture_gama.Gama(23)), + fixture_group.Group(fixture_alpha.Alpha(24), fixture_beta.Beta(25), fixture_gama.Gama(26)), + fixture_group.Group(fixture_alpha.Alpha(27), fixture_beta.Beta(28), fixture_gama.Gama(29)), + ]), + ); + }); + + test('alpha', () { + const dto = <fixture_alpha.AlphaDto>[ + fixture_alpha.AlphaDto(4), + fixture_alpha.AlphaDto(5), + ]; + final converted = mappr.convertList<fixture_alpha.AlphaDto, fixture_alpha.Alpha>(dto); + + expect( + converted, + equals(const [fixture_alpha.Alpha(4), fixture_alpha.Alpha(5)]), + ); + }); + + test('beta', () { + const dto = <fixture_beta.BetaDto>[ + fixture_beta.BetaDto(6), + fixture_beta.BetaDto(7), + fixture_beta.BetaDto(8), + ]; + final converted = mappr.convertList<fixture_beta.BetaDto, fixture_beta.Beta>(dto); + + expect( + converted, + equals(const [ + fixture_beta.Beta(6), + fixture_beta.Beta(7), + fixture_beta.Beta(8), + ]), + ); + }); + + test('gama', () { + const dto = <fixture_gama.GamaDto>[ + fixture_gama.GamaDto(9), + fixture_gama.GamaDto(10), + ]; + final converted = mappr.convertList<fixture_gama.GamaDto, fixture_gama.Gama>(dto); + + expect(converted, equals(const [fixture_gama.Gama(9), fixture_gama.Gama(10)])); + }); + }); + + group('tryConvertList', () { + test('group', () { + const dto = <fixture_group.GroupDto?>[ + fixture_group.GroupDto(fixture_alpha.AlphaDto(31), fixture_beta.BetaDto(32), fixture_gama.GamaDto(33)), + fixture_group.GroupDto(fixture_alpha.AlphaDto(34), fixture_beta.BetaDto(35), fixture_gama.GamaDto(36)), + fixture_group.GroupDto(fixture_alpha.AlphaDto(37), fixture_beta.BetaDto(38), fixture_gama.GamaDto(39)), + ]; + final converted = mappr.tryConvertList<fixture_group.GroupDto, fixture_group.Group>(dto); + + expect( + converted, + equals(const [ + fixture_group.Group(fixture_alpha.Alpha(31), fixture_beta.Beta(32), fixture_gama.Gama(33)), + fixture_group.Group(fixture_alpha.Alpha(34), fixture_beta.Beta(35), fixture_gama.Gama(36)), + fixture_group.Group(fixture_alpha.Alpha(37), fixture_beta.Beta(38), fixture_gama.Gama(39)), + ]), + ); + }); + + test('group w/ null', () { + const dto = <fixture_group.GroupDto?>[ + fixture_group.GroupDto(fixture_alpha.AlphaDto(221), fixture_beta.BetaDto(222), fixture_gama.GamaDto(223)), + null, + fixture_group.GroupDto(fixture_alpha.AlphaDto(231), fixture_beta.BetaDto(232), fixture_gama.GamaDto(233)), + ]; + final converted = mappr.tryConvertList<fixture_group.GroupDto, fixture_group.Group>(dto); + + expect( + converted, + equals(const [ + fixture_group.GroupDto(fixture_alpha.AlphaDto(221), fixture_beta.BetaDto(222), fixture_gama.GamaDto(223)), + null, + fixture_group.GroupDto(fixture_alpha.AlphaDto(231), fixture_beta.BetaDto(232), fixture_gama.GamaDto(233)), + ]), + ); + }); + + test('alpha', () { + const dto = <fixture_alpha.AlphaDto?>[ + fixture_alpha.AlphaDto(4), + fixture_alpha.AlphaDto(5), + ]; + final converted = mappr.tryConvertList<fixture_alpha.AlphaDto, fixture_alpha.Alpha>(dto); + + expect( + converted, + equals(const [fixture_alpha.Alpha(4), fixture_alpha.Alpha(5)]), + ); + }); + + test('alpha w/ null', () { + const dto = <fixture_alpha.AlphaDto?>[ + fixture_alpha.AlphaDto(4), + fixture_alpha.AlphaDto(5), + null, + ]; + final converted = mappr.tryConvertList<fixture_alpha.AlphaDto, fixture_alpha.Alpha>(dto); + + expect( + converted, + equals(const [fixture_alpha.Alpha(4), fixture_alpha.Alpha(5), null]), + ); + }); + + test('beta', () { + const dto = <fixture_beta.BetaDto?>[ + fixture_beta.BetaDto(6), + fixture_beta.BetaDto(7), + fixture_beta.BetaDto(8), + ]; + final converted = mappr.tryConvertList<fixture_beta.BetaDto, fixture_beta.Beta>(dto); + + expect( + converted, + equals(const [ + fixture_beta.Beta(6), + fixture_beta.Beta(7), + fixture_beta.Beta(8), + ]), + ); + }); + + test('beta w/ null', () { + const dto = <fixture_beta.BetaDto?>[ + null, + fixture_beta.BetaDto(7), + fixture_beta.BetaDto(8), + ]; + final converted = mappr.tryConvertList<fixture_beta.BetaDto, fixture_beta.Beta>(dto); + + expect( + converted, + equals(const [null, fixture_beta.Beta(7), fixture_beta.Beta(8)]), + ); + }); + + test('gama', () { + const dto = <fixture_gama.GamaDto?>[ + fixture_gama.GamaDto(9), + fixture_gama.GamaDto(10), + ]; + final converted = mappr.tryConvertList<fixture_gama.GamaDto, fixture_gama.Gama>(dto); + + expect(converted, equals(const [fixture_gama.Gama(9), fixture_gama.Gama(10)])); + }); + + test('gama w/ null', () { + const dto = <fixture_gama.GamaDto?>[ + null, + fixture_gama.GamaDto(9), + fixture_gama.GamaDto(10), + ]; + final converted = mappr.tryConvertList<fixture_gama.GamaDto, fixture_gama.Gama>(dto); + + expect( + converted, + equals(const [null, fixture_gama.Gama(9), fixture_gama.Gama(10)]), + ); + }); + }); + + group('convertSet', () { + test('group', () { + const dto = <fixture_group.GroupDto>{ + fixture_group.GroupDto(fixture_alpha.AlphaDto(41), fixture_beta.BetaDto(42), fixture_gama.GamaDto(43)), + fixture_group.GroupDto(fixture_alpha.AlphaDto(44), fixture_beta.BetaDto(45), fixture_gama.GamaDto(46)), + fixture_group.GroupDto(fixture_alpha.AlphaDto(47), fixture_beta.BetaDto(48), fixture_gama.GamaDto(49)), + }; + final converted = mappr.convertSet<fixture_group.GroupDto, fixture_group.Group>(dto); + + expect( + converted, + equals(const [ + fixture_group.Group(fixture_alpha.Alpha(41), fixture_beta.Beta(42), fixture_gama.Gama(43)), + fixture_group.Group(fixture_alpha.Alpha(44), fixture_beta.Beta(45), fixture_gama.Gama(46)), + fixture_group.Group(fixture_alpha.Alpha(47), fixture_beta.Beta(48), fixture_gama.Gama(49)), + ]), + ); + }); + + test('alpha', () { + const dto = <fixture_alpha.AlphaDto>{ + fixture_alpha.AlphaDto(4), + fixture_alpha.AlphaDto(5), + }; + final converted = mappr.convertSet<fixture_alpha.AlphaDto, fixture_alpha.Alpha>(dto); + + expect( + converted, + equals(const [fixture_alpha.Alpha(4), fixture_alpha.Alpha(5)]), + ); + }); + + test('beta', () { + const dto = <fixture_beta.BetaDto>{ + fixture_beta.BetaDto(6), + fixture_beta.BetaDto(7), + fixture_beta.BetaDto(8), + }; + final converted = mappr.convertSet<fixture_beta.BetaDto, fixture_beta.Beta>(dto); + + expect( + converted, + equals(const [ + fixture_beta.Beta(6), + fixture_beta.Beta(7), + fixture_beta.Beta(8), + ]), + ); + }); + + test('gama', () { + const dto = <fixture_gama.GamaDto>{ + fixture_gama.GamaDto(9), + fixture_gama.GamaDto(10), + }; + final converted = mappr.convertSet<fixture_gama.GamaDto, fixture_gama.Gama>(dto); + + expect(converted, equals(const [fixture_gama.Gama(9), fixture_gama.Gama(10)])); + }); + }); + + group('tryConvertSet', () { + test('group', () { + const dto = <fixture_group.GroupDto?>{ + fixture_group.GroupDto(fixture_alpha.AlphaDto(51), fixture_beta.BetaDto(52), fixture_gama.GamaDto(53)), + fixture_group.GroupDto(fixture_alpha.AlphaDto(54), fixture_beta.BetaDto(55), fixture_gama.GamaDto(56)), + fixture_group.GroupDto(fixture_alpha.AlphaDto(57), fixture_beta.BetaDto(58), fixture_gama.GamaDto(59)), + }; + final converted = mappr.tryConvertSet<fixture_group.GroupDto, fixture_group.Group>(dto); + + expect( + converted, + equals(const [ + fixture_group.Group(fixture_alpha.Alpha(51), fixture_beta.Beta(52), fixture_gama.Gama(53)), + fixture_group.Group(fixture_alpha.Alpha(54), fixture_beta.Beta(55), fixture_gama.Gama(56)), + fixture_group.Group(fixture_alpha.Alpha(57), fixture_beta.Beta(58), fixture_gama.Gama(59)), + ]), + ); + }); + + test('group w/ null', () { + const dto = <fixture_group.GroupDto?>{ + fixture_group.GroupDto(fixture_alpha.AlphaDto(421), fixture_beta.BetaDto(422), fixture_gama.GamaDto(423)), + null, + fixture_group.GroupDto(fixture_alpha.AlphaDto(431), fixture_beta.BetaDto(432), fixture_gama.GamaDto(433)), + }; + final converted = mappr.tryConvertSet<fixture_group.GroupDto, fixture_group.Group>(dto); + + expect( + converted, + equals(const [ + fixture_group.Group(fixture_alpha.Alpha(421), fixture_beta.Beta(422), fixture_gama.Gama(423)), + null, + fixture_group.Group(fixture_alpha.Alpha(431), fixture_beta.Beta(432), fixture_gama.Gama(433)), + ]), + ); + }); + + test('alpha', () { + const dto = <fixture_alpha.AlphaDto?>{ + fixture_alpha.AlphaDto(4), + fixture_alpha.AlphaDto(5), + }; + final converted = mappr.tryConvertSet<fixture_alpha.AlphaDto, fixture_alpha.Alpha>(dto); + + expect( + converted, + equals(const [fixture_alpha.Alpha(4), fixture_alpha.Alpha(5)]), + ); + }); + + test('alpha w/ null', () { + const dto = <fixture_alpha.AlphaDto?>{ + fixture_alpha.AlphaDto(4), + fixture_alpha.AlphaDto(5), + null, + }; + final converted = mappr.tryConvertSet<fixture_alpha.AlphaDto, fixture_alpha.Alpha>(dto); + + expect( + converted, + equals(const [fixture_alpha.Alpha(4), fixture_alpha.Alpha(5), null]), + ); + }); + + test('beta', () { + const dto = <fixture_beta.BetaDto?>{ + fixture_beta.BetaDto(6), + fixture_beta.BetaDto(7), + fixture_beta.BetaDto(8), + }; + final converted = mappr.tryConvertSet<fixture_beta.BetaDto, fixture_beta.Beta>(dto); + + expect( + converted, + equals(const [ + fixture_beta.Beta(6), + fixture_beta.Beta(7), + fixture_beta.Beta(8), + ]), + ); + }); + + test('beta w/ null', () { + const dto = <fixture_beta.BetaDto?>{ + null, + fixture_beta.BetaDto(7), + fixture_beta.BetaDto(8), + }; + final converted = mappr.tryConvertSet<fixture_beta.BetaDto, fixture_beta.Beta>(dto); + + expect( + converted, + equals(const [null, fixture_beta.Beta(7), fixture_beta.Beta(8)]), + ); + }); + + test('gama', () { + const dto = <fixture_gama.GamaDto?>{ + fixture_gama.GamaDto(9), + fixture_gama.GamaDto(10), + }; + final converted = mappr.tryConvertSet<fixture_gama.GamaDto, fixture_gama.Gama>(dto); + + expect(converted, equals(const [fixture_gama.Gama(9), fixture_gama.Gama(10)])); + }); + + test('gama w/ null', () { + const dto = <fixture_gama.GamaDto?>{ + null, + fixture_gama.GamaDto(9), + fixture_gama.GamaDto(10), + }; + final converted = mappr.tryConvertSet<fixture_gama.GamaDto, fixture_gama.Gama>(dto); + + expect( + converted, + equals(const [null, fixture_gama.Gama(9), fixture_gama.Gama(10)]), + ); + }); + }); +} From cb2d47b4fad54e3a6ab83ca6c3f44dcb3432a41a Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 4 Sep 2023 16:30:51 +0200 Subject: [PATCH 14/48] Update builder --- examples/drift/.gitignore | 1 + .../{mappr.g.dart => mappr.auto_mappr.dart} | 4 +- examples/drift/lib/mappr.dart | 2 +- examples/example/.gitignore | 1 + .../lib/{enum.g.dart => enum.auto_mappr.dart} | 4 +- examples/example/lib/enum.dart | 2 +- ...table.g.dart => equatable.auto_mappr.dart} | 4 +- examples/example/lib/equatable.dart | 2 +- .../{nested.g.dart => nested.auto_mappr.dart} | 4 +- examples/example/lib/nested.dart | 2 +- ...llable.g.dart => nullable.auto_mappr.dart} | 4 +- examples/example/lib/nullable.dart | 2 +- .../{rename.g.dart => rename.auto_mappr.dart} | 4 +- examples/example/lib/rename.dart | 2 +- examples/freezed/.gitignore | 1 + ...g.dart => freezed_example.auto_mappr.dart} | 4 +- examples/freezed/lib/freezed_example.dart | 2 +- examples/injectable/.gitignore | 1 + .../{mappr.g.dart => mappr.auto_mappr.dart} | 4 +- examples/injectable/lib/mappr.dart | 3 +- examples/json_serializable/.gitignore | 1 + ...le.g.dart => serializable.auto_mappr.dart} | 28 +----------- .../json_serializable/lib/serializable.dart | 3 +- ...dart => json_serializable.auto_mappr.dart} | 28 +----------- .../test/fixture/json_serializable.dart | 2 +- packages/auto_mappr/.gitignore | 1 + packages/auto_mappr/CHANGELOG.md | 3 ++ packages/auto_mappr/README.md | 45 ++++--------------- packages/auto_mappr/build.yaml | 11 +---- packages/auto_mappr/example/.gitignore | 1 + .../{mappr.g.dart => mappr.auto_mappr.dart} | 4 +- packages/auto_mappr/example/lib/mappr.dart | 2 +- packages/auto_mappr/lib/auto_mappr.dart | 13 +++--- .../lib/src/builder/auto_mappr_builder.dart | 7 ++- .../error_fixture/enum_mapping_not_enum.dart | 2 +- .../error_fixture/enum_mapping_subset.dart | 2 +- .../integration/fixture/complex_types.dart | 2 +- .../fixture/constructor_parameters.dart | 2 +- .../integration/fixture/convert_iterable.dart | 2 +- .../integration/fixture/custom_mapping.dart | 2 +- .../integration/fixture/default_field.dart | 2 +- .../integration/fixture/default_target.dart | 2 +- .../test/integration/fixture/delegates.dart | 2 +- .../fixture/delegates/module_alpha.dart | 3 +- .../fixture/delegates/module_beta.dart | 3 +- .../fixture/delegates/module_gama.dart | 2 +- .../integration/fixture/enum_mapping.dart | 2 +- .../test/integration/fixture/equatable.dart | 2 +- .../fixture/forced_null_source_field.dart | 2 +- .../test/integration/fixture/generics.dart | 2 +- .../integration/fixture/import_alias.dart | 2 +- .../import_alias/import_alias_module.dart | 2 +- .../test/integration/fixture/includes.dart | 2 +- .../fixture/includes/module_alpha.dart | 3 +- .../fixture/includes/module_beta.dart | 3 +- .../fixture/includes/module_gama.dart | 2 +- .../test/integration/fixture/iterable.dart | 2 +- .../test/integration/fixture/list.dart | 2 +- .../test/integration/fixture/map.dart | 2 +- .../fixture/mapping_from_source.dart | 2 +- .../fixture/mapping_to_target.dart | 2 +- .../fixture/multiple_annotations.dart | 2 +- .../integration/fixture/primitive_types.dart | 2 +- .../fixture/regression/uint8_issue_77.dart | 2 +- .../test/integration/fixture/rename.dart | 2 +- .../test/integration/fixture/reverse.dart | 2 +- .../fixture/selecting_constructor.dart | 2 +- .../test/integration/fixture/set.dart | 2 +- .../fixture/special_characters.dart | 2 +- .../test/integration/fixture/super_class.dart | 2 +- .../test/integration/fixture/try_convert.dart | 2 +- .../fixture/when_source_is_null.dart | 2 +- packages/auto_mappr_annotation/README.md | 2 +- .../example/lib/main.dart | 2 +- 74 files changed, 104 insertions(+), 182 deletions(-) rename examples/drift/lib/{mappr.g.dart => mappr.auto_mappr.dart} (99%) rename examples/example/lib/{enum.g.dart => enum.auto_mappr.dart} (99%) rename examples/example/lib/{equatable.g.dart => equatable.auto_mappr.dart} (99%) rename examples/example/lib/{nested.g.dart => nested.auto_mappr.dart} (99%) rename examples/example/lib/{nullable.g.dart => nullable.auto_mappr.dart} (99%) rename examples/example/lib/{rename.g.dart => rename.auto_mappr.dart} (99%) rename examples/freezed/lib/{freezed_example.g.dart => freezed_example.auto_mappr.dart} (99%) rename examples/injectable/lib/{mappr.g.dart => mappr.auto_mappr.dart} (99%) rename examples/json_serializable/lib/{serializable.g.dart => serializable.auto_mappr.dart} (91%) rename examples/json_serializable/test/fixture/{json_serializable.g.dart => json_serializable.auto_mappr.dart} (91%) rename packages/auto_mappr/example/lib/{mappr.g.dart => mappr.auto_mappr.dart} (99%) diff --git a/examples/drift/.gitignore b/examples/drift/.gitignore index b94efff6..adce9480 100644 --- a/examples/drift/.gitignore +++ b/examples/drift/.gitignore @@ -11,3 +11,4 @@ pubspec.lock # Example !*.g.dart +!*.auto_mappr.dart diff --git a/examples/drift/lib/mappr.g.dart b/examples/drift/lib/mappr.auto_mappr.dart similarity index 99% rename from examples/drift/lib/mappr.g.dart rename to examples/drift/lib/mappr.auto_mappr.dart index 717d0c4c..38d1d478 100644 --- a/examples/drift/lib/mappr.g.dart +++ b/examples/drift/lib/mappr.auto_mappr.dart @@ -1,7 +1,5 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'mappr.dart'; - // ************************************************************************** // AutoMapprGenerator // ************************************************************************** @@ -12,6 +10,8 @@ part of 'mappr.dart'; // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; + /// {@template package:examples_drift/mappr.dart} /// Available mappings: /// - `Todo` → `TodoItem`. diff --git a/examples/drift/lib/mappr.dart b/examples/drift/lib/mappr.dart index a996efc6..971c9813 100644 --- a/examples/drift/lib/mappr.dart +++ b/examples/drift/lib/mappr.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:examples_drift/db.dart'; -part 'mappr.g.dart'; +import 'mappr.auto_mappr.dart'; class TodoItem { final int id; diff --git a/examples/example/.gitignore b/examples/example/.gitignore index b94efff6..adce9480 100644 --- a/examples/example/.gitignore +++ b/examples/example/.gitignore @@ -11,3 +11,4 @@ pubspec.lock # Example !*.g.dart +!*.auto_mappr.dart diff --git a/examples/example/lib/enum.g.dart b/examples/example/lib/enum.auto_mappr.dart similarity index 99% rename from examples/example/lib/enum.g.dart rename to examples/example/lib/enum.auto_mappr.dart index 7e05cc9d..67f7cba6 100644 --- a/examples/example/lib/enum.g.dart +++ b/examples/example/lib/enum.auto_mappr.dart @@ -1,7 +1,5 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'enum.dart'; - // ************************************************************************** // AutoMapprGenerator // ************************************************************************** @@ -12,6 +10,8 @@ part of 'enum.dart'; // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; + /// {@template package:examples_example/enum.dart} /// Available mappings: /// - `UserType` → `PersonType`. diff --git a/examples/example/lib/enum.dart b/examples/example/lib/enum.dart index 670a1438..ee44c3cb 100644 --- a/examples/example/lib/enum.dart +++ b/examples/example/lib/enum.dart @@ -1,6 +1,6 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; -part 'enum.g.dart'; +import 'package:examples_example/enum.auto_mappr.dart'; enum UserType { student, admin, parent } diff --git a/examples/example/lib/equatable.g.dart b/examples/example/lib/equatable.auto_mappr.dart similarity index 99% rename from examples/example/lib/equatable.g.dart rename to examples/example/lib/equatable.auto_mappr.dart index 3ac31a03..c65f85af 100644 --- a/examples/example/lib/equatable.g.dart +++ b/examples/example/lib/equatable.auto_mappr.dart @@ -1,7 +1,5 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'equatable.dart'; - // ************************************************************************** // AutoMapprGenerator // ************************************************************************** @@ -12,6 +10,8 @@ part of 'equatable.dart'; // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; + /// {@template package:examples_example/equatable.dart} /// Available mappings: /// - `UserDto` → `User`. diff --git a/examples/example/lib/equatable.dart b/examples/example/lib/equatable.dart index 29fee030..ac72afd4 100644 --- a/examples/example/lib/equatable.dart +++ b/examples/example/lib/equatable.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'equatable.g.dart'; +import 'package:examples_example/equatable.auto_mappr.dart'; @AutoMappr([ MapType<UserDto, User>(), diff --git a/examples/example/lib/nested.g.dart b/examples/example/lib/nested.auto_mappr.dart similarity index 99% rename from examples/example/lib/nested.g.dart rename to examples/example/lib/nested.auto_mappr.dart index cace55e7..738966fa 100644 --- a/examples/example/lib/nested.g.dart +++ b/examples/example/lib/nested.auto_mappr.dart @@ -1,7 +1,5 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'nested.dart'; - // ************************************************************************** // AutoMapprGenerator // ************************************************************************** @@ -12,6 +10,8 @@ part of 'nested.dart'; // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; + /// {@template package:examples_example/nested.dart} /// Available mappings: /// - `UserDto` → `User`. diff --git a/examples/example/lib/nested.dart b/examples/example/lib/nested.dart index 68a83b79..cbd79836 100644 --- a/examples/example/lib/nested.dart +++ b/examples/example/lib/nested.dart @@ -3,7 +3,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'nested.g.dart'; +import 'package:examples_example/nested.auto_mappr.dart'; @AutoMappr([ MapType<UserDto, User>(), diff --git a/examples/example/lib/nullable.g.dart b/examples/example/lib/nullable.auto_mappr.dart similarity index 99% rename from examples/example/lib/nullable.g.dart rename to examples/example/lib/nullable.auto_mappr.dart index ed59201b..abe9da92 100644 --- a/examples/example/lib/nullable.g.dart +++ b/examples/example/lib/nullable.auto_mappr.dart @@ -1,7 +1,5 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'nullable.dart'; - // ************************************************************************** // AutoMapprGenerator // ************************************************************************** @@ -12,6 +10,8 @@ part of 'nullable.dart'; // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; + /// {@template package:examples_example/nullable.dart} /// Available mappings: /// - `UserDto` → `User` -- With default value. diff --git a/examples/example/lib/nullable.dart b/examples/example/lib/nullable.dart index 42ee90e5..04eb4fc7 100644 --- a/examples/example/lib/nullable.dart +++ b/examples/example/lib/nullable.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'nullable.g.dart'; +import 'package:examples_example/nullable.auto_mappr.dart'; @AutoMappr([ MapType<UserDto, User>( diff --git a/examples/example/lib/rename.g.dart b/examples/example/lib/rename.auto_mappr.dart similarity index 99% rename from examples/example/lib/rename.g.dart rename to examples/example/lib/rename.auto_mappr.dart index 2a8a4626..b45a9dc7 100644 --- a/examples/example/lib/rename.g.dart +++ b/examples/example/lib/rename.auto_mappr.dart @@ -1,7 +1,5 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'rename.dart'; - // ************************************************************************** // AutoMapprGenerator // ************************************************************************** @@ -12,6 +10,8 @@ part of 'rename.dart'; // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; + /// {@template package:examples_example/rename.dart} /// Available mappings: /// - `UserDto` → `User`. diff --git a/examples/example/lib/rename.dart b/examples/example/lib/rename.dart index 9def8c16..59b1bf8c 100644 --- a/examples/example/lib/rename.dart +++ b/examples/example/lib/rename.dart @@ -1,6 +1,6 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; -part 'rename.g.dart'; +import 'package:examples_example/rename.auto_mappr.dart'; @AutoMappr([ MapType<UserDto, User>( diff --git a/examples/freezed/.gitignore b/examples/freezed/.gitignore index b94efff6..adce9480 100644 --- a/examples/freezed/.gitignore +++ b/examples/freezed/.gitignore @@ -11,3 +11,4 @@ pubspec.lock # Example !*.g.dart +!*.auto_mappr.dart diff --git a/examples/freezed/lib/freezed_example.g.dart b/examples/freezed/lib/freezed_example.auto_mappr.dart similarity index 99% rename from examples/freezed/lib/freezed_example.g.dart rename to examples/freezed/lib/freezed_example.auto_mappr.dart index c7964b8e..e42f9032 100644 --- a/examples/freezed/lib/freezed_example.g.dart +++ b/examples/freezed/lib/freezed_example.auto_mappr.dart @@ -1,7 +1,5 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'freezed_example.dart'; - // ************************************************************************** // AutoMapprGenerator // ************************************************************************** @@ -12,6 +10,8 @@ part of 'freezed_example.dart'; // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; + /// {@template package:examples_freezed/freezed_example.dart} /// Available mappings: /// - `UserInfo` → `UserInfoCompanion`. diff --git a/examples/freezed/lib/freezed_example.dart b/examples/freezed/lib/freezed_example.dart index 9861f228..86270d48 100644 --- a/examples/freezed/lib/freezed_example.dart +++ b/examples/freezed/lib/freezed_example.dart @@ -1,8 +1,8 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +import 'package:examples_freezed/freezed_example.auto_mappr.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'freezed_example.freezed.dart'; -part 'freezed_example.g.dart'; @freezed class UserInfoUnion with _$UserInfoUnion { diff --git a/examples/injectable/.gitignore b/examples/injectable/.gitignore index b94efff6..adce9480 100644 --- a/examples/injectable/.gitignore +++ b/examples/injectable/.gitignore @@ -11,3 +11,4 @@ pubspec.lock # Example !*.g.dart +!*.auto_mappr.dart diff --git a/examples/injectable/lib/mappr.g.dart b/examples/injectable/lib/mappr.auto_mappr.dart similarity index 99% rename from examples/injectable/lib/mappr.g.dart rename to examples/injectable/lib/mappr.auto_mappr.dart index bb04a465..05023986 100644 --- a/examples/injectable/lib/mappr.g.dart +++ b/examples/injectable/lib/mappr.auto_mappr.dart @@ -1,7 +1,5 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'mappr.dart'; - // ************************************************************************** // AutoMapprGenerator // ************************************************************************** @@ -12,6 +10,8 @@ part of 'mappr.dart'; // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; + /// {@template package:examples_injectable/mappr.dart} /// Available mappings: /// - `UserDto` → `User`. diff --git a/examples/injectable/lib/mappr.dart b/examples/injectable/lib/mappr.dart index 696257ba..44acf6a1 100644 --- a/examples/injectable/lib/mappr.dart +++ b/examples/injectable/lib/mappr.dart @@ -1,8 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +import 'package:examples_injectable/mappr.auto_mappr.dart'; import 'package:injectable/injectable.dart'; -part 'mappr.g.dart'; - class User { final int id; final String name; diff --git a/examples/json_serializable/.gitignore b/examples/json_serializable/.gitignore index b94efff6..adce9480 100644 --- a/examples/json_serializable/.gitignore +++ b/examples/json_serializable/.gitignore @@ -11,3 +11,4 @@ pubspec.lock # Example !*.g.dart +!*.auto_mappr.dart diff --git a/examples/json_serializable/lib/serializable.g.dart b/examples/json_serializable/lib/serializable.auto_mappr.dart similarity index 91% rename from examples/json_serializable/lib/serializable.g.dart rename to examples/json_serializable/lib/serializable.auto_mappr.dart index 3a92c1ba..5425f115 100644 --- a/examples/json_serializable/lib/serializable.g.dart +++ b/examples/json_serializable/lib/serializable.auto_mappr.dart @@ -1,7 +1,5 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'serializable.dart'; - // ************************************************************************** // AutoMapprGenerator // ************************************************************************** @@ -12,6 +10,8 @@ part of 'serializable.dart'; // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; + /// {@template package:examples_json_serializable/serializable.dart} /// Available mappings: /// - `UserDto` → `User`. @@ -241,27 +241,3 @@ class $Mappr implements AutoMapprInterface { return ValueHolder(model.json); } } - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -UserDto _$UserDtoFromJson(Map<String, dynamic> json) => UserDto( - firstName: json['firstName'] as String, - lastName: json['lastName'] as String, - ); - -Map<String, dynamic> _$UserDtoToJson(UserDto instance) => <String, dynamic>{ - 'firstName': instance.firstName, - 'lastName': instance.lastName, - }; - -ValueHolderDto _$ValueHolderDtoFromJson(Map<String, dynamic> json) => - ValueHolderDto( - json['json'] as Map<String, dynamic>, - ); - -Map<String, dynamic> _$ValueHolderDtoToJson(ValueHolderDto instance) => - <String, dynamic>{ - 'json': instance.json, - }; diff --git a/examples/json_serializable/lib/serializable.dart b/examples/json_serializable/lib/serializable.dart index ac32698a..2dee434b 100644 --- a/examples/json_serializable/lib/serializable.dart +++ b/examples/json_serializable/lib/serializable.dart @@ -1,8 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +import 'package:examples_json_serializable/serializable.auto_mappr.dart'; import 'package:json_annotation/json_annotation.dart'; -part 'serializable.g.dart'; - @AutoMappr([ MapType<UserDto, User>(), MapType<ValueHolderDto, ValueHolder>(), diff --git a/examples/json_serializable/test/fixture/json_serializable.g.dart b/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart similarity index 91% rename from examples/json_serializable/test/fixture/json_serializable.g.dart rename to examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart index 4293c37b..74c78092 100644 --- a/examples/json_serializable/test/fixture/json_serializable.g.dart +++ b/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart @@ -1,7 +1,5 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'json_serializable.dart'; - // ************************************************************************** // AutoMapprGenerator // ************************************************************************** @@ -12,6 +10,8 @@ part of 'json_serializable.dart'; // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; + /// {@template asset:examples_json_serializable/test/fixture/json_serializable.dart} /// Available mappings: /// - `UserDto` → `User`. @@ -241,27 +241,3 @@ class $Mappr implements AutoMapprInterface { return ValueHolder(model.json); } } - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -UserDto _$UserDtoFromJson(Map<String, dynamic> json) => UserDto( - firstName: json['firstName'] as String, - lastName: json['lastName'] as String, - ); - -Map<String, dynamic> _$UserDtoToJson(UserDto instance) => <String, dynamic>{ - 'firstName': instance.firstName, - 'lastName': instance.lastName, - }; - -ValueHolderDto _$ValueHolderDtoFromJson(Map<String, dynamic> json) => - ValueHolderDto( - json['json'] as Map<String, dynamic>, - ); - -Map<String, dynamic> _$ValueHolderDtoToJson(ValueHolderDto instance) => - <String, dynamic>{ - 'json': instance.json, - }; diff --git a/examples/json_serializable/test/fixture/json_serializable.dart b/examples/json_serializable/test/fixture/json_serializable.dart index 317e4ceb..6c9fb526 100644 --- a/examples/json_serializable/test/fixture/json_serializable.dart +++ b/examples/json_serializable/test/fixture/json_serializable.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:json_annotation/json_annotation.dart'; -part 'json_serializable.g.dart'; +import 'json_serializable.auto_mappr.dart'; @AutoMappr([ MapType<UserDto, User>(), diff --git a/packages/auto_mappr/.gitignore b/packages/auto_mappr/.gitignore index c6e36089..5f71119f 100644 --- a/packages/auto_mappr/.gitignore +++ b/packages/auto_mappr/.gitignore @@ -1,4 +1,5 @@ *.g.dart +*.auto_mappr.dart # Files and directories created by pub. .dart_tool/ diff --git a/packages/auto_mappr/CHANGELOG.md b/packages/auto_mappr/CHANGELOG.md index 87f9aa4f..59bd60fc 100644 --- a/packages/auto_mappr/CHANGELOG.md +++ b/packages/auto_mappr/CHANGELOG.md @@ -3,6 +3,9 @@ ## Unreleased - Add a `reverse` option on `MapType`, which includes the reverse mapping. [#115](https://github.com/netglade/auto_mappr/pull/115) +- Allow use modules using `includes` on `@AutoMappr`. Previous `modules` is now `delegates`. +- Remove shared AutoMappr builder that used PartBuilder, now `.auto_mappr.dart` is generated using LibraryBuilder. + ## 1.7.0 - Adhere to netglade_analysis. [#94](https://github.com/netglade/auto_mappr/pull/94) - Update analyzer and mocktail packages. [#111](https://github.com/netglade/auto_mappr/pull/111) diff --git a/packages/auto_mappr/README.md b/packages/auto_mappr/README.md index 5a0586eb..90454965 100644 --- a/packages/auto_mappr/README.md +++ b/packages/auto_mappr/README.md @@ -111,7 +111,7 @@ Then use `MapType<Source, Target>()` for each mapping. ```dart import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; -part 'my_file.g.dart'; +import 'my_file.auto_mappr.dart'; @AutoMappr([ MapType<UserDto, User>(), @@ -126,7 +126,7 @@ See [features](#-features) for a complete list. ```dart import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; -part 'my_file.g.dart'; +import 'my_file.auto_mappr.dart'; @AutoMappr([ MapType<UserDto, User>( @@ -666,8 +666,8 @@ Equatable and other packages with similar conditions implicitly works. ### Works with `json_serializable` -AutoMappr uses a `SharedPartBuilder`. -That means it can share the `.g.dart` file with packages like JSON Serializable +AutoMappr uses a `LibraryBuilder` with `.auto_mappr.dart` file output. +That means it does not interfere with shared `.g.dart` file with packages like JSON Serializable to generate other code to the generated super class. ### Works with generated source and target classes @@ -685,10 +685,8 @@ Check the [customizing the build](#-customizing-the-build) chapter to learn more ## ⚙ Customizing the build -By default, AutoMappr uses the `auto_mappr:auto_mappr` builder -that works with `SharedPartBuilder`, which generates combined `.g.dart` files. -If you need to use `PartBuilder` to generate not-shared `.auto_mappr.dart` part files, -you can use the `auto_mappr:not_shared` builder. +By default, AutoMappr uses the `auto_mappr:auto_mappr` builder that works with `LibraryBuilder`, +which generates `.auto_mappr.dart` file. Modify your `build.yaml` file: @@ -700,19 +698,16 @@ targets: builders: # Or disable specific ones. auto_mappr: - enabled: false - # And enable the not_shared builder. - auto_mappr:not_shared: enabled: true ``` ### Builder options -- ignoreNullableSourceField - Force bang operator on non-nullable target's field if source's field is nullable + +- `ignoreNullableSourceField` - Force bang operator on non-nullable target's field if source's field is nullable ### Default dependencies -By default both `auto_mappr` builders has defined required inputs for freezed -and drift classes. +By default the `auto_mappr` builder has defined required inputs for freezed and drift classes. ```yaml required_inputs: [".freezed.dart", ".drift.dart"] @@ -729,25 +724,6 @@ which you can add a input dependency to. Specify the `required_inputs` dependency on your local AutoMappr builder and disable the builders provided by AutoMappr. -Shared builder: - -```yaml -targets: - $default: - auto_apply_builders: true - builders: - # Enable their generators according to their documentation. - drift_dev:not_shared: - enabled: true - drift_dev:preparing_builder: - enabled: true - # Disable Drift's shared builder - drift_dev:drift_dev: - enabled: false -``` - -Not shared builder: - ```yaml targets: $default: @@ -763,9 +739,6 @@ targets: enabled: false auto_mappr: - enabled: false - # Enable the not_shared builder. - auto_mappr:not_shared: enabled: true ``` diff --git a/packages/auto_mappr/build.yaml b/packages/auto_mappr/build.yaml index 905672fe..2fe76f57 100644 --- a/packages/auto_mappr/build.yaml +++ b/packages/auto_mappr/build.yaml @@ -13,16 +13,7 @@ builders: auto_mappr: import: "package:auto_mappr/auto_mappr.dart" builder_factories: ["autoMapprBuilder"] - build_extensions: { ".dart": [".auto_mappr.g.part"] } - auto_apply: dependents - build_to: cache - applies_builders: ["source_gen:combining_builder"] - required_inputs: [".freezed.dart", ".drift.dart"] - - not_shared: - import: "package:auto_mappr/auto_mappr.dart" - builder_factories: ["autoMapprBuilderNotShared"] build_extensions: { ".dart": [".auto_mappr.dart"] } - auto_apply: none + auto_apply: dependents build_to: source required_inputs: [".freezed.dart", ".drift.dart"] diff --git a/packages/auto_mappr/example/.gitignore b/packages/auto_mappr/example/.gitignore index 641b8adc..38c84cf9 100644 --- a/packages/auto_mappr/example/.gitignore +++ b/packages/auto_mappr/example/.gitignore @@ -1,2 +1,3 @@ # Example !*.g.dart +!*.auto_mappr.dart diff --git a/packages/auto_mappr/example/lib/mappr.g.dart b/packages/auto_mappr/example/lib/mappr.auto_mappr.dart similarity index 99% rename from packages/auto_mappr/example/lib/mappr.g.dart rename to packages/auto_mappr/example/lib/mappr.auto_mappr.dart index c290fb31..ac03cda5 100644 --- a/packages/auto_mappr/example/lib/mappr.g.dart +++ b/packages/auto_mappr/example/lib/mappr.auto_mappr.dart @@ -1,7 +1,5 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'mappr.dart'; - // ************************************************************************** // AutoMapprGenerator // ************************************************************************** @@ -12,6 +10,8 @@ part of 'mappr.dart'; // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; + /// {@template asset:auto_mappr/example/lib/mappr.dart} /// Available mappings: /// - `UserDto` → `User`. diff --git a/packages/auto_mappr/example/lib/mappr.dart b/packages/auto_mappr/example/lib/mappr.dart index 77eaeeb2..76449bc2 100644 --- a/packages/auto_mappr/example/lib/mappr.dart +++ b/packages/auto_mappr/example/lib/mappr.dart @@ -1,6 +1,6 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; -part 'mappr.g.dart'; +import 'mappr.auto_mappr.dart'; @AutoMappr([ MapType<UserDto, User>( diff --git a/packages/auto_mappr/lib/auto_mappr.dart b/packages/auto_mappr/lib/auto_mappr.dart index 48fc4da3..f6458534 100644 --- a/packages/auto_mappr/lib/auto_mappr.dart +++ b/packages/auto_mappr/lib/auto_mappr.dart @@ -5,12 +5,9 @@ import 'package:build/build.dart'; import 'package:source_gen/source_gen.dart'; /// Main Builder for the `AutoMappr` Annotation. -Builder autoMapprBuilder(BuilderOptions options) => SharedPartBuilder( - [AutoMapprGenerator(builderOptions: options)], - 'auto_mappr', - ); - -Builder autoMapprBuilderNotShared(BuilderOptions options) => PartBuilder( - [AutoMapprGenerator(builderOptions: options)], - '.auto_mappr.dart', +Builder autoMapprBuilder(BuilderOptions options) => LibraryBuilder( + AutoMapprGenerator(builderOptions: options), + generatedExtension: '.auto_mappr.dart', + allowSyntaxErrors: true, + options: options, ); diff --git a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart index 3f076c92..ae786cea 100644 --- a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart +++ b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart @@ -32,13 +32,18 @@ class AutoMapprBuilder { }); Library build() { + // TODO(modules): first process class and then generate library and its imports + return Library( (b) => b ..ignoreForFile = ListBuilder(fileIgnores) + ..directives = ListBuilder(<Directive>[ + Directive.import('package:auto_mappr_annotation/auto_mappr_annotation.dart'), + ]) ..body.addAll( [ Class( - (b) => b + (cb) => cb ..name = '\$${mapperClassElement.displayName}' ..implements = ListBuilder([refer('AutoMapprInterface')]) ..methods.addAll(_buildMethods()) diff --git a/packages/auto_mappr/test/integration/error_fixture/enum_mapping_not_enum.dart b/packages/auto_mappr/test/integration/error_fixture/enum_mapping_not_enum.dart index d797631e..7bbc575d 100644 --- a/packages/auto_mappr/test/integration/error_fixture/enum_mapping_not_enum.dart +++ b/packages/auto_mappr/test/integration/error_fixture/enum_mapping_not_enum.dart @@ -1,6 +1,6 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; -part 'enum_mapping_not_enum.g.dart'; +import 'enum_mapping_not_enum.auto_mappr.dart'; enum Source { a, b } diff --git a/packages/auto_mappr/test/integration/error_fixture/enum_mapping_subset.dart b/packages/auto_mappr/test/integration/error_fixture/enum_mapping_subset.dart index 0491f219..ff222e7e 100644 --- a/packages/auto_mappr/test/integration/error_fixture/enum_mapping_subset.dart +++ b/packages/auto_mappr/test/integration/error_fixture/enum_mapping_subset.dart @@ -1,6 +1,6 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; -part 'enum_mapping_subset.g.dart'; +import 'enum_mapping_subset.auto_mappr.dart'; enum Source { a, b } diff --git a/packages/auto_mappr/test/integration/fixture/complex_types.dart b/packages/auto_mappr/test/integration/fixture/complex_types.dart index 5a885dc9..45802458 100644 --- a/packages/auto_mappr/test/integration/fixture/complex_types.dart +++ b/packages/auto_mappr/test/integration/fixture/complex_types.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'complex_types.g.dart'; +import 'complex_types.auto_mappr.dart'; @AutoMappr( [ diff --git a/packages/auto_mappr/test/integration/fixture/constructor_parameters.dart b/packages/auto_mappr/test/integration/fixture/constructor_parameters.dart index 7098f990..d21eec25 100644 --- a/packages/auto_mappr/test/integration/fixture/constructor_parameters.dart +++ b/packages/auto_mappr/test/integration/fixture/constructor_parameters.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'constructor_parameters.g.dart'; +import 'constructor_parameters.auto_mappr.dart'; @AutoMappr([ MapType<Positional, Positional>(), diff --git a/packages/auto_mappr/test/integration/fixture/convert_iterable.dart b/packages/auto_mappr/test/integration/fixture/convert_iterable.dart index ea5acefa..e415e811 100644 --- a/packages/auto_mappr/test/integration/fixture/convert_iterable.dart +++ b/packages/auto_mappr/test/integration/fixture/convert_iterable.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'convert_iterable.g.dart'; +import 'convert_iterable.auto_mappr.dart'; @AutoMappr([ MapType<UserDto, User>(), diff --git a/packages/auto_mappr/test/integration/fixture/custom_mapping.dart b/packages/auto_mappr/test/integration/fixture/custom_mapping.dart index 21164069..5c5470e4 100644 --- a/packages/auto_mappr/test/integration/fixture/custom_mapping.dart +++ b/packages/auto_mappr/test/integration/fixture/custom_mapping.dart @@ -3,7 +3,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'custom_mapping.g.dart'; +import 'custom_mapping.auto_mappr.dart'; @AutoMappr([ // custom type diff --git a/packages/auto_mappr/test/integration/fixture/default_field.dart b/packages/auto_mappr/test/integration/fixture/default_field.dart index 9175bfb9..36871b23 100644 --- a/packages/auto_mappr/test/integration/fixture/default_field.dart +++ b/packages/auto_mappr/test/integration/fixture/default_field.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'default_field.g.dart'; +import 'default_field.auto_mappr.dart'; @AutoMappr([ MapType<NestedDto, Nested>(), diff --git a/packages/auto_mappr/test/integration/fixture/default_target.dart b/packages/auto_mappr/test/integration/fixture/default_target.dart index 3ebdad5e..255570e2 100644 --- a/packages/auto_mappr/test/integration/fixture/default_target.dart +++ b/packages/auto_mappr/test/integration/fixture/default_target.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'default_target.g.dart'; +import 'default_target.auto_mappr.dart'; @AutoMappr([ MapType<NestedDto, Nested>(), diff --git a/packages/auto_mappr/test/integration/fixture/delegates.dart b/packages/auto_mappr/test/integration/fixture/delegates.dart index b5f873ca..0be70b50 100644 --- a/packages/auto_mappr/test/integration/fixture/delegates.dart +++ b/packages/auto_mappr/test/integration/fixture/delegates.dart @@ -3,7 +3,7 @@ import 'package:equatable/equatable.dart'; import 'modules/module_alpha.dart'; -part 'delegates.g.dart'; +import 'delegates.auto_mappr.dart'; @AutoMappr([MapType<GroupDto, Group>()], delegates: [MapprAlpha()]) class MapprGroup extends $MapprGroup { diff --git a/packages/auto_mappr/test/integration/fixture/delegates/module_alpha.dart b/packages/auto_mappr/test/integration/fixture/delegates/module_alpha.dart index c9ca910e..1dd873a5 100644 --- a/packages/auto_mappr/test/integration/fixture/delegates/module_alpha.dart +++ b/packages/auto_mappr/test/integration/fixture/delegates/module_alpha.dart @@ -1,10 +1,9 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; +import 'module_alpha.auto_mappr.dart'; import 'module_beta.dart'; -part 'module_alpha.g.dart'; - @AutoMappr([MapType<AlphaDto, Alpha>()], delegates: [MapprBeta()]) class MapprAlpha extends $MapprAlpha { const MapprAlpha(); diff --git a/packages/auto_mappr/test/integration/fixture/delegates/module_beta.dart b/packages/auto_mappr/test/integration/fixture/delegates/module_beta.dart index 17e1b0d1..1cd48ac3 100644 --- a/packages/auto_mappr/test/integration/fixture/delegates/module_beta.dart +++ b/packages/auto_mappr/test/integration/fixture/delegates/module_beta.dart @@ -1,10 +1,9 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; +import 'module_beta.auto_mappr.dart'; import 'module_gama.dart'; -part 'module_beta.g.dart'; - @AutoMappr([MapType<BetaDto, Beta>()], delegates: [MapprGama()]) class MapprBeta extends $MapprBeta { const MapprBeta(); diff --git a/packages/auto_mappr/test/integration/fixture/delegates/module_gama.dart b/packages/auto_mappr/test/integration/fixture/delegates/module_gama.dart index fee4a6d6..e00e7f7a 100644 --- a/packages/auto_mappr/test/integration/fixture/delegates/module_gama.dart +++ b/packages/auto_mappr/test/integration/fixture/delegates/module_gama.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'module_gama.g.dart'; +import 'module_gama.auto_mappr.dart'; @AutoMappr([MapType<GamaDto, Gama>()]) class MapprGama extends $MapprGama { diff --git a/packages/auto_mappr/test/integration/fixture/enum_mapping.dart b/packages/auto_mappr/test/integration/fixture/enum_mapping.dart index 74509e4d..456f4e25 100644 --- a/packages/auto_mappr/test/integration/fixture/enum_mapping.dart +++ b/packages/auto_mappr/test/integration/fixture/enum_mapping.dart @@ -1,6 +1,6 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; -part 'enum_mapping.g.dart'; +import 'enum_mapping.auto_mappr.dart'; enum Person { employee, parent, student } diff --git a/packages/auto_mappr/test/integration/fixture/equatable.dart b/packages/auto_mappr/test/integration/fixture/equatable.dart index 662754b5..723f1c5f 100644 --- a/packages/auto_mappr/test/integration/fixture/equatable.dart +++ b/packages/auto_mappr/test/integration/fixture/equatable.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'equatable.g.dart'; +import 'equatable.auto_mappr.dart'; @AutoMappr([MapType<Source, Target>()]) class Mappr extends $Mappr { diff --git a/packages/auto_mappr/test/integration/fixture/forced_null_source_field.dart b/packages/auto_mappr/test/integration/fixture/forced_null_source_field.dart index 937d51bf..068b8f91 100644 --- a/packages/auto_mappr/test/integration/fixture/forced_null_source_field.dart +++ b/packages/auto_mappr/test/integration/fixture/forced_null_source_field.dart @@ -1,6 +1,6 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; -part 'forced_null_source_field.g.dart'; +import 'forced_null_source_field.auto_mappr.dart'; @AutoMappr([ MapType<Source, Target>( diff --git a/packages/auto_mappr/test/integration/fixture/generics.dart b/packages/auto_mappr/test/integration/fixture/generics.dart index 542e67b4..96bfa463 100644 --- a/packages/auto_mappr/test/integration/fixture/generics.dart +++ b/packages/auto_mappr/test/integration/fixture/generics.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'generics.g.dart'; +import 'generics.auto_mappr.dart'; @AutoMappr([ // simple diff --git a/packages/auto_mappr/test/integration/fixture/import_alias.dart b/packages/auto_mappr/test/integration/fixture/import_alias.dart index 4bb75de6..e95f2d09 100644 --- a/packages/auto_mappr/test/integration/fixture/import_alias.dart +++ b/packages/auto_mappr/test/integration/fixture/import_alias.dart @@ -5,7 +5,7 @@ import 'import_alias/import_alias_1.dart' as a1; import 'import_alias/import_alias_2.dart' as a2; import 'import_alias/import_alias_module.dart' as module; -part 'import_alias.g.dart'; +import 'import_alias.auto_mappr.dart'; @AutoMappr( [ diff --git a/packages/auto_mappr/test/integration/fixture/import_alias/import_alias_module.dart b/packages/auto_mappr/test/integration/fixture/import_alias/import_alias_module.dart index db1a6de6..8aaa412f 100644 --- a/packages/auto_mappr/test/integration/fixture/import_alias/import_alias_module.dart +++ b/packages/auto_mappr/test/integration/fixture/import_alias/import_alias_module.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'import_alias_module.g.dart'; +import 'import_alias_module.auto_mappr.dart'; @AutoMappr([MapType<UserDto, User>()]) class ImportAliasModule extends $ImportAliasModule { diff --git a/packages/auto_mappr/test/integration/fixture/includes.dart b/packages/auto_mappr/test/integration/fixture/includes.dart index 36162185..f81a497e 100644 --- a/packages/auto_mappr/test/integration/fixture/includes.dart +++ b/packages/auto_mappr/test/integration/fixture/includes.dart @@ -3,7 +3,7 @@ import 'package:equatable/equatable.dart'; import 'includes/module_alpha.dart' as alpha_feature; -part 'includes.g.dart'; +import 'includes.auto_mappr.dart'; @AutoMappr([MapType<GroupDto, Group>()], includes: [alpha_feature.MapprAlpha()]) class MapprGroup extends $MapprGroup { diff --git a/packages/auto_mappr/test/integration/fixture/includes/module_alpha.dart b/packages/auto_mappr/test/integration/fixture/includes/module_alpha.dart index ec313d6e..d4390764 100644 --- a/packages/auto_mappr/test/integration/fixture/includes/module_alpha.dart +++ b/packages/auto_mappr/test/integration/fixture/includes/module_alpha.dart @@ -1,10 +1,9 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; +import 'module_alpha.auto_mappr.dart'; import 'module_beta.dart'; -part 'module_alpha.g.dart'; - @AutoMappr([MapType<AlphaDto, Alpha>()], includes: [MapprBeta()]) class MapprAlpha extends $MapprAlpha { const MapprAlpha(); diff --git a/packages/auto_mappr/test/integration/fixture/includes/module_beta.dart b/packages/auto_mappr/test/integration/fixture/includes/module_beta.dart index 78bfc57d..1f00211f 100644 --- a/packages/auto_mappr/test/integration/fixture/includes/module_beta.dart +++ b/packages/auto_mappr/test/integration/fixture/includes/module_beta.dart @@ -1,10 +1,9 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; +import 'module_beta.auto_mappr.dart'; import 'module_gama.dart'; -part 'module_beta.g.dart'; - @AutoMappr([MapType<BetaDto, Beta>()], includes: [MapprGama()]) class MapprBeta extends $MapprBeta { const MapprBeta(); diff --git a/packages/auto_mappr/test/integration/fixture/includes/module_gama.dart b/packages/auto_mappr/test/integration/fixture/includes/module_gama.dart index fee4a6d6..e00e7f7a 100644 --- a/packages/auto_mappr/test/integration/fixture/includes/module_gama.dart +++ b/packages/auto_mappr/test/integration/fixture/includes/module_gama.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'module_gama.g.dart'; +import 'module_gama.auto_mappr.dart'; @AutoMappr([MapType<GamaDto, Gama>()]) class MapprGama extends $MapprGama { diff --git a/packages/auto_mappr/test/integration/fixture/iterable.dart b/packages/auto_mappr/test/integration/fixture/iterable.dart index aa3844c0..b2f9c82b 100644 --- a/packages/auto_mappr/test/integration/fixture/iterable.dart +++ b/packages/auto_mappr/test/integration/fixture/iterable.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'iterable.g.dart'; +import 'iterable.auto_mappr.dart'; @AutoMappr([ MapType<NestedTagDto, NestedTag>(), diff --git a/packages/auto_mappr/test/integration/fixture/list.dart b/packages/auto_mappr/test/integration/fixture/list.dart index 4a99430d..1c592926 100644 --- a/packages/auto_mappr/test/integration/fixture/list.dart +++ b/packages/auto_mappr/test/integration/fixture/list.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'list.g.dart'; +import 'list.auto_mappr.dart'; @AutoMappr([ MapType<NestedTagDto, NestedTag>(), diff --git a/packages/auto_mappr/test/integration/fixture/map.dart b/packages/auto_mappr/test/integration/fixture/map.dart index 541ba39b..736855c2 100644 --- a/packages/auto_mappr/test/integration/fixture/map.dart +++ b/packages/auto_mappr/test/integration/fixture/map.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'map.g.dart'; +import 'map.auto_mappr.dart'; @AutoMappr([ MapType<NestedTagDto, NestedTag>(), diff --git a/packages/auto_mappr/test/integration/fixture/mapping_from_source.dart b/packages/auto_mappr/test/integration/fixture/mapping_from_source.dart index 921cfe83..9c6edfbf 100644 --- a/packages/auto_mappr/test/integration/fixture/mapping_from_source.dart +++ b/packages/auto_mappr/test/integration/fixture/mapping_from_source.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'mapping_from_source.g.dart'; +import 'mapping_from_source.auto_mappr.dart'; @AutoMappr([ MapType<InstanceField, ValueHolder>(), diff --git a/packages/auto_mappr/test/integration/fixture/mapping_to_target.dart b/packages/auto_mappr/test/integration/fixture/mapping_to_target.dart index 91d56590..79e92a29 100644 --- a/packages/auto_mappr/test/integration/fixture/mapping_to_target.dart +++ b/packages/auto_mappr/test/integration/fixture/mapping_to_target.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'mapping_to_target.g.dart'; +import 'mapping_to_target.auto_mappr.dart'; @AutoMappr([MapType<OneDto, One>()]) class Mappr extends $Mappr { diff --git a/packages/auto_mappr/test/integration/fixture/multiple_annotations.dart b/packages/auto_mappr/test/integration/fixture/multiple_annotations.dart index 0c397738..fa11e821 100644 --- a/packages/auto_mappr/test/integration/fixture/multiple_annotations.dart +++ b/packages/auto_mappr/test/integration/fixture/multiple_annotations.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'multiple_annotations.g.dart'; +import 'multiple_annotations.auto_mappr.dart'; class AnnotationA { const AnnotationA(); diff --git a/packages/auto_mappr/test/integration/fixture/primitive_types.dart b/packages/auto_mappr/test/integration/fixture/primitive_types.dart index 73b320f1..1a92c855 100644 --- a/packages/auto_mappr/test/integration/fixture/primitive_types.dart +++ b/packages/auto_mappr/test/integration/fixture/primitive_types.dart @@ -2,7 +2,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; -part 'primitive_types.g.dart'; +import 'primitive_types.auto_mappr.dart'; @AutoMappr([ MapType<NumHolderDto, NumHolder>(), diff --git a/packages/auto_mappr/test/integration/fixture/regression/uint8_issue_77.dart b/packages/auto_mappr/test/integration/fixture/regression/uint8_issue_77.dart index 3de6ca91..cebc91ad 100644 --- a/packages/auto_mappr/test/integration/fixture/regression/uint8_issue_77.dart +++ b/packages/auto_mappr/test/integration/fixture/regression/uint8_issue_77.dart @@ -3,7 +3,7 @@ import 'dart:typed_data'; import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'uint8_issue_77.g.dart'; +import 'uint8_issue_77.auto_mappr.dart'; class Source { final Uint8List int8List; diff --git a/packages/auto_mappr/test/integration/fixture/rename.dart b/packages/auto_mappr/test/integration/fixture/rename.dart index 90cfedcc..32bfa30d 100644 --- a/packages/auto_mappr/test/integration/fixture/rename.dart +++ b/packages/auto_mappr/test/integration/fixture/rename.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'rename.g.dart'; +import 'rename.auto_mappr.dart'; @AutoMappr([ // nested diff --git a/packages/auto_mappr/test/integration/fixture/reverse.dart b/packages/auto_mappr/test/integration/fixture/reverse.dart index c79569b0..58acf2d5 100644 --- a/packages/auto_mappr/test/integration/fixture/reverse.dart +++ b/packages/auto_mappr/test/integration/fixture/reverse.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'reverse.g.dart'; +import 'reverse.auto_mappr.dart'; @AutoMappr([ MapType<PrimitiveDto, Primitive>(reverse: true), diff --git a/packages/auto_mappr/test/integration/fixture/selecting_constructor.dart b/packages/auto_mappr/test/integration/fixture/selecting_constructor.dart index 2c2bb7fa..f3fbcff5 100644 --- a/packages/auto_mappr/test/integration/fixture/selecting_constructor.dart +++ b/packages/auto_mappr/test/integration/fixture/selecting_constructor.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'selecting_constructor.g.dart'; +import 'selecting_constructor.auto_mappr.dart'; @AutoMappr([ // empty diff --git a/packages/auto_mappr/test/integration/fixture/set.dart b/packages/auto_mappr/test/integration/fixture/set.dart index 1fb5e99b..2f40bee8 100644 --- a/packages/auto_mappr/test/integration/fixture/set.dart +++ b/packages/auto_mappr/test/integration/fixture/set.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'set.g.dart'; +import 'set.auto_mappr.dart'; @AutoMappr([ MapType<NestedTagDto, NestedTag>(), diff --git a/packages/auto_mappr/test/integration/fixture/special_characters.dart b/packages/auto_mappr/test/integration/fixture/special_characters.dart index 24bb41d1..8a7b6663 100644 --- a/packages/auto_mappr/test/integration/fixture/special_characters.dart +++ b/packages/auto_mappr/test/integration/fixture/special_characters.dart @@ -3,7 +3,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'special_characters.g.dart'; +import 'special_characters.auto_mappr.dart'; @AutoMappr([ // in class diff --git a/packages/auto_mappr/test/integration/fixture/super_class.dart b/packages/auto_mappr/test/integration/fixture/super_class.dart index 6f0a1071..403c369c 100644 --- a/packages/auto_mappr/test/integration/fixture/super_class.dart +++ b/packages/auto_mappr/test/integration/fixture/super_class.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'super_class.g.dart'; +import 'super_class.auto_mappr.dart'; @AutoMappr([ MapType<FlattenedClass, SubClass>(), diff --git a/packages/auto_mappr/test/integration/fixture/try_convert.dart b/packages/auto_mappr/test/integration/fixture/try_convert.dart index 8339278b..54cf9e81 100644 --- a/packages/auto_mappr/test/integration/fixture/try_convert.dart +++ b/packages/auto_mappr/test/integration/fixture/try_convert.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'try_convert.g.dart'; +import 'try_convert.auto_mappr.dart'; @AutoMappr([ MapType<NestedDto, Nested>(), diff --git a/packages/auto_mappr/test/integration/fixture/when_source_is_null.dart b/packages/auto_mappr/test/integration/fixture/when_source_is_null.dart index e13d284b..f9605c01 100644 --- a/packages/auto_mappr/test/integration/fixture/when_source_is_null.dart +++ b/packages/auto_mappr/test/integration/fixture/when_source_is_null.dart @@ -1,6 +1,6 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; -part 'when_source_is_null.g.dart'; +import 'when_source_is_null.auto_mappr.dart'; class SourceValue { final String? name; diff --git a/packages/auto_mappr_annotation/README.md b/packages/auto_mappr_annotation/README.md index 889d2292..0d023843 100644 --- a/packages/auto_mappr_annotation/README.md +++ b/packages/auto_mappr_annotation/README.md @@ -21,7 +21,7 @@ Developed with 💚 by [netglade][netglade_link] ```dart import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; -part 'main.g.dart'; +import 'main.auto_mappr.dart'; @AutoMappr([ MapType<UserDto, User>(), diff --git a/packages/auto_mappr_annotation/example/lib/main.dart b/packages/auto_mappr_annotation/example/lib/main.dart index d8d842d6..d6b539ce 100644 --- a/packages/auto_mappr_annotation/example/lib/main.dart +++ b/packages/auto_mappr_annotation/example/lib/main.dart @@ -1,6 +1,6 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; -// part 'main.g.dart'; +// part 'main.auto_mappr.dart'; @AutoMappr([ MapType<UserDto, User>(), From 0fcd4b72711ff2fdd469394a5a4e8741838019aa Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 4 Sep 2023 16:34:45 +0200 Subject: [PATCH 15/48] Update --- examples/drift/lib/mappr.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/drift/lib/mappr.dart b/examples/drift/lib/mappr.dart index 971c9813..567df05a 100644 --- a/examples/drift/lib/mappr.dart +++ b/examples/drift/lib/mappr.dart @@ -1,7 +1,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:examples_drift/db.dart'; -import 'mappr.auto_mappr.dart'; +import 'package:examples_drift/mappr.auto_mappr.dart'; class TodoItem { final int id; From a2d1087ba4f367240c4c89527cc8820fa4eb1df5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 21:43:49 +0000 Subject: [PATCH 16/48] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 79d59391..fc5dadd6 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dart-lang/setup-dart@v1 - uses: bluefireteam/melos-action@v2 From 94b78974135a8c05b4f5e7b5331bfd6ce70b6815 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Thu, 7 Sep 2023 11:04:04 +0200 Subject: [PATCH 17/48] Add EmitterHelper, run in zones, relative and absolute imports --- examples/drift/lib/mappr.auto_mappr.dart | 24 ++-- examples/example/lib/enum.auto_mappr.dart | 57 ++++----- .../example/lib/equatable.auto_mappr.dart | 23 ++-- examples/example/lib/nested.auto_mappr.dart | 55 +++++---- examples/example/lib/nullable.auto_mappr.dart | 39 +++--- examples/example/lib/rename.auto_mappr.dart | 23 ++-- .../lib/freezed_example.auto_mappr.dart | 25 ++-- examples/injectable/lib/mappr.auto_mappr.dart | 23 ++-- .../lib/serializable.auto_mappr.dart | 39 +++--- .../json_serializable/lib/serializable.dart | 2 + .../json_serializable/lib/serializable.g.dart | 27 +++++ .../fixture/json_serializable.auto_mappr.dart | 39 +++--- .../example/lib/mappr.auto_mappr.dart | 43 ++++--- .../iterable_assignment_builder.dart | 7 +- .../assignments/map_assignment_builder.dart | 14 +-- .../assignments/nested_object_mixin.dart | 6 +- .../record_assignment_builder.dart | 13 +- .../lib/src/builder/auto_mappr_builder.dart | 27 ++--- .../map_bodies/class_body_builder.dart | 9 +- .../builder/map_bodies/enum_body_builder.dart | 3 +- .../convert_iterable_method_builder.dart | 6 +- .../builder/methods/method_builder_base.dart | 7 +- .../private_convert_method_builder.dart | 3 +- .../private_modules_method_builder.dart | 8 +- .../try_convert_iterable_method_builder.dart | 7 +- .../src/builder/value_assignment_builder.dart | 5 +- .../src/extensions/dart_object_extension.dart | 4 +- .../src/extensions/dart_type_extension.dart | 16 ++- .../src/extensions/expression_extension.dart | 27 ++--- .../src/extensions/reference_extension.dart | 3 +- .../src/generator/auto_mappr_generator.dart | 111 ++++++++++-------- packages/auto_mappr/lib/src/helpers/di.dart | 0 .../lib/src/helpers/emitter_helper.dart | 97 +++++++++++++++ packages/auto_mappr/lib/src/helpers/urls.dart | 3 + packages/auto_mappr/pubspec.yaml | 1 + .../integration/fixture/import_alias.dart | 3 +- 36 files changed, 504 insertions(+), 295 deletions(-) create mode 100644 examples/json_serializable/lib/serializable.g.dart create mode 100644 packages/auto_mappr/lib/src/helpers/di.dart create mode 100644 packages/auto_mappr/lib/src/helpers/emitter_helper.dart create mode 100644 packages/auto_mappr/lib/src/helpers/urls.dart diff --git a/examples/drift/lib/mappr.auto_mappr.dart b/examples/drift/lib/mappr.auto_mappr.dart index 38d1d478..b6ad2dc1 100644 --- a/examples/drift/lib/mappr.auto_mappr.dart +++ b/examples/drift/lib/mappr.auto_mappr.dart @@ -10,17 +10,21 @@ // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings -import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; + +import 'db.dart' as _i2; +import 'mappr.dart' as _i3; /// {@template package:examples_drift/mappr.dart} /// Available mappings: /// - `Todo` → `TodoItem`. /// {@endtemplate} -class $Mappr implements AutoMapprInterface { +class $Mappr implements _i1.AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _delegates => const []; + List<_i1.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_drift/mappr.dart} @@ -28,9 +32,10 @@ class $Mappr implements AutoMapprInterface { bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<Todo>() || sourceTypeOf == _typeOf<Todo?>()) && - (targetTypeOf == _typeOf<TodoItem>() || - targetTypeOf == _typeOf<TodoItem?>())) { + if ((sourceTypeOf == _typeOf<_i2.Todo>() || + sourceTypeOf == _typeOf<_i2.Todo?>()) && + (targetTypeOf == _typeOf<_i3.TodoItem>() || + targetTypeOf == _typeOf<_i3.TodoItem?>())) { return true; } if (recursive) { @@ -190,9 +195,10 @@ class $Mappr implements AutoMapprInterface { }) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<Todo>() || sourceTypeOf == _typeOf<Todo?>()) && - (targetTypeOf == _typeOf<TodoItem>() || - targetTypeOf == _typeOf<TodoItem?>())) { + if ((sourceTypeOf == _typeOf<_i2.Todo>() || + sourceTypeOf == _typeOf<_i2.Todo?>()) && + (targetTypeOf == _typeOf<_i3.TodoItem>() || + targetTypeOf == _typeOf<_i3.TodoItem?>())) { if (canReturnNull && model == null) { return null; } diff --git a/examples/example/lib/enum.auto_mappr.dart b/examples/example/lib/enum.auto_mappr.dart index 67f7cba6..48600227 100644 --- a/examples/example/lib/enum.auto_mappr.dart +++ b/examples/example/lib/enum.auto_mappr.dart @@ -10,7 +10,10 @@ // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings -import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; + +import 'enum.dart' as _i2; /// {@template package:examples_example/enum.dart} /// Available mappings: @@ -18,11 +21,11 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; /// - `Vehicle` → `Vehicle`. /// - `Vehicle` → `VehicleX`. /// {@endtemplate} -class $Mappr implements AutoMapprInterface { +class $Mappr implements _i1.AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _delegates => const []; + List<_i1.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_example/enum.dart} @@ -30,22 +33,22 @@ class $Mappr implements AutoMapprInterface { bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserType>() || - sourceTypeOf == _typeOf<UserType?>()) && - (targetTypeOf == _typeOf<PersonType>() || - targetTypeOf == _typeOf<PersonType?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserType>() || + sourceTypeOf == _typeOf<_i2.UserType?>()) && + (targetTypeOf == _typeOf<_i2.PersonType>() || + targetTypeOf == _typeOf<_i2.PersonType?>())) { return true; } - if ((sourceTypeOf == _typeOf<Vehicle>() || - sourceTypeOf == _typeOf<Vehicle?>()) && - (targetTypeOf == _typeOf<Vehicle>() || - targetTypeOf == _typeOf<Vehicle?>())) { + if ((sourceTypeOf == _typeOf<_i2.Vehicle>() || + sourceTypeOf == _typeOf<_i2.Vehicle?>()) && + (targetTypeOf == _typeOf<_i2.Vehicle>() || + targetTypeOf == _typeOf<_i2.Vehicle?>())) { return true; } - if ((sourceTypeOf == _typeOf<Vehicle>() || - sourceTypeOf == _typeOf<Vehicle?>()) && - (targetTypeOf == _typeOf<VehicleX>() || - targetTypeOf == _typeOf<VehicleX?>())) { + if ((sourceTypeOf == _typeOf<_i2.Vehicle>() || + sourceTypeOf == _typeOf<_i2.Vehicle?>()) && + (targetTypeOf == _typeOf<_i2.VehicleX>() || + targetTypeOf == _typeOf<_i2.VehicleX?>())) { return true; } if (recursive) { @@ -205,28 +208,28 @@ class $Mappr implements AutoMapprInterface { }) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserType>() || - sourceTypeOf == _typeOf<UserType?>()) && - (targetTypeOf == _typeOf<PersonType>() || - targetTypeOf == _typeOf<PersonType?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserType>() || + sourceTypeOf == _typeOf<_i2.UserType?>()) && + (targetTypeOf == _typeOf<_i2.PersonType>() || + targetTypeOf == _typeOf<_i2.PersonType?>())) { if (canReturnNull && model == null) { return null; } return (_map__UserType__To__PersonType((model as UserType?)) as TARGET); } - if ((sourceTypeOf == _typeOf<Vehicle>() || - sourceTypeOf == _typeOf<Vehicle?>()) && - (targetTypeOf == _typeOf<Vehicle>() || - targetTypeOf == _typeOf<Vehicle?>())) { + if ((sourceTypeOf == _typeOf<_i2.Vehicle>() || + sourceTypeOf == _typeOf<_i2.Vehicle?>()) && + (targetTypeOf == _typeOf<_i2.Vehicle>() || + targetTypeOf == _typeOf<_i2.Vehicle?>())) { if (canReturnNull && model == null) { return null; } return (_map__Vehicle__To__Vehicle((model as Vehicle?)) as TARGET); } - if ((sourceTypeOf == _typeOf<Vehicle>() || - sourceTypeOf == _typeOf<Vehicle?>()) && - (targetTypeOf == _typeOf<VehicleX>() || - targetTypeOf == _typeOf<VehicleX?>())) { + if ((sourceTypeOf == _typeOf<_i2.Vehicle>() || + sourceTypeOf == _typeOf<_i2.Vehicle?>()) && + (targetTypeOf == _typeOf<_i2.VehicleX>() || + targetTypeOf == _typeOf<_i2.VehicleX?>())) { if (canReturnNull && model == null) { return null; } diff --git a/examples/example/lib/equatable.auto_mappr.dart b/examples/example/lib/equatable.auto_mappr.dart index c65f85af..c7025cf5 100644 --- a/examples/example/lib/equatable.auto_mappr.dart +++ b/examples/example/lib/equatable.auto_mappr.dart @@ -10,17 +10,20 @@ // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings -import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; + +import 'equatable.dart' as _i2; /// {@template package:examples_example/equatable.dart} /// Available mappings: /// - `UserDto` → `User`. /// {@endtemplate} -class $Mappr implements AutoMapprInterface { +class $Mappr implements _i1.AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _delegates => const []; + List<_i1.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_example/equatable.dart} @@ -28,9 +31,10 @@ class $Mappr implements AutoMapprInterface { bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { return true; } if (recursive) { @@ -190,9 +194,10 @@ class $Mappr implements AutoMapprInterface { }) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { if (canReturnNull && model == null) { return null; } diff --git a/examples/example/lib/nested.auto_mappr.dart b/examples/example/lib/nested.auto_mappr.dart index 738966fa..423616a6 100644 --- a/examples/example/lib/nested.auto_mappr.dart +++ b/examples/example/lib/nested.auto_mappr.dart @@ -10,7 +10,10 @@ // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings -import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; + +import 'nested.dart' as _i2; /// {@template package:examples_example/nested.dart} /// Available mappings: @@ -18,11 +21,11 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; /// - `NestedDto` → `Nested`. /// - `NestedTagDto` → `NestedTag`. /// {@endtemplate} -class $Mappr implements AutoMapprInterface { +class $Mappr implements _i1.AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _delegates => const []; + List<_i1.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_example/nested.dart} @@ -30,21 +33,22 @@ class $Mappr implements AutoMapprInterface { bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { return true; } - if ((sourceTypeOf == _typeOf<NestedDto>() || - sourceTypeOf == _typeOf<NestedDto?>()) && - (targetTypeOf == _typeOf<Nested>() || - targetTypeOf == _typeOf<Nested?>())) { + if ((sourceTypeOf == _typeOf<_i2.NestedDto>() || + sourceTypeOf == _typeOf<_i2.NestedDto?>()) && + (targetTypeOf == _typeOf<_i2.Nested>() || + targetTypeOf == _typeOf<_i2.Nested?>())) { return true; } - if ((sourceTypeOf == _typeOf<NestedTagDto>() || - sourceTypeOf == _typeOf<NestedTagDto?>()) && - (targetTypeOf == _typeOf<NestedTag>() || - targetTypeOf == _typeOf<NestedTag?>())) { + if ((sourceTypeOf == _typeOf<_i2.NestedTagDto>() || + sourceTypeOf == _typeOf<_i2.NestedTagDto?>()) && + (targetTypeOf == _typeOf<_i2.NestedTag>() || + targetTypeOf == _typeOf<_i2.NestedTag?>())) { return true; } if (recursive) { @@ -204,27 +208,28 @@ class $Mappr implements AutoMapprInterface { }) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { if (canReturnNull && model == null) { return null; } return (_map__UserDto__To__User((model as UserDto?)) as TARGET); } - if ((sourceTypeOf == _typeOf<NestedDto>() || - sourceTypeOf == _typeOf<NestedDto?>()) && - (targetTypeOf == _typeOf<Nested>() || - targetTypeOf == _typeOf<Nested?>())) { + if ((sourceTypeOf == _typeOf<_i2.NestedDto>() || + sourceTypeOf == _typeOf<_i2.NestedDto?>()) && + (targetTypeOf == _typeOf<_i2.Nested>() || + targetTypeOf == _typeOf<_i2.Nested?>())) { if (canReturnNull && model == null) { return null; } return (_map__NestedDto__To__Nested((model as NestedDto?)) as TARGET); } - if ((sourceTypeOf == _typeOf<NestedTagDto>() || - sourceTypeOf == _typeOf<NestedTagDto?>()) && - (targetTypeOf == _typeOf<NestedTag>() || - targetTypeOf == _typeOf<NestedTag?>())) { + if ((sourceTypeOf == _typeOf<_i2.NestedTagDto>() || + sourceTypeOf == _typeOf<_i2.NestedTagDto?>()) && + (targetTypeOf == _typeOf<_i2.NestedTag>() || + targetTypeOf == _typeOf<_i2.NestedTag?>())) { if (canReturnNull && model == null) { return null; } diff --git a/examples/example/lib/nullable.auto_mappr.dart b/examples/example/lib/nullable.auto_mappr.dart index abe9da92..a8ec920a 100644 --- a/examples/example/lib/nullable.auto_mappr.dart +++ b/examples/example/lib/nullable.auto_mappr.dart @@ -10,18 +10,21 @@ // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings -import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; + +import 'nullable.dart' as _i2; /// {@template package:examples_example/nullable.dart} /// Available mappings: /// - `UserDto` → `User` -- With default value. /// - `NestedDto` → `Nested`. /// {@endtemplate} -class $Mappr implements AutoMapprInterface { +class $Mappr implements _i1.AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _delegates => const []; + List<_i1.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_example/nullable.dart} @@ -29,15 +32,16 @@ class $Mappr implements AutoMapprInterface { bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { return true; } - if ((sourceTypeOf == _typeOf<NestedDto>() || - sourceTypeOf == _typeOf<NestedDto?>()) && - (targetTypeOf == _typeOf<Nested>() || - targetTypeOf == _typeOf<Nested?>())) { + if ((sourceTypeOf == _typeOf<_i2.NestedDto>() || + sourceTypeOf == _typeOf<_i2.NestedDto?>()) && + (targetTypeOf == _typeOf<_i2.Nested>() || + targetTypeOf == _typeOf<_i2.Nested?>())) { return true; } if (recursive) { @@ -197,9 +201,10 @@ class $Mappr implements AutoMapprInterface { }) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { if (canReturnNull && model == null) { return (const User( id: 1, @@ -211,10 +216,10 @@ class $Mappr implements AutoMapprInterface { } return (_map__UserDto__To__User((model as UserDto?)) as TARGET); } - if ((sourceTypeOf == _typeOf<NestedDto>() || - sourceTypeOf == _typeOf<NestedDto?>()) && - (targetTypeOf == _typeOf<Nested>() || - targetTypeOf == _typeOf<Nested?>())) { + if ((sourceTypeOf == _typeOf<_i2.NestedDto>() || + sourceTypeOf == _typeOf<_i2.NestedDto?>()) && + (targetTypeOf == _typeOf<_i2.Nested>() || + targetTypeOf == _typeOf<_i2.Nested?>())) { if (canReturnNull && model == null) { return null; } diff --git a/examples/example/lib/rename.auto_mappr.dart b/examples/example/lib/rename.auto_mappr.dart index b45a9dc7..fe445cf5 100644 --- a/examples/example/lib/rename.auto_mappr.dart +++ b/examples/example/lib/rename.auto_mappr.dart @@ -10,17 +10,20 @@ // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings -import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; + +import 'rename.dart' as _i2; /// {@template package:examples_example/rename.dart} /// Available mappings: /// - `UserDto` → `User`. /// {@endtemplate} -class $Mappr implements AutoMapprInterface { +class $Mappr implements _i1.AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _delegates => const []; + List<_i1.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_example/rename.dart} @@ -28,9 +31,10 @@ class $Mappr implements AutoMapprInterface { bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { return true; } if (recursive) { @@ -190,9 +194,10 @@ class $Mappr implements AutoMapprInterface { }) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { if (canReturnNull && model == null) { return null; } diff --git a/examples/freezed/lib/freezed_example.auto_mappr.dart b/examples/freezed/lib/freezed_example.auto_mappr.dart index e42f9032..8190dce6 100644 --- a/examples/freezed/lib/freezed_example.auto_mappr.dart +++ b/examples/freezed/lib/freezed_example.auto_mappr.dart @@ -10,17 +10,20 @@ // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings -import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; + +import 'freezed_example.dart' as _i2; /// {@template package:examples_freezed/freezed_example.dart} /// Available mappings: /// - `UserInfo` → `UserInfoCompanion`. /// {@endtemplate} -class $Mappr implements AutoMapprInterface { +class $Mappr implements _i1.AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _delegates => const []; + List<_i1.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_freezed/freezed_example.dart} @@ -28,10 +31,10 @@ class $Mappr implements AutoMapprInterface { bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserInfo>() || - sourceTypeOf == _typeOf<UserInfo?>()) && - (targetTypeOf == _typeOf<UserInfoCompanion>() || - targetTypeOf == _typeOf<UserInfoCompanion?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserInfo>() || + sourceTypeOf == _typeOf<_i2.UserInfo?>()) && + (targetTypeOf == _typeOf<_i2.UserInfoCompanion>() || + targetTypeOf == _typeOf<_i2.UserInfoCompanion?>())) { return true; } if (recursive) { @@ -191,10 +194,10 @@ class $Mappr implements AutoMapprInterface { }) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserInfo>() || - sourceTypeOf == _typeOf<UserInfo?>()) && - (targetTypeOf == _typeOf<UserInfoCompanion>() || - targetTypeOf == _typeOf<UserInfoCompanion?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserInfo>() || + sourceTypeOf == _typeOf<_i2.UserInfo?>()) && + (targetTypeOf == _typeOf<_i2.UserInfoCompanion>() || + targetTypeOf == _typeOf<_i2.UserInfoCompanion?>())) { if (canReturnNull && model == null) { return null; } diff --git a/examples/injectable/lib/mappr.auto_mappr.dart b/examples/injectable/lib/mappr.auto_mappr.dart index 05023986..4f4fc15b 100644 --- a/examples/injectable/lib/mappr.auto_mappr.dart +++ b/examples/injectable/lib/mappr.auto_mappr.dart @@ -10,17 +10,20 @@ // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings -import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; + +import 'mappr.dart' as _i2; /// {@template package:examples_injectable/mappr.dart} /// Available mappings: /// - `UserDto` → `User`. /// {@endtemplate} -class $Mappr implements AutoMapprInterface { +class $Mappr implements _i1.AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _delegates => const []; + List<_i1.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_injectable/mappr.dart} @@ -28,9 +31,10 @@ class $Mappr implements AutoMapprInterface { bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { return true; } if (recursive) { @@ -190,9 +194,10 @@ class $Mappr implements AutoMapprInterface { }) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { if (canReturnNull && model == null) { return null; } diff --git a/examples/json_serializable/lib/serializable.auto_mappr.dart b/examples/json_serializable/lib/serializable.auto_mappr.dart index 5425f115..8244f2d7 100644 --- a/examples/json_serializable/lib/serializable.auto_mappr.dart +++ b/examples/json_serializable/lib/serializable.auto_mappr.dart @@ -10,18 +10,21 @@ // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings -import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; + +import 'serializable.dart' as _i2; /// {@template package:examples_json_serializable/serializable.dart} /// Available mappings: /// - `UserDto` → `User`. /// - `ValueHolderDto` → `ValueHolder`. /// {@endtemplate} -class $Mappr implements AutoMapprInterface { +class $Mappr implements _i1.AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _delegates => const []; + List<_i1.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_json_serializable/serializable.dart} @@ -29,15 +32,16 @@ class $Mappr implements AutoMapprInterface { bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { return true; } - if ((sourceTypeOf == _typeOf<ValueHolderDto>() || - sourceTypeOf == _typeOf<ValueHolderDto?>()) && - (targetTypeOf == _typeOf<ValueHolder>() || - targetTypeOf == _typeOf<ValueHolder?>())) { + if ((sourceTypeOf == _typeOf<_i2.ValueHolderDto>() || + sourceTypeOf == _typeOf<_i2.ValueHolderDto?>()) && + (targetTypeOf == _typeOf<_i2.ValueHolder>() || + targetTypeOf == _typeOf<_i2.ValueHolder?>())) { return true; } if (recursive) { @@ -197,18 +201,19 @@ class $Mappr implements AutoMapprInterface { }) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { if (canReturnNull && model == null) { return null; } return (_map__UserDto__To__User((model as UserDto?)) as TARGET); } - if ((sourceTypeOf == _typeOf<ValueHolderDto>() || - sourceTypeOf == _typeOf<ValueHolderDto?>()) && - (targetTypeOf == _typeOf<ValueHolder>() || - targetTypeOf == _typeOf<ValueHolder?>())) { + if ((sourceTypeOf == _typeOf<_i2.ValueHolderDto>() || + sourceTypeOf == _typeOf<_i2.ValueHolderDto?>()) && + (targetTypeOf == _typeOf<_i2.ValueHolder>() || + targetTypeOf == _typeOf<_i2.ValueHolder?>())) { if (canReturnNull && model == null) { return null; } diff --git a/examples/json_serializable/lib/serializable.dart b/examples/json_serializable/lib/serializable.dart index 2dee434b..61325968 100644 --- a/examples/json_serializable/lib/serializable.dart +++ b/examples/json_serializable/lib/serializable.dart @@ -2,6 +2,8 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:examples_json_serializable/serializable.auto_mappr.dart'; import 'package:json_annotation/json_annotation.dart'; +part 'serializable.g.dart'; + @AutoMappr([ MapType<UserDto, User>(), MapType<ValueHolderDto, ValueHolder>(), diff --git a/examples/json_serializable/lib/serializable.g.dart b/examples/json_serializable/lib/serializable.g.dart new file mode 100644 index 00000000..532b7555 --- /dev/null +++ b/examples/json_serializable/lib/serializable.g.dart @@ -0,0 +1,27 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'serializable.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserDto _$UserDtoFromJson(Map<String, dynamic> json) => UserDto( + firstName: json['firstName'] as String, + lastName: json['lastName'] as String, + ); + +Map<String, dynamic> _$UserDtoToJson(UserDto instance) => <String, dynamic>{ + 'firstName': instance.firstName, + 'lastName': instance.lastName, + }; + +ValueHolderDto _$ValueHolderDtoFromJson(Map<String, dynamic> json) => + ValueHolderDto( + json['json'] as Map<String, dynamic>, + ); + +Map<String, dynamic> _$ValueHolderDtoToJson(ValueHolderDto instance) => + <String, dynamic>{ + 'json': instance.json, + }; diff --git a/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart b/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart index 74c78092..9504d6d5 100644 --- a/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart +++ b/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart @@ -10,18 +10,21 @@ // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings -import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; + +import 'json_serializable.dart' as _i2; /// {@template asset:examples_json_serializable/test/fixture/json_serializable.dart} /// Available mappings: /// - `UserDto` → `User`. /// - `ValueHolderDto` → `ValueHolder`. /// {@endtemplate} -class $Mappr implements AutoMapprInterface { +class $Mappr implements _i1.AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _delegates => const []; + List<_i1.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro asset:examples_json_serializable/test/fixture/json_serializable.dart} @@ -29,15 +32,16 @@ class $Mappr implements AutoMapprInterface { bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { return true; } - if ((sourceTypeOf == _typeOf<ValueHolderDto>() || - sourceTypeOf == _typeOf<ValueHolderDto?>()) && - (targetTypeOf == _typeOf<ValueHolder>() || - targetTypeOf == _typeOf<ValueHolder?>())) { + if ((sourceTypeOf == _typeOf<_i2.ValueHolderDto>() || + sourceTypeOf == _typeOf<_i2.ValueHolderDto?>()) && + (targetTypeOf == _typeOf<_i2.ValueHolder>() || + targetTypeOf == _typeOf<_i2.ValueHolder?>())) { return true; } if (recursive) { @@ -197,18 +201,19 @@ class $Mappr implements AutoMapprInterface { }) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { if (canReturnNull && model == null) { return null; } return (_map__UserDto__To__User((model as UserDto?)) as TARGET); } - if ((sourceTypeOf == _typeOf<ValueHolderDto>() || - sourceTypeOf == _typeOf<ValueHolderDto?>()) && - (targetTypeOf == _typeOf<ValueHolder>() || - targetTypeOf == _typeOf<ValueHolder?>())) { + if ((sourceTypeOf == _typeOf<_i2.ValueHolderDto>() || + sourceTypeOf == _typeOf<_i2.ValueHolderDto?>()) && + (targetTypeOf == _typeOf<_i2.ValueHolder>() || + targetTypeOf == _typeOf<_i2.ValueHolder?>())) { if (canReturnNull && model == null) { return null; } diff --git a/packages/auto_mappr/example/lib/mappr.auto_mappr.dart b/packages/auto_mappr/example/lib/mappr.auto_mappr.dart index c55703ce..a1f062b4 100644 --- a/packages/auto_mappr/example/lib/mappr.auto_mappr.dart +++ b/packages/auto_mappr/example/lib/mappr.auto_mappr.dart @@ -10,27 +10,31 @@ // ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis // ignore_for_file: unnecessary_raw_strings -import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; -/// {@template package:auto_mappr_example/mappr.dart} +import 'mappr.dart' as _i2; + +/// {@template asset:auto_mappr/example/lib/mappr.dart} /// Available mappings: /// - `UserDto` → `User`. /// {@endtemplate} -class $Mappr implements AutoMapprInterface { +class $Mappr implements _i1.AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<AutoMapprInterface> get _delegates => const []; + List<_i1.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { return true; } if (recursive) { @@ -44,7 +48,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:convert} - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override TARGET convert<SOURCE, TARGET>(SOURCE? model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -60,7 +64,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:tryConvert} - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override TARGET? tryConvert<SOURCE, TARGET>(SOURCE? model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -79,7 +83,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:convertIterable} - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override Iterable<TARGET> convertIterable<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -98,7 +102,7 @@ class $Mappr implements AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override Iterable<TARGET?> tryConvertIterable<SOURCE, TARGET>( Iterable<SOURCE?> model) { @@ -115,7 +119,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:convertList} - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override List<TARGET> convertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -134,7 +138,7 @@ class $Mappr implements AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override List<TARGET?> tryConvertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -150,7 +154,7 @@ class $Mappr implements AutoMapprInterface { } /// {@macro AutoMapprInterface:convertSet} - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override Set<TARGET> convertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -169,7 +173,7 @@ class $Mappr implements AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override Set<TARGET?> tryConvertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -190,9 +194,10 @@ class $Mappr implements AutoMapprInterface { }) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<UserDto>() || - sourceTypeOf == _typeOf<UserDto?>()) && - (targetTypeOf == _typeOf<User>() || targetTypeOf == _typeOf<User?>())) { + if ((sourceTypeOf == _typeOf<_i2.UserDto>() || + sourceTypeOf == _typeOf<_i2.UserDto?>()) && + (targetTypeOf == _typeOf<_i2.User>() || + targetTypeOf == _typeOf<_i2.User?>())) { if (canReturnNull && model == null) { return null; } diff --git a/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart index ca7ccf8f..8309311d 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart @@ -24,14 +24,13 @@ class IterableAssignmentBuilder extends AssignmentBuilderBase with NestedObjectM final sourceType = assignment.sourceType!; final targetType = assignment.targetType; - final sourceNullable = sourceType.nullabilitySuffix == NullabilitySuffix.question; - final targetNullable = targetType.nullabilitySuffix == NullabilitySuffix.question; + final sourceNullable = sourceType.isNullable; + final targetNullable = targetType.isNullable; final sourceIterableType = sourceType.genericParameterTypeOrSelf; final targetIterableType = targetType.genericParameterTypeOrSelf; - final shouldFilterNullInSource = sourceIterableType.nullabilitySuffix == NullabilitySuffix.question && - targetIterableType.nullabilitySuffix != NullabilitySuffix.question; + final shouldFilterNullInSource = sourceIterableType.isNullable && targetIterableType.isNotNullable; final assignNestedObject = (!targetIterableType.isPrimitiveType && !targetIterableType.isSpecializedListType) && (!targetIterableType.isSame(sourceIterableType)); diff --git a/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart index a387e675..872b5f4d 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart @@ -1,9 +1,9 @@ -import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; import 'package:auto_mappr/src/builder/assignments/nested_object_mixin.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/extensions/expression_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/models.dart'; import 'package:code_builder/code_builder.dart'; import 'package:collection/collection.dart'; @@ -27,7 +27,7 @@ class MapAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin final sourceType = assignment.sourceType!; final targetType = assignment.targetType; - final sourceNullable = sourceType.nullabilitySuffix == NullabilitySuffix.question; + final sourceNullable = sourceType.isNullable; final sourceKeyType = (sourceType as ParameterizedType).typeArguments.firstOrNull; final sourceValueType = sourceType.typeArguments.lastOrNull; @@ -35,10 +35,10 @@ class MapAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin final targetKeyType = (targetType as ParameterizedType).typeArguments.firstOrNull; final targetValueType = targetType.typeArguments.lastOrNull; - final sourceNullableKey = sourceKeyType?.nullabilitySuffix == NullabilitySuffix.question; - final sourceNullableValue = sourceValueType?.nullabilitySuffix == NullabilitySuffix.question; - final targetNullableKey = targetKeyType?.nullabilitySuffix == NullabilitySuffix.question; - final targetNullableValue = targetValueType?.nullabilitySuffix == NullabilitySuffix.question; + final sourceNullableKey = sourceKeyType?.isNullable ?? false; + final sourceNullableValue = sourceValueType?.isNullable ?? false; + final targetNullableKey = targetKeyType?.isNullable ?? false; + final targetNullableValue = targetValueType?.isNullable ?? false; if (targetKeyType == null || targetValueType == null) { throw InvalidGenerationSourceError( @@ -152,7 +152,7 @@ class MapAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin : targetMapExpression; return refer( - '(key, value) => MapEntry(${keyExpression.accept(DartEmitter())}, ${valueExpression.accept(DartEmitter())})', + '(key, value) => MapEntry(${keyExpression.accept(EmitterHelper.current.emitter)}, ${valueExpression.accept(EmitterHelper.current.emitter)})', ); } } diff --git a/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart b/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart index 6a83a62d..acd85d56 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart @@ -38,7 +38,7 @@ mixin NestedObjectMixin on AssignmentBuilderBase { ); final sourceName = assignment.sourceField?.getDisplayString(withNullability: true); - if (target.nullabilitySuffix == NullabilitySuffix.question) { + if (target.isNullable) { log.warning("Can't find nested mapping '$assignment' but target is nullable. Setting null"); return literalNull; @@ -60,7 +60,7 @@ mixin NestedObjectMixin on AssignmentBuilderBase { // If source == null and target not nullable -> use whenNullDefault if possible final fieldMapping = mapping.tryGetFieldMapping(assignment.targetName); - if (source.nullabilitySuffix == NullabilitySuffix.question && (fieldMapping?.whenNullExpression != null)) { + if (source.isNullable && (fieldMapping?.whenNullExpression != null)) { // Generates code like: // // model.name == null @@ -93,7 +93,7 @@ mixin NestedObjectMixin on AssignmentBuilderBase { Expression? convertMethodArgument, bool includeGenericTypes = false, }) { - final targetNullable = target.nullabilitySuffix == NullabilitySuffix.question; + final targetNullable = target.isNullable; final useNullableMethod = targetNullable && !mapping.hasWhenNullDefault(); diff --git a/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart index 39ab0bb7..064111f1 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart @@ -5,6 +5,7 @@ import 'package:analyzer/dart/element/type.dart' as type; import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; import 'package:auto_mappr/src/builder/assignments/nested_object_mixin.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/source_assignment.dart'; import 'package:code_builder/code_builder.dart'; import 'package:collection/collection.dart'; @@ -63,7 +64,7 @@ class RecordAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMix source: sourcePositional.elementAtOrNull(index), target: targetField, index: index + 1, - ).accept(DartEmitter()).toString(), + ).accept(EmitterHelper.current.emitter).toString(), ]; final namedFields = <({String key, String value})>[ @@ -74,7 +75,7 @@ class RecordAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMix assignment: assignment, source: sourceNamed.firstWhereOrNull((sourceField) => sourceField.name == targetField.name), target: targetField, - ).accept(DartEmitter()).toString(), + ).accept(EmitterHelper.current.emitter).toString(), ), ]; @@ -104,7 +105,7 @@ class RecordAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMix final targetRecordExpression = refer(assignment.sourceField!.name); if (!shouldAssignNestedObject) { - return refer('model.${targetRecordExpression.accept(DartEmitter())}.${source.name}'); + return refer('model.${targetRecordExpression.accept(EmitterHelper.current.emitter)}.${source.name}'); } final valueExpression = assignNestedObject( @@ -114,7 +115,7 @@ class RecordAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMix convertMethodArgument: valuesAreSameType ? null : targetRecordExpression, ); - return refer('${valueExpression.accept(DartEmitter())})'); + return refer('${valueExpression.accept(EmitterHelper.current.emitter)})'); } // Handles mapping of only one positional field. @@ -137,7 +138,7 @@ class RecordAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMix final targetRecordExpression = refer(assignment.sourceField!.name); if (!shouldAssignNestedObject) { - return refer('model.${targetRecordExpression.accept(DartEmitter())}.\$$index'); + return refer('model.${targetRecordExpression.accept(EmitterHelper.current.emitter)}.\$$index'); } final valueExpression = assignNestedObject( @@ -147,6 +148,6 @@ class RecordAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMix convertMethodArgument: valuesAreSameType ? null : targetRecordExpression, ); - return refer('${valueExpression.accept(DartEmitter())})'); + return refer('${valueExpression.accept(EmitterHelper.current.emitter)})'); } } diff --git a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart index e879200a..1f5daef5 100644 --- a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart +++ b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart @@ -4,6 +4,8 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:auto_mappr/src/builder/map_model_body_method_builder.dart'; import 'package:auto_mappr/src/builder/methods/methods.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; +import 'package:auto_mappr/src/helpers/urls.dart'; import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:auto_mappr/src/models/type_mapping.dart'; import 'package:built_collection/built_collection.dart'; @@ -35,24 +37,19 @@ class AutoMapprBuilder { Library build() { // TODO(modules): first process class and then generate library and its imports + final generatedClass = Class( + (cb) => cb + ..name = '\$${mapperClassElement.displayName}' + ..implements = ListBuilder([refer('AutoMapprInterface', Urls.annotationPackageUrl)]) + ..methods.addAll(_buildMethods()) + ..constructors.addAll(_buildConstructors()) + ..docs = ListBuilder(config.getAvailableMappingsDocComment()), + ); + return Library( (b) => b ..ignoreForFile = ListBuilder(fileIgnores) - ..directives = ListBuilder(<Directive>[ - Directive.import('package:auto_mappr_annotation/auto_mappr_annotation.dart'), - ]) - ..body.addAll( - [ - Class( - (cb) => cb - ..name = '\$${mapperClassElement.displayName}' - ..implements = ListBuilder([refer('AutoMapprInterface')]) - ..methods.addAll(_buildMethods()) - ..constructors.addAll(_buildConstructors()) - ..docs = ListBuilder(config.getAvailableMappingsDocComment()), - ), - ], - ), + ..body.addAll([generatedClass]), ); } diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart index 91c8685f..e60206b8 100644 --- a/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart +++ b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart @@ -3,6 +3,7 @@ import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/builder/map_bodies/map_body_builder_base.dart'; import 'package:auto_mappr/src/builder/value_assignment_builder.dart'; +import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/extensions/element_extension.dart'; import 'package:auto_mappr/src/extensions/interface_type_extension.dart'; import 'package:auto_mappr/src/models/source_assignment.dart'; @@ -205,13 +206,13 @@ class ClassBodyBuilder extends MapBodyBuilderBase { void _assertParamFieldCanBeIgnored(ParameterElement param, PropertyAccessorElement sourceField) { final sourceFieldName = sourceField.getDisplayString(withNullability: true); - if (param.isPositional && param.type.nullabilitySuffix != NullabilitySuffix.question) { + if (param.isPositional && param.type.isNotNullable) { throw InvalidGenerationSourceError( "Can't ignore field '$sourceFieldName' as it is positional not-nullable parameter", ); } - if (param.isRequiredNamed && param.type.nullabilitySuffix != NullabilitySuffix.question) { + if (param.isRequiredNamed && param.type.isNotNullable) { throw InvalidGenerationSourceError( "Can't ignore field '$sourceFieldName' as it is required named not-nullable parameter", ); @@ -325,13 +326,13 @@ class ClassBodyBuilder extends MapBodyBuilderBase { void _assertNotMappedConstructorParameters(Iterable<ParameterElement> notMapped) { for (final param in notMapped) { - if (param.isPositional && param.type.nullabilitySuffix != NullabilitySuffix.question) { + if (param.isPositional && param.type.isNotNullable) { throw InvalidGenerationSourceError( "Can't generate mapping $mapping as there is non mapped not-nullable positional parameter ${param.displayName}", ); } - if (param.isRequiredNamed && param.type.nullabilitySuffix != NullabilitySuffix.question) { + if (param.isRequiredNamed && param.type.isNotNullable) { if (param.type.isDartCoreList) return; throw InvalidGenerationSourceError( "Can't generate mapping $mapping as there is non mapped not-nullable required named parameter ${param.displayName}", diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart b/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart index 1caef1e1..1f6d5039 100644 --- a/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart +++ b/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart @@ -1,6 +1,7 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:auto_mappr/src/builder/map_bodies/map_body_builder_base.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:code_builder/code_builder.dart'; import 'package:source_gen/source_gen.dart'; @@ -57,7 +58,7 @@ class EnumBodyBuilder extends MapBodyBuilderBase { { if (mapping.hasWhenNullDefault()) 'orElse': refer( - '() => ${mapping.whenSourceIsNullExpression!.accept(DartEmitter())}', + '() => ${mapping.whenSourceIsNullExpression!.accept(EmitterHelper.current.emitter)}', ), }, ) diff --git a/packages/auto_mappr/lib/src/builder/methods/convert_iterable_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/convert_iterable_method_builder.dart index 6fcc683b..680ecc79 100644 --- a/packages/auto_mappr/lib/src/builder/methods/convert_iterable_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/convert_iterable_method_builder.dart @@ -1,6 +1,7 @@ import 'package:auto_mappr/src/builder/methods/can_convert_method_builder.dart'; import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; import 'package:auto_mappr/src/extensions/expression_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:built_collection/built_collection.dart'; import 'package:code_builder/code_builder.dart'; @@ -31,10 +32,11 @@ class ConvertIterableMethodBuilder extends MethodBuilderBase { Parameter( (p) => p ..name = 'model' - ..type = Reference('Iterable<${MethodBuilderBase.nullableSourceTypeReference.accept(DartEmitter())}>'), + ..type = + Reference('Iterable<${MethodBuilderBase.nullableSourceTypeReference.accept(EmitterHelper.current.emitter)}>'), ), ) - ..returns = Reference('$wrapper<${MethodBuilderBase.targetTypeReference.accept(DartEmitter())}>') + ..returns = Reference('$wrapper<${MethodBuilderBase.targetTypeReference.accept(EmitterHelper.current.emitter)}>') ..body = buildBody(), ); } diff --git a/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart b/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart index 9e015227..8f789a31 100644 --- a/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart +++ b/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart @@ -1,6 +1,7 @@ import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/extensions/expression_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:auto_mappr/src/models/type_mapping.dart'; import 'package:built_collection/built_collection.dart'; @@ -80,8 +81,10 @@ abstract class MethodBuilderBase { required Reference targetTypeOfReference, required Spec inIfExpression, }) { - final sourceName = mapping.source.getDisplayStringWithLibraryAlias(config: config); - final targetName = mapping.target.getDisplayStringWithLibraryAlias(config: config); + // final sourceName = mapping.source.getDisplayStringWithLibraryAlias(config: config); + // final targetName = mapping.target.getDisplayStringWithLibraryAlias(config: config); + final sourceName = EmitterHelper.current.typeReferEmitted(type: mapping.source); + final targetName = EmitterHelper.current.typeReferEmitted(type: mapping.target); final modelIsTypeExpression = sourceTypeOfReference .equalTo(refer('_typeOf<$sourceName>()')) diff --git a/packages/auto_mappr/lib/src/builder/methods/private_convert_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/private_convert_method_builder.dart index 56fe1ae0..a78752dc 100644 --- a/packages/auto_mappr/lib/src/builder/methods/private_convert_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/private_convert_method_builder.dart @@ -1,6 +1,7 @@ import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/extensions/expression_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:code_builder/code_builder.dart'; class PrivateConvertMethodBuilder extends MethodBuilderBase { @@ -89,7 +90,7 @@ class PrivateConvertMethodBuilder extends MethodBuilderBase { block.addExpression( refer('Exception').newInstance( - [refer("'No \${model.runtimeType} -> \$${targetTypeOfReference.accept(DartEmitter())} mapping.'")], + [refer("'No \${model.runtimeType} -> \$${targetTypeOfReference.accept(EmitterHelper.current.emitter)} mapping.'")], ).thrown, ); diff --git a/packages/auto_mappr/lib/src/builder/methods/private_modules_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/private_modules_method_builder.dart index 406498b6..9c87be53 100644 --- a/packages/auto_mappr/lib/src/builder/methods/private_modules_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/private_modules_method_builder.dart @@ -1,4 +1,6 @@ import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; +import 'package:auto_mappr/src/helpers/urls.dart'; import 'package:code_builder/code_builder.dart'; class PrivateModulesMethodBuilder extends MethodBuilderBase { @@ -6,10 +8,12 @@ class PrivateModulesMethodBuilder extends MethodBuilderBase { @override Method buildMethod() { + final interfaceRefer = EmitterHelper.current.referEmitted('AutoMapprInterface', Urls.annotationPackageUrl); + return Method( (builder) => builder ..name = MethodBuilderBase.delegatesField - ..returns = refer('List<AutoMapprInterface>') + ..returns = refer('List<$interfaceRefer>') ..lambda = true ..type = MethodType.getter ..body = buildBody(), @@ -18,6 +22,6 @@ class PrivateModulesMethodBuilder extends MethodBuilderBase { @override Code buildBody() { - return refer('const ${(config.modulesCode ?? literalList([])).accept(DartEmitter())}').code; + return refer('const ${(config.modulesCode ?? literalList([])).accept(EmitterHelper.current.emitter)}').code; } } diff --git a/packages/auto_mappr/lib/src/builder/methods/try_convert_iterable_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/try_convert_iterable_method_builder.dart index cba40c6a..3b695077 100644 --- a/packages/auto_mappr/lib/src/builder/methods/try_convert_iterable_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/try_convert_iterable_method_builder.dart @@ -1,6 +1,7 @@ import 'package:auto_mappr/src/builder/methods/can_convert_method_builder.dart'; import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; import 'package:auto_mappr/src/extensions/expression_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:built_collection/built_collection.dart'; import 'package:code_builder/code_builder.dart'; @@ -34,10 +35,12 @@ class TryConvertIterableMethodBuilder extends MethodBuilderBase { Parameter( (p) => p ..name = 'model' - ..type = Reference('Iterable<${MethodBuilderBase.nullableSourceTypeReference.accept(DartEmitter())}>'), + ..type = + Reference('Iterable<${MethodBuilderBase.nullableSourceTypeReference.accept(EmitterHelper.current.emitter)}>'), ), ) - ..returns = Reference('$wrapper<${MethodBuilderBase.nullableTargetTypeReference.accept(DartEmitter())}>') + ..returns = + Reference('$wrapper<${MethodBuilderBase.nullableTargetTypeReference.accept(EmitterHelper.current.emitter)}>') ..body = buildBody(), ); } diff --git a/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart index 8a3c411e..f58beb5e 100644 --- a/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart @@ -1,5 +1,6 @@ import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:auto_mappr/src/builder/assignments/assignments.dart'; +import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/models/models.dart'; import 'package:code_builder/code_builder.dart'; @@ -82,8 +83,8 @@ class ValueAssignmentBuilder { return rightSide.ifNullThen(fieldMapping!.whenNullExpression!); } - final sourceNullable = assignment.sourceType!.nullabilitySuffix == NullabilitySuffix.question; - final targetNullable = assignment.targetType.nullabilitySuffix == NullabilitySuffix.question; + final sourceNullable = assignment.sourceType!.isNullable; + final targetNullable = assignment.targetType.isNullable; // BANG operator when Source is nullable and Target not final shouldIgnoreNull = fieldMapping?.ignoreNull ?? diff --git a/packages/auto_mappr/lib/src/extensions/dart_object_extension.dart b/packages/auto_mappr/lib/src/extensions/dart_object_extension.dart index c1e7b0b4..f1b0e3a7 100644 --- a/packages/auto_mappr/lib/src/extensions/dart_object_extension.dart +++ b/packages/auto_mappr/lib/src/extensions/dart_object_extension.dart @@ -3,6 +3,7 @@ import 'package:analyzer/dart/constant/value.dart'; import 'package:auto_mappr/src/extensions/element_extension.dart'; import 'package:auto_mappr/src/extensions/executable_element_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:code_builder/code_builder.dart'; import 'package:collection/collection.dart'; @@ -28,8 +29,7 @@ extension DartObjectExtension on DartObject { ]); } - final emitter = DartEmitter(); - final output = _ToCodeExpressionConverter(config: config).convert(this).accept(emitter); + final output = _ToCodeExpressionConverter(config: config).convert(this).accept(EmitterHelper.current.emitter); return CodeExpression(Code('$output')); } diff --git a/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart b/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart index f0a1ac63..b5380ed8 100644 --- a/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart +++ b/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart @@ -15,6 +15,14 @@ extension DartTypeExtension on DartType { isDartCoreEnum || isDartCoreSymbol; + bool get isNullable { + return nullabilitySuffix == NullabilitySuffix.question; + } + + bool get isNotNullable { + return !isNullable; + } + /// Is special variant of integer. /// /// See `[Uint8List], [Uint16List], [Uint32List], [Uint64List]`. @@ -60,8 +68,8 @@ extension DartTypeExtension on DartType { } // Nullability matches. - final thisNullability = nullabilitySuffix == NullabilitySuffix.question; - final otherNullability = other.nullabilitySuffix == NullabilitySuffix.question; + final thisNullability = isNullable; + final otherNullability = other.isNullable; final isSameNullability = thisNullability == otherNullability; return isSameExceptNullability && isSameNullability; @@ -118,7 +126,7 @@ extension DartTypeExtension on DartType { } // Nullability - if (withNullability && nullabilitySuffix == NullabilitySuffix.question) { + if (withNullability && isNullable) { buffer.write('?'); } @@ -147,7 +155,7 @@ extension DartTypeExtension on DartType { } // Nullability - if (withNullability && nullabilitySuffix == NullabilitySuffix.question) { + if (withNullability && isNullable) { buffer.write('?'); } diff --git a/packages/auto_mappr/lib/src/extensions/expression_extension.dart b/packages/auto_mappr/lib/src/extensions/expression_extension.dart index 54a45bc2..ae96ef37 100644 --- a/packages/auto_mappr/lib/src/extensions/expression_extension.dart +++ b/packages/auto_mappr/lib/src/extensions/expression_extension.dart @@ -1,5 +1,6 @@ import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:code_builder/code_builder.dart'; @@ -111,21 +112,17 @@ extension ExpressionExtension on Expression { required Spec ifBody, Spec? elseBody, }) { - final dartEmitter = DartEmitter(); + final ifBlock = '{ ${ifBody.accept(EmitterHelper.current.emitter)} }'; + final elseBlock = (elseBody != null) ? 'else { ${elseBody.accept(EmitterHelper.current.emitter)} }' : ''; - final ifBlock = '{ ${ifBody.accept(dartEmitter)} }'; - final elseBlock = (elseBody != null) ? 'else { ${elseBody.accept(dartEmitter)} }' : ''; - - return refer('''if ( ${condition.accept(dartEmitter)} ) $ifBlock $elseBlock'''); + return refer('''if ( ${condition.accept(EmitterHelper.current.emitter)} ) $ifBlock $elseBlock'''); } Expression ifStatement2({required Spec ifBody, Spec? elseBody}) { - final dartEmitter = DartEmitter(); - - final ifBlock = '{ ${ifBody.accept(dartEmitter)} }'; - final elseBlock = (elseBody != null) ? 'else { ${elseBody.accept(dartEmitter)} }' : ''; + final ifBlock = '{ ${ifBody.accept(EmitterHelper.current.emitter)} }'; + final elseBlock = (elseBody != null) ? 'else { ${elseBody.accept(EmitterHelper.current.emitter)} }' : ''; - return refer('''if ( ${accept(dartEmitter)} ) $ifBlock $elseBlock'''); + return refer('''if ( ${accept(EmitterHelper.current.emitter)} ) $ifBlock $elseBlock'''); } static Expression forStatement({ @@ -133,21 +130,19 @@ extension ExpressionExtension on Expression { required Reference iterable, required Spec body, }) { - final dartEmitter = DartEmitter(); - return refer(''' -for (final ${item.accept(dartEmitter)} in ${iterable.accept(dartEmitter)}) { - ${body.accept(dartEmitter)} +for (final ${item.accept(EmitterHelper.current.emitter)} in ${iterable.accept(EmitterHelper.current.emitter)}) { + ${body.accept(EmitterHelper.current.emitter)} } '''); } Expression bracketed() { - return refer('(${accept(DartEmitter())})'); + return refer('(${accept(EmitterHelper.current.emitter)})'); } Expression nullabled() { - return refer('${accept(DartEmitter())}?'); + return refer('${accept(EmitterHelper.current.emitter)}?'); } Expression equalToNull() => equalTo(literalNull); diff --git a/packages/auto_mappr/lib/src/extensions/reference_extension.dart b/packages/auto_mappr/lib/src/extensions/reference_extension.dart index cab8b802..769f7ffa 100644 --- a/packages/auto_mappr/lib/src/extensions/reference_extension.dart +++ b/packages/auto_mappr/lib/src/extensions/reference_extension.dart @@ -1,5 +1,6 @@ +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:code_builder/code_builder.dart'; extension ReferenceExtension on Reference { - Reference get nullabled => refer('${accept(DartEmitter())}?'); + Reference get nullabled => refer('${accept(EmitterHelper.current.emitter)}?'); } diff --git a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart index b235a0cb..877131cc 100644 --- a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart +++ b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart @@ -1,5 +1,7 @@ //ignore_for_file: avoid-dynamic +import 'dart:async'; + import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; @@ -7,6 +9,7 @@ import 'package:auto_mappr/src/builder/auto_mappr_builder.dart'; import 'package:auto_mappr/src/extensions/dart_object_extension.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/extensions/list_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/auto_mappr_options.dart'; import 'package:auto_mappr/src/models/models.dart'; import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; @@ -44,62 +47,70 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { @override dynamic generateForAnnotatedElement(Element element, ConstantReader annotation, BuildStep buildStep) { - if (element is! ClassElement) { - throw InvalidGenerationSourceError( - '${element.displayName} is not a class and cannot be annotated with @AutoMappr.', - element: element, - todo: 'Use @AutoMappr annotation on a class', - ); - } + final filePath = element.library?.identifier; + final fileUri = filePath != null ? Uri.parse(filePath) : null; + + // We need to use zones so we can easily have "scoped globals" for EmitterHelper. + return runZoned( + () { + if (element is! ClassElement) { + throw InvalidGenerationSourceError( + '${element.displayName} is not a class and cannot be annotated with @AutoMappr.', + element: element, + todo: 'Use @AutoMappr annotation on a class', + ); + } - final libraryUriToAlias = _getLibraryAliases(element: element); + final libraryUriToAlias = _getLibraryAliases(element: element); + + final mapprOptions = AutoMapprOptions.fromJson(builderOptions.config); + + final tmpConfig = AutoMapprConfig( + mappers: [], + availableMappingsMacroId: 'tmp', + libraryUriToAlias: libraryUriToAlias, + mapprOptions: mapprOptions, + ); + + final constant = annotation.objectValue; + final mappersList = constant.getField(annotationFieldMappers)!.toListValue()!; + final delegatesExpression = constant.getField(annotationFieldDelegates)!.toCodeExpression(config: tmpConfig); + final delegatesList = constant.getField(annotationFieldDelegates)!.toListValue(); + final includesList = constant.getField(annotationFieldIncludes)!.toListValue(); + + final allMappers = [...mappersList, ..._mappersFromRecursiveIncludes(includesList: includesList ?? [])]; + final mappers = _processMappers( + mappers: allMappers, + element: element, + config: tmpConfig, + ); + + final duplicates = mappers.duplicates; + if (duplicates.isNotEmpty) { + throw InvalidGenerationSourceError( + '@AutoMappr has configured duplicated mappings:\n\t${duplicates.map( + (e) => e.toStringWithLibraryAlias(config: tmpConfig), + ).join('\n\t')}', + ); + } - final mapprOptions = AutoMapprOptions.fromJson(builderOptions.config); + final config = AutoMapprConfig( + mappers: mappers, + availableMappingsMacroId: element.library.identifier, + libraryUriToAlias: libraryUriToAlias, + modulesCode: delegatesExpression, + modulesList: delegatesList ?? [], + mapprOptions: mapprOptions, + ); - final tmpConfig = AutoMapprConfig( - mappers: [], - availableMappingsMacroId: 'tmp', - libraryUriToAlias: libraryUriToAlias, - mapprOptions: mapprOptions, - ); + final builder = AutoMapprBuilder(mapperClassElement: element, config: config); - final constant = annotation.objectValue; - final mappersList = constant.getField(annotationFieldMappers)!.toListValue()!; - final delegatesExpression = constant.getField(annotationFieldDelegates)!.toCodeExpression(config: tmpConfig); - final delegatesList = constant.getField(annotationFieldDelegates)!.toListValue(); - final includesList = constant.getField(annotationFieldIncludes)!.toListValue(); - - final allMappers = [...mappersList, ..._mappersFromRecursiveIncludes(includesList: includesList ?? [])]; - final mappers = _processMappers( - mappers: allMappers, - element: element, - config: tmpConfig, - ); + final output = builder.build(); - final duplicates = mappers.duplicates; - if (duplicates.isNotEmpty) { - throw InvalidGenerationSourceError( - '@AutoMappr has configured duplicated mappings:\n\t${duplicates.map( - (e) => e.toStringWithLibraryAlias(config: tmpConfig), - ).join('\n\t')}', - ); - } - - final config = AutoMapprConfig( - mappers: mappers, - availableMappingsMacroId: element.library.identifier, - libraryUriToAlias: libraryUriToAlias, - modulesCode: delegatesExpression, - modulesList: delegatesList ?? [], - mapprOptions: mapprOptions, + return '${output.accept(EmitterHelper.current.emitter)}'; + }, + zoneValues: {EmitterHelper.zoneSymbol: EmitterHelper(fileWithAnnotation: fileUri)}, ); - - final builder = AutoMapprBuilder(mapperClassElement: element, config: config); - - final output = builder.build(); - final emitter = DartEmitter(orderDirectives: true, useNullSafetySyntax: true); - - return '${output.accept(emitter)}'; } List<TypeMapping> _processMappers({ diff --git a/packages/auto_mappr/lib/src/helpers/di.dart b/packages/auto_mappr/lib/src/helpers/di.dart new file mode 100644 index 00000000..e69de29b diff --git a/packages/auto_mappr/lib/src/helpers/emitter_helper.dart b/packages/auto_mappr/lib/src/helpers/emitter_helper.dart new file mode 100644 index 00000000..57794129 --- /dev/null +++ b/packages/auto_mappr/lib/src/helpers/emitter_helper.dart @@ -0,0 +1,97 @@ +import 'dart:async'; + +import 'package:analyzer/dart/element/type.dart'; +import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:code_builder/code_builder.dart'; +import 'package:path/path.dart' as p; + +/// Helper class for emitting and package import uri resolution. +class EmitterHelper { + /// Global emitter so we can emit on the fly and all imports are preserved. + final DartEmitter emitter = DartEmitter( + allocator: Allocator.simplePrefixing(), + orderDirectives: true, + useNullSafetySyntax: true, + ); + + final Uri fileWithAnnotation; + + static Symbol get zoneSymbol => #autoMapprEmitter; + static EmitterHelper get current => Zone.current[zoneSymbol] as EmitterHelper; + + EmitterHelper({required this.fileWithAnnotation}); + + /// `refer` that is emitted to String using [emitter]. + String referEmitted(String symbol, [String? url]) { + return refer(symbol, url).accept(emitter).toString(); + } + + /// [typeRefer] that is also emitted to String using [emitter]. + String typeReferEmitted({ + required DartType type, + // Uri? targetFile, + bool withNullabilitySuffix = true, + }) { + return '${typeRefer(type: type, withNullabilitySuffix: withNullabilitySuffix).accept(emitter)}'; + } + + /// Produces a reference to [type] with an import alias prefix. + /// When [fileWithAnnotation] is also set, import is relative. + /// + /// Inspired by injectable. + Reference typeRefer({ + required DartType type, + bool withNullabilitySuffix = true, + }) { + final libraryPath = type.element?.library?.identifier; + final importUrl = type.isPrimitiveType || type.isDartCoreObject + ? _resolveAssetImport(libraryPath) + : _relative(libraryPath, fileWithAnnotation); + + return TypeReference((reference) { + reference + ..symbol = type.element?.name + ..url = importUrl + ..isNullable = withNullabilitySuffix && type.isNullable; + + if (type is ParameterizedType && type.typeArguments.isNotEmpty) { + reference.types.addAll( + type.typeArguments.map((e) => typeRefer(type: e)), + ); + } + }); + } + + String? _relative(String? path, Uri? to) { + if (path == null || to == null) { + return null; + } + + final fileUri = Uri.parse(path); + final libName = to.pathSegments.firstOrNull; + + if ((to.scheme == 'package' && fileUri.scheme == 'package' && fileUri.pathSegments.firstOrNull == libName) || + (to.scheme == 'asset' && fileUri.scheme != 'package')) { + if (fileUri.path == to.path) { + return fileUri.pathSegments.lastOrNull; + } + + return p.posix.relative(fileUri.path, from: to.path).replaceFirst('../', ''); + } + + return path; + } + + String? _resolveAssetImport(String? path) { + if (path == null) { + return null; + } + + final fileUri = Uri.parse(path); + if (fileUri.scheme == 'asset') { + return '/${fileUri.path}'; + } + + return path; + } +} diff --git a/packages/auto_mappr/lib/src/helpers/urls.dart b/packages/auto_mappr/lib/src/helpers/urls.dart new file mode 100644 index 00000000..42769fd1 --- /dev/null +++ b/packages/auto_mappr/lib/src/helpers/urls.dart @@ -0,0 +1,3 @@ +class Urls { + static const annotationPackageUrl = 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +} diff --git a/packages/auto_mappr/pubspec.yaml b/packages/auto_mappr/pubspec.yaml index 16041bce..2f031382 100644 --- a/packages/auto_mappr/pubspec.yaml +++ b/packages/auto_mappr/pubspec.yaml @@ -19,6 +19,7 @@ dependencies: code_builder: ^4.4.0 collection: ^1.17.0 equatable: ^2.0.5 + get_it: ^7.6.4 meta: ^1.8.0 path: ^1.8.2 source_gen: ^1.2.6 diff --git a/packages/auto_mappr/test/integration/fixture/import_alias.dart b/packages/auto_mappr/test/integration/fixture/import_alias.dart index e95f2d09..87f84fee 100644 --- a/packages/auto_mappr/test/integration/fixture/import_alias.dart +++ b/packages/auto_mappr/test/integration/fixture/import_alias.dart @@ -1,12 +1,11 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; +import 'import_alias.auto_mappr.dart'; import 'import_alias/import_alias_1.dart' as a1; import 'import_alias/import_alias_2.dart' as a2; import 'import_alias/import_alias_module.dart' as module; -import 'import_alias.auto_mappr.dart'; - @AutoMappr( [ MapType<UserDto, User>(), From caaadf0f51cb9361339fe106d1c59228a4fea981 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Thu, 7 Sep 2023 11:09:16 +0200 Subject: [PATCH 18/48] Cleanup and deprecate internal libraryUriToAlias --- packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart | 1 - .../auto_mappr/lib/src/builder/methods/method_builder_base.dart | 2 -- packages/auto_mappr/lib/src/extensions/dart_type_extension.dart | 1 + packages/auto_mappr/lib/src/extensions/element_extension.dart | 1 + packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart | 1 + packages/auto_mappr/lib/src/models/auto_mappr_config.dart | 2 ++ 6 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart index 1f5daef5..78df04ab 100644 --- a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart +++ b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart @@ -4,7 +4,6 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:auto_mappr/src/builder/map_model_body_method_builder.dart'; import 'package:auto_mappr/src/builder/methods/methods.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; -import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/helpers/urls.dart'; import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:auto_mappr/src/models/type_mapping.dart'; diff --git a/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart b/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart index 8f789a31..63185be1 100644 --- a/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart +++ b/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart @@ -81,8 +81,6 @@ abstract class MethodBuilderBase { required Reference targetTypeOfReference, required Spec inIfExpression, }) { - // final sourceName = mapping.source.getDisplayStringWithLibraryAlias(config: config); - // final targetName = mapping.target.getDisplayStringWithLibraryAlias(config: config); final sourceName = EmitterHelper.current.typeReferEmitted(type: mapping.source); final targetName = EmitterHelper.current.typeReferEmitted(type: mapping.target); diff --git a/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart b/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart index b5380ed8..ab155291 100644 --- a/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart +++ b/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart @@ -99,6 +99,7 @@ extension DartTypeExtension on DartType { ); } + @Deprecated('use EmitterHelper.current.typeReferenceEmitted instead') String getDisplayStringWithLibraryAlias({ required AutoMapprConfig config, bool withNullability = false, diff --git a/packages/auto_mappr/lib/src/extensions/element_extension.dart b/packages/auto_mappr/lib/src/extensions/element_extension.dart index 4d75f685..8efad799 100644 --- a/packages/auto_mappr/lib/src/extensions/element_extension.dart +++ b/packages/auto_mappr/lib/src/extensions/element_extension.dart @@ -4,6 +4,7 @@ import 'package:auto_mappr/src/models/auto_mappr_config.dart'; extension ElementExtension on Element { /// Returns an library alias with [postfix] (usually '.'), /// or empty string if no alias detected. + @Deprecated('use EmitterHelper.current.typeReferenceEmitted instead') String getLibraryAlias({ required AutoMapprConfig config, String postfix = '.', diff --git a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart index 877131cc..63e8f848 100644 --- a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart +++ b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart @@ -185,6 +185,7 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { .toList(); } + @Deprecated('use EmitterHelper.current.typeReferenceEmitted instead') Map<String, String> _getLibraryAliases({required ClassElement element}) { final libraryUriToAlias = <String, String>{}; diff --git a/packages/auto_mappr/lib/src/models/auto_mappr_config.dart b/packages/auto_mappr/lib/src/models/auto_mappr_config.dart index 0a65e03c..1a552d4d 100644 --- a/packages/auto_mappr/lib/src/models/auto_mappr_config.dart +++ b/packages/auto_mappr/lib/src/models/auto_mappr_config.dart @@ -12,6 +12,7 @@ class AutoMapprConfig { final String availableMappingsMacroId; final Expression? modulesCode; final List<DartObject> modulesList; + @Deprecated('use EmitterHelper.current.typeReferenceEmitted instead') final Map<String, String> libraryUriToAlias; final AutoMapprOptions mapprOptions; @@ -25,6 +26,7 @@ class AutoMapprConfig { const AutoMapprConfig({ required this.mappers, required this.availableMappingsMacroId, + @Deprecated('use EmitterHelper.current.typeReferenceEmitted instead') required this.libraryUriToAlias, required this.mapprOptions, this.modulesCode, From 19c4abb0e1fdad964d46c90b77d2778096a00728 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Thu, 7 Sep 2023 18:29:39 +0200 Subject: [PATCH 19/48] Finish modules --- examples/drift/lib/mappr.auto_mappr.dart | 14 +-- examples/example/lib/enum.auto_mappr.dart | 33 ++++--- .../example/lib/equatable.auto_mappr.dart | 15 ++- examples/example/lib/nested.auto_mappr.dart | 61 ++++++------ examples/example/lib/nullable.auto_mappr.dart | 76 ++++++++------- examples/example/lib/rename.auto_mappr.dart | 15 ++- .../lib/freezed_example.auto_mappr.dart | 17 ++-- examples/injectable/lib/mappr.auto_mappr.dart | 15 ++- examples/json_serializable/build.yaml | 2 + .../lib/serializable.auto_mappr.dart | 26 +++-- .../fixture/json_serializable.auto_mappr.dart | 26 +++-- .../test/fixture/json_serializable.dart | 1 + .../test/fixture/json_serializable.g.dart | 27 ++++++ .../example/lib/mappr.auto_mappr.dart | 15 ++- .../iterable_assignment_builder.dart | 13 +-- .../assignments/map_assignment_builder.dart | 23 +++-- .../assignments/nested_object_mixin.dart | 13 +-- .../lib/src/builder/auto_mappr_builder.dart | 52 ++++------ .../map_bodies/class_body_builder.dart | 17 ++-- .../builder/map_bodies/enum_body_builder.dart | 22 ++--- .../methods/mapping_method_builder.dart | 5 +- .../builder/methods/method_builder_base.dart | 5 +- .../private_convert_method_builder.dart | 10 +- .../src/builder/value_assignment_builder.dart | 11 ++- .../src/extensions/dart_object_extension.dart | 9 +- .../src/extensions/dart_type_extension.dart | 95 +++---------------- .../lib/src/extensions/element_extension.dart | 17 ---- .../src/extensions/expression_extension.dart | 35 ++++--- .../src/generator/auto_mappr_generator.dart | 57 ++--------- .../lib/src/helpers/emitter_helper.dart | 34 +++++-- .../lib/src/models/auto_mappr_config.dart | 49 ++++++---- .../lib/src/models/source_assignment.dart | 7 +- .../lib/src/models/type_mapping.dart | 10 +- .../builder/convert_method_builder_test.dart | 4 - .../test/integration/fixture/delegates.dart | 3 +- .../integration/fixture/enum_mapping.dart | 5 +- .../test/integration/fixture/includes.dart | 19 ++-- .../test/integration/fixture/record.dart | 4 +- .../fixture/when_source_is_null.dart | 9 +- 39 files changed, 380 insertions(+), 491 deletions(-) create mode 100644 examples/json_serializable/test/fixture/json_serializable.g.dart delete mode 100644 packages/auto_mappr/lib/src/extensions/element_extension.dart diff --git a/examples/drift/lib/mappr.auto_mappr.dart b/examples/drift/lib/mappr.auto_mappr.dart index b6ad2dc1..dc14009f 100644 --- a/examples/drift/lib/mappr.auto_mappr.dart +++ b/examples/drift/lib/mappr.auto_mappr.dart @@ -4,11 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings +// ignore_for_file: type=lint // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; @@ -202,19 +198,19 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__Todo__To__TodoItem((model as Todo?)) as TARGET); + return (_map___i2$Todo__To___i3$TodoItem((model as _i2.Todo?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - TodoItem _map__Todo__To__TodoItem(Todo? input) { + _i3.TodoItem _map___i2$Todo__To___i3$TodoItem(_i2.Todo? input) { final model = input; if (model == null) { throw Exception( - r'Mapping Todo → TodoItem failed because Todo was null, and no default value was provided. ' + r'Mapping _i2.Todo → _i3.TodoItem failed because Todo was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<Todo, TodoItem> to handle null values during mapping.'); } - return TodoItem( + return _i3.TodoItem( id: model.id, title: model.title, ); diff --git a/examples/example/lib/enum.auto_mappr.dart b/examples/example/lib/enum.auto_mappr.dart index 48600227..98ff82df 100644 --- a/examples/example/lib/enum.auto_mappr.dart +++ b/examples/example/lib/enum.auto_mappr.dart @@ -4,11 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings +// ignore_for_file: type=lint // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; @@ -215,7 +211,8 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__UserType__To__PersonType((model as UserType?)) as TARGET); + return (_map___i2$UserType__To___i2$PersonType((model as _i2.UserType?)) + as TARGET); } if ((sourceTypeOf == _typeOf<_i2.Vehicle>() || sourceTypeOf == _typeOf<_i2.Vehicle?>()) && @@ -224,7 +221,8 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__Vehicle__To__Vehicle((model as Vehicle?)) as TARGET); + return (_map___i2$Vehicle__To___i2$Vehicle((model as _i2.Vehicle?)) + as TARGET); } if ((sourceTypeOf == _typeOf<_i2.Vehicle>() || sourceTypeOf == _typeOf<_i2.Vehicle?>()) && @@ -233,38 +231,39 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__Vehicle__To__VehicleX((model as Vehicle?)) as TARGET); + return (_map___i2$Vehicle__To___i2$VehicleX((model as _i2.Vehicle?)) + as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - PersonType _map__UserType__To__PersonType(UserType? input) { + _i2.PersonType _map___i2$UserType__To___i2$PersonType(_i2.UserType? input) { final model = input; if (model == null) { throw Exception( - r'Mapping UserType → PersonType failed because UserType was null, and no default value was provided. ' + r'Mapping _i2.UserType → _i2.PersonType failed because UserType was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserType, PersonType> to handle null values during mapping.'); } - return PersonType.values.firstWhere((x) => x.name == model.name); + return _i2.PersonType.values.firstWhere((x) => x.name == model.name); } - Vehicle _map__Vehicle__To__Vehicle(Vehicle? input) { + _i2.Vehicle _map___i2$Vehicle__To___i2$Vehicle(_i2.Vehicle? input) { final model = input; if (model == null) { throw Exception( - r'Mapping Vehicle → Vehicle failed because Vehicle was null, and no default value was provided. ' + r'Mapping _i2.Vehicle → _i2.Vehicle failed because Vehicle was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<Vehicle, Vehicle> to handle null values during mapping.'); } - return Vehicle.values.firstWhere((x) => x.name == model.name); + return _i2.Vehicle.values.firstWhere((x) => x.name == model.name); } - VehicleX _map__Vehicle__To__VehicleX(Vehicle? input) { + _i2.VehicleX _map___i2$Vehicle__To___i2$VehicleX(_i2.Vehicle? input) { final model = input; if (model == null) { throw Exception( - r'Mapping Vehicle → VehicleX failed because Vehicle was null, and no default value was provided. ' + r'Mapping _i2.Vehicle → _i2.VehicleX failed because Vehicle was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<Vehicle, VehicleX> to handle null values during mapping.'); } - return VehicleX.values.firstWhere((x) => x.name == model.name); + return _i2.VehicleX.values.firstWhere((x) => x.name == model.name); } } diff --git a/examples/example/lib/equatable.auto_mappr.dart b/examples/example/lib/equatable.auto_mappr.dart index c7025cf5..78263521 100644 --- a/examples/example/lib/equatable.auto_mappr.dart +++ b/examples/example/lib/equatable.auto_mappr.dart @@ -4,11 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings +// ignore_for_file: type=lint // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; @@ -201,19 +197,20 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__UserDto__To__User((model as UserDto?)) as TARGET); + return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) + as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - User _map__UserDto__To__User(UserDto? input) { + _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( - r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' + r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } - return User( + return _i2.User( id: model.id, name: model.name, tag: null, diff --git a/examples/example/lib/nested.auto_mappr.dart b/examples/example/lib/nested.auto_mappr.dart index 423616a6..103514ed 100644 --- a/examples/example/lib/nested.auto_mappr.dart +++ b/examples/example/lib/nested.auto_mappr.dart @@ -4,11 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings +// ignore_for_file: type=lint // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; @@ -215,7 +211,8 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__UserDto__To__User((model as UserDto?)) as TARGET); + return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) + as TARGET); } if ((sourceTypeOf == _typeOf<_i2.NestedDto>() || sourceTypeOf == _typeOf<_i2.NestedDto?>()) && @@ -224,7 +221,8 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__NestedDto__To__Nested((model as NestedDto?)) as TARGET); + return (_map___i2$NestedDto__To___i2$Nested((model as _i2.NestedDto?)) + as TARGET); } if ((sourceTypeOf == _typeOf<_i2.NestedTagDto>() || sourceTypeOf == _typeOf<_i2.NestedTagDto?>()) && @@ -233,75 +231,78 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__NestedTagDto__To__NestedTag((model as NestedTagDto?)) - as TARGET); + return (_map___i2$NestedTagDto__To___i2$NestedTag( + (model as _i2.NestedTagDto?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - User _map__UserDto__To__User(UserDto? input) { + _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( - r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' + r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } - return User( + return _i2.User( id: model.id, - name: _map__NestedDto__To__Nested(model.name), - nestedItems: - model.nestedItems.map<Nested>(_map__NestedDto__To__Nested).toList(), + name: _map___i2$NestedDto__To___i2$Nested(model.name), + nestedItems: model.nestedItems + .map<_i2.Nested>(_map___i2$NestedDto__To___i2$Nested) + .toList(), nestedItemsNullable: model.nestedItemsNullable - ?.map<Nested>(_map__NestedDto__To__Nested) + ?.map<_i2.Nested>(_map___i2$NestedDto__To___i2$Nested) .toList() ?? - <Nested>[], + <_i2.Nested>[], nestedItemsNullable2: model.nestedItemsNullable2 - .map<Nested>(_map__NestedDto__To__Nested) + .map<_i2.Nested>(_map___i2$NestedDto__To___i2$Nested) .toList(), itemsWithNullableItem: model.itemsWithNullableItem .whereNotNull() - .map<Nested>(_map__NestedDto__To__Nested) + .map<_i2.Nested>(_map___i2$NestedDto__To___i2$Nested) .toList(), itemsWithNullableItem2: model.itemsWithNullableItem2 - .map<Nested?>(_map__NestedDto__To__Nested_Nullable) + .map<_i2.Nested?>(_map___i2$NestedDto__To___i2$Nested_Nullable) .toList(), tag: null, ); } - Nested _map__NestedDto__To__Nested(NestedDto? input) { + _i2.Nested _map___i2$NestedDto__To___i2$Nested(_i2.NestedDto? input) { final model = input; if (model == null) { throw Exception( - r'Mapping NestedDto → Nested failed because NestedDto was null, and no default value was provided. ' + r'Mapping _i2.NestedDto → _i2.Nested failed because NestedDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<NestedDto, Nested> to handle null values during mapping.'); } - return Nested( + return _i2.Nested( id: model.id, name: model.name, - tag: _map__NestedTagDto__To__NestedTag(model.tag), + tag: _map___i2$NestedTagDto__To___i2$NestedTag(model.tag), ); } - NestedTag _map__NestedTagDto__To__NestedTag(NestedTagDto? input) { + _i2.NestedTag _map___i2$NestedTagDto__To___i2$NestedTag( + _i2.NestedTagDto? input) { final model = input; if (model == null) { throw Exception( - r'Mapping NestedTagDto → NestedTag failed because NestedTagDto was null, and no default value was provided. ' + r'Mapping _i2.NestedTagDto → _i2.NestedTag failed because NestedTagDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<NestedTagDto, NestedTag> to handle null values during mapping.'); } - return NestedTag(); + return _i2.NestedTag(); } - Nested? _map__NestedDto__To__Nested_Nullable(NestedDto? input) { + _i2.Nested? _map___i2$NestedDto__To___i2$Nested_Nullable( + _i2.NestedDto? input) { final model = input; if (model == null) { return null; } - return Nested( + return _i2.Nested( id: model.id, name: model.name, - tag: _map__NestedTagDto__To__NestedTag(model.tag), + tag: _map___i2$NestedTagDto__To___i2$NestedTag(model.tag), ); } } diff --git a/examples/example/lib/nullable.auto_mappr.dart b/examples/example/lib/nullable.auto_mappr.dart index a8ec920a..fa8e883e 100644 --- a/examples/example/lib/nullable.auto_mappr.dart +++ b/examples/example/lib/nullable.auto_mappr.dart @@ -4,27 +4,23 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings +// ignore_for_file: type=lint // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i2; -import 'nullable.dart' as _i2; +import 'nullable.dart' as _i1; /// {@template package:examples_example/nullable.dart} /// Available mappings: /// - `UserDto` → `User` -- With default value. /// - `NestedDto` → `Nested`. /// {@endtemplate} -class $Mappr implements _i1.AutoMapprInterface { +class $Mappr implements _i2.AutoMapprInterface { const $Mappr(); Type _typeOf<T>() => T; - List<_i1.AutoMapprInterface> get _delegates => const []; + List<_i2.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} /// {@macro package:examples_example/nullable.dart} @@ -32,16 +28,16 @@ class $Mappr implements _i1.AutoMapprInterface { bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<_i2.UserDto>() || - sourceTypeOf == _typeOf<_i2.UserDto?>()) && - (targetTypeOf == _typeOf<_i2.User>() || - targetTypeOf == _typeOf<_i2.User?>())) { + if ((sourceTypeOf == _typeOf<_i1.UserDto>() || + sourceTypeOf == _typeOf<_i1.UserDto?>()) && + (targetTypeOf == _typeOf<_i1.User>() || + targetTypeOf == _typeOf<_i1.User?>())) { return true; } - if ((sourceTypeOf == _typeOf<_i2.NestedDto>() || - sourceTypeOf == _typeOf<_i2.NestedDto?>()) && - (targetTypeOf == _typeOf<_i2.Nested>() || - targetTypeOf == _typeOf<_i2.Nested?>())) { + if ((sourceTypeOf == _typeOf<_i1.NestedDto>() || + sourceTypeOf == _typeOf<_i1.NestedDto?>()) && + (targetTypeOf == _typeOf<_i1.Nested>() || + targetTypeOf == _typeOf<_i1.Nested?>())) { return true; } if (recursive) { @@ -201,61 +197,63 @@ class $Mappr implements _i1.AutoMapprInterface { }) { final sourceTypeOf = _typeOf<SOURCE>(); final targetTypeOf = _typeOf<TARGET>(); - if ((sourceTypeOf == _typeOf<_i2.UserDto>() || - sourceTypeOf == _typeOf<_i2.UserDto?>()) && - (targetTypeOf == _typeOf<_i2.User>() || - targetTypeOf == _typeOf<_i2.User?>())) { + if ((sourceTypeOf == _typeOf<_i1.UserDto>() || + sourceTypeOf == _typeOf<_i1.UserDto?>()) && + (targetTypeOf == _typeOf<_i1.User>() || + targetTypeOf == _typeOf<_i1.User?>())) { if (canReturnNull && model == null) { - return (const User( + return (const _i1.User( id: 1, - tag: Nested( + tag: _i1.Nested( id: 1, name: r'default', ), ) as TARGET); } - return (_map__UserDto__To__User((model as UserDto?)) as TARGET); + return (_map___i1$UserDto__To___i1$User((model as _i1.UserDto?)) + as TARGET); } - if ((sourceTypeOf == _typeOf<_i2.NestedDto>() || - sourceTypeOf == _typeOf<_i2.NestedDto?>()) && - (targetTypeOf == _typeOf<_i2.Nested>() || - targetTypeOf == _typeOf<_i2.Nested?>())) { + if ((sourceTypeOf == _typeOf<_i1.NestedDto>() || + sourceTypeOf == _typeOf<_i1.NestedDto?>()) && + (targetTypeOf == _typeOf<_i1.Nested>() || + targetTypeOf == _typeOf<_i1.Nested?>())) { if (canReturnNull && model == null) { return null; } - return (_map__NestedDto__To__Nested((model as NestedDto?)) as TARGET); + return (_map___i1$NestedDto__To___i1$Nested((model as _i1.NestedDto?)) + as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - User _map__UserDto__To__User(UserDto? input) { + _i1.User _map___i1$UserDto__To___i1$User(_i1.UserDto? input) { final model = input; if (model == null) { - return const User( + return const _i1.User( id: 1, - tag: Nested( + tag: _i1.Nested( id: 1, name: r'default', ), ); } - return User( + return _i1.User( id: model.id, tag: model.tag == null - ? Mappr.defaultNested() - : _map__NestedDto__To__Nested(model.tag), - name: _map__NestedDto__To__Nested(model.name), + ? _i1.Mappr.defaultNested() + : _map___i1$NestedDto__To___i1$Nested(model.tag), + name: _map___i1$NestedDto__To___i1$Nested(model.name), ); } - Nested _map__NestedDto__To__Nested(NestedDto? input) { + _i1.Nested _map___i1$NestedDto__To___i1$Nested(_i1.NestedDto? input) { final model = input; if (model == null) { throw Exception( - r'Mapping NestedDto → Nested failed because NestedDto was null, and no default value was provided. ' + r'Mapping _i1.NestedDto → _i1.Nested failed because NestedDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<NestedDto, Nested> to handle null values during mapping.'); } - return Nested( + return _i1.Nested( id: model.id, name: model.name, ); diff --git a/examples/example/lib/rename.auto_mappr.dart b/examples/example/lib/rename.auto_mappr.dart index fe445cf5..3d391199 100644 --- a/examples/example/lib/rename.auto_mappr.dart +++ b/examples/example/lib/rename.auto_mappr.dart @@ -4,11 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings +// ignore_for_file: type=lint // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; @@ -201,19 +197,20 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__UserDto__To__User((model as UserDto?)) as TARGET); + return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) + as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - User _map__UserDto__To__User(UserDto? input) { + _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( - r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' + r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } - return User( + return _i2.User( id: model.id, name: model.xname, ); diff --git a/examples/freezed/lib/freezed_example.auto_mappr.dart b/examples/freezed/lib/freezed_example.auto_mappr.dart index 8190dce6..99f61113 100644 --- a/examples/freezed/lib/freezed_example.auto_mappr.dart +++ b/examples/freezed/lib/freezed_example.auto_mappr.dart @@ -4,11 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings +// ignore_for_file: type=lint // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; @@ -201,20 +197,21 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__UserInfo__To__UserInfoCompanion((model as UserInfo?)) - as TARGET); + return (_map___i2$UserInfo__To___i2$UserInfoCompanion( + (model as _i2.UserInfo?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - UserInfoCompanion _map__UserInfo__To__UserInfoCompanion(UserInfo? input) { + _i2.UserInfoCompanion _map___i2$UserInfo__To___i2$UserInfoCompanion( + _i2.UserInfo? input) { final model = input; if (model == null) { throw Exception( - r'Mapping UserInfo → UserInfoCompanion failed because UserInfo was null, and no default value was provided. ' + r'Mapping _i2.UserInfo → _i2.UserInfoCompanion failed because UserInfo was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserInfo, UserInfoCompanion> to handle null values during mapping.'); } - return UserInfoCompanion( + return _i2.UserInfoCompanion( email: model.email, loginIdentifier: model.loginIdentifier, updatedAt: model.updatedAt, diff --git a/examples/injectable/lib/mappr.auto_mappr.dart b/examples/injectable/lib/mappr.auto_mappr.dart index 4f4fc15b..8edd9784 100644 --- a/examples/injectable/lib/mappr.auto_mappr.dart +++ b/examples/injectable/lib/mappr.auto_mappr.dart @@ -4,11 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings +// ignore_for_file: type=lint // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; @@ -201,19 +197,20 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__UserDto__To__User((model as UserDto?)) as TARGET); + return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) + as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - User _map__UserDto__To__User(UserDto? input) { + _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( - r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' + r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } - return User( + return _i2.User( id: model.id, name: model.name, ); diff --git a/examples/json_serializable/build.yaml b/examples/json_serializable/build.yaml index 0a0ad92b..1fd05e48 100644 --- a/examples/json_serializable/build.yaml +++ b/examples/json_serializable/build.yaml @@ -3,3 +3,5 @@ targets: builders: auto_mappr: enabled: true + json_serializable: + enabled: true diff --git a/examples/json_serializable/lib/serializable.auto_mappr.dart b/examples/json_serializable/lib/serializable.auto_mappr.dart index 8244f2d7..fb238ad7 100644 --- a/examples/json_serializable/lib/serializable.auto_mappr.dart +++ b/examples/json_serializable/lib/serializable.auto_mappr.dart @@ -4,11 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings +// ignore_for_file: type=lint // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; @@ -208,7 +204,8 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__UserDto__To__User((model as UserDto?)) as TARGET); + return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) + as TARGET); } if ((sourceTypeOf == _typeOf<_i2.ValueHolderDto>() || sourceTypeOf == _typeOf<_i2.ValueHolderDto?>()) && @@ -217,32 +214,33 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__ValueHolderDto__To__ValueHolder((model as ValueHolderDto?)) - as TARGET); + return (_map___i2$ValueHolderDto__To___i2$ValueHolder( + (model as _i2.ValueHolderDto?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - User _map__UserDto__To__User(UserDto? input) { + _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( - r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' + r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } - return User( + return _i2.User( firstName: model.firstName, lastName: model.lastName, ); } - ValueHolder _map__ValueHolderDto__To__ValueHolder(ValueHolderDto? input) { + _i2.ValueHolder _map___i2$ValueHolderDto__To___i2$ValueHolder( + _i2.ValueHolderDto? input) { final model = input; if (model == null) { throw Exception( - r'Mapping ValueHolderDto → ValueHolder failed because ValueHolderDto was null, and no default value was provided. ' + r'Mapping _i2.ValueHolderDto → _i2.ValueHolder failed because ValueHolderDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<ValueHolderDto, ValueHolder> to handle null values during mapping.'); } - return ValueHolder(model.json); + return _i2.ValueHolder(model.json); } } diff --git a/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart b/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart index 9504d6d5..8e818c21 100644 --- a/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart +++ b/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart @@ -4,11 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings +// ignore_for_file: type=lint // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; @@ -208,7 +204,8 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__UserDto__To__User((model as UserDto?)) as TARGET); + return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) + as TARGET); } if ((sourceTypeOf == _typeOf<_i2.ValueHolderDto>() || sourceTypeOf == _typeOf<_i2.ValueHolderDto?>()) && @@ -217,32 +214,33 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__ValueHolderDto__To__ValueHolder((model as ValueHolderDto?)) - as TARGET); + return (_map___i2$ValueHolderDto__To___i2$ValueHolder( + (model as _i2.ValueHolderDto?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - User _map__UserDto__To__User(UserDto? input) { + _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( - r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' + r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } - return User( + return _i2.User( firstName: model.firstName, lastName: model.lastName, ); } - ValueHolder _map__ValueHolderDto__To__ValueHolder(ValueHolderDto? input) { + _i2.ValueHolder _map___i2$ValueHolderDto__To___i2$ValueHolder( + _i2.ValueHolderDto? input) { final model = input; if (model == null) { throw Exception( - r'Mapping ValueHolderDto → ValueHolder failed because ValueHolderDto was null, and no default value was provided. ' + r'Mapping _i2.ValueHolderDto → _i2.ValueHolder failed because ValueHolderDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<ValueHolderDto, ValueHolder> to handle null values during mapping.'); } - return ValueHolder(model.json); + return _i2.ValueHolder(model.json); } } diff --git a/examples/json_serializable/test/fixture/json_serializable.dart b/examples/json_serializable/test/fixture/json_serializable.dart index 6c9fb526..01ecb731 100644 --- a/examples/json_serializable/test/fixture/json_serializable.dart +++ b/examples/json_serializable/test/fixture/json_serializable.dart @@ -2,6 +2,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:json_annotation/json_annotation.dart'; import 'json_serializable.auto_mappr.dart'; +part 'json_serializable.g.dart'; @AutoMappr([ MapType<UserDto, User>(), diff --git a/examples/json_serializable/test/fixture/json_serializable.g.dart b/examples/json_serializable/test/fixture/json_serializable.g.dart new file mode 100644 index 00000000..7445c5c6 --- /dev/null +++ b/examples/json_serializable/test/fixture/json_serializable.g.dart @@ -0,0 +1,27 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'json_serializable.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserDto _$UserDtoFromJson(Map<String, dynamic> json) => UserDto( + firstName: json['firstName'] as String, + lastName: json['lastName'] as String, + ); + +Map<String, dynamic> _$UserDtoToJson(UserDto instance) => <String, dynamic>{ + 'firstName': instance.firstName, + 'lastName': instance.lastName, + }; + +ValueHolderDto _$ValueHolderDtoFromJson(Map<String, dynamic> json) => + ValueHolderDto( + json['json'] as Map<String, dynamic>, + ); + +Map<String, dynamic> _$ValueHolderDtoToJson(ValueHolderDto instance) => + <String, dynamic>{ + 'json': instance.json, + }; diff --git a/packages/auto_mappr/example/lib/mappr.auto_mappr.dart b/packages/auto_mappr/example/lib/mappr.auto_mappr.dart index a1f062b4..e3fbc092 100644 --- a/packages/auto_mappr/example/lib/mappr.auto_mappr.dart +++ b/packages/auto_mappr/example/lib/mappr.auto_mappr.dart @@ -4,11 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: non_constant_identifier_names, prefer_const_constructors -// ignore_for_file: prefer_const_literals_to_create_immutables -// ignore_for_file: require_trailing_commas, unnecessary_const -// ignore_for_file: unnecessary_lambdas, unnecessary_parenthesis -// ignore_for_file: unnecessary_raw_strings +// ignore_for_file: type=lint // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; @@ -201,19 +197,20 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map__UserDto__To__User((model as UserDto?)) as TARGET); + return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) + as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - User _map__UserDto__To__User(UserDto? input) { + _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( - r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' + r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } - return User( + return _i2.User( id: model.id, name: model.xname, ); diff --git a/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart index 8309311d..20692d70 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart @@ -1,8 +1,8 @@ -import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; import 'package:auto_mappr/src/builder/assignments/nested_object_mixin.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/extensions/expression_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/models.dart'; import 'package:code_builder/code_builder.dart'; @@ -41,7 +41,7 @@ class IterableAssignmentBuilder extends AssignmentBuilderBase with NestedObjectM isOnNullable: sourceNullable, ); - final defaultIterableValueExpression = targetType.defaultIterableExpression(config: mapperConfig); + final defaultIterableValueExpression = targetType.defaultIterableExpression(); if (assignNestedObject) { return sourceIterableExpression @@ -50,14 +50,7 @@ class IterableAssignmentBuilder extends AssignmentBuilderBase with NestedObjectM .call( [_map(assignment)], {}, - [ - refer( - targetIterableType.getDisplayStringWithLibraryAlias( - withNullability: true, - config: mapperConfig, - ), - ), - ], + [EmitterHelper.current.typeRefer(type: targetIterableType)], ) // Call toList, toSet or nothing. // isOnNullable is false, because if map() was called, the value is non-null diff --git a/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart index 872b5f4d..79052c8b 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/map_assignment_builder.dart @@ -41,14 +41,18 @@ class MapAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin final targetNullableValue = targetValueType?.isNullable ?? false; if (targetKeyType == null || targetValueType == null) { + final emittedTarget = EmitterHelper.current.typeReferEmitted(type: targetType); + throw InvalidGenerationSourceError( - 'Target key or value type is null for ${targetType.getDisplayStringWithLibraryAlias(config: assignment.config)}', + 'Target key or value type is null for $emittedTarget', ); } if (sourceKeyType == null || sourceValueType == null) { + final emittedSource = EmitterHelper.current.typeReferEmitted(type: sourceType); + throw InvalidGenerationSourceError( - 'Source key or value type is null for ${sourceType.getDisplayStringWithLibraryAlias(config: assignment.config)}', + 'Source key or value type is null for $emittedSource', ); } @@ -67,8 +71,8 @@ class MapAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin final defaultMapValueExpression = literalMap( {}, - refer(targetKeyType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), - refer(targetValueType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), + EmitterHelper.current.typeRefer(type: targetKeyType), + EmitterHelper.current.typeRefer(type: targetValueType), ); final assignNestedObjectKey = !targetKeyType.isPrimitiveType && (targetKeyType != sourceKeyType); @@ -84,7 +88,6 @@ class MapAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin valueIsNullable: shouldRemoveNullsValue, keyType: sourceKeyType, valueType: sourceValueType, - config: mapperConfig, ) .maybeCall( 'map', @@ -93,8 +96,8 @@ class MapAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin condition: shouldDoMapCall, positionalArguments: [_map(assignment)], typeArguments: [ - refer(targetKeyType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), - refer(targetValueType.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), + EmitterHelper.current.typeRefer(type: targetKeyType), + EmitterHelper.current.typeRefer(type: targetValueType), ], ) // When [sourceNullable], use default value. @@ -108,14 +111,16 @@ class MapAssignmentBuilder extends AssignmentBuilderBase with NestedObjectMixin final targetValueType = (assignment.targetType as ParameterizedType).typeArguments.lastOrNull; if (targetKeyType == null || targetValueType == null) { + final emittedTarget = EmitterHelper.current.typeReferEmitted(type: assignment.targetType); throw InvalidGenerationSourceError( - 'Target key or value type is null for ${assignment.targetType.getDisplayStringWithLibraryAlias(config: assignment.config)}', + 'Target key or value type is null for $emittedTarget', ); } if (sourceKeyType == null || sourceValueType == null) { + final emittedSource = EmitterHelper.current.typeReferEmitted(type: assignment.sourceType); throw InvalidGenerationSourceError( - 'Source key or value type is null for ${assignment.sourceType?.getDisplayStringWithLibraryAlias(config: assignment.config)}', + 'Source key or value type is null for $emittedSource', ); } diff --git a/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart b/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart index acd85d56..ddd49796 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart @@ -1,8 +1,8 @@ -import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/models.dart'; import 'package:build/build.dart'; import 'package:code_builder/code_builder.dart'; @@ -32,10 +32,6 @@ mixin NestedObjectMixin on AssignmentBuilderBase { ); if (nestedMapping == null) { - final targetTypeName = target.getDisplayStringWithLibraryAlias( - withNullability: true, - config: mapperConfig, - ); final sourceName = assignment.sourceField?.getDisplayString(withNullability: true); if (target.isNullable) { @@ -44,9 +40,10 @@ mixin NestedObjectMixin on AssignmentBuilderBase { return literalNull; } + final emittedTarget = EmitterHelper.current.typeReferEmitted(type: target); throw InvalidGenerationSourceError( 'Trying to map nested object from "$assignment" but no mapping is configured.', - todo: 'Configure mapping from $sourceName to $targetTypeName', + todo: 'Configure mapping from $sourceName to $emittedTarget', ); } @@ -126,8 +123,8 @@ mixin NestedObjectMixin on AssignmentBuilderBase { {}, includeGenericTypes ? [ - refer(source.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), - refer(target.getDisplayStringWithLibraryAlias(withNullability: true, config: mapperConfig)), + EmitterHelper.current.typeRefer(type: source), + EmitterHelper.current.typeRefer(type: target), ] : [], ); diff --git a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart index 78df04ab..d6f2129b 100644 --- a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart +++ b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart @@ -3,7 +3,8 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:auto_mappr/src/builder/map_model_body_method_builder.dart'; import 'package:auto_mappr/src/builder/methods/methods.dart'; -import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:auto_mappr/src/extensions/expression_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/helpers/urls.dart'; import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:auto_mappr/src/models/type_mapping.dart'; @@ -16,16 +17,9 @@ class AutoMapprBuilder { final ClassElement mapperClassElement; static const List<String> fileIgnores = [ - 'unnecessary_parenthesis', - 'non_constant_identifier_names', - 'unnecessary_const', - 'require_trailing_commas', - 'unnecessary_raw_strings', - 'unnecessary_lambdas', - - // Can we fix this somehow? (const defaults, const customs). - 'prefer_const_constructors', - 'prefer_const_literals_to_create_immutables', + // ignore everything + // ignore: unnecessary-trailing-comma + 'type=lint', ]; const AutoMapprBuilder({ @@ -34,21 +28,19 @@ class AutoMapprBuilder { }); Library build() { - // TODO(modules): first process class and then generate library and its imports - - final generatedClass = Class( - (cb) => cb - ..name = '\$${mapperClassElement.displayName}' - ..implements = ListBuilder([refer('AutoMapprInterface', Urls.annotationPackageUrl)]) - ..methods.addAll(_buildMethods()) - ..constructors.addAll(_buildConstructors()) - ..docs = ListBuilder(config.getAvailableMappingsDocComment()), - ); - return Library( (b) => b ..ignoreForFile = ListBuilder(fileIgnores) - ..body.addAll([generatedClass]), + ..body.addAll([ + Class( + (cb) => cb + ..name = '\$${mapperClassElement.displayName}' + ..implements = ListBuilder([refer('AutoMapprInterface', Urls.annotationPackageUrl)]) + ..methods.addAll(_buildMethods()) + ..constructors.addAll(_buildConstructors()) + ..docs = ListBuilder(config.getAvailableMappingsDocComment()), + ), + ]), ); } @@ -126,12 +118,10 @@ class AutoMapprBuilder { Parameter( (p) => p ..name = 'input' - ..type = refer('${mapping.source.getDisplayStringWithLibraryAlias(config: config)}?'), + ..type = EmitterHelper.current.typeRefer(type: mapping.source).nullabled(), ), ]) - ..returns = refer( - mapping.target.getDisplayStringWithLibraryAlias(config: config), - ) + ..returns = EmitterHelper.current.typeRefer(type: mapping.target) ..body = MapModelBodyMethodBuilder( mapping: mapping, mapperConfig: config, @@ -141,6 +131,7 @@ class AutoMapprBuilder { // Generates nullable mapping method only when nullable method is used. // TODO(later): switch to MappingMethodBuilder. + // ignore: avoid-shadowing for (final mapping in config.mappers.where(nullableMappings.contains)) Method( (b) => b @@ -149,13 +140,10 @@ class AutoMapprBuilder { Parameter( (p) => p ..name = 'input' - ..type = refer('${mapping.source.getDisplayStringWithLibraryAlias(config: config)}?'), + ..type = EmitterHelper.current.typeRefer(type: mapping.source).nullabled(), ), ]) - ..returns = refer('${mapping.target.getDisplayStringWithLibraryAlias( - withNullability: true, - config: config, - )}?') + ..returns = EmitterHelper.current.typeRefer(type: mapping.target).nullabled() ..body = MapModelBodyMethodBuilder( mapping: mapping, mapperConfig: config, diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart index e60206b8..16daeb18 100644 --- a/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart +++ b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart @@ -1,14 +1,13 @@ import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/builder/map_bodies/map_body_builder_base.dart'; import 'package:auto_mappr/src/builder/value_assignment_builder.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; -import 'package:auto_mappr/src/extensions/element_extension.dart'; import 'package:auto_mappr/src/extensions/interface_type_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/source_assignment.dart'; import 'package:build/build.dart'; -import 'package:code_builder/code_builder.dart' show Code, Expression, refer; +import 'package:code_builder/code_builder.dart' show Code, Expression; import 'package:collection/collection.dart'; import 'package:source_gen/source_gen.dart'; @@ -104,8 +103,7 @@ class ClassBodyBuilder extends MapBodyBuilderBase { // Custom mapping has precedence. if (fieldMapping?.hasCustomMapping() ?? false) { - final targetField = - targetClassGetters.firstWhereOrNull((targetField) => targetField.displayName == fieldMapping?.field); + final targetField = targetClassGetters.firstWhereOrNull((f) => f.displayName == fieldMapping?.field); if (targetField == null) continue; @@ -159,9 +157,9 @@ class ClassBodyBuilder extends MapBodyBuilderBase { final targetField = (mapping.target).getAllGetters().firstWhereOrNull((field) => field.displayName == param.displayName); - final fieldMapping = mapping.tryGetFieldMapping(param.displayName); + final fieldMappingX = mapping.tryGetFieldMapping(param.displayName); - if (targetField == null && fieldMapping == null) { + if (targetField == null && fieldMappingX == null) { throw InvalidGenerationSourceError( "Can't find mapping for target's constructor parameter: ${param.displayName}. Parameter is required and no mapping or target's class field not found", ); @@ -171,7 +169,7 @@ class ClassBodyBuilder extends MapBodyBuilderBase { SourceAssignment( sourceField: null, targetField: targetField, - fieldMapping: fieldMapping, + fieldMapping: fieldMappingX, targetConstructorParam: constructorAssignment, typeMapping: mapping, config: mapperConfig, @@ -300,10 +298,9 @@ class ClassBodyBuilder extends MapBodyBuilderBase { required List<SourceAssignment> positional, required List<SourceAssignment> named, }) { - final alias = targetConstructor.enclosingElement.getLibraryAlias(config: mapperConfig); final constructorName = targetConstructor.displayName; - return refer('$alias$constructorName').newInstance( + return EmitterHelper.current.refer(constructorName, targetConstructor.library.identifier).newInstance( positional.map( (assignment) => ValueAssignmentBuilder( mapperConfig: mapperConfig, diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart b/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart index 1f6d5039..f6a33728 100644 --- a/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart +++ b/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart @@ -1,6 +1,5 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:auto_mappr/src/builder/map_bodies/map_body_builder_base.dart'; -import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:code_builder/code_builder.dart'; import 'package:source_gen/source_gen.dart'; @@ -17,14 +16,13 @@ class EnumBodyBuilder extends MapBodyBuilderBase { Code build() { final isSourceEnum = mapping.source.element is EnumElement; final isTargetEnum = mapping.target.element is EnumElement; + // Check that both source and target enums are enums. if (!isSourceEnum || !isTargetEnum) { + final emittedSource = EmitterHelper.current.typeReferEmitted(type: mapping.source); + final emittedTarget = EmitterHelper.current.typeReferEmitted(type: mapping.target); throw InvalidGenerationSourceError( - 'Failed to map $mapping because ${isSourceEnum ? 'target ${mapping.target.getDisplayStringWithLibraryAlias( - config: mapperConfig, - )}' : 'source ${mapping.source.getDisplayStringWithLibraryAlias( - config: mapperConfig, - )}'} is not an enum.', + 'Failed to map $mapping because ${isSourceEnum ? 'target $emittedTarget' : 'source $emittedSource'} is not an enum.', ); } @@ -37,18 +35,14 @@ class EnumBodyBuilder extends MapBodyBuilderBase { final sourceIsSubset = targetValues.containsAll(sourceValues); if (!sourceIsSubset && !mapping.hasWhenNullDefault()) { + final emittedMappingSource = EmitterHelper.current.typeRefer(type: mapping.source); + final emittedMappingTarget = EmitterHelper.current.typeRefer(type: mapping.target); throw InvalidGenerationSourceError( - "Can't map enum ${mapping.source.getDisplayStringWithLibraryAlias( - config: mapperConfig, - )} into ${mapping.target.getDisplayStringWithLibraryAlias( - config: mapperConfig, - )}. Target enum is not superset of source enum.", + "Can't map enum $emittedMappingSource into $emittedMappingTarget. Target enum is not superset of source enum.", ); } - final targetReference = refer( - mapping.target.getDisplayStringWithLibraryAlias(config: mapperConfig), - ); + final targetReference = EmitterHelper.current.typeRefer(type: mapping.target); return targetReference .property('values') diff --git a/packages/auto_mappr/lib/src/builder/methods/mapping_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/mapping_method_builder.dart index 9ca9631b..6e50c4bc 100644 --- a/packages/auto_mappr/lib/src/builder/methods/mapping_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/mapping_method_builder.dart @@ -1,5 +1,6 @@ import 'package:auto_mappr/src/builder/map_model_body_method_builder.dart'; import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/type_mapping.dart'; import 'package:code_builder/code_builder.dart'; @@ -26,10 +27,10 @@ class MappingMethodBuilder extends MethodBuilderBase { Parameter( (p) => p ..name = 'input' - ..type = refer('${mapping.source.getDisplayString(withNullability: false)}?'), + ..type = EmitterHelper.current.typeRefer(type: mapping.source), ), ]) - ..returns = refer(mapping.target.getDisplayString(withNullability: false)) + ..returns = EmitterHelper.current.typeRefer(type: mapping.target) ..body = MapModelBodyMethodBuilder( mapping: mapping, mapperConfig: config, diff --git a/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart b/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart index 63185be1..21e20058 100644 --- a/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart +++ b/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart @@ -34,10 +34,7 @@ abstract class MethodBuilderBase { required DartType target, required AutoMapprConfig config, }) => - '_map__${source.toConvertMethodName(withNullability: false, config: config)}__To__${target.toConvertMethodName( - withNullability: false, - config: config, - )}'; + '_map__${source.toConvertMethodName()}__To__${target.toConvertMethodName()}'; static String constructNullableConvertMethodName({ required DartType source, diff --git a/packages/auto_mappr/lib/src/builder/methods/private_convert_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/private_convert_method_builder.dart index a78752dc..c742ca23 100644 --- a/packages/auto_mappr/lib/src/builder/methods/private_convert_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/private_convert_method_builder.dart @@ -1,5 +1,4 @@ import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; -import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/extensions/expression_extension.dart'; import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:code_builder/code_builder.dart'; @@ -75,8 +74,7 @@ class PrivateConvertMethodBuilder extends MethodBuilderBase { refer(mapping.mappingMethodName(config: config)) .call( [ - refer('model') - .asA(refer('${mapping.source.getDisplayStringWithLibraryAlias(config: config)}?')), + refer('model').asA(EmitterHelper.current.typeRefer(type: mapping.source).nullabled()), ], ) .asA(MethodBuilderBase.targetTypeReference) @@ -90,7 +88,11 @@ class PrivateConvertMethodBuilder extends MethodBuilderBase { block.addExpression( refer('Exception').newInstance( - [refer("'No \${model.runtimeType} -> \$${targetTypeOfReference.accept(EmitterHelper.current.emitter)} mapping.'")], + [ + refer( + "'No \${model.runtimeType} -> \$${targetTypeOfReference.accept(EmitterHelper.current.emitter)} mapping.'", + ), + ], ).thrown, ); diff --git a/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart index f58beb5e..b606802d 100644 --- a/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart @@ -1,6 +1,6 @@ -import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:auto_mappr/src/builder/assignments/assignments.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/models.dart'; import 'package:code_builder/code_builder.dart'; @@ -35,8 +35,13 @@ class ValueAssignmentBuilder { return fieldMapping.apply(assignment); } - final rightSide = - refer(sourceField.isStatic ? '${sourceField.enclosingElement.name}' : 'model').property(sourceField.name); + final rightSide = (sourceField.isStatic + // Static field. + ? EmitterHelper.current + .refer(sourceField.enclosingElement.name!, sourceField.enclosingElement.library?.identifier) + // Non static field. + : refer(sourceField.isStatic ? '${sourceField.enclosingElement.name}' : 'model')) + .property(sourceField.name); final assignmentBuilders = [ // Iterable. diff --git a/packages/auto_mappr/lib/src/extensions/dart_object_extension.dart b/packages/auto_mappr/lib/src/extensions/dart_object_extension.dart index f1b0e3a7..f9d370e5 100644 --- a/packages/auto_mappr/lib/src/extensions/dart_object_extension.dart +++ b/packages/auto_mappr/lib/src/extensions/dart_object_extension.dart @@ -1,7 +1,6 @@ //ignore_for_file: no-object-declaration import 'package:analyzer/dart/constant/value.dart'; -import 'package:auto_mappr/src/extensions/element_extension.dart'; import 'package:auto_mappr/src/extensions/executable_element_extension.dart'; import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/auto_mappr_config.dart'; @@ -24,7 +23,7 @@ extension DartObjectExtension on DartObject { // If the top most object is function, call it. final asFunction = toFunctionValue(); if (asFunction != null) { - return refer(asFunction.referCallString).call([ + return EmitterHelper.current.refer(asFunction.referCallString, asFunction.library.identifier).call([ if (passModelArgument) refer('model'), ]); } @@ -91,13 +90,13 @@ class _ToCodeExpressionConverter { final revived = ConstantReader(dartObject).revive(); final location = revived.source.toString().split('#'); - final libraryAlias = dartObject.type!.element!.getLibraryAlias(config: config); + final libraryUrl = dartObject.type?.element?.library?.identifier; // Getters, Setters, Methods can't be declared as constants so this // literal must either be a top-level constant or a static constant and // can be directly accessed by `revived.accessor`. if (location.length <= 1) { - return refer('$libraryAlias${revived.accessor}'); + return EmitterHelper.current.refer(revived.accessor, libraryUrl); } // If this is a class instantiation then `location[1]` will be populated @@ -108,7 +107,7 @@ class _ToCodeExpressionConverter { final instantiation = location.elementAtOrNull(1); final useNamedConstructor = revived.accessor.isNotEmpty; - final revivedInstance = refer('$libraryAlias$instantiation'); + final revivedInstance = EmitterHelper.current.refer('$instantiation', libraryUrl); final positionalArguments = revived.positionalArguments.map<Expression>((argument) => _toSpec(argument) as Expression); diff --git a/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart b/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart index ab155291..a9e5baa6 100644 --- a/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart +++ b/packages/auto_mappr/lib/src/extensions/dart_type_extension.dart @@ -1,7 +1,6 @@ import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; -import 'package:auto_mappr/src/extensions/element_extension.dart'; -import 'package:auto_mappr/src/models/auto_mappr_config.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:code_builder/code_builder.dart'; import 'package:collection/collection.dart'; @@ -75,90 +74,24 @@ extension DartTypeExtension on DartType { return isSameExceptNullability && isSameNullability; } - Expression defaultIterableExpression({required AutoMapprConfig config}) { + Expression defaultIterableExpression() { final itemType = genericParameterTypeOrSelf; return isDartCoreSet - ? literalSet( - {}, - refer( - itemType.getDisplayStringWithLibraryAlias( - config: config, - withNullability: true, - ), - ), - ) - : literalList( - [], - refer( - itemType.getDisplayStringWithLibraryAlias( - config: config, - withNullability: true, - ), - ), - ); + ? literalSet({}, EmitterHelper.current.typeRefer(type: itemType)) + : literalList([], EmitterHelper.current.typeRefer(type: itemType)); } - @Deprecated('use EmitterHelper.current.typeReferenceEmitted instead') - String getDisplayStringWithLibraryAlias({ - required AutoMapprConfig config, - bool withNullability = false, - }) { - final alias = element?.getLibraryAlias(config: config); - final typeName = element?.name; - - if (alias == null || typeName == null) { - return '??'; - } - - final buffer = StringBuffer('$alias$typeName'); - - if (this is ParameterizedType && (this as ParameterizedType).typeArguments.isNotEmpty) { - final arguments = (this as ParameterizedType) - .typeArguments - .map<String>( - (argument) => argument.getDisplayStringWithLibraryAlias( - withNullability: withNullability, - config: config, - ), - ) - .join(','); - buffer.write('<$arguments>'); - } - - // Nullability - if (withNullability && isNullable) { - buffer.write('?'); - } - - return buffer.toString(); - } - - String toConvertMethodName({ - required bool withNullability, - required AutoMapprConfig config, - }) { - final alias = element!.getLibraryAlias(config: config, postfix: '_'); - final typeName = element!.name; - final buffer = StringBuffer()..write('$alias$typeName'); - - if (this is ParameterizedType && (this as ParameterizedType).typeArguments.isNotEmpty) { - final arguments = (this as ParameterizedType) - .typeArguments - .map<String>( - (argument) => argument.toConvertMethodName( - withNullability: withNullability, - config: config, - ), - ) - .join(r'$'); - buffer.write('\$$arguments'); - } - - // Nullability - if (withNullability && isNullable) { - buffer.write('?'); - } + String toConvertMethodName() { + final emittedThis = EmitterHelper.current + .typeReferEmitted(type: this) + .replaceAll(' ', '') + .replaceAll('?', '') + .replaceAll('.', r'$') + .replaceAll(',', r'_$') + .replaceAll('<', r'$') + .replaceAll('>', r'$'); + final buffer = StringBuffer()..write(emittedThis); return buffer.toString(); } diff --git a/packages/auto_mappr/lib/src/extensions/element_extension.dart b/packages/auto_mappr/lib/src/extensions/element_extension.dart deleted file mode 100644 index 8efad799..00000000 --- a/packages/auto_mappr/lib/src/extensions/element_extension.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:analyzer/dart/element/element.dart'; -import 'package:auto_mappr/src/models/auto_mappr_config.dart'; - -extension ElementExtension on Element { - /// Returns an library alias with [postfix] (usually '.'), - /// or empty string if no alias detected. - @Deprecated('use EmitterHelper.current.typeReferenceEmitted instead') - String getLibraryAlias({ - required AutoMapprConfig config, - String postfix = '.', - }) { - final libraryUri = source?.uri.toString(); - final contains = config.libraryUriToAlias.containsKey(libraryUri); - - return contains ? '${config.libraryUriToAlias[libraryUri]!}$postfix' : ''; - } -} diff --git a/packages/auto_mappr/lib/src/extensions/expression_extension.dart b/packages/auto_mappr/lib/src/extensions/expression_extension.dart index ae96ef37..46e602e9 100644 --- a/packages/auto_mappr/lib/src/extensions/expression_extension.dart +++ b/packages/auto_mappr/lib/src/extensions/expression_extension.dart @@ -1,7 +1,6 @@ import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/helpers/emitter_helper.dart'; -import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:code_builder/code_builder.dart'; extension ExpressionExtension on Expression { @@ -20,7 +19,10 @@ extension ExpressionExtension on Expression { } if ((source.isDartCoreList || forceCast) && target.isSpecializedListType) { - return refer(target.getDisplayString(withNullability: false)).property('fromList').call([this]); + return EmitterHelper.current + .typeRefer(type: target, withNullabilitySuffix: false) + .property('fromList') + .call([this]); } // Keep iterable as is. @@ -83,7 +85,6 @@ extension ExpressionExtension on Expression { required bool valueIsNullable, required DartType keyType, required DartType valueType, - required AutoMapprConfig config, }) { if (!keyIsNullable && !valueIsNullable) return this; @@ -95,8 +96,8 @@ extension ExpressionExtension on Expression { [refer('(key, value) => $keyCondition $and $valueCondition')], {}, [ - refer(keyType.getDisplayStringWithLibraryAlias(config: config)), - refer(valueType.getDisplayStringWithLibraryAlias(config: config)), + EmitterHelper.current.typeRefer(type: keyType, withNullabilitySuffix: false), + EmitterHelper.current.typeRefer(type: valueType, withNullabilitySuffix: false), ], ); } @@ -107,41 +108,45 @@ extension ExpressionExtension on Expression { return asA(expression); } - static Expression ifStatement({ + static Reference ifStatement({ required Spec condition, required Spec ifBody, Spec? elseBody, }) { - final ifBlock = '{ ${ifBody.accept(EmitterHelper.current.emitter)} }'; - final elseBlock = (elseBody != null) ? 'else { ${elseBody.accept(EmitterHelper.current.emitter)} }' : ''; + final emitter = EmitterHelper.current.emitter; - return refer('''if ( ${condition.accept(EmitterHelper.current.emitter)} ) $ifBlock $elseBlock'''); + final ifBlock = '{ ${ifBody.accept(emitter)} }'; + final elseBlock = (elseBody != null) ? 'else { ${elseBody.accept(emitter)} }' : ''; + + return refer('''if ( ${condition.accept(emitter)} ) $ifBlock $elseBlock'''); } - Expression ifStatement2({required Spec ifBody, Spec? elseBody}) { + Reference ifStatement2({required Spec ifBody, Spec? elseBody}) { final ifBlock = '{ ${ifBody.accept(EmitterHelper.current.emitter)} }'; final elseBlock = (elseBody != null) ? 'else { ${elseBody.accept(EmitterHelper.current.emitter)} }' : ''; return refer('''if ( ${accept(EmitterHelper.current.emitter)} ) $ifBlock $elseBlock'''); } - static Expression forStatement({ + static Reference forStatement({ required Reference item, required Reference iterable, required Spec body, }) { + final emitter = EmitterHelper.current.emitter; + return refer(''' -for (final ${item.accept(EmitterHelper.current.emitter)} in ${iterable.accept(EmitterHelper.current.emitter)}) { - ${body.accept(EmitterHelper.current.emitter)} +for (final ${item.accept(emitter)} in ${iterable.accept(emitter)}) { + ${body.accept(emitter)} } '''); } - Expression bracketed() { + Reference bracketed() { return refer('(${accept(EmitterHelper.current.emitter)})'); } - Expression nullabled() { + Reference nullabled() { return refer('${accept(EmitterHelper.current.emitter)}?'); } diff --git a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart index 63e8f848..05f4f019 100644 --- a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart +++ b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart @@ -7,14 +7,12 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/builder/auto_mappr_builder.dart'; import 'package:auto_mappr/src/extensions/dart_object_extension.dart'; -import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/extensions/list_extension.dart'; import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/auto_mappr_options.dart'; import 'package:auto_mappr/src/models/models.dart'; import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:build/build.dart'; -import 'package:code_builder/code_builder.dart'; import 'package:collection/collection.dart'; import 'package:source_gen/source_gen.dart'; @@ -61,14 +59,11 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { ); } - final libraryUriToAlias = _getLibraryAliases(element: element); - final mapprOptions = AutoMapprOptions.fromJson(builderOptions.config); final tmpConfig = AutoMapprConfig( mappers: [], availableMappingsMacroId: 'tmp', - libraryUriToAlias: libraryUriToAlias, mapprOptions: mapprOptions, ); @@ -89,7 +84,7 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { if (duplicates.isNotEmpty) { throw InvalidGenerationSourceError( '@AutoMappr has configured duplicated mappings:\n\t${duplicates.map( - (e) => e.toStringWithLibraryAlias(config: tmpConfig), + (e) => e.toString(), ).join('\n\t')}', ); } @@ -97,9 +92,8 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { final config = AutoMapprConfig( mappers: mappers, availableMappingsMacroId: element.library.identifier, - libraryUriToAlias: libraryUriToAlias, modulesCode: delegatesExpression, - modulesList: delegatesList ?? [], + delegatesList: delegatesList ?? [], mapprOptions: mapprOptions, ); @@ -126,15 +120,19 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { final targetType = mapperType.typeArguments.lastOrNull; if (sourceType is! InterfaceType) { + final emittedSource = EmitterHelper.current.typeReferEmitted(type: sourceType); + throw InvalidGenerationSourceError( - '${sourceType?.getDisplayStringWithLibraryAlias(config: config, withNullability: true)} is not a class and cannot be mapped from', + '$emittedSource is not a class and cannot be mapped from', element: element, todo: 'Use a class', ); } if (targetType is! InterfaceType) { + final emittedTarget = EmitterHelper.current.typeReferEmitted(type: targetType); + throw InvalidGenerationSourceError( - '${targetType?.getDisplayStringWithLibraryAlias(config: config, withNullability: true)} is not a class and cannot be mapped to', + '$emittedTarget is not a class and cannot be mapped to', element: element, todo: 'Use a class', ); @@ -185,45 +183,6 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { .toList(); } - @Deprecated('use EmitterHelper.current.typeReferenceEmitted instead') - Map<String, String> _getLibraryAliases({required ClassElement element}) { - final libraryUriToAlias = <String, String>{}; - - final imports = element.library.libraryImports; - final aliases = imports.map((e) => e.prefix?.element.name).toList(); - final uris = imports.map((e) => e.importedLibrary!.identifier).toList(); - - for (var i = 0; i < imports.length; i++) { - final currentAlias = aliases.elementAtOrNull(i); - if (currentAlias == null) continue; - - final importedLibrary = imports.elementAtOrNull(i)?.importedLibrary; - final exports = importedLibrary == null ? <LibraryElement>[] : _getRecursiveLibraryExports(importedLibrary); - - final uri = uris.elementAtOrNull(i); - - libraryUriToAlias.addAll({ - // Current library. - if (uri != null) uri: currentAlias, - // It's exports. - for (final exported in exports) exported.identifier: currentAlias, - }); - } - - return libraryUriToAlias; - } - - /// Recursively returns all exports (even nested) for [library]. - Iterable<LibraryElement> _getRecursiveLibraryExports(LibraryElement library) { - final exports = library.libraryExports; - if (exports.isEmpty) return []; - - return [ - ...exports.map((e) => e.exportedLibrary!), - ...exports.map((e) => _getRecursiveLibraryExports(e.exportedLibrary!)).flattened, - ]; - } - /// Recursively returns all mappings from includes. Iterable<DartObject> _mappersFromRecursiveIncludes({required List<DartObject> includesList}) { final mappings = <DartObject>[]; diff --git a/packages/auto_mappr/lib/src/helpers/emitter_helper.dart b/packages/auto_mappr/lib/src/helpers/emitter_helper.dart index 57794129..f2f3aba3 100644 --- a/packages/auto_mappr/lib/src/helpers/emitter_helper.dart +++ b/packages/auto_mappr/lib/src/helpers/emitter_helper.dart @@ -2,25 +2,37 @@ import 'dart:async'; import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; -import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/code_builder.dart' as cb; import 'package:path/path.dart' as p; /// Helper class for emitting and package import uri resolution. class EmitterHelper { /// Global emitter so we can emit on the fly and all imports are preserved. - final DartEmitter emitter = DartEmitter( - allocator: Allocator.simplePrefixing(), + final cb.DartEmitter emitter = cb.DartEmitter( + allocator: cb.Allocator.simplePrefixing(), orderDirectives: true, useNullSafetySyntax: true, ); - final Uri fileWithAnnotation; + final Uri? fileWithAnnotation; static Symbol get zoneSymbol => #autoMapprEmitter; static EmitterHelper get current => Zone.current[zoneSymbol] as EmitterHelper; EmitterHelper({required this.fileWithAnnotation}); + /// `refer` that is processed by helper. + cb.Reference refer(String symbol, String? url) { + final importUrl = + // TODO(module): can we check whether the url is from THIS package and therefore we can use relative, also in current project test must be relative + // type.isPrimitiveType || type.isDartCoreObject + // ? _resolveAssetImport(libraryPath) + // : + _relative(url, fileWithAnnotation); + + return cb.refer(symbol, importUrl); + } + /// `refer` that is emitted to String using [emitter]. String referEmitted(String symbol, [String? url]) { return refer(symbol, url).accept(emitter).toString(); @@ -28,10 +40,14 @@ class EmitterHelper { /// [typeRefer] that is also emitted to String using [emitter]. String typeReferEmitted({ - required DartType type, + required DartType? type, // Uri? targetFile, bool withNullabilitySuffix = true, }) { + if (type == null) { + return '???'; + } + return '${typeRefer(type: type, withNullabilitySuffix: withNullabilitySuffix).accept(emitter)}'; } @@ -39,7 +55,7 @@ class EmitterHelper { /// When [fileWithAnnotation] is also set, import is relative. /// /// Inspired by injectable. - Reference typeRefer({ + cb.Reference typeRefer({ required DartType type, bool withNullabilitySuffix = true, }) { @@ -48,7 +64,7 @@ class EmitterHelper { ? _resolveAssetImport(libraryPath) : _relative(libraryPath, fileWithAnnotation); - return TypeReference((reference) { + return cb.TypeReference((reference) { reference ..symbol = type.element?.name ..url = importUrl @@ -70,6 +86,10 @@ class EmitterHelper { final fileUri = Uri.parse(path); final libName = to.pathSegments.firstOrNull; + if (fileUri.scheme == 'dart') { + return 'dart:${fileUri.path}'; + } + if ((to.scheme == 'package' && fileUri.scheme == 'package' && fileUri.pathSegments.firstOrNull == libName) || (to.scheme == 'asset' && fileUri.scheme != 'package')) { if (fileUri.path == to.path) { diff --git a/packages/auto_mappr/lib/src/models/auto_mappr_config.dart b/packages/auto_mappr/lib/src/models/auto_mappr_config.dart index 1a552d4d..367ba88b 100644 --- a/packages/auto_mappr/lib/src/models/auto_mappr_config.dart +++ b/packages/auto_mappr/lib/src/models/auto_mappr_config.dart @@ -1,7 +1,7 @@ import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; -import 'package:auto_mappr/src/extensions/element_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/auto_mappr_options.dart'; import 'package:auto_mappr/src/models/type_mapping.dart'; import 'package:code_builder/code_builder.dart'; @@ -11,26 +11,24 @@ class AutoMapprConfig { final List<TypeMapping> mappers; final String availableMappingsMacroId; final Expression? modulesCode; - final List<DartObject> modulesList; - @Deprecated('use EmitterHelper.current.typeReferenceEmitted instead') - final Map<String, String> libraryUriToAlias; + final List<DartObject> importsList; + final List<DartObject> delegatesList; final AutoMapprOptions mapprOptions; String get availableMappingsDocComment { return [ '/// {@macro $availableMappingsMacroId}', - ..._modulesDocComment(), + ..._delegatesDocComment(), ].join('\n'); } const AutoMapprConfig({ required this.mappers, required this.availableMappingsMacroId, - @Deprecated('use EmitterHelper.current.typeReferenceEmitted instead') - required this.libraryUriToAlias, required this.mapprOptions, this.modulesCode, - this.modulesList = const [], + this.importsList = const [], + this.delegatesList = const [], }); TypeMapping? findMapping({ @@ -48,18 +46,32 @@ class AutoMapprConfig { '/// Available mappings:', for (final mapper in mappers) _getTypeMappingDocs(mapper), '/// {@endtemplate}', - ..._modulesDocComment(), + ..._importsDocComment(), + ..._delegatesDocComment(), ]; } - List<String> _modulesDocComment() { + List<String> _importsDocComment() { return [ - if (modulesList.isNotEmpty) ...[ + if (importsList.isNotEmpty) ...[ '///', - "/// Available modules: ${modulesList.map((e) { - final alias = e.type!.element!.getLibraryAlias(config: this); + "/// Used imports: ${importsList.map((e) { + final emittedImport = EmitterHelper.current.typeReferEmitted(type: e.type); - return '[$alias\$${e.type!.getDisplayString(withNullability: false)}]'; + return '[$emittedImport]'; + }).join(', ')}", + ], + ]; + } + + List<String> _delegatesDocComment() { + return [ + if (delegatesList.isNotEmpty) ...[ + '///', + "/// Used delegates: ${delegatesList.map((e) { + final emittedDelegate = EmitterHelper.current.typeReferEmitted(type: e.type); + + return '[$emittedDelegate]'; }).join(', ')}", ], ]; @@ -67,12 +79,11 @@ class AutoMapprConfig { String _getTypeMappingDocs(TypeMapping typeMapping) { final trailingPart = typeMapping.hasWhenNullDefault() ? ' -- With default value.' : '.'; + // Display without import aliases. + final emittedSource = typeMapping.source.getDisplayString(withNullability: true); + final emittedTarget = typeMapping.target.getDisplayString(withNullability: true); // ignore: avoid-non-ascii-symbols, it is ok - return '/// - `${typeMapping.source.getDisplayStringWithLibraryAlias( - config: this, - )}` → `${typeMapping.target.getDisplayStringWithLibraryAlias( - config: this, - )}`$trailingPart'; + return '/// - `$emittedSource` → `$emittedTarget`$trailingPart'; } } diff --git a/packages/auto_mappr/lib/src/models/source_assignment.dart b/packages/auto_mappr/lib/src/models/source_assignment.dart index 455520f8..1caab431 100644 --- a/packages/auto_mappr/lib/src/models/source_assignment.dart +++ b/packages/auto_mappr/lib/src/models/source_assignment.dart @@ -3,6 +3,7 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/models.dart'; import 'package:code_builder/code_builder.dart' show Expression, literalList, literalMap, literalNull, literalSet; @@ -73,10 +74,10 @@ class SourceAssignment { @override String toString() { - final sourceTypeName = sourceType?.getDisplayStringWithLibraryAlias(withNullability: true, config: config); - final targetTypeName = targetType.getDisplayStringWithLibraryAlias(withNullability: true, config: config); + final emittedSource = EmitterHelper.current.typeReferEmitted(type: sourceType); + final emittedTarget = EmitterHelper.current.typeReferEmitted(type: targetType); - return '$sourceTypeName $sourceName -> $targetTypeName $targetName'; + return '$emittedSource $sourceName -> $emittedTarget $targetName'; } Expression getDefaultValue() { diff --git a/packages/auto_mappr/lib/src/models/type_mapping.dart b/packages/auto_mappr/lib/src/models/type_mapping.dart index 59ee7d15..d9f04e1f 100644 --- a/packages/auto_mappr/lib/src/models/type_mapping.dart +++ b/packages/auto_mappr/lib/src/models/type_mapping.dart @@ -1,7 +1,7 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; -import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:auto_mappr/src/models/field_mapping.dart'; import 'package:code_builder/code_builder.dart'; @@ -66,12 +66,10 @@ class TypeMapping extends Equatable { @override String toString() { - // ignore: avoid-non-ascii-symbols, it is ok - return '$source → $target'; - } + final sourceAsString = EmitterHelper.current.typeReferEmitted(type: source); + final targetAsString = EmitterHelper.current.typeReferEmitted(type: target); - String toStringWithLibraryAlias({required AutoMapprConfig config}) { // ignore: avoid-non-ascii-symbols, it is ok - return '${source.getDisplayStringWithLibraryAlias(config: config)} → ${target.getDisplayStringWithLibraryAlias(config: config)}'; + return '$sourceAsString → $targetAsString'; } } diff --git a/packages/auto_mappr/test/builder/convert_method_builder_test.dart b/packages/auto_mappr/test/builder/convert_method_builder_test.dart index 11386c54..1651ab96 100644 --- a/packages/auto_mappr/test/builder/convert_method_builder_test.dart +++ b/packages/auto_mappr/test/builder/convert_method_builder_test.dart @@ -15,7 +15,6 @@ void main() { const AutoMapprConfig( mappers: [], availableMappingsMacroId: 'test', - libraryUriToAlias: {}, mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), ), ).buildMethod(); @@ -42,7 +41,6 @@ void main() { const AutoMapprConfig( mappers: [], availableMappingsMacroId: 'test', - libraryUriToAlias: {}, mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), ), ).buildMethod(); @@ -69,7 +67,6 @@ void main() { const AutoMapprConfig( mappers: [], availableMappingsMacroId: 'test', - libraryUriToAlias: {}, mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), ), ).buildMethod(); @@ -96,7 +93,6 @@ void main() { const AutoMapprConfig( mappers: [], availableMappingsMacroId: 'test', - libraryUriToAlias: {}, mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), ), ).buildMethod(); diff --git a/packages/auto_mappr/test/integration/fixture/delegates.dart b/packages/auto_mappr/test/integration/fixture/delegates.dart index 0be70b50..d8baa72c 100644 --- a/packages/auto_mappr/test/integration/fixture/delegates.dart +++ b/packages/auto_mappr/test/integration/fixture/delegates.dart @@ -1,9 +1,8 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -import 'modules/module_alpha.dart'; - import 'delegates.auto_mappr.dart'; +import 'delegates/module_alpha.dart'; @AutoMappr([MapType<GroupDto, Group>()], delegates: [MapprAlpha()]) class MapprGroup extends $MapprGroup { diff --git a/packages/auto_mappr/test/integration/fixture/enum_mapping.dart b/packages/auto_mappr/test/integration/fixture/enum_mapping.dart index 456f4e25..2e9fafad 100644 --- a/packages/auto_mappr/test/integration/fixture/enum_mapping.dart +++ b/packages/auto_mappr/test/integration/fixture/enum_mapping.dart @@ -53,12 +53,13 @@ enum EnhancedTarget { String get row => '$id+$name'; } -LocalPerson _localRemoteUnknownDefault() => LocalPerson.unknown; +// ignore: prefer-static-class, for testing +LocalPerson localRemoteUnknownDefault() => LocalPerson.unknown; @AutoMappr([ MapType<Person, User>(), MapType<RemotePerson, LocalPerson>( - whenSourceIsNull: _localRemoteUnknownDefault, + whenSourceIsNull: localRemoteUnknownDefault, ), MapType<EnhancedSource, EnhancedTarget>(), MapType<EnhancedSourceWithUnknown, EnhancedTarget>( diff --git a/packages/auto_mappr/test/integration/fixture/includes.dart b/packages/auto_mappr/test/integration/fixture/includes.dart index f81a497e..e3e64025 100644 --- a/packages/auto_mappr/test/integration/fixture/includes.dart +++ b/packages/auto_mappr/test/integration/fixture/includes.dart @@ -1,9 +1,10 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -import 'includes/module_alpha.dart' as alpha_feature; - import 'includes.auto_mappr.dart'; +import 'includes/module_alpha.dart' as alpha_feature; +import 'includes/module_beta.dart'; +import 'includes/module_gama.dart'; @AutoMappr([MapType<GroupDto, Group>()], includes: [alpha_feature.MapprAlpha()]) class MapprGroup extends $MapprGroup { @@ -12,19 +13,19 @@ class MapprGroup extends $MapprGroup { class GroupDto { final alpha_feature.AlphaDto alpha; - // final BetaDto beta; - // final GamaDto gama; + final BetaDto beta; + final GamaDto gama; - const GroupDto(this.alpha); + const GroupDto(this.alpha, this.beta, this.gama); } class Group with EquatableMixin { final alpha_feature.Alpha alpha; - // final Beta beta; - // final Gama gama; + final Beta beta; + final Gama gama; @override - List<Object?> get props => [alpha]; + List<Object?> get props => [alpha, beta, gama]; - const Group(this.alpha); + const Group(this.alpha, this.beta, this.gama); } diff --git a/packages/auto_mappr/test/integration/fixture/record.dart b/packages/auto_mappr/test/integration/fixture/record.dart index 74454579..faca3e81 100644 --- a/packages/auto_mappr/test/integration/fixture/record.dart +++ b/packages/auto_mappr/test/integration/fixture/record.dart @@ -3,7 +3,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:equatable/equatable.dart'; -part 'record.g.dart'; +import 'record.auto_mappr.dart'; @AutoMappr([ // simple @@ -41,7 +41,6 @@ class PositionalDto extends Equatable { } class PositionalNullable extends Equatable { - // ignore: prefer-trailing-comma, false positive final (int?, bool?, String?, int?, bool?) value; @override @@ -69,7 +68,6 @@ class Named extends Equatable { } class NamedNullable extends Equatable { - // ignore: prefer-trailing-comma, dcm has to fix this final ({int alpha, bool beta, String gama, int? delta, bool? epsilon}) value; @override diff --git a/packages/auto_mappr/test/integration/fixture/when_source_is_null.dart b/packages/auto_mappr/test/integration/fixture/when_source_is_null.dart index f9605c01..2555e2db 100644 --- a/packages/auto_mappr/test/integration/fixture/when_source_is_null.dart +++ b/packages/auto_mappr/test/integration/fixture/when_source_is_null.dart @@ -25,18 +25,19 @@ class Target { @AutoMappr([ MapType<SourceValue, Target>(fields: [Field('name', whenNull: 'static')]), MapType<SourceStatic, Target>( - fields: [Field('name', whenNull: Mappr._whenSourceIsNull)], + fields: [Field('name', whenNull: Mappr.whenSourceIsNull)], ), MapType<SourceTopLevel, Target>( - fields: [Field('name', whenNull: _whenSourceIsNullTopLevel)], + fields: [Field('name', whenNull: whenSourceIsNullTopLevel)], ), ]) class Mappr extends $Mappr { - static String _whenSourceIsNull() { + static String whenSourceIsNull() { return 'whenSourceIsNull'; } } -String _whenSourceIsNullTopLevel() { +// ignore: prefer-static-class, for testing +String whenSourceIsNullTopLevel() { return 'whenSourceIsNullTopLevel'; } From 58ad1e15b79679986fb7f84130fc659cc6467962 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Thu, 7 Sep 2023 19:02:11 +0200 Subject: [PATCH 20/48] Finish modules - includes and delegates --- .../builder/map_bodies/enum_body_builder.dart | 13 +- .../src/generator/auto_mappr_generator.dart | 97 +++++----- .../lib/src/helpers/run_zoned_auto_mappr.dart | 14 ++ .../lib/src/models/type_mapping.dart | 6 +- .../builder/convert_method_builder_test.dart | 167 +++++++++--------- .../test/integration/enum_mapping_test.dart | 69 ++++---- .../test/integration/includes_test.dart | 4 +- 7 files changed, 198 insertions(+), 172 deletions(-) create mode 100644 packages/auto_mappr/lib/src/helpers/run_zoned_auto_mappr.dart diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart b/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart index f6a33728..4daa1199 100644 --- a/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart +++ b/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart @@ -19,10 +19,11 @@ class EnumBodyBuilder extends MapBodyBuilderBase { // Check that both source and target enums are enums. if (!isSourceEnum || !isTargetEnum) { - final emittedSource = EmitterHelper.current.typeReferEmitted(type: mapping.source); - final emittedTarget = EmitterHelper.current.typeReferEmitted(type: mapping.target); + final sourceDisplay = mapping.source.getDisplayString(withNullability: true); + final targetDisplay = mapping.target.getDisplayString(withNullability: true); + throw InvalidGenerationSourceError( - 'Failed to map $mapping because ${isSourceEnum ? 'target $emittedTarget' : 'source $emittedSource'} is not an enum.', + 'Failed to map $mapping because ${isSourceEnum ? 'target $targetDisplay' : 'source $sourceDisplay'} is not an enum.', ); } @@ -35,10 +36,10 @@ class EnumBodyBuilder extends MapBodyBuilderBase { final sourceIsSubset = targetValues.containsAll(sourceValues); if (!sourceIsSubset && !mapping.hasWhenNullDefault()) { - final emittedMappingSource = EmitterHelper.current.typeRefer(type: mapping.source); - final emittedMappingTarget = EmitterHelper.current.typeRefer(type: mapping.target); + final sourceDisplay = mapping.source.getDisplayString(withNullability: true); + final targetDisplay = mapping.target.getDisplayString(withNullability: true); throw InvalidGenerationSourceError( - "Can't map enum $emittedMappingSource into $emittedMappingTarget. Target enum is not superset of source enum.", + "Can't map enum $sourceDisplay into $targetDisplay. Target enum is not superset of source enum.", ); } diff --git a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart index 05f4f019..3a64d229 100644 --- a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart +++ b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart @@ -9,6 +9,7 @@ import 'package:auto_mappr/src/builder/auto_mappr_builder.dart'; import 'package:auto_mappr/src/extensions/dart_object_extension.dart'; import 'package:auto_mappr/src/extensions/list_extension.dart'; import 'package:auto_mappr/src/helpers/emitter_helper.dart'; +import 'package:auto_mappr/src/helpers/run_zoned_auto_mappr.dart'; import 'package:auto_mappr/src/models/auto_mappr_options.dart'; import 'package:auto_mappr/src/models/models.dart'; import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; @@ -48,63 +49,59 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { final filePath = element.library?.identifier; final fileUri = filePath != null ? Uri.parse(filePath) : null; - // We need to use zones so we can easily have "scoped globals" for EmitterHelper. - return runZoned( - () { - if (element is! ClassElement) { - throw InvalidGenerationSourceError( - '${element.displayName} is not a class and cannot be annotated with @AutoMappr.', - element: element, - todo: 'Use @AutoMappr annotation on a class', - ); - } - - final mapprOptions = AutoMapprOptions.fromJson(builderOptions.config); - - final tmpConfig = AutoMapprConfig( - mappers: [], - availableMappingsMacroId: 'tmp', - mapprOptions: mapprOptions, - ); - - final constant = annotation.objectValue; - final mappersList = constant.getField(annotationFieldMappers)!.toListValue()!; - final delegatesExpression = constant.getField(annotationFieldDelegates)!.toCodeExpression(config: tmpConfig); - final delegatesList = constant.getField(annotationFieldDelegates)!.toListValue(); - final includesList = constant.getField(annotationFieldIncludes)!.toListValue(); - - final allMappers = [...mappersList, ..._mappersFromRecursiveIncludes(includesList: includesList ?? [])]; - final mappers = _processMappers( - mappers: allMappers, + return runZonedAutoMappr(libraryUri: fileUri, () { + if (element is! ClassElement) { + throw InvalidGenerationSourceError( + '${element.displayName} is not a class and cannot be annotated with @AutoMappr.', element: element, - config: tmpConfig, + todo: 'Use @AutoMappr annotation on a class', ); + } - final duplicates = mappers.duplicates; - if (duplicates.isNotEmpty) { - throw InvalidGenerationSourceError( - '@AutoMappr has configured duplicated mappings:\n\t${duplicates.map( - (e) => e.toString(), - ).join('\n\t')}', - ); - } - - final config = AutoMapprConfig( - mappers: mappers, - availableMappingsMacroId: element.library.identifier, - modulesCode: delegatesExpression, - delegatesList: delegatesList ?? [], - mapprOptions: mapprOptions, + final mapprOptions = AutoMapprOptions.fromJson(builderOptions.config); + + final tmpConfig = AutoMapprConfig( + mappers: [], + availableMappingsMacroId: 'tmp', + mapprOptions: mapprOptions, + ); + + final constant = annotation.objectValue; + final mappersList = constant.getField(annotationFieldMappers)!.toListValue()!; + final delegatesExpression = constant.getField(annotationFieldDelegates)!.toCodeExpression(config: tmpConfig); + final delegatesList = constant.getField(annotationFieldDelegates)!.toListValue(); + final includesList = constant.getField(annotationFieldIncludes)!.toListValue(); + + final allMappers = [...mappersList, ..._mappersFromRecursiveIncludes(includesList: includesList ?? [])]; + final mappers = _processMappers( + mappers: allMappers, + element: element, + config: tmpConfig, + ); + + final duplicates = mappers.duplicates; + if (duplicates.isNotEmpty) { + throw InvalidGenerationSourceError( + '@AutoMappr has configured duplicated mappings:\n\t${duplicates.map( + (e) => e.toString(), + ).join('\n\t')}', ); + } + + final config = AutoMapprConfig( + mappers: mappers, + availableMappingsMacroId: element.library.identifier, + modulesCode: delegatesExpression, + delegatesList: delegatesList ?? [], + mapprOptions: mapprOptions, + ); - final builder = AutoMapprBuilder(mapperClassElement: element, config: config); + final builder = AutoMapprBuilder(mapperClassElement: element, config: config); - final output = builder.build(); + final output = builder.build(); - return '${output.accept(EmitterHelper.current.emitter)}'; - }, - zoneValues: {EmitterHelper.zoneSymbol: EmitterHelper(fileWithAnnotation: fileUri)}, - ); + return '${output.accept(EmitterHelper.current.emitter)}'; + }); } List<TypeMapping> _processMappers({ diff --git a/packages/auto_mappr/lib/src/helpers/run_zoned_auto_mappr.dart b/packages/auto_mappr/lib/src/helpers/run_zoned_auto_mappr.dart new file mode 100644 index 00000000..8d4dfa49 --- /dev/null +++ b/packages/auto_mappr/lib/src/helpers/run_zoned_auto_mappr.dart @@ -0,0 +1,14 @@ +import 'dart:async'; + +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; + +/// We need to use zones so we can easily have "scoped globals" for EmitterHelper. +// ignore: prefer-static-class, must be top level +R runZonedAutoMappr<R>(R Function() body, {Uri? libraryUri}) { + return runZoned( + () { + return body(); + }, + zoneValues: {EmitterHelper.zoneSymbol: EmitterHelper(fileWithAnnotation: libraryUri)}, + ); +} diff --git a/packages/auto_mappr/lib/src/models/type_mapping.dart b/packages/auto_mappr/lib/src/models/type_mapping.dart index d9f04e1f..2715595a 100644 --- a/packages/auto_mappr/lib/src/models/type_mapping.dart +++ b/packages/auto_mappr/lib/src/models/type_mapping.dart @@ -1,7 +1,6 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; -import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:auto_mappr/src/models/field_mapping.dart'; import 'package:code_builder/code_builder.dart'; @@ -66,8 +65,9 @@ class TypeMapping extends Equatable { @override String toString() { - final sourceAsString = EmitterHelper.current.typeReferEmitted(type: source); - final targetAsString = EmitterHelper.current.typeReferEmitted(type: target); + // Without import aliases, used to display errors to user. + final sourceAsString = source.getDisplayString(withNullability: true); + final targetAsString = target.getDisplayString(withNullability: true); // ignore: avoid-non-ascii-symbols, it is ok return '$sourceAsString → $targetAsString'; diff --git a/packages/auto_mappr/test/builder/convert_method_builder_test.dart b/packages/auto_mappr/test/builder/convert_method_builder_test.dart index 1651ab96..4503ee85 100644 --- a/packages/auto_mappr/test/builder/convert_method_builder_test.dart +++ b/packages/auto_mappr/test/builder/convert_method_builder_test.dart @@ -3,6 +3,7 @@ import 'package:auto_mappr/src/builder/methods/private_convert_method_builder.da import 'package:auto_mappr/src/builder/methods/try_convert_method_builder.dart'; import 'package:auto_mappr/src/builder/methods/type_of_method_builder.dart'; import 'package:auto_mappr/src/extensions/reference_extension.dart'; +import 'package:auto_mappr/src/helpers/run_zoned_auto_mappr.dart'; import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:auto_mappr/src/models/auto_mappr_options.dart'; import 'package:code_builder/code_builder.dart'; @@ -11,97 +12,105 @@ import 'package:test/test.dart'; void main() { test('buildConvertMethod has the correct interface', () { - final result = ConvertMethodBuilder( - const AutoMapprConfig( - mappers: [], - availableMappingsMacroId: 'test', - mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), - ), - ).buildMethod(); - - expect(result, isA<Method>()); - expect(result.name, equals('convert')); - expect(result.types.length, equals(2)); - expect(result.returns, equals(result.types.elementAtOrNull(1))); - expect(result.optionalParameters, isEmpty); - expect( - result.requiredParameters, - equals([ - Parameter( - (p) => p - ..name = 'model' - ..type = result.types.firstOrNull?.nullabled, + runZonedAutoMappr(() { + final result = ConvertMethodBuilder( + const AutoMapprConfig( + mappers: [], + availableMappingsMacroId: 'test', + mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), ), - ]), - ); + ).buildMethod(); + + expect(result, isA<Method>()); + expect(result.name, equals('convert')); + expect(result.types.length, equals(2)); + expect(result.returns, equals(result.types.elementAtOrNull(1))); + expect(result.optionalParameters, isEmpty); + expect( + result.requiredParameters, + equals([ + Parameter( + (p) => p + ..name = 'model' + ..type = result.types.firstOrNull?.nullabled, + ), + ]), + ); + }); }); test('buildTryConvertMethod has the correct interface', () { - final result = TryConvertMethodBuilder( - const AutoMapprConfig( - mappers: [], - availableMappingsMacroId: 'test', - mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), - ), - ).buildMethod(); - - expect(result, isA<Method>()); - expect(result.name, equals('tryConvert')); - expect(result.types.length, equals(2)); - expect(result.returns, equals(result.types.elementAtOrNull(1)?.nullabled)); - expect(result.optionalParameters, isEmpty); - expect( - result.requiredParameters, - equals([ - Parameter( - (p) => p - ..name = 'model' - ..type = result.types.firstOrNull?.nullabled, + runZonedAutoMappr(() { + final result = TryConvertMethodBuilder( + const AutoMapprConfig( + mappers: [], + availableMappingsMacroId: 'test', + mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), ), - ]), - ); + ).buildMethod(); + + expect(result, isA<Method>()); + expect(result.name, equals('tryConvert')); + expect(result.types.length, equals(2)); + expect(result.returns, equals(result.types.elementAtOrNull(1)?.nullabled)); + expect(result.optionalParameters, isEmpty); + expect( + result.requiredParameters, + equals([ + Parameter( + (p) => p + ..name = 'model' + ..type = result.types.firstOrNull?.nullabled, + ), + ]), + ); + }); }); test('buildInternalConvertMethod has the correct interface', () { - final result = PrivateConvertMethodBuilder( - const AutoMapprConfig( - mappers: [], - availableMappingsMacroId: 'test', - mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), - ), - ).buildMethod(); - - expect(result, isA<Method>()); - expect(result.name, equals('_convert')); - expect(result.types.length, equals(2)); - expect(result.returns, equals(result.types.elementAtOrNull(1)?.nullabled)); - expect(result.optionalParameters.isEmpty, isFalse); - expect( - result.requiredParameters, - equals([ - Parameter( - (p) => p - ..name = 'model' - ..type = result.types.firstOrNull?.nullabled, + runZonedAutoMappr(() { + final result = PrivateConvertMethodBuilder( + const AutoMapprConfig( + mappers: [], + availableMappingsMacroId: 'test', + mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), ), - ]), - ); + ).buildMethod(); + + expect(result, isA<Method>()); + expect(result.name, equals('_convert')); + expect(result.types.length, equals(2)); + expect(result.returns, equals(result.types.elementAtOrNull(1)?.nullabled)); + expect(result.optionalParameters.isEmpty, isFalse); + expect( + result.requiredParameters, + equals([ + Parameter( + (p) => p + ..name = 'model' + ..type = result.types.firstOrNull?.nullabled, + ), + ]), + ); + }); }); test('buildTypeOfHelperMethod has the correct interface', () { - final result = TypeOfMethodBuilder( - const AutoMapprConfig( - mappers: [], - availableMappingsMacroId: 'test', - mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), - ), - ).buildMethod(); + runZonedAutoMappr(() { + final result = TypeOfMethodBuilder( + const AutoMapprConfig( + mappers: [], + availableMappingsMacroId: 'test', + mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), + ), + ).buildMethod(); - expect(result, isA<Method>()); - expect(result.name, equals('_typeOf')); - expect(result.types.length, equals(1)); - expect(result.returns, equals(refer('Type'))); - expect(result.optionalParameters, isEmpty); - expect(result.requiredParameters, isEmpty); + expect(result, isA<Method>()); + expect(result.name, equals('_typeOf')); + expect(result.types.length, equals(1)); + expect(result.returns, equals(refer('Type'))); + expect(result.optionalParameters, isEmpty); + expect(result.requiredParameters, isEmpty); + }); }); } diff --git a/packages/auto_mappr/test/integration/enum_mapping_test.dart b/packages/auto_mappr/test/integration/enum_mapping_test.dart index 1d50cd7a..67ba32fd 100644 --- a/packages/auto_mappr/test/integration/enum_mapping_test.dart +++ b/packages/auto_mappr/test/integration/enum_mapping_test.dart @@ -1,4 +1,5 @@ import 'package:auto_mappr/auto_mappr.dart'; +import 'package:auto_mappr/src/helpers/run_zoned_auto_mappr.dart'; import 'package:generator_test/generator_test.dart'; import 'package:source_gen/source_gen.dart'; import 'package:test/test.dart'; @@ -45,43 +46,47 @@ void main() { group('Error handling', () { test("Can't map source enum to target when target is not enum", () { - final generator = SuccessGenerator.fromBuilder( - 'enum_mapping_not_enum', - autoMapprBuilder, - inputDir: 'test/integration/error_fixture', - compareWithFixture: false, - ); - - expect( - generator.test, - throwsA( - isA<InvalidGenerationSourceError>().having( - (x) => x.message, - 'Match message', - 'Failed to map Source → Target because target Target is not an enum.', + runZonedAutoMappr(() { + final generator = SuccessGenerator.fromBuilder( + 'enum_mapping_not_enum', + autoMapprBuilder, + inputDir: 'test/integration/error_fixture', + compareWithFixture: false, + ); + + expect( + generator.test, + throwsA( + isA<InvalidGenerationSourceError>().having( + (x) => x.message, + 'Match message', + 'Failed to map Source → Target because target Target is not an enum.', + ), ), - ), - ); + ); + }); }); test("Can't map source enum to target when target is not superset of source", () { - final generator = SuccessGenerator.fromBuilder( - 'enum_mapping_subset', - autoMapprBuilder, - inputDir: 'test/integration/error_fixture', - compareWithFixture: false, - ); - - expect( - generator.test, - throwsA( - isA<InvalidGenerationSourceError>().having( - (x) => x.message, - 'Match message', - "Can't map enum Source into Target. Target enum is not superset of source enum.", + runZonedAutoMappr(() { + final generator = SuccessGenerator.fromBuilder( + 'enum_mapping_subset', + autoMapprBuilder, + inputDir: 'test/integration/error_fixture', + compareWithFixture: false, + ); + + expect( + generator.test, + throwsA( + isA<InvalidGenerationSourceError>().having( + (x) => x.message, + 'Match message', + "Can't map enum Source into Target. Target enum is not superset of source enum.", + ), ), - ), - ); + ); + }); }); }); } diff --git a/packages/auto_mappr/test/integration/includes_test.dart b/packages/auto_mappr/test/integration/includes_test.dart index a2e27960..c4d563f0 100644 --- a/packages/auto_mappr/test/integration/includes_test.dart +++ b/packages/auto_mappr/test/integration/includes_test.dart @@ -385,9 +385,9 @@ void main() { expect( converted, equals(const [ - fixture_group.GroupDto(fixture_alpha.AlphaDto(221), fixture_beta.BetaDto(222), fixture_gama.GamaDto(223)), + fixture_group.Group(fixture_alpha.Alpha(221), fixture_beta.Beta(222), fixture_gama.Gama(223)), null, - fixture_group.GroupDto(fixture_alpha.AlphaDto(231), fixture_beta.BetaDto(232), fixture_gama.GamaDto(233)), + fixture_group.Group(fixture_alpha.Alpha(231), fixture_beta.Beta(232), fixture_gama.Gama(233)), ]), ); }); From 76baa04d7086e880de2d31bf874cf0562dce66ca Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Thu, 7 Sep 2023 19:09:21 +0200 Subject: [PATCH 21/48] Cleanup --- packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart index 3a64d229..f02f5d02 100644 --- a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart +++ b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart @@ -1,7 +1,5 @@ //ignore_for_file: avoid-dynamic -import 'dart:async'; - import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; From c54eacb0a36b6bbed873e76598e282d14dabfbc0 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Thu, 7 Sep 2023 19:16:01 +0200 Subject: [PATCH 22/48] Fix DCM --- examples/drift/pubspec.yaml | 2 +- examples/example/pubspec.yaml | 2 +- examples/freezed/pubspec.yaml | 2 +- examples/injectable/pubspec.yaml | 2 +- examples/json_serializable/pubspec.yaml | 2 +- packages/auto_mappr/example/pubspec.yaml | 2 +- packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart | 1 + packages/auto_mappr/lib/src/helpers/emitter_helper.dart | 1 + packages/auto_mappr/pubspec.yaml | 2 +- packages/auto_mappr_annotation/example/pubspec.yaml | 2 +- packages/auto_mappr_annotation/pubspec.yaml | 2 +- 11 files changed, 11 insertions(+), 9 deletions(-) diff --git a/examples/drift/pubspec.yaml b/examples/drift/pubspec.yaml index b642eea2..10ff61c0 100644 --- a/examples/drift/pubspec.yaml +++ b/examples/drift/pubspec.yaml @@ -15,5 +15,5 @@ dev_dependencies: auto_mappr: ^1.6.0 build_runner: ^2.0.0 drift_dev: ^2.7.0 - netglade_analysis: ^4.0.0 + netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/examples/example/pubspec.yaml b/examples/example/pubspec.yaml index 64aa0f2d..d4a1ae55 100644 --- a/examples/example/pubspec.yaml +++ b/examples/example/pubspec.yaml @@ -13,5 +13,5 @@ dependencies: dev_dependencies: auto_mappr: ^1.3.0 build_runner: ^2.0.0 - netglade_analysis: ^4.0.0 + netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/examples/freezed/pubspec.yaml b/examples/freezed/pubspec.yaml index b9f6c438..2faceeac 100644 --- a/examples/freezed/pubspec.yaml +++ b/examples/freezed/pubspec.yaml @@ -15,5 +15,5 @@ dev_dependencies: auto_mappr: ^1.6.0 build_runner: ^2.0.0 freezed: ^2.3.2 - netglade_analysis: ^4.0.0 + netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/examples/injectable/pubspec.yaml b/examples/injectable/pubspec.yaml index 65cb9f49..b6963415 100644 --- a/examples/injectable/pubspec.yaml +++ b/examples/injectable/pubspec.yaml @@ -16,5 +16,5 @@ dev_dependencies: auto_mappr: ^1.6.0 build_runner: ^2.0.0 injectable_generator: ^2.1.5 - netglade_analysis: ^4.0.0 + netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/examples/json_serializable/pubspec.yaml b/examples/json_serializable/pubspec.yaml index ab88881e..de12a25c 100644 --- a/examples/json_serializable/pubspec.yaml +++ b/examples/json_serializable/pubspec.yaml @@ -14,5 +14,5 @@ dev_dependencies: auto_mappr: ^1.6.0 build_runner: ^2.0.0 json_serializable: ^6.6.1 - netglade_analysis: ^4.0.0 + netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/packages/auto_mappr/example/pubspec.yaml b/packages/auto_mappr/example/pubspec.yaml index 0d169acf..3c5d8dd3 100644 --- a/packages/auto_mappr/example/pubspec.yaml +++ b/packages/auto_mappr/example/pubspec.yaml @@ -13,5 +13,5 @@ dependencies: dev_dependencies: auto_mappr: ^1.3.0 build_runner: ^2.0.0 - netglade_analysis: ^4.0.0 + netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart index f02f5d02..54c2cd13 100644 --- a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart +++ b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart @@ -197,6 +197,7 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { // Bellow -- recursive includes. final includes = includeConstant.getField(annotationFieldIncludes)?.toListValue(); if (includes != null) { + // ignore: avoid-recursive-calls, it's handled mappings.addAll(_mappersFromRecursiveIncludes(includesList: includes)); } } diff --git a/packages/auto_mappr/lib/src/helpers/emitter_helper.dart b/packages/auto_mappr/lib/src/helpers/emitter_helper.dart index f2f3aba3..6ec87878 100644 --- a/packages/auto_mappr/lib/src/helpers/emitter_helper.dart +++ b/packages/auto_mappr/lib/src/helpers/emitter_helper.dart @@ -72,6 +72,7 @@ class EmitterHelper { if (type is ParameterizedType && type.typeArguments.isNotEmpty) { reference.types.addAll( + // ignore: avoid-recursive-calls, it's handled type.typeArguments.map((e) => typeRefer(type: e)), ); } diff --git a/packages/auto_mappr/pubspec.yaml b/packages/auto_mappr/pubspec.yaml index 2f031382..c1db7e29 100644 --- a/packages/auto_mappr/pubspec.yaml +++ b/packages/auto_mappr/pubspec.yaml @@ -28,6 +28,6 @@ dev_dependencies: build_runner: ^2.0.0 generator_test: ^0.2.0 mocktail: ^1.0.0 - netglade_analysis: ^4.0.0 + netglade_analysis: ^4.2.0 source_gen_test: ^1.0.4 test: ^1.16.0 diff --git a/packages/auto_mappr_annotation/example/pubspec.yaml b/packages/auto_mappr_annotation/example/pubspec.yaml index 3a603837..250c3f1c 100644 --- a/packages/auto_mappr_annotation/example/pubspec.yaml +++ b/packages/auto_mappr_annotation/example/pubspec.yaml @@ -12,5 +12,5 @@ dependencies: dev_dependencies: build_runner: ^2.0.0 - netglade_analysis: ^4.0.0 + netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/packages/auto_mappr_annotation/pubspec.yaml b/packages/auto_mappr_annotation/pubspec.yaml index 13b63e20..bea1c50c 100644 --- a/packages/auto_mappr_annotation/pubspec.yaml +++ b/packages/auto_mappr_annotation/pubspec.yaml @@ -8,5 +8,5 @@ environment: sdk: ^3.0.0 dev_dependencies: - netglade_analysis: ^4.0.0 + netglade_analysis: ^4.2.0 test: ^1.16.0 From 319a0b67e80239a088fa24beed605b11356a0f23 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 8 Sep 2023 11:35:00 +0200 Subject: [PATCH 23/48] Fix imports->includes naming, and other review --- examples/drift/lib/mappr.auto_mappr.dart | 2 +- examples/example/lib/enum.auto_mappr.dart | 6 +++--- examples/example/lib/equatable.auto_mappr.dart | 2 +- examples/example/lib/nested.auto_mappr.dart | 6 +++--- examples/example/lib/nullable.auto_mappr.dart | 2 +- examples/example/lib/rename.auto_mappr.dart | 2 +- .../freezed/lib/freezed_example.auto_mappr.dart | 2 +- examples/injectable/lib/mappr.auto_mappr.dart | 2 +- .../lib/serializable.auto_mappr.dart | 4 ++-- .../fixture/json_serializable.auto_mappr.dart | 4 ++-- .../auto_mappr/example/lib/mappr.auto_mappr.dart | 2 +- .../builder/map_bodies/class_body_builder.dart | 6 ++---- .../lib/src/models/auto_mappr_config.dart | 16 ++++++++-------- 13 files changed, 27 insertions(+), 29 deletions(-) diff --git a/examples/drift/lib/mappr.auto_mappr.dart b/examples/drift/lib/mappr.auto_mappr.dart index dc14009f..341c1c79 100644 --- a/examples/drift/lib/mappr.auto_mappr.dart +++ b/examples/drift/lib/mappr.auto_mappr.dart @@ -207,7 +207,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.Todo → _i3.TodoItem failed because Todo was null, and no default value was provided. ' + r'Mapping Todo → TodoItem failed because Todo was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<Todo, TodoItem> to handle null values during mapping.'); } return _i3.TodoItem( diff --git a/examples/example/lib/enum.auto_mappr.dart b/examples/example/lib/enum.auto_mappr.dart index 98ff82df..97bbe7e9 100644 --- a/examples/example/lib/enum.auto_mappr.dart +++ b/examples/example/lib/enum.auto_mappr.dart @@ -241,7 +241,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.UserType → _i2.PersonType failed because UserType was null, and no default value was provided. ' + r'Mapping UserType → PersonType failed because UserType was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserType, PersonType> to handle null values during mapping.'); } return _i2.PersonType.values.firstWhere((x) => x.name == model.name); @@ -251,7 +251,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.Vehicle → _i2.Vehicle failed because Vehicle was null, and no default value was provided. ' + r'Mapping Vehicle → Vehicle failed because Vehicle was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<Vehicle, Vehicle> to handle null values during mapping.'); } return _i2.Vehicle.values.firstWhere((x) => x.name == model.name); @@ -261,7 +261,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.Vehicle → _i2.VehicleX failed because Vehicle was null, and no default value was provided. ' + r'Mapping Vehicle → VehicleX failed because Vehicle was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<Vehicle, VehicleX> to handle null values during mapping.'); } return _i2.VehicleX.values.firstWhere((x) => x.name == model.name); diff --git a/examples/example/lib/equatable.auto_mappr.dart b/examples/example/lib/equatable.auto_mappr.dart index 78263521..5fa12e51 100644 --- a/examples/example/lib/equatable.auto_mappr.dart +++ b/examples/example/lib/equatable.auto_mappr.dart @@ -207,7 +207,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' + r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } return _i2.User( diff --git a/examples/example/lib/nested.auto_mappr.dart b/examples/example/lib/nested.auto_mappr.dart index 103514ed..d7c10103 100644 --- a/examples/example/lib/nested.auto_mappr.dart +++ b/examples/example/lib/nested.auto_mappr.dart @@ -241,7 +241,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' + r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } return _i2.User( @@ -272,7 +272,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.NestedDto → _i2.Nested failed because NestedDto was null, and no default value was provided. ' + r'Mapping NestedDto → Nested failed because NestedDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<NestedDto, Nested> to handle null values during mapping.'); } return _i2.Nested( @@ -287,7 +287,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.NestedTagDto → _i2.NestedTag failed because NestedTagDto was null, and no default value was provided. ' + r'Mapping NestedTagDto → NestedTag failed because NestedTagDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<NestedTagDto, NestedTag> to handle null values during mapping.'); } return _i2.NestedTag(); diff --git a/examples/example/lib/nullable.auto_mappr.dart b/examples/example/lib/nullable.auto_mappr.dart index fa8e883e..e78d8190 100644 --- a/examples/example/lib/nullable.auto_mappr.dart +++ b/examples/example/lib/nullable.auto_mappr.dart @@ -250,7 +250,7 @@ class $Mappr implements _i2.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i1.NestedDto → _i1.Nested failed because NestedDto was null, and no default value was provided. ' + r'Mapping NestedDto → Nested failed because NestedDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<NestedDto, Nested> to handle null values during mapping.'); } return _i1.Nested( diff --git a/examples/example/lib/rename.auto_mappr.dart b/examples/example/lib/rename.auto_mappr.dart index 3d391199..7c3cd1af 100644 --- a/examples/example/lib/rename.auto_mappr.dart +++ b/examples/example/lib/rename.auto_mappr.dart @@ -207,7 +207,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' + r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } return _i2.User( diff --git a/examples/freezed/lib/freezed_example.auto_mappr.dart b/examples/freezed/lib/freezed_example.auto_mappr.dart index 99f61113..2502248b 100644 --- a/examples/freezed/lib/freezed_example.auto_mappr.dart +++ b/examples/freezed/lib/freezed_example.auto_mappr.dart @@ -208,7 +208,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.UserInfo → _i2.UserInfoCompanion failed because UserInfo was null, and no default value was provided. ' + r'Mapping UserInfo → UserInfoCompanion failed because UserInfo was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserInfo, UserInfoCompanion> to handle null values during mapping.'); } return _i2.UserInfoCompanion( diff --git a/examples/injectable/lib/mappr.auto_mappr.dart b/examples/injectable/lib/mappr.auto_mappr.dart index 8edd9784..961b48f8 100644 --- a/examples/injectable/lib/mappr.auto_mappr.dart +++ b/examples/injectable/lib/mappr.auto_mappr.dart @@ -207,7 +207,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' + r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } return _i2.User( diff --git a/examples/json_serializable/lib/serializable.auto_mappr.dart b/examples/json_serializable/lib/serializable.auto_mappr.dart index fb238ad7..195b3a0e 100644 --- a/examples/json_serializable/lib/serializable.auto_mappr.dart +++ b/examples/json_serializable/lib/serializable.auto_mappr.dart @@ -224,7 +224,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' + r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } return _i2.User( @@ -238,7 +238,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.ValueHolderDto → _i2.ValueHolder failed because ValueHolderDto was null, and no default value was provided. ' + r'Mapping ValueHolderDto → ValueHolder failed because ValueHolderDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<ValueHolderDto, ValueHolder> to handle null values during mapping.'); } return _i2.ValueHolder(model.json); diff --git a/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart b/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart index 8e818c21..d93e4e43 100644 --- a/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart +++ b/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart @@ -224,7 +224,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' + r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } return _i2.User( @@ -238,7 +238,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.ValueHolderDto → _i2.ValueHolder failed because ValueHolderDto was null, and no default value was provided. ' + r'Mapping ValueHolderDto → ValueHolder failed because ValueHolderDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<ValueHolderDto, ValueHolder> to handle null values during mapping.'); } return _i2.ValueHolder(model.json); diff --git a/packages/auto_mappr/example/lib/mappr.auto_mappr.dart b/packages/auto_mappr/example/lib/mappr.auto_mappr.dart index e3fbc092..884c0f17 100644 --- a/packages/auto_mappr/example/lib/mappr.auto_mappr.dart +++ b/packages/auto_mappr/example/lib/mappr.auto_mappr.dart @@ -207,7 +207,7 @@ class $Mappr implements _i1.AutoMapprInterface { final model = input; if (model == null) { throw Exception( - r'Mapping _i2.UserDto → _i2.User failed because UserDto was null, and no default value was provided. ' + r'Mapping UserDto → User failed because UserDto was null, and no default value was provided. ' r'Consider setting the whenSourceIsNull parameter on the MapType<UserDto, User> to handle null values during mapping.'); } return _i2.User( diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart index 16daeb18..97c48c88 100644 --- a/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart +++ b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart @@ -157,9 +157,7 @@ class ClassBodyBuilder extends MapBodyBuilderBase { final targetField = (mapping.target).getAllGetters().firstWhereOrNull((field) => field.displayName == param.displayName); - final fieldMappingX = mapping.tryGetFieldMapping(param.displayName); - - if (targetField == null && fieldMappingX == null) { + if (targetField == null && fieldMapping == null) { throw InvalidGenerationSourceError( "Can't find mapping for target's constructor parameter: ${param.displayName}. Parameter is required and no mapping or target's class field not found", ); @@ -169,7 +167,7 @@ class ClassBodyBuilder extends MapBodyBuilderBase { SourceAssignment( sourceField: null, targetField: targetField, - fieldMapping: fieldMappingX, + fieldMapping: fieldMapping, targetConstructorParam: constructorAssignment, typeMapping: mapping, config: mapperConfig, diff --git a/packages/auto_mappr/lib/src/models/auto_mappr_config.dart b/packages/auto_mappr/lib/src/models/auto_mappr_config.dart index 367ba88b..20659be9 100644 --- a/packages/auto_mappr/lib/src/models/auto_mappr_config.dart +++ b/packages/auto_mappr/lib/src/models/auto_mappr_config.dart @@ -11,7 +11,7 @@ class AutoMapprConfig { final List<TypeMapping> mappers; final String availableMappingsMacroId; final Expression? modulesCode; - final List<DartObject> importsList; + final List<DartObject> includesList; final List<DartObject> delegatesList; final AutoMapprOptions mapprOptions; @@ -27,7 +27,7 @@ class AutoMapprConfig { required this.availableMappingsMacroId, required this.mapprOptions, this.modulesCode, - this.importsList = const [], + this.includesList = const [], this.delegatesList = const [], }); @@ -46,19 +46,19 @@ class AutoMapprConfig { '/// Available mappings:', for (final mapper in mappers) _getTypeMappingDocs(mapper), '/// {@endtemplate}', - ..._importsDocComment(), + ..._includesDocComment(), ..._delegatesDocComment(), ]; } - List<String> _importsDocComment() { + List<String> _includesDocComment() { return [ - if (importsList.isNotEmpty) ...[ + if (includesList.isNotEmpty) ...[ '///', - "/// Used imports: ${importsList.map((e) { - final emittedImport = EmitterHelper.current.typeReferEmitted(type: e.type); + "/// Used includes: ${includesList.map((e) { + final emittedInclude = EmitterHelper.current.typeReferEmitted(type: e.type); - return '[$emittedImport]'; + return '[$emittedInclude]'; }).join(', ')}", ], ]; From fac61f428ccccf17ef6e77f9dbc20a9db1a71f6f Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 8 Sep 2023 11:37:35 +0200 Subject: [PATCH 24/48] Update docs --- packages/auto_mappr/README.md | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/packages/auto_mappr/README.md b/packages/auto_mappr/README.md index 0cfb43a1..7536685b 100644 --- a/packages/auto_mappr/README.md +++ b/packages/auto_mappr/README.md @@ -535,11 +535,6 @@ import 'my_domain.dart' as entity; class Mappr extends $Mappr {} ``` -Note that importing a list of `MapType` from another library -and putting it inside `@AutoMappr` annotation is not possible, -since we cannot generate the type correctly (it can overlap with something else) -while using shared part builder. - ### Modules Each AutoMappr can be considered as a **module**. @@ -547,13 +542,11 @@ The only rule is that the mappr must be constant, and that most of the time means you have to add an `const` constructor to be able to use it. Other modules (AutoMappr classes) can then use it in two ways. -#### Importing - -Note: Feature TBA +#### Including -Importing a module means that you want to "absorb" it's mappings +Including a module means that you want to "absorb" it's mappings and use them later anywhere **inside** any mapped object. -Basically imagine copy-pasting definitions from imported module to yours. +Basically imagine copy-pasting definitions from included module to yours. That can be handy when you have a common/shared mappr with mappings between objects shared across the app. Since you want to use these common/shared mappings, From 8d9d8b58207cde72d2b79e201ee6df8f1e01d92f Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 8 Sep 2023 12:36:26 +0200 Subject: [PATCH 25/48] Remove unused code --- packages/auto_mappr/CHANGELOG.md | 5 +- .../lib/src/builder/auto_mappr_builder.dart | 45 +++-------------- .../map_bodies/class_body_builder.dart | 9 ---- .../builder/map_bodies/enum_body_builder.dart | 1 - .../map_bodies/map_body_builder_base.dart | 2 - .../map_model_body_method_builder.dart | 2 - .../methods/can_convert_method_builder.dart | 2 +- .../convert_iterable_method_builder.dart | 2 +- .../methods/convert_method_builder.dart | 2 +- .../methods/mapping_method_builder.dart | 49 +++++++------------ .../builder/methods/method_builder_base.dart | 13 +---- .../private_convert_method_builder.dart | 2 +- .../private_modules_method_builder.dart | 2 +- .../try_convert_iterable_method_builder.dart | 2 +- .../methods/try_convert_method_builder.dart | 2 +- .../methods/type_of_method_builder.dart | 2 +- .../src/extensions/dart_object_extension.dart | 12 ++--- .../src/extensions/expression_extension.dart | 6 --- .../src/extensions/reference_extension.dart | 6 --- .../src/generator/auto_mappr_generator.dart | 23 ++------- .../lib/src/models/field_mapping.dart | 4 -- .../lib/src/models/source_assignment.dart | 13 ----- .../builder/convert_method_builder_test.dart | 28 +++++------ 23 files changed, 57 insertions(+), 177 deletions(-) delete mode 100644 packages/auto_mappr/lib/src/extensions/reference_extension.dart diff --git a/packages/auto_mappr/CHANGELOG.md b/packages/auto_mappr/CHANGELOG.md index ca509292..1b644e47 100644 --- a/packages/auto_mappr/CHANGELOG.md +++ b/packages/auto_mappr/CHANGELOG.md @@ -1,12 +1,11 @@ [//]: # (## Unreleased) ## Unreleased +- **Breaking**: Allow "absorbing" modules using `includes` on `@AutoMappr`. Previous `modules` is now `delegates`. +- **Breaking**: Remove shared AutoMappr builder that used PartBuilder, now `.auto_mappr.dart` is generated using LibraryBuilder. - Add a `reverse` option on `MapType`, which includes the reverse mapping. [#115](https://github.com/netglade/auto_mappr/pull/115) - Add a support for Dart 3 and Records feature. [#116](https://github.com/netglade/auto_mappr/pull/116) -- Allow use modules using `includes` on `@AutoMappr`. Previous `modules` is now `delegates`. -- Remove shared AutoMappr builder that used PartBuilder, now `.auto_mappr.dart` is generated using LibraryBuilder. - ## 1.7.0 - Adhere to netglade_analysis. [#94](https://github.com/netglade/auto_mappr/pull/94) - Update analyzer and mocktail packages. [#111](https://github.com/netglade/auto_mappr/pull/111) diff --git a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart index d6f2129b..449d5f45 100644 --- a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart +++ b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart @@ -1,10 +1,7 @@ // ignore_for_file: public_member_api_docs import 'package:analyzer/dart/element/element.dart'; -import 'package:auto_mappr/src/builder/map_model_body_method_builder.dart'; import 'package:auto_mappr/src/builder/methods/methods.dart'; -import 'package:auto_mappr/src/extensions/expression_extension.dart'; -import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/helpers/urls.dart'; import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:auto_mappr/src/models/type_mapping.dart'; @@ -109,47 +106,17 @@ class AutoMapprBuilder { PrivateConvertMethodBuilder(config).buildMethod(), // Generate non-nullable mapping method. - // TODO(later): switch to MappingMethodBuilder. for (final mapping in config.mappers) - Method( - (b) => b - ..name = mapping.mappingMethodName(config: config) - ..requiredParameters.addAll([ - Parameter( - (p) => p - ..name = 'input' - ..type = EmitterHelper.current.typeRefer(type: mapping.source).nullabled(), - ), - ]) - ..returns = EmitterHelper.current.typeRefer(type: mapping.target) - ..body = MapModelBodyMethodBuilder( - mapping: mapping, - mapperConfig: config, - usedNullableMethodCallback: usedNullableMappingMethod, - ).build(), - ), + MappingMethodBuilder( + config, + mapping: mapping, + usedNullableMethodCallback: usedNullableMappingMethod, + ).buildMethod(), // Generates nullable mapping method only when nullable method is used. - // TODO(later): switch to MappingMethodBuilder. // ignore: avoid-shadowing for (final mapping in config.mappers.where(nullableMappings.contains)) - Method( - (b) => b - ..name = mapping.nullableMappingMethodName(config: config) - ..requiredParameters.addAll([ - Parameter( - (p) => p - ..name = 'input' - ..type = EmitterHelper.current.typeRefer(type: mapping.source).nullabled(), - ), - ]) - ..returns = EmitterHelper.current.typeRefer(type: mapping.target).nullabled() - ..body = MapModelBodyMethodBuilder( - mapping: mapping, - mapperConfig: config, - nullable: true, - ).build(), - ), + MappingMethodBuilder(config, mapping: mapping, nullable: true).buildMethod(), ]; } } diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart index 97c48c88..dd372c83 100644 --- a/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart +++ b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart @@ -15,7 +15,6 @@ class ClassBodyBuilder extends MapBodyBuilderBase { const ClassBodyBuilder({ required super.mapperConfig, required super.mapping, - required super.nullable, required super.usedNullableMethodCallback, }); @@ -116,8 +115,6 @@ class ClassBodyBuilder extends MapBodyBuilderBase { targetField: targetField, targetConstructorParam: constructorAssignment, fieldMapping: mapping.tryGetFieldMapping(targetField.displayName), - typeMapping: mapping, - config: mapperConfig, ); mappedTargetConstructorParams.add(sourceAssignment); @@ -144,8 +141,6 @@ class ClassBodyBuilder extends MapBodyBuilderBase { targetField: targetField, targetConstructorParam: constructorAssignment, fieldMapping: mapping.tryGetFieldMapping(targetField.displayName), - typeMapping: mapping, - config: mapperConfig, ); mappedTargetConstructorParams.add(sourceAssignment); @@ -169,8 +164,6 @@ class ClassBodyBuilder extends MapBodyBuilderBase { targetField: targetField, fieldMapping: fieldMapping, targetConstructorParam: constructorAssignment, - typeMapping: mapping, - config: mapperConfig, ), ); } @@ -252,8 +245,6 @@ class ClassBodyBuilder extends MapBodyBuilderBase { assignment: SourceAssignment( sourceField: sourceField, targetField: targetField, - typeMapping: mapping, - config: mapperConfig, ), usedNullableMethodCallback: usedNullableMethodCallback, ).build(), diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart b/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart index 4daa1199..cc2bb8b4 100644 --- a/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart +++ b/packages/auto_mappr/lib/src/builder/map_bodies/enum_body_builder.dart @@ -8,7 +8,6 @@ class EnumBodyBuilder extends MapBodyBuilderBase { const EnumBodyBuilder({ required super.mapperConfig, required super.mapping, - required super.nullable, required super.usedNullableMethodCallback, }); diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/map_body_builder_base.dart b/packages/auto_mappr/lib/src/builder/map_bodies/map_body_builder_base.dart index d90dff23..259a0c4a 100644 --- a/packages/auto_mappr/lib/src/builder/map_bodies/map_body_builder_base.dart +++ b/packages/auto_mappr/lib/src/builder/map_bodies/map_body_builder_base.dart @@ -6,13 +6,11 @@ abstract class MapBodyBuilderBase { final AutoMapprConfig mapperConfig; final TypeMapping mapping; - final bool nullable; final void Function(TypeMapping? mapping)? usedNullableMethodCallback; const MapBodyBuilderBase({ required this.mapperConfig, required this.mapping, - required this.nullable, required this.usedNullableMethodCallback, }); diff --git a/packages/auto_mappr/lib/src/builder/map_model_body_method_builder.dart b/packages/auto_mappr/lib/src/builder/map_model_body_method_builder.dart index 687d0fd4..d842306b 100644 --- a/packages/auto_mappr/lib/src/builder/map_model_body_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/map_model_body_method_builder.dart @@ -29,7 +29,6 @@ class MapModelBodyMethodBuilder { final enumMapBodyBuilder = EnumBodyBuilder( mapperConfig: mapperConfig, mapping: mapping, - nullable: nullable, usedNullableMethodCallback: usedNullableMethodCallback, ); if (enumMapBodyBuilder.canProcess()) { @@ -41,7 +40,6 @@ class MapModelBodyMethodBuilder { final classMapBodyBuilder = ClassBodyBuilder( mapperConfig: mapperConfig, mapping: mapping, - nullable: nullable, usedNullableMethodCallback: usedNullableMethodCallback, ); diff --git a/packages/auto_mappr/lib/src/builder/methods/can_convert_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/can_convert_method_builder.dart index 7c78a90c..7cd79b23 100644 --- a/packages/auto_mappr/lib/src/builder/methods/can_convert_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/can_convert_method_builder.dart @@ -6,7 +6,7 @@ import 'package:built_collection/built_collection.dart'; import 'package:code_builder/code_builder.dart'; class CanConvertMethodBuilder extends MethodBuilderBase implements CallableMethod, CallableProperty { - CanConvertMethodBuilder(super.config); + const CanConvertMethodBuilder(super.config); @override Method buildMethod() { diff --git a/packages/auto_mappr/lib/src/builder/methods/convert_iterable_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/convert_iterable_method_builder.dart index 680ecc79..8cf7b7c6 100644 --- a/packages/auto_mappr/lib/src/builder/methods/convert_iterable_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/convert_iterable_method_builder.dart @@ -11,7 +11,7 @@ class ConvertIterableMethodBuilder extends MethodBuilderBase { final String wrapper; final String? iterableTransformer; - ConvertIterableMethodBuilder( + const ConvertIterableMethodBuilder( super.config, { required this.wrapper, this.iterableTransformer, diff --git a/packages/auto_mappr/lib/src/builder/methods/convert_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/convert_method_builder.dart index ebf16562..9c78a0c1 100644 --- a/packages/auto_mappr/lib/src/builder/methods/convert_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/convert_method_builder.dart @@ -5,7 +5,7 @@ import 'package:built_collection/built_collection.dart'; import 'package:code_builder/code_builder.dart'; class ConvertMethodBuilder extends MethodBuilderBase { - ConvertMethodBuilder(super.config); + const ConvertMethodBuilder(super.config); @override Method buildMethod() { diff --git a/packages/auto_mappr/lib/src/builder/methods/mapping_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/mapping_method_builder.dart index 6e50c4bc..de2cbaff 100644 --- a/packages/auto_mappr/lib/src/builder/methods/mapping_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/mapping_method_builder.dart @@ -1,5 +1,6 @@ import 'package:auto_mappr/src/builder/map_model_body_method_builder.dart'; import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; +import 'package:auto_mappr/src/extensions/expression_extension.dart'; import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/type_mapping.dart'; import 'package:code_builder/code_builder.dart'; @@ -9,7 +10,7 @@ class MappingMethodBuilder extends MethodBuilderBase { final bool nullable; final void Function(TypeMapping? mapping)? usedNullableMethodCallback; - MappingMethodBuilder( + const MappingMethodBuilder( super.config, { required this.mapping, this.nullable = false, @@ -18,49 +19,35 @@ class MappingMethodBuilder extends MethodBuilderBase { @override Method buildMethod() { - // TODO(later): rework mapping to this builder + var returnType = EmitterHelper.current.typeRefer(type: mapping.target); + + if (nullable) { + returnType = returnType.nullabled(); + } return Method( (b) => b - ..name = mapping.mappingMethodName(config: config) + ..name = + nullable ? mapping.nullableMappingMethodName(config: config) : mapping.mappingMethodName(config: config) ..requiredParameters.addAll([ Parameter( (p) => p ..name = 'input' - ..type = EmitterHelper.current.typeRefer(type: mapping.source), + ..type = EmitterHelper.current.typeRefer(type: mapping.source).nullabled(), ), ]) - ..returns = EmitterHelper.current.typeRefer(type: mapping.target) - ..body = MapModelBodyMethodBuilder( - mapping: mapping, - mapperConfig: config, - usedNullableMethodCallback: usedNullableMethodCallback, - ).build(), + ..returns = returnType + ..body = buildBody(), ); - - // nullable - // return Method( - // (b) => b - // ..name = mapping.nullableMappingMethodName - // ..requiredParameters.addAll([ - // Parameter( - // (p) => p - // ..name = 'input' - // ..type = refer('${mapping.source.getDisplayString(withNullability: false)}?'), - // ) - // ]) - // ..returns = refer('${mapping.target.getDisplayString(withNullability: true)}?') - // ..body = MapModelBodyMethodBuilder( - // mapping: mapping, - // mapperConfig: config, - // nullable: true, - // ).build(), - // ); } @override Code buildBody() { - // TODO(later): rework - return const Code('T'); + return MapModelBodyMethodBuilder( + mapping: mapping, + mapperConfig: config, + usedNullableMethodCallback: usedNullableMethodCallback, + nullable: nullable, + ).build(); } } diff --git a/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart b/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart index 21e20058..e0dc25d4 100644 --- a/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart +++ b/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart @@ -25,9 +25,8 @@ abstract class MethodBuilderBase { static final ListBuilder<Reference> overrideAnnotation = ListBuilder([const Reference('override')]); final AutoMapprConfig config; - final Set<TypeMapping> nullableMappings; - MethodBuilderBase(this.config) : nullableMappings = {}; + const MethodBuilderBase(this.config); static String constructConvertMethodName({ required DartType source, @@ -47,16 +46,6 @@ abstract class MethodBuilderBase { config: config, )}_Nullable'; - bool shouldGenerateNullableMappingMethod(TypeMapping mapping) { - return nullableMappings.contains(mapping); - } - - void usedNullableMappingMethod(TypeMapping? mapping) { - if (mapping == null) return; - - final _ = nullableMappings.add(mapping); - } - Method buildMethod(); @protected diff --git a/packages/auto_mappr/lib/src/builder/methods/private_convert_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/private_convert_method_builder.dart index c742ca23..28613960 100644 --- a/packages/auto_mappr/lib/src/builder/methods/private_convert_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/private_convert_method_builder.dart @@ -4,7 +4,7 @@ import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:code_builder/code_builder.dart'; class PrivateConvertMethodBuilder extends MethodBuilderBase { - PrivateConvertMethodBuilder(super.config); + const PrivateConvertMethodBuilder(super.config); @override Method buildMethod() { diff --git a/packages/auto_mappr/lib/src/builder/methods/private_modules_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/private_modules_method_builder.dart index 9c87be53..15963b97 100644 --- a/packages/auto_mappr/lib/src/builder/methods/private_modules_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/private_modules_method_builder.dart @@ -4,7 +4,7 @@ import 'package:auto_mappr/src/helpers/urls.dart'; import 'package:code_builder/code_builder.dart'; class PrivateModulesMethodBuilder extends MethodBuilderBase { - PrivateModulesMethodBuilder(super.config); + const PrivateModulesMethodBuilder(super.config); @override Method buildMethod() { diff --git a/packages/auto_mappr/lib/src/builder/methods/try_convert_iterable_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/try_convert_iterable_method_builder.dart index 3b695077..7e49756c 100644 --- a/packages/auto_mappr/lib/src/builder/methods/try_convert_iterable_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/try_convert_iterable_method_builder.dart @@ -11,7 +11,7 @@ class TryConvertIterableMethodBuilder extends MethodBuilderBase { final String wrapper; final String? iterableTransformer; - TryConvertIterableMethodBuilder( + const TryConvertIterableMethodBuilder( super.config, { required this.wrapper, this.iterableTransformer, diff --git a/packages/auto_mappr/lib/src/builder/methods/try_convert_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/try_convert_method_builder.dart index 65bead72..3f7b6d43 100644 --- a/packages/auto_mappr/lib/src/builder/methods/try_convert_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/try_convert_method_builder.dart @@ -7,7 +7,7 @@ import 'package:code_builder/code_builder.dart'; // modules OK // modules tests OK class TryConvertMethodBuilder extends MethodBuilderBase { - TryConvertMethodBuilder(super.config); + const TryConvertMethodBuilder(super.config); @override Method buildMethod() { diff --git a/packages/auto_mappr/lib/src/builder/methods/type_of_method_builder.dart b/packages/auto_mappr/lib/src/builder/methods/type_of_method_builder.dart index 8cd1a31a..b5acc7fb 100644 --- a/packages/auto_mappr/lib/src/builder/methods/type_of_method_builder.dart +++ b/packages/auto_mappr/lib/src/builder/methods/type_of_method_builder.dart @@ -2,7 +2,7 @@ import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; import 'package:code_builder/code_builder.dart'; class TypeOfMethodBuilder extends MethodBuilderBase { - TypeOfMethodBuilder(super.config); + const TypeOfMethodBuilder(super.config); @override Method buildMethod() { diff --git a/packages/auto_mappr/lib/src/extensions/dart_object_extension.dart b/packages/auto_mappr/lib/src/extensions/dart_object_extension.dart index f9d370e5..4ea1550c 100644 --- a/packages/auto_mappr/lib/src/extensions/dart_object_extension.dart +++ b/packages/auto_mappr/lib/src/extensions/dart_object_extension.dart @@ -3,7 +3,6 @@ import 'package:analyzer/dart/constant/value.dart'; import 'package:auto_mappr/src/extensions/executable_element_extension.dart'; import 'package:auto_mappr/src/helpers/emitter_helper.dart'; -import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:code_builder/code_builder.dart'; import 'package:collection/collection.dart'; import 'package:source_gen/source_gen.dart'; @@ -12,10 +11,7 @@ extension DartObjectExtension on DartObject { /// If the top most object is a function, then return its code expression. /// /// Otherwise return code expression of literals or objects. - Expression? toCodeExpression({ - required AutoMapprConfig config, - bool passModelArgument = false, - }) { + Expression? toCodeExpression({bool passModelArgument = false}) { if (isNull) { return null; } @@ -28,16 +24,14 @@ extension DartObjectExtension on DartObject { ]); } - final output = _ToCodeExpressionConverter(config: config).convert(this).accept(EmitterHelper.current.emitter); + final output = const _ToCodeExpressionConverter().convert(this).accept(EmitterHelper.current.emitter); return CodeExpression(Code('$output')); } } class _ToCodeExpressionConverter { - final AutoMapprConfig config; - - const _ToCodeExpressionConverter({required this.config}); + const _ToCodeExpressionConverter(); Spec convert(DartObject dartObject) { return _toSpec(dartObject); diff --git a/packages/auto_mappr/lib/src/extensions/expression_extension.dart b/packages/auto_mappr/lib/src/extensions/expression_extension.dart index 46e602e9..bd45eeb1 100644 --- a/packages/auto_mappr/lib/src/extensions/expression_extension.dart +++ b/packages/auto_mappr/lib/src/extensions/expression_extension.dart @@ -102,12 +102,6 @@ extension ExpressionExtension on Expression { ); } - Expression maybeAsA(Expression expression, {required bool condition}) { - if (!condition) return this; - - return asA(expression); - } - static Reference ifStatement({ required Spec condition, required Spec ifBody, diff --git a/packages/auto_mappr/lib/src/extensions/reference_extension.dart b/packages/auto_mappr/lib/src/extensions/reference_extension.dart deleted file mode 100644 index 769f7ffa..00000000 --- a/packages/auto_mappr/lib/src/extensions/reference_extension.dart +++ /dev/null @@ -1,6 +0,0 @@ -import 'package:auto_mappr/src/helpers/emitter_helper.dart'; -import 'package:code_builder/code_builder.dart'; - -extension ReferenceExtension on Reference { - Reference get nullabled => refer('${accept(EmitterHelper.current.emitter)}?'); -} diff --git a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart index 54c2cd13..369d537e 100644 --- a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart +++ b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart @@ -58,24 +58,14 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { final mapprOptions = AutoMapprOptions.fromJson(builderOptions.config); - final tmpConfig = AutoMapprConfig( - mappers: [], - availableMappingsMacroId: 'tmp', - mapprOptions: mapprOptions, - ); - final constant = annotation.objectValue; final mappersList = constant.getField(annotationFieldMappers)!.toListValue()!; - final delegatesExpression = constant.getField(annotationFieldDelegates)!.toCodeExpression(config: tmpConfig); + final delegatesExpression = constant.getField(annotationFieldDelegates)!.toCodeExpression(); final delegatesList = constant.getField(annotationFieldDelegates)!.toListValue(); final includesList = constant.getField(annotationFieldIncludes)!.toListValue(); final allMappers = [...mappersList, ..._mappersFromRecursiveIncludes(includesList: includesList ?? [])]; - final mappers = _processMappers( - mappers: allMappers, - element: element, - config: tmpConfig, - ); + final mappers = _processMappers(mappers: allMappers, element: element); final duplicates = mappers.duplicates; if (duplicates.isNotEmpty) { @@ -105,7 +95,6 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { List<TypeMapping> _processMappers({ required List<DartObject> mappers, required ClassElement element, - required AutoMapprConfig config, }) { return mappers .map((mapper) { @@ -134,7 +123,7 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { } final fields = mapper.getField(mapTypeFieldFields)?.toListValue(); - final whenSourceIsNull = mapper.getField(mapTypeFieldWhenSourceIsNull)?.toCodeExpression(config: config); + final whenSourceIsNull = mapper.getField(mapTypeFieldWhenSourceIsNull)?.toCodeExpression(); final constructor = mapper.getField(mapTypeFieldConstructor)?.toStringValue(); final ignoreFieldNull = mapper.getField(mapTypeFieldIgnoreFieldNull)?.toBoolValue(); final reverse = mapper.getField(mapTypeFieldReverse)?.toBoolValue(); @@ -145,10 +134,8 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { field: fieldMapping.getField(fieldFieldField)!.toStringValue()!, ignore: fieldMapping.getField(fieldFieldIgnore)!.toBoolValue()!, from: fieldMapping.getField(fieldFieldFrom)!.toStringValue(), - customExpression: fieldMapping - .getField(fieldFieldCustom)! - .toCodeExpression(passModelArgument: true, config: config), - whenNullExpression: fieldMapping.getField(fieldFieldWhenNull)!.toCodeExpression(config: config), + customExpression: fieldMapping.getField(fieldFieldCustom)!.toCodeExpression(passModelArgument: true), + whenNullExpression: fieldMapping.getField(fieldFieldWhenNull)!.toCodeExpression(), ignoreNull: fieldMapping.getField(fieldFieldIgnoreNull)?.toBoolValue(), ), ) diff --git a/packages/auto_mappr/lib/src/models/field_mapping.dart b/packages/auto_mappr/lib/src/models/field_mapping.dart index d98cc4ef..95ac3de9 100644 --- a/packages/auto_mappr/lib/src/models/field_mapping.dart +++ b/packages/auto_mappr/lib/src/models/field_mapping.dart @@ -30,10 +30,6 @@ class FieldMapping extends Equatable { this.whenNullExpression, }); - bool isRenamed() { - return from != null; - } - bool hasCustomMapping() { return customExpression != null; } diff --git a/packages/auto_mappr/lib/src/models/source_assignment.dart b/packages/auto_mappr/lib/src/models/source_assignment.dart index 1caab431..3e6fc7a1 100644 --- a/packages/auto_mappr/lib/src/models/source_assignment.dart +++ b/packages/auto_mappr/lib/src/models/source_assignment.dart @@ -27,15 +27,6 @@ class SourceAssignment { /// Like filed 'name' from 'userName' etc. final FieldMapping? fieldMapping; - /// Mapping of type. - /// - /// Like UserDto to User. - final TypeMapping typeMapping; - - final AutoMapprConfig config; - - bool get shouldBeIgnored => fieldMapping?.ignore ?? false; - DartType? get sourceType => sourceField?.returnType; String? get sourceName => sourceField?.displayName; @@ -47,8 +38,6 @@ class SourceAssignment { const SourceAssignment({ required this.sourceField, required this.targetField, - required this.typeMapping, - required this.config, this.targetConstructorParam, this.fieldMapping, }); @@ -70,8 +59,6 @@ class SourceAssignment { return isSourceRecord && isTargetRecord; } - bool canAssignComplexObject() => !targetType.isPrimitiveType; - @override String toString() { final emittedSource = EmitterHelper.current.typeReferEmitted(type: sourceType); diff --git a/packages/auto_mappr/test/builder/convert_method_builder_test.dart b/packages/auto_mappr/test/builder/convert_method_builder_test.dart index 4503ee85..3a8036be 100644 --- a/packages/auto_mappr/test/builder/convert_method_builder_test.dart +++ b/packages/auto_mappr/test/builder/convert_method_builder_test.dart @@ -2,7 +2,7 @@ import 'package:auto_mappr/src/builder/methods/convert_method_builder.dart'; import 'package:auto_mappr/src/builder/methods/private_convert_method_builder.dart'; import 'package:auto_mappr/src/builder/methods/try_convert_method_builder.dart'; import 'package:auto_mappr/src/builder/methods/type_of_method_builder.dart'; -import 'package:auto_mappr/src/extensions/reference_extension.dart'; +import 'package:auto_mappr/src/extensions/expression_extension.dart'; import 'package:auto_mappr/src/helpers/run_zoned_auto_mappr.dart'; import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:auto_mappr/src/models/auto_mappr_options.dart'; @@ -13,8 +13,8 @@ import 'package:test/test.dart'; void main() { test('buildConvertMethod has the correct interface', () { runZonedAutoMappr(() { - final result = ConvertMethodBuilder( - const AutoMapprConfig( + final result = const ConvertMethodBuilder( + AutoMapprConfig( mappers: [], availableMappingsMacroId: 'test', mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), @@ -32,7 +32,7 @@ void main() { Parameter( (p) => p ..name = 'model' - ..type = result.types.firstOrNull?.nullabled, + ..type = result.types.firstOrNull?.nullabled(), ), ]), ); @@ -41,8 +41,8 @@ void main() { test('buildTryConvertMethod has the correct interface', () { runZonedAutoMappr(() { - final result = TryConvertMethodBuilder( - const AutoMapprConfig( + final result = const TryConvertMethodBuilder( + AutoMapprConfig( mappers: [], availableMappingsMacroId: 'test', mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), @@ -52,7 +52,7 @@ void main() { expect(result, isA<Method>()); expect(result.name, equals('tryConvert')); expect(result.types.length, equals(2)); - expect(result.returns, equals(result.types.elementAtOrNull(1)?.nullabled)); + expect(result.returns, equals(result.types.elementAtOrNull(1)?.nullabled())); expect(result.optionalParameters, isEmpty); expect( result.requiredParameters, @@ -60,7 +60,7 @@ void main() { Parameter( (p) => p ..name = 'model' - ..type = result.types.firstOrNull?.nullabled, + ..type = result.types.firstOrNull?.nullabled(), ), ]), ); @@ -69,8 +69,8 @@ void main() { test('buildInternalConvertMethod has the correct interface', () { runZonedAutoMappr(() { - final result = PrivateConvertMethodBuilder( - const AutoMapprConfig( + final result = const PrivateConvertMethodBuilder( + AutoMapprConfig( mappers: [], availableMappingsMacroId: 'test', mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), @@ -80,7 +80,7 @@ void main() { expect(result, isA<Method>()); expect(result.name, equals('_convert')); expect(result.types.length, equals(2)); - expect(result.returns, equals(result.types.elementAtOrNull(1)?.nullabled)); + expect(result.returns, equals(result.types.elementAtOrNull(1)?.nullabled())); expect(result.optionalParameters.isEmpty, isFalse); expect( result.requiredParameters, @@ -88,7 +88,7 @@ void main() { Parameter( (p) => p ..name = 'model' - ..type = result.types.firstOrNull?.nullabled, + ..type = result.types.firstOrNull?.nullabled(), ), ]), ); @@ -97,8 +97,8 @@ void main() { test('buildTypeOfHelperMethod has the correct interface', () { runZonedAutoMappr(() { - final result = TypeOfMethodBuilder( - const AutoMapprConfig( + final result = const TypeOfMethodBuilder( + AutoMapprConfig( mappers: [], availableMappingsMacroId: 'test', mapprOptions: AutoMapprOptions(ignoreNullableSourceField: false), From 348d820771dd256e49bf2dc066da88e2277e5c48 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 8 Sep 2023 13:48:47 +0200 Subject: [PATCH 26/48] Bump versions to RC --- packages/auto_mappr/CHANGELOG.md | 2 +- packages/auto_mappr/pubspec.yaml | 4 ++-- packages/auto_mappr_annotation/CHANGELOG.md | 2 +- packages/auto_mappr_annotation/pubspec.yaml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/auto_mappr/CHANGELOG.md b/packages/auto_mappr/CHANGELOG.md index 1b644e47..3a233fec 100644 --- a/packages/auto_mappr/CHANGELOG.md +++ b/packages/auto_mappr/CHANGELOG.md @@ -1,6 +1,6 @@ [//]: # (## Unreleased) -## Unreleased +## 2.0.0-rc.1 - **Breaking**: Allow "absorbing" modules using `includes` on `@AutoMappr`. Previous `modules` is now `delegates`. - **Breaking**: Remove shared AutoMappr builder that used PartBuilder, now `.auto_mappr.dart` is generated using LibraryBuilder. - Add a `reverse` option on `MapType`, which includes the reverse mapping. [#115](https://github.com/netglade/auto_mappr/pull/115) diff --git a/packages/auto_mappr/pubspec.yaml b/packages/auto_mappr/pubspec.yaml index c1db7e29..14693b90 100644 --- a/packages/auto_mappr/pubspec.yaml +++ b/packages/auto_mappr/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr description: Code generation for mapping between different objects with ease. -version: 1.7.0 +version: 2.0.0-rc.1 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues screenshots: @@ -13,7 +13,7 @@ environment: dependencies: # TODO: Support analyzer same way as json_serializable https://github.com/google/json_serializable.dart/pull/1333 analyzer: ">=5.4.0 <7.0.0" - auto_mappr_annotation: ^1.2.0 + auto_mappr_annotation: ^2.0.0-rc.1 build: ^2.3.1 built_collection: ^5.1.1 code_builder: ^4.4.0 diff --git a/packages/auto_mappr_annotation/CHANGELOG.md b/packages/auto_mappr_annotation/CHANGELOG.md index 4fe11239..209e4478 100644 --- a/packages/auto_mappr_annotation/CHANGELOG.md +++ b/packages/auto_mappr_annotation/CHANGELOG.md @@ -1,6 +1,6 @@ [//]: # (## Unreleased) -## Unreleased +## 2.0.0-rc.1 - Adhere to netglade_analysis 4.0.0 - Add `reverse` option to `MapType`. diff --git a/packages/auto_mappr_annotation/pubspec.yaml b/packages/auto_mappr_annotation/pubspec.yaml index bea1c50c..2ce34dca 100644 --- a/packages/auto_mappr_annotation/pubspec.yaml +++ b/packages/auto_mappr_annotation/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr_annotation description: Annotations for the auto_mappr code-generator of mapping between objects with ease. -version: 1.2.0 +version: 2.0.0-rc.1 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues From f362740bfb18af790fed0493e1bf5deac391da85 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 8 Sep 2023 14:07:29 +0200 Subject: [PATCH 27/48] Versions are beta --- packages/auto_mappr/CHANGELOG.md | 2 +- packages/auto_mappr/pubspec.yaml | 4 ++-- packages/auto_mappr_annotation/CHANGELOG.md | 2 +- packages/auto_mappr_annotation/pubspec.yaml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/auto_mappr/CHANGELOG.md b/packages/auto_mappr/CHANGELOG.md index 3a233fec..57f29e11 100644 --- a/packages/auto_mappr/CHANGELOG.md +++ b/packages/auto_mappr/CHANGELOG.md @@ -1,6 +1,6 @@ [//]: # (## Unreleased) -## 2.0.0-rc.1 +## 2.0.0-beta.1 - **Breaking**: Allow "absorbing" modules using `includes` on `@AutoMappr`. Previous `modules` is now `delegates`. - **Breaking**: Remove shared AutoMappr builder that used PartBuilder, now `.auto_mappr.dart` is generated using LibraryBuilder. - Add a `reverse` option on `MapType`, which includes the reverse mapping. [#115](https://github.com/netglade/auto_mappr/pull/115) diff --git a/packages/auto_mappr/pubspec.yaml b/packages/auto_mappr/pubspec.yaml index 14693b90..96a13a6f 100644 --- a/packages/auto_mappr/pubspec.yaml +++ b/packages/auto_mappr/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr description: Code generation for mapping between different objects with ease. -version: 2.0.0-rc.1 +version: 2.0.0-beta.1 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues screenshots: @@ -13,7 +13,7 @@ environment: dependencies: # TODO: Support analyzer same way as json_serializable https://github.com/google/json_serializable.dart/pull/1333 analyzer: ">=5.4.0 <7.0.0" - auto_mappr_annotation: ^2.0.0-rc.1 + auto_mappr_annotation: ^2.0.0-beta.1 build: ^2.3.1 built_collection: ^5.1.1 code_builder: ^4.4.0 diff --git a/packages/auto_mappr_annotation/CHANGELOG.md b/packages/auto_mappr_annotation/CHANGELOG.md index 209e4478..4423071d 100644 --- a/packages/auto_mappr_annotation/CHANGELOG.md +++ b/packages/auto_mappr_annotation/CHANGELOG.md @@ -1,6 +1,6 @@ [//]: # (## Unreleased) -## 2.0.0-rc.1 +## 2.0.0-beta.1 - Adhere to netglade_analysis 4.0.0 - Add `reverse` option to `MapType`. diff --git a/packages/auto_mappr_annotation/pubspec.yaml b/packages/auto_mappr_annotation/pubspec.yaml index 2ce34dca..ff756ca0 100644 --- a/packages/auto_mappr_annotation/pubspec.yaml +++ b/packages/auto_mappr_annotation/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr_annotation description: Annotations for the auto_mappr code-generator of mapping between objects with ease. -version: 2.0.0-rc.1 +version: 2.0.0-beta.1 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues From 13da0126ce61a50b6c994cb580f7089b4817d1a9 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 8 Sep 2023 14:08:09 +0200 Subject: [PATCH 28/48] Update --- packages/auto_mappr/CHANGELOG.md | 2 +- packages/auto_mappr/pubspec.yaml | 4 ++-- packages/auto_mappr_annotation/CHANGELOG.md | 2 +- packages/auto_mappr_annotation/pubspec.yaml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/auto_mappr/CHANGELOG.md b/packages/auto_mappr/CHANGELOG.md index 57f29e11..468fccd9 100644 --- a/packages/auto_mappr/CHANGELOG.md +++ b/packages/auto_mappr/CHANGELOG.md @@ -1,6 +1,6 @@ [//]: # (## Unreleased) -## 2.0.0-beta.1 +## 2.0.0-beta1 - **Breaking**: Allow "absorbing" modules using `includes` on `@AutoMappr`. Previous `modules` is now `delegates`. - **Breaking**: Remove shared AutoMappr builder that used PartBuilder, now `.auto_mappr.dart` is generated using LibraryBuilder. - Add a `reverse` option on `MapType`, which includes the reverse mapping. [#115](https://github.com/netglade/auto_mappr/pull/115) diff --git a/packages/auto_mappr/pubspec.yaml b/packages/auto_mappr/pubspec.yaml index 96a13a6f..7c38a8ec 100644 --- a/packages/auto_mappr/pubspec.yaml +++ b/packages/auto_mappr/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr description: Code generation for mapping between different objects with ease. -version: 2.0.0-beta.1 +version: 2.0.0-beta1 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues screenshots: @@ -13,7 +13,7 @@ environment: dependencies: # TODO: Support analyzer same way as json_serializable https://github.com/google/json_serializable.dart/pull/1333 analyzer: ">=5.4.0 <7.0.0" - auto_mappr_annotation: ^2.0.0-beta.1 + auto_mappr_annotation: ^2.0.0-beta1 build: ^2.3.1 built_collection: ^5.1.1 code_builder: ^4.4.0 diff --git a/packages/auto_mappr_annotation/CHANGELOG.md b/packages/auto_mappr_annotation/CHANGELOG.md index 4423071d..d5074e29 100644 --- a/packages/auto_mappr_annotation/CHANGELOG.md +++ b/packages/auto_mappr_annotation/CHANGELOG.md @@ -1,6 +1,6 @@ [//]: # (## Unreleased) -## 2.0.0-beta.1 +## 2.0.0-beta1 - Adhere to netglade_analysis 4.0.0 - Add `reverse` option to `MapType`. diff --git a/packages/auto_mappr_annotation/pubspec.yaml b/packages/auto_mappr_annotation/pubspec.yaml index ff756ca0..f30d5f06 100644 --- a/packages/auto_mappr_annotation/pubspec.yaml +++ b/packages/auto_mappr_annotation/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr_annotation description: Annotations for the auto_mappr code-generator of mapping between objects with ease. -version: 2.0.0-beta.1 +version: 2.0.0-beta1 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues From 9ef0be15973e8d57a54e8a4458d6fc7a1133026f Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 11 Sep 2023 06:30:13 +0200 Subject: [PATCH 29/48] Update changleog --- packages/auto_mappr/CHANGELOG.md | 4 ++-- packages/auto_mappr_annotation/CHANGELOG.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/auto_mappr/CHANGELOG.md b/packages/auto_mappr/CHANGELOG.md index 468fccd9..aee46a6c 100644 --- a/packages/auto_mappr/CHANGELOG.md +++ b/packages/auto_mappr/CHANGELOG.md @@ -1,8 +1,8 @@ [//]: # (## Unreleased) ## 2.0.0-beta1 -- **Breaking**: Allow "absorbing" modules using `includes` on `@AutoMappr`. Previous `modules` is now `delegates`. -- **Breaking**: Remove shared AutoMappr builder that used PartBuilder, now `.auto_mappr.dart` is generated using LibraryBuilder. +- **Breaking**: Allow "absorbing" modules using `includes` on `@AutoMappr`. Previous `modules` is now `delegates`. [#117](https://github.com/netglade/auto_mappr/pull/117) +- **Breaking**: Remove shared AutoMappr builder that used PartBuilder, now `.auto_mappr.dart` is generated using LibraryBuilder. [#117](https://github.com/netglade/auto_mappr/pull/117) - Add a `reverse` option on `MapType`, which includes the reverse mapping. [#115](https://github.com/netglade/auto_mappr/pull/115) - Add a support for Dart 3 and Records feature. [#116](https://github.com/netglade/auto_mappr/pull/116) diff --git a/packages/auto_mappr_annotation/CHANGELOG.md b/packages/auto_mappr_annotation/CHANGELOG.md index d5074e29..18dd15e6 100644 --- a/packages/auto_mappr_annotation/CHANGELOG.md +++ b/packages/auto_mappr_annotation/CHANGELOG.md @@ -1,8 +1,8 @@ [//]: # (## Unreleased) ## 2.0.0-beta1 -- Adhere to netglade_analysis 4.0.0 -- Add `reverse` option to `MapType`. +- Adhere to netglade_analysis 4.0.0. [#111](https://github.com/netglade/auto_mappr/pull/111) +- Add `reverse` option to `MapType`. [#115](https://github.com/netglade/auto_mappr/pull/115) ## 1.2.0 - Add `ignoreFieldNull` in `MapType` to force non-nullable field for when source's field is nullable From 850e5278082aab43e6e98715e4c1d7e3472db9f8 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 11 Sep 2023 07:26:15 +0200 Subject: [PATCH 30/48] Init type converters to type mapping --- packages/auto_mappr/CHANGELOG.md | 3 + .../converters/type_converters_builder.dart | 0 .../src/generator/auto_mappr_generator.dart | 74 ++++++++++++++++--- .../lib/src/models/type_converter.dart | 18 +++++ .../lib/src/models/type_mapping.dart | 4 + packages/auto_mappr_annotation/CHANGELOG.md | 3 + .../lib/src/auto_mappr.dart | 15 +++- .../lib/src/map_type.dart | 5 ++ .../lib/src/type_converter.dart | 8 ++ 9 files changed, 118 insertions(+), 12 deletions(-) create mode 100644 packages/auto_mappr/lib/src/builder/converters/type_converters_builder.dart create mode 100644 packages/auto_mappr/lib/src/models/type_converter.dart create mode 100644 packages/auto_mappr_annotation/lib/src/type_converter.dart diff --git a/packages/auto_mappr/CHANGELOG.md b/packages/auto_mappr/CHANGELOG.md index aee46a6c..ffb69485 100644 --- a/packages/auto_mappr/CHANGELOG.md +++ b/packages/auto_mappr/CHANGELOG.md @@ -1,5 +1,8 @@ [//]: # (## Unreleased) +## Unreleased +- Add type converters, use `converters` on `AutoMappr` or `MapType`. [#119](https://github.com/netglade/auto_mappr/pull/119) + ## 2.0.0-beta1 - **Breaking**: Allow "absorbing" modules using `includes` on `@AutoMappr`. Previous `modules` is now `delegates`. [#117](https://github.com/netglade/auto_mappr/pull/117) - **Breaking**: Remove shared AutoMappr builder that used PartBuilder, now `.auto_mappr.dart` is generated using LibraryBuilder. [#117](https://github.com/netglade/auto_mappr/pull/117) diff --git a/packages/auto_mappr/lib/src/builder/converters/type_converters_builder.dart b/packages/auto_mappr/lib/src/builder/converters/type_converters_builder.dart new file mode 100644 index 00000000..e69de29b diff --git a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart index 369d537e..48df1689 100644 --- a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart +++ b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart @@ -10,6 +10,7 @@ import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/helpers/run_zoned_auto_mappr.dart'; import 'package:auto_mappr/src/models/auto_mappr_options.dart'; import 'package:auto_mappr/src/models/models.dart'; +import 'package:auto_mappr/src/models/type_converter.dart'; import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; import 'package:build/build.dart'; import 'package:collection/collection.dart'; @@ -21,12 +22,14 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { // Constants for AutoMappr. static const String annotationAutoMappr = 'AutoMappr'; - static const String annotationFieldDelegates = 'delegates'; static const String annotationFieldMappers = 'mappers'; + static const String annotationFieldConverters = 'converters'; + static const String annotationFieldDelegates = 'delegates'; static const String annotationFieldIncludes = 'includes'; // Constants for MapType. static const String mapTypeFieldFields = 'fields'; + static const String mapTypeFieldConverters = 'converters'; static const String mapTypeFieldWhenSourceIsNull = 'whenSourceIsNull'; static const String mapTypeFieldConstructor = 'constructor'; static const String mapTypeFieldIgnoreFieldNull = 'ignoreFieldNull'; @@ -40,6 +43,9 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { static const String fieldFieldWhenNull = 'whenNull'; static const String fieldFieldIgnoreNull = 'ignoreNull'; + // Constants for TypeConverter. + static const String typeConverterFieldConverter = 'converter'; + const AutoMapprGenerator({required this.builderOptions}); @override @@ -59,13 +65,16 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { final mapprOptions = AutoMapprOptions.fromJson(builderOptions.config); final constant = annotation.objectValue; - final mappersList = constant.getField(annotationFieldMappers)!.toListValue()!; - final delegatesExpression = constant.getField(annotationFieldDelegates)!.toCodeExpression(); - final delegatesList = constant.getField(annotationFieldDelegates)!.toListValue(); - final includesList = constant.getField(annotationFieldIncludes)!.toListValue(); + final mappersList = constant.getField(annotationFieldMappers)?.toListValue() ?? <DartObject>[]; + final convertersList = constant.getField(annotationFieldConverters)?.toListValue() ?? <DartObject>[]; + final delegatesExpression = constant.getField(annotationFieldDelegates)?.toCodeExpression(); + final delegatesList = constant.getField(annotationFieldDelegates)?.toListValue() ?? <DartObject>[]; + final includesList = constant.getField(annotationFieldIncludes)?.toListValue() ?? <DartObject>[]; - final allMappers = [...mappersList, ..._mappersFromRecursiveIncludes(includesList: includesList ?? [])]; - final mappers = _processMappers(mappers: allMappers, element: element); + final allMappers = [...mappersList, ..._mappersFromRecursiveIncludes(includesList: includesList)]; + final allConverters = + _toTypeConverters([...convertersList, ..._convertersFromRecursiveIncludes(includesList: includesList)]); + final mappers = _processMappers(mappers: allMappers, globalConverters: allConverters, element: element); final duplicates = mappers.duplicates; if (duplicates.isNotEmpty) { @@ -80,7 +89,7 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { mappers: mappers, availableMappingsMacroId: element.library.identifier, modulesCode: delegatesExpression, - delegatesList: delegatesList ?? [], + delegatesList: delegatesList, mapprOptions: mapprOptions, ); @@ -94,6 +103,7 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { List<TypeMapping> _processMappers({ required List<DartObject> mappers, + required List<TypeConverter> globalConverters, required ClassElement element, }) { return mappers @@ -123,6 +133,7 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { } final fields = mapper.getField(mapTypeFieldFields)?.toListValue(); + final mapTypeConverters = mapper.getField(mapTypeFieldConverters)?.toListValue() ?? []; final whenSourceIsNull = mapper.getField(mapTypeFieldWhenSourceIsNull)?.toCodeExpression(); final constructor = mapper.getField(mapTypeFieldConstructor)?.toStringValue(); final ignoreFieldNull = mapper.getField(mapTypeFieldIgnoreFieldNull)?.toBoolValue(); @@ -136,7 +147,7 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { from: fieldMapping.getField(fieldFieldFrom)!.toStringValue(), customExpression: fieldMapping.getField(fieldFieldCustom)!.toCodeExpression(passModelArgument: true), whenNullExpression: fieldMapping.getField(fieldFieldWhenNull)!.toCodeExpression(), - ignoreNull: fieldMapping.getField(fieldFieldIgnoreNull)?.toBoolValue(), + ignoreNull: fieldMapping.getField(fieldFieldIgnoreNull)!.toBoolValue(), ), ) .toList(); @@ -146,6 +157,7 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { source: sourceType, target: targetType, fieldMappings: fieldMappings, + converters: [...globalConverters, ..._toTypeConverters(mapTypeConverters)], whenSourceIsNullExpression: whenSourceIsNull, constructor: constructor, ignoreFieldNull: ignoreFieldNull, @@ -192,4 +204,48 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { return mappings; } + + List<TypeConverter> _toTypeConverters(List<DartObject> source) { + return source.map((converter) { + final converterType = converter.type! as ParameterizedType; + // ignore: avoid-unsafe-collection-methods, is checked by the TypeConverter interface + final sourceType = converterType.typeArguments.first; + // ignore: avoid-unsafe-collection-methods, is checked by the TypeConverter interface + final targetType = converterType.typeArguments.last; + + return TypeConverter( + source: sourceType, + target: targetType, + converter: converter.getField(typeConverterFieldConverter)?.toCodeExpression(), + ); + }).toList(); + } + + /// Recursively returns all type converters from includes. + Iterable<DartObject> _convertersFromRecursiveIncludes({required List<DartObject> includesList}) { + final mappings = <DartObject>[]; + + for (final include in includesList) { + // For each include locate AutoMappr annotation. + if (include.type?.element?.metadata + .firstWhereOrNull((data) => data.element?.displayName == annotationAutoMappr) + ?.computeConstantValue() + case final includeConstant?) { + // This -- converters. + final converters = includeConstant.getField(annotationFieldConverters)?.toListValue(); + if (converters != null) { + mappings.addAll(converters); + } + + // Bellow -- recursive includes. + final includes = includeConstant.getField(annotationFieldIncludes)?.toListValue(); + if (includes != null) { + // ignore: avoid-recursive-calls, it's handled + mappings.addAll(_convertersFromRecursiveIncludes(includesList: includes)); + } + } + } + + return mappings; + } } diff --git a/packages/auto_mappr/lib/src/models/type_converter.dart b/packages/auto_mappr/lib/src/models/type_converter.dart new file mode 100644 index 00000000..b6f60e6d --- /dev/null +++ b/packages/auto_mappr/lib/src/models/type_converter.dart @@ -0,0 +1,18 @@ +import 'package:analyzer/dart/element/type.dart'; +import 'package:code_builder/code_builder.dart'; +import 'package:equatable/equatable.dart'; + +class TypeConverter extends Equatable { + final DartType source; + final DartType target; + final Expression? converter; + + @override + List<Object?> get props => [source, target, converter]; + + const TypeConverter({ + required this.source, + required this.target, + required this.converter, + }); +} diff --git a/packages/auto_mappr/lib/src/models/type_mapping.dart b/packages/auto_mappr/lib/src/models/type_mapping.dart index 2715595a..ce8edae6 100644 --- a/packages/auto_mappr/lib/src/models/type_mapping.dart +++ b/packages/auto_mappr/lib/src/models/type_mapping.dart @@ -3,6 +3,7 @@ import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; import 'package:auto_mappr/src/models/auto_mappr_config.dart'; import 'package:auto_mappr/src/models/field_mapping.dart'; +import 'package:auto_mappr/src/models/type_converter.dart'; import 'package:code_builder/code_builder.dart'; import 'package:collection/collection.dart'; import 'package:equatable/equatable.dart'; @@ -11,6 +12,7 @@ class TypeMapping extends Equatable { final InterfaceType source; final InterfaceType target; final List<FieldMapping>? fieldMappings; + final List<TypeConverter>? converters; final Expression? whenSourceIsNullExpression; final String? constructor; final bool? ignoreFieldNull; @@ -23,6 +25,7 @@ class TypeMapping extends Equatable { source, target, fieldMappings, + converters, whenSourceIsNullExpression, constructor, ignoreFieldNull, @@ -34,6 +37,7 @@ class TypeMapping extends Equatable { required this.target, required this.ignoreFieldNull, this.fieldMappings, + this.converters, this.whenSourceIsNullExpression, this.constructor, }); diff --git a/packages/auto_mappr_annotation/CHANGELOG.md b/packages/auto_mappr_annotation/CHANGELOG.md index 18dd15e6..ca1f930f 100644 --- a/packages/auto_mappr_annotation/CHANGELOG.md +++ b/packages/auto_mappr_annotation/CHANGELOG.md @@ -1,5 +1,8 @@ [//]: # (## Unreleased) +## Unreleased +- Add type converters, use `converters` on `AutoMappr` or `MapType`. [#119](https://github.com/netglade/auto_mappr/pull/119) + ## 2.0.0-beta1 - Adhere to netglade_analysis 4.0.0. [#111](https://github.com/netglade/auto_mappr/pull/111) - Add `reverse` option to `MapType`. [#115](https://github.com/netglade/auto_mappr/pull/115) diff --git a/packages/auto_mappr_annotation/lib/src/auto_mappr.dart b/packages/auto_mappr_annotation/lib/src/auto_mappr.dart index cac577f1..0a2b2aa2 100644 --- a/packages/auto_mappr_annotation/lib/src/auto_mappr.dart +++ b/packages/auto_mappr_annotation/lib/src/auto_mappr.dart @@ -1,22 +1,31 @@ import 'package:auto_mappr_annotation/src/auto_mappr_interface.dart'; import 'package:auto_mappr_annotation/src/map_type.dart'; +import 'package:auto_mappr_annotation/src/type_converter.dart'; /// Annotates class which will be used as base for generated mappr. final class AutoMappr { /// List of mapprs. final List<MapType<Object, Object>> mappers; + /// List of type converters. + final List<TypeConverter<Object, Object>> converters; + /// List of mapprs that should be included to this mappr. /// /// Imagine copy-pasting mappings from included mappr to this one. - final List<AutoMapprInterface>? includes; + final List<AutoMapprInterface> includes; /// List of mapprs used as delegates. /// /// When current mappr cannot convert source to target, /// it lets modules in order try to convert it instead. - final List<AutoMapprInterface>? delegates; + final List<AutoMapprInterface> delegates; /// Constructs AutoMappr. - const AutoMappr(this.mappers, {this.includes, this.delegates}); + const AutoMappr( + this.mappers, { + this.converters = const [], + this.includes = const [], + this.delegates = const [], + }); } diff --git a/packages/auto_mappr_annotation/lib/src/map_type.dart b/packages/auto_mappr_annotation/lib/src/map_type.dart index 53ebb459..7292111c 100644 --- a/packages/auto_mappr_annotation/lib/src/map_type.dart +++ b/packages/auto_mappr_annotation/lib/src/map_type.dart @@ -1,10 +1,14 @@ import 'package:auto_mappr_annotation/src/field.dart'; +import 'package:auto_mappr_annotation/src/type_converter.dart'; /// Configured mapping from [SOURCE] to [TARGET]. final class MapType<SOURCE, TARGET> { /// Configuration for [TARGET]'s fields. final List<Field> fields; + /// List of type converters. + final List<TypeConverter<Object, Object>> converters; + /// Provides default value if SOURCE is null. /// /// Additionally if mapping an enum "unknown" values in SOURCE will be mapped @@ -35,6 +39,7 @@ final class MapType<SOURCE, TARGET> { /// Constructs mapping between [SOURCE] and [TARGET] types. const MapType({ this.fields = const [], + this.converters = const [], this.whenSourceIsNull, this.constructor, this.ignoreFieldNull, diff --git a/packages/auto_mappr_annotation/lib/src/type_converter.dart b/packages/auto_mappr_annotation/lib/src/type_converter.dart new file mode 100644 index 00000000..caca4217 --- /dev/null +++ b/packages/auto_mappr_annotation/lib/src/type_converter.dart @@ -0,0 +1,8 @@ +/// Configured type converter from [SOURCE] to [TARGET]. +final class TypeConverter<SOURCE, TARGET> { + /// A function that does type converter. + final TARGET Function(SOURCE source) converter; + + /// Constructs type converter between [SOURCE] and [TARGET]. + const TypeConverter(this.converter); +} From ee755b8276e8c5e6823f053a9fe105460a3b98b0 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 11 Sep 2023 13:29:51 +0200 Subject: [PATCH 31/48] Finish type converters --- examples/drift/lib/mappr.auto_mappr.dart | 4 +- examples/example/lib/enum.auto_mappr.dart | 12 +- .../example/lib/equatable.auto_mappr.dart | 5 +- examples/example/lib/nested.auto_mappr.dart | 34 ++-- examples/example/lib/nullable.auto_mappr.dart | 13 +- examples/example/lib/rename.auto_mappr.dart | 5 +- .../lib/freezed_example.auto_mappr.dart | 4 +- examples/injectable/lib/mappr.auto_mappr.dart | 5 +- .../lib/serializable.auto_mappr.dart | 9 +- .../fixture/json_serializable.auto_mappr.dart | 9 +- packages/auto_mappr/README.md | 69 ++++++++ .../example/lib/mappr.auto_mappr.dart | 25 ++- .../src/builder/assignments/assignments.dart | 1 + .../iterable_assignment_builder.dart | 5 +- .../assignments/nested_object_mixin.dart | 47 ++++- .../assignments/type_converter_builder.dart | 57 ++++++ .../converters/type_converters_builder.dart | 0 .../map_bodies/class_body_builder.dart | 1 + .../builder/methods/method_builder_base.dart | 2 +- .../src/builder/value_assignment_builder.dart | 13 ++ .../src/generator/auto_mappr_generator.dart | 12 +- packages/auto_mappr/lib/src/helpers/di.dart | 0 .../lib/src/models/source_assignment.dart | 4 + .../lib/src/models/type_converter.dart | 29 +++- .../lib/src/models/type_mapping.dart | 16 +- .../integration/fixture/type_converters.dart | 163 ++++++++++++++++++ .../fixture/type_converters/module_alpha.dart | 12 ++ .../integration/type_converters_test.dart | 75 ++++++++ .../lib/auto_mappr_annotation.dart | 1 + 29 files changed, 544 insertions(+), 88 deletions(-) create mode 100644 packages/auto_mappr/lib/src/builder/assignments/type_converter_builder.dart delete mode 100644 packages/auto_mappr/lib/src/builder/converters/type_converters_builder.dart delete mode 100644 packages/auto_mappr/lib/src/helpers/di.dart create mode 100644 packages/auto_mappr/test/integration/fixture/type_converters.dart create mode 100644 packages/auto_mappr/test/integration/fixture/type_converters/module_alpha.dart create mode 100644 packages/auto_mappr/test/integration/type_converters_test.dart diff --git a/examples/drift/lib/mappr.auto_mappr.dart b/examples/drift/lib/mappr.auto_mappr.dart index 341c1c79..d7a8b69e 100644 --- a/examples/drift/lib/mappr.auto_mappr.dart +++ b/examples/drift/lib/mappr.auto_mappr.dart @@ -198,12 +198,12 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$Todo__To___i3$TodoItem((model as _i2.Todo?)) as TARGET); + return (_map__i2$Todo_To__i3$TodoItem((model as _i2.Todo?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - _i3.TodoItem _map___i2$Todo__To___i3$TodoItem(_i2.Todo? input) { + _i3.TodoItem _map__i2$Todo_To__i3$TodoItem(_i2.Todo? input) { final model = input; if (model == null) { throw Exception( diff --git a/examples/example/lib/enum.auto_mappr.dart b/examples/example/lib/enum.auto_mappr.dart index 97bbe7e9..d0f030da 100644 --- a/examples/example/lib/enum.auto_mappr.dart +++ b/examples/example/lib/enum.auto_mappr.dart @@ -211,7 +211,7 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$UserType__To___i2$PersonType((model as _i2.UserType?)) + return (_map__i2$UserType_To__i2$PersonType((model as _i2.UserType?)) as TARGET); } if ((sourceTypeOf == _typeOf<_i2.Vehicle>() || @@ -221,7 +221,7 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$Vehicle__To___i2$Vehicle((model as _i2.Vehicle?)) + return (_map__i2$Vehicle_To__i2$Vehicle((model as _i2.Vehicle?)) as TARGET); } if ((sourceTypeOf == _typeOf<_i2.Vehicle>() || @@ -231,13 +231,13 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$Vehicle__To___i2$VehicleX((model as _i2.Vehicle?)) + return (_map__i2$Vehicle_To__i2$VehicleX((model as _i2.Vehicle?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - _i2.PersonType _map___i2$UserType__To___i2$PersonType(_i2.UserType? input) { + _i2.PersonType _map__i2$UserType_To__i2$PersonType(_i2.UserType? input) { final model = input; if (model == null) { throw Exception( @@ -247,7 +247,7 @@ class $Mappr implements _i1.AutoMapprInterface { return _i2.PersonType.values.firstWhere((x) => x.name == model.name); } - _i2.Vehicle _map___i2$Vehicle__To___i2$Vehicle(_i2.Vehicle? input) { + _i2.Vehicle _map__i2$Vehicle_To__i2$Vehicle(_i2.Vehicle? input) { final model = input; if (model == null) { throw Exception( @@ -257,7 +257,7 @@ class $Mappr implements _i1.AutoMapprInterface { return _i2.Vehicle.values.firstWhere((x) => x.name == model.name); } - _i2.VehicleX _map___i2$Vehicle__To___i2$VehicleX(_i2.Vehicle? input) { + _i2.VehicleX _map__i2$Vehicle_To__i2$VehicleX(_i2.Vehicle? input) { final model = input; if (model == null) { throw Exception( diff --git a/examples/example/lib/equatable.auto_mappr.dart b/examples/example/lib/equatable.auto_mappr.dart index 5fa12e51..7a3c2591 100644 --- a/examples/example/lib/equatable.auto_mappr.dart +++ b/examples/example/lib/equatable.auto_mappr.dart @@ -197,13 +197,12 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) - as TARGET); + return (_map__i2$UserDto_To__i2$User((model as _i2.UserDto?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { + _i2.User _map__i2$UserDto_To__i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( diff --git a/examples/example/lib/nested.auto_mappr.dart b/examples/example/lib/nested.auto_mappr.dart index d7c10103..97db1d3b 100644 --- a/examples/example/lib/nested.auto_mappr.dart +++ b/examples/example/lib/nested.auto_mappr.dart @@ -211,8 +211,7 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) - as TARGET); + return (_map__i2$UserDto_To__i2$User((model as _i2.UserDto?)) as TARGET); } if ((sourceTypeOf == _typeOf<_i2.NestedDto>() || sourceTypeOf == _typeOf<_i2.NestedDto?>()) && @@ -221,7 +220,7 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$NestedDto__To___i2$Nested((model as _i2.NestedDto?)) + return (_map__i2$NestedDto_To__i2$Nested((model as _i2.NestedDto?)) as TARGET); } if ((sourceTypeOf == _typeOf<_i2.NestedTagDto>() || @@ -231,13 +230,13 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$NestedTagDto__To___i2$NestedTag( + return (_map__i2$NestedTagDto_To__i2$NestedTag( (model as _i2.NestedTagDto?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { + _i2.User _map__i2$UserDto_To__i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( @@ -246,29 +245,31 @@ class $Mappr implements _i1.AutoMapprInterface { } return _i2.User( id: model.id, - name: _map___i2$NestedDto__To___i2$Nested(model.name), + name: _map__i2$NestedDto_To__i2$Nested(model.name), nestedItems: model.nestedItems - .map<_i2.Nested>(_map___i2$NestedDto__To___i2$Nested) + .map<_i2.Nested>((value) => _map__i2$NestedDto_To__i2$Nested(value)) .toList(), nestedItemsNullable: model.nestedItemsNullable - ?.map<_i2.Nested>(_map___i2$NestedDto__To___i2$Nested) + ?.map<_i2.Nested>( + (value) => _map__i2$NestedDto_To__i2$Nested(value)) .toList() ?? <_i2.Nested>[], nestedItemsNullable2: model.nestedItemsNullable2 - .map<_i2.Nested>(_map___i2$NestedDto__To___i2$Nested) + .map<_i2.Nested>((value) => _map__i2$NestedDto_To__i2$Nested(value)) .toList(), itemsWithNullableItem: model.itemsWithNullableItem .whereNotNull() - .map<_i2.Nested>(_map___i2$NestedDto__To___i2$Nested) + .map<_i2.Nested>((value) => _map__i2$NestedDto_To__i2$Nested(value)) .toList(), itemsWithNullableItem2: model.itemsWithNullableItem2 - .map<_i2.Nested?>(_map___i2$NestedDto__To___i2$Nested_Nullable) + .map<_i2.Nested?>( + (value) => _map__i2$NestedDto_To__i2$Nested_Nullable(value)) .toList(), tag: null, ); } - _i2.Nested _map___i2$NestedDto__To___i2$Nested(_i2.NestedDto? input) { + _i2.Nested _map__i2$NestedDto_To__i2$Nested(_i2.NestedDto? input) { final model = input; if (model == null) { throw Exception( @@ -278,11 +279,11 @@ class $Mappr implements _i1.AutoMapprInterface { return _i2.Nested( id: model.id, name: model.name, - tag: _map___i2$NestedTagDto__To___i2$NestedTag(model.tag), + tag: _map__i2$NestedTagDto_To__i2$NestedTag(model.tag), ); } - _i2.NestedTag _map___i2$NestedTagDto__To___i2$NestedTag( + _i2.NestedTag _map__i2$NestedTagDto_To__i2$NestedTag( _i2.NestedTagDto? input) { final model = input; if (model == null) { @@ -293,8 +294,7 @@ class $Mappr implements _i1.AutoMapprInterface { return _i2.NestedTag(); } - _i2.Nested? _map___i2$NestedDto__To___i2$Nested_Nullable( - _i2.NestedDto? input) { + _i2.Nested? _map__i2$NestedDto_To__i2$Nested_Nullable(_i2.NestedDto? input) { final model = input; if (model == null) { return null; @@ -302,7 +302,7 @@ class $Mappr implements _i1.AutoMapprInterface { return _i2.Nested( id: model.id, name: model.name, - tag: _map___i2$NestedTagDto__To___i2$NestedTag(model.tag), + tag: _map__i2$NestedTagDto_To__i2$NestedTag(model.tag), ); } } diff --git a/examples/example/lib/nullable.auto_mappr.dart b/examples/example/lib/nullable.auto_mappr.dart index e78d8190..a66328f1 100644 --- a/examples/example/lib/nullable.auto_mappr.dart +++ b/examples/example/lib/nullable.auto_mappr.dart @@ -210,8 +210,7 @@ class $Mappr implements _i2.AutoMapprInterface { ), ) as TARGET); } - return (_map___i1$UserDto__To___i1$User((model as _i1.UserDto?)) - as TARGET); + return (_map__i1$UserDto_To__i1$User((model as _i1.UserDto?)) as TARGET); } if ((sourceTypeOf == _typeOf<_i1.NestedDto>() || sourceTypeOf == _typeOf<_i1.NestedDto?>()) && @@ -220,13 +219,13 @@ class $Mappr implements _i2.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i1$NestedDto__To___i1$Nested((model as _i1.NestedDto?)) + return (_map__i1$NestedDto_To__i1$Nested((model as _i1.NestedDto?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - _i1.User _map___i1$UserDto__To___i1$User(_i1.UserDto? input) { + _i1.User _map__i1$UserDto_To__i1$User(_i1.UserDto? input) { final model = input; if (model == null) { return const _i1.User( @@ -241,12 +240,12 @@ class $Mappr implements _i2.AutoMapprInterface { id: model.id, tag: model.tag == null ? _i1.Mappr.defaultNested() - : _map___i1$NestedDto__To___i1$Nested(model.tag), - name: _map___i1$NestedDto__To___i1$Nested(model.name), + : _map__i1$NestedDto_To__i1$Nested(model.tag), + name: _map__i1$NestedDto_To__i1$Nested(model.name), ); } - _i1.Nested _map___i1$NestedDto__To___i1$Nested(_i1.NestedDto? input) { + _i1.Nested _map__i1$NestedDto_To__i1$Nested(_i1.NestedDto? input) { final model = input; if (model == null) { throw Exception( diff --git a/examples/example/lib/rename.auto_mappr.dart b/examples/example/lib/rename.auto_mappr.dart index 7c3cd1af..0926d97b 100644 --- a/examples/example/lib/rename.auto_mappr.dart +++ b/examples/example/lib/rename.auto_mappr.dart @@ -197,13 +197,12 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) - as TARGET); + return (_map__i2$UserDto_To__i2$User((model as _i2.UserDto?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { + _i2.User _map__i2$UserDto_To__i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( diff --git a/examples/freezed/lib/freezed_example.auto_mappr.dart b/examples/freezed/lib/freezed_example.auto_mappr.dart index 2502248b..e1999c0d 100644 --- a/examples/freezed/lib/freezed_example.auto_mappr.dart +++ b/examples/freezed/lib/freezed_example.auto_mappr.dart @@ -197,13 +197,13 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$UserInfo__To___i2$UserInfoCompanion( + return (_map__i2$UserInfo_To__i2$UserInfoCompanion( (model as _i2.UserInfo?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - _i2.UserInfoCompanion _map___i2$UserInfo__To___i2$UserInfoCompanion( + _i2.UserInfoCompanion _map__i2$UserInfo_To__i2$UserInfoCompanion( _i2.UserInfo? input) { final model = input; if (model == null) { diff --git a/examples/injectable/lib/mappr.auto_mappr.dart b/examples/injectable/lib/mappr.auto_mappr.dart index 961b48f8..6e9123c3 100644 --- a/examples/injectable/lib/mappr.auto_mappr.dart +++ b/examples/injectable/lib/mappr.auto_mappr.dart @@ -197,13 +197,12 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) - as TARGET); + return (_map__i2$UserDto_To__i2$User((model as _i2.UserDto?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { + _i2.User _map__i2$UserDto_To__i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( diff --git a/examples/json_serializable/lib/serializable.auto_mappr.dart b/examples/json_serializable/lib/serializable.auto_mappr.dart index 195b3a0e..35b76e2b 100644 --- a/examples/json_serializable/lib/serializable.auto_mappr.dart +++ b/examples/json_serializable/lib/serializable.auto_mappr.dart @@ -204,8 +204,7 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) - as TARGET); + return (_map__i2$UserDto_To__i2$User((model as _i2.UserDto?)) as TARGET); } if ((sourceTypeOf == _typeOf<_i2.ValueHolderDto>() || sourceTypeOf == _typeOf<_i2.ValueHolderDto?>()) && @@ -214,13 +213,13 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$ValueHolderDto__To___i2$ValueHolder( + return (_map__i2$ValueHolderDto_To__i2$ValueHolder( (model as _i2.ValueHolderDto?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { + _i2.User _map__i2$UserDto_To__i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( @@ -233,7 +232,7 @@ class $Mappr implements _i1.AutoMapprInterface { ); } - _i2.ValueHolder _map___i2$ValueHolderDto__To___i2$ValueHolder( + _i2.ValueHolder _map__i2$ValueHolderDto_To__i2$ValueHolder( _i2.ValueHolderDto? input) { final model = input; if (model == null) { diff --git a/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart b/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart index d93e4e43..91310fc8 100644 --- a/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart +++ b/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart @@ -204,8 +204,7 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) - as TARGET); + return (_map__i2$UserDto_To__i2$User((model as _i2.UserDto?)) as TARGET); } if ((sourceTypeOf == _typeOf<_i2.ValueHolderDto>() || sourceTypeOf == _typeOf<_i2.ValueHolderDto?>()) && @@ -214,13 +213,13 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$ValueHolderDto__To___i2$ValueHolder( + return (_map__i2$ValueHolderDto_To__i2$ValueHolder( (model as _i2.ValueHolderDto?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { + _i2.User _map__i2$UserDto_To__i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( @@ -233,7 +232,7 @@ class $Mappr implements _i1.AutoMapprInterface { ); } - _i2.ValueHolder _map___i2$ValueHolderDto__To___i2$ValueHolder( + _i2.ValueHolder _map__i2$ValueHolderDto_To__i2$ValueHolder( _i2.ValueHolderDto? input) { final model = input; if (model == null) { diff --git a/packages/auto_mappr/README.md b/packages/auto_mappr/README.md index 7536685b..a68d6902 100644 --- a/packages/auto_mappr/README.md +++ b/packages/auto_mappr/README.md @@ -45,6 +45,7 @@ Heavily inspired by [C# AutoMapper][auto_mapper_net_link]. - [Mapping from source](#mapping-from-source) - [Nullability handling](#nullability-handling) - [Forced non-nullable field for nullable source](#forced-non-nullable-field-for-nullable-source) + - [Type converters](#type-converters) - [Generics](#generics) - [Library import aliases](#library-import-aliases) - [Modules](#modules) @@ -638,6 +639,74 @@ final User user = mappr.convert(UserDto(...)); // delegates to user feature mapp That can be handy for example with dependency injection, so you can only provide one main mappr that can handle everything by delegating to other mapprs. +### Type converters + +`MapType`s are usefull for mappings that you can use from the **outside**. +AutoMappr mapps one object to another using constructors and fields +and you use the `.convert()` method on it. + +But when you need to customize an **inner** converting of types, +there are `TypeConverter`s that help you with that. +Boxing, `String` to `DateTime`, and stuff like that, `TypeConverter`s are your friend. +Note since type converters are only used internally, +you cannot in any way use them using the `.convert()` method. +Note that global type converters are also "absorbed" when including a module. + +Use `MapType` for most of the things. +Use `TypeConverter` only for cases that cannot be solve otherwise. + +Imagine you have an `UserDto` with a date in a `String` and a `User` model with a date in `DateTime`. +`MapType` will handle mapping of all the constructor parameters and other fields, +while `TypeConverter` will convert `String` to `DateTime`. + +```dart +@AutoMappr( + [ + MapType<UserDto, User>( + // MapType specific + converters: [ + TypeConverter<String, DateTime>() + ], + ), + ], + converters: [ + // or globally here + ], +) +class Mappr extends $Mappr { + static DateTime stringToDateTime(String source) { + // ... + } +} +``` + +You can also create methods that can convert "any" (to "any") using `Object`. +But if you work with type parameters (generics) +note that you have to either return the correct type with correct type parameters +or initialize it inside correctly. +It cannot be cast successfully otherwise. +Therefore if you need a method that converts `"any"` to `Value("any")`, +and to make it work of `int` and `String`, +it must look like one of these: + +```dart +static Value<T> objectToValueObject<T extends Object>(T source) { + return Value<T>(source); +} + +static Value<Object> objectToValueObject2(Object source) { + if (source is int) { + return Value<int>(source); + } + + if (source is String) { + return Value<String>(source); + } + + return Value(source); +} +``` + ### Reverse mapping When you want to create a bidirectional mapping (e.g. normal: source to target and reversed: target to source), diff --git a/packages/auto_mappr/example/lib/mappr.auto_mappr.dart b/packages/auto_mappr/example/lib/mappr.auto_mappr.dart index 884c0f17..6ea88f78 100644 --- a/packages/auto_mappr/example/lib/mappr.auto_mappr.dart +++ b/packages/auto_mappr/example/lib/mappr.auto_mappr.dart @@ -11,7 +11,7 @@ import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; import 'mappr.dart' as _i2; -/// {@template asset:auto_mappr/example/lib/mappr.dart} +/// {@template package:auto_mappr_example/mappr.dart} /// Available mappings: /// - `UserDto` → `User`. /// {@endtemplate} @@ -22,7 +22,7 @@ class $Mappr implements _i1.AutoMapprInterface { List<_i1.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); @@ -44,7 +44,7 @@ class $Mappr implements _i1.AutoMapprInterface { } /// {@macro AutoMapprInterface:convert} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override TARGET convert<SOURCE, TARGET>(SOURCE? model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -60,7 +60,7 @@ class $Mappr implements _i1.AutoMapprInterface { } /// {@macro AutoMapprInterface:tryConvert} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override TARGET? tryConvert<SOURCE, TARGET>(SOURCE? model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -79,7 +79,7 @@ class $Mappr implements _i1.AutoMapprInterface { } /// {@macro AutoMapprInterface:convertIterable} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override Iterable<TARGET> convertIterable<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -98,7 +98,7 @@ class $Mappr implements _i1.AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override Iterable<TARGET?> tryConvertIterable<SOURCE, TARGET>( Iterable<SOURCE?> model) { @@ -115,7 +115,7 @@ class $Mappr implements _i1.AutoMapprInterface { } /// {@macro AutoMapprInterface:convertList} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override List<TARGET> convertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -134,7 +134,7 @@ class $Mappr implements _i1.AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override List<TARGET?> tryConvertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -150,7 +150,7 @@ class $Mappr implements _i1.AutoMapprInterface { } /// {@macro AutoMapprInterface:convertSet} - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override Set<TARGET> convertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -169,7 +169,7 @@ class $Mappr implements _i1.AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro asset:auto_mappr/example/lib/mappr.dart} + /// {@macro package:auto_mappr_example/mappr.dart} @override Set<TARGET?> tryConvertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -197,13 +197,12 @@ class $Mappr implements _i1.AutoMapprInterface { if (canReturnNull && model == null) { return null; } - return (_map___i2$UserDto__To___i2$User((model as _i2.UserDto?)) - as TARGET); + return (_map__i2$UserDto_To__i2$User((model as _i2.UserDto?)) as TARGET); } throw Exception('No ${model.runtimeType} -> $targetTypeOf mapping.'); } - _i2.User _map___i2$UserDto__To___i2$User(_i2.UserDto? input) { + _i2.User _map__i2$UserDto_To__i2$User(_i2.UserDto? input) { final model = input; if (model == null) { throw Exception( diff --git a/packages/auto_mappr/lib/src/builder/assignments/assignments.dart b/packages/auto_mappr/lib/src/builder/assignments/assignments.dart index 5df7a1c5..916cc770 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/assignments.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/assignments.dart @@ -3,3 +3,4 @@ export 'iterable_assignment_builder.dart'; export 'map_assignment_builder.dart'; export 'nested_object_assignment_builder.dart'; export 'record_assignment_builder.dart'; +export 'type_converter_builder.dart'; diff --git a/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart index 20692d70..c6fafe79 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/iterable_assignment_builder.dart @@ -81,10 +81,13 @@ class IterableAssignmentBuilder extends AssignmentBuilderBase with NestedObjectM final targetListType = assignment.targetType.genericParameterTypeOrSelf; final sourceListType = assignment.sourceType!.genericParameterTypeOrSelf; - return assignNestedObject( + final body = assignNestedObject( assignment: assignment, source: sourceListType, target: targetListType, + convertMethodArgument: refer('value'), ); + + return refer('(value) => ${body.accept(EmitterHelper.current.emitter)}'); } } diff --git a/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart b/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart index ddd49796..82e73190 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart @@ -1,5 +1,5 @@ import 'package:analyzer/dart/element/type.dart'; -import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; +import 'package:auto_mappr/src/builder/assignments/assignments.dart'; import 'package:auto_mappr/src/builder/methods/method_builder_base.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/helpers/emitter_helper.dart'; @@ -12,7 +12,7 @@ import 'package:source_gen/source_gen.dart'; mixin NestedObjectMixin on AssignmentBuilderBase { /// Assigns nested object as either: /// - default value - /// - call to already generated mapping between two types + /// - call to already generated mapping between two typ`es /// /// If [convertMethodArgument] is null, uses a tear off call instead. Expression assignNestedObject({ @@ -22,8 +22,11 @@ mixin NestedObjectMixin on AssignmentBuilderBase { Expression? convertMethodArgument, bool includeGenericTypes = false, }) { + final sourceOnModel = refer('model').property(assignment.sourceField!.displayName); + + // Source and target is the same. if (source.isSame(target)) { - return refer('model').property(assignment.sourceField!.displayName); + return sourceOnModel; } final nestedMapping = mapperConfig.findMapping( @@ -31,6 +34,42 @@ mixin NestedObjectMixin on AssignmentBuilderBase { target: target, ); + // Type converters. + final typeConvertersBuilder = TypeConverterBuilder( + assignment: assignment, + mapperConfig: mapperConfig, + mapping: mapping, + usedNullableMethodCallback: null, + convertMethodArgument: convertMethodArgument, + source: source, + target: target, + ); + if (typeConvertersBuilder.canAssign()) { + return typeConvertersBuilder.buildAssignment(); + } + + // if (assignment.typeConverters + // .firstWhereOrNull((converter) => converter.canBeUsed(mappingSource: source, mappingTarget: target)) + // case final converter?) { + // // Call. + // if (convertMethodArgument != null) { + // final targetRefer = EmitterHelper.current.typeRefer(type: target); + + // return EmitterHelper.current + // .refer(converter.converter.referCallString, converter.converter.library.identifier) + // .call([convertMethodArgument]).asA(targetRefer); + // } + + // final sourceEmitted = EmitterHelper.current.typeReferEmitted(type: source); + // final targetEmitted = EmitterHelper.current.typeReferEmitted(type: target); + + // // Tear-off. + // return EmitterHelper.current + // .refer(converter.converter.referCallString, converter.converter.library.identifier) + // .asA(refer('$targetEmitted Function($sourceEmitted)')); + // } + + // Unknown mapping. if (nestedMapping == null) { final sourceName = assignment.sourceField?.getDisplayString(withNullability: true); @@ -66,7 +105,7 @@ mixin NestedObjectMixin on AssignmentBuilderBase { // name: 'test', // ) // : _map_NestedDto_To_Nested(model.name), - return refer('model').property(assignment.sourceField!.displayName).equalTo(literalNull).conditional( + return sourceOnModel.equalTo(literalNull).conditional( fieldMapping!.whenNullExpression!, convertCallExpression, ); diff --git a/packages/auto_mappr/lib/src/builder/assignments/type_converter_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/type_converter_builder.dart new file mode 100644 index 00000000..3540c004 --- /dev/null +++ b/packages/auto_mappr/lib/src/builder/assignments/type_converter_builder.dart @@ -0,0 +1,57 @@ +import 'package:analyzer/dart/element/type.dart'; +import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; +import 'package:auto_mappr/src/extensions/executable_element_extension.dart'; +import 'package:auto_mappr/src/helpers/emitter_helper.dart'; +import 'package:code_builder/code_builder.dart'; +import 'package:collection/collection.dart'; + +class TypeConverterBuilder extends AssignmentBuilderBase { + final Expression? convertMethodArgument; + final DartType source; + final DartType target; + + const TypeConverterBuilder({ + required super.assignment, + required super.mapperConfig, + required super.mapping, + required super.usedNullableMethodCallback, + required this.convertMethodArgument, + required this.source, + required this.target, + }); + + @override + bool canAssign() { + return assignment.typeConverters.firstWhereOrNull( + (converter) => converter.canBeUsed( + mappingSource: source, + mappingTarget: target, + ), + ) != + null; + } + + @override + Expression buildAssignment() { + final converter = assignment.typeConverters + // ignore: avoid-unsafe-collection-methods, checked by [canAssign] + .firstWhere((c) => c.canBeUsed(mappingSource: source, mappingTarget: target)); + + // Call. + if (convertMethodArgument case final methodArgument?) { + final targetRefer = EmitterHelper.current.typeRefer(type: target); + + return EmitterHelper.current + .refer(converter.converter.referCallString, converter.converter.library.identifier) + .call([methodArgument]).asA(targetRefer); + } + + final sourceEmitted = EmitterHelper.current.typeReferEmitted(type: source); + final targetEmitted = EmitterHelper.current.typeReferEmitted(type: target); + + // Tear-off. + return EmitterHelper.current + .refer(converter.converter.referCallString, converter.converter.library.identifier) + .asA(refer('$targetEmitted Function($sourceEmitted)')); + } +} diff --git a/packages/auto_mappr/lib/src/builder/converters/type_converters_builder.dart b/packages/auto_mappr/lib/src/builder/converters/type_converters_builder.dart deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart index dd372c83..16f1d6ad 100644 --- a/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart +++ b/packages/auto_mappr/lib/src/builder/map_bodies/class_body_builder.dart @@ -141,6 +141,7 @@ class ClassBodyBuilder extends MapBodyBuilderBase { targetField: targetField, targetConstructorParam: constructorAssignment, fieldMapping: mapping.tryGetFieldMapping(targetField.displayName), + typeConverters: mapping.typeConverters, ); mappedTargetConstructorParams.add(sourceAssignment); diff --git a/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart b/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart index e0dc25d4..ac2d1a7c 100644 --- a/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart +++ b/packages/auto_mappr/lib/src/builder/methods/method_builder_base.dart @@ -33,7 +33,7 @@ abstract class MethodBuilderBase { required DartType target, required AutoMapprConfig config, }) => - '_map__${source.toConvertMethodName()}__To__${target.toConvertMethodName()}'; + '_map_${source.toConvertMethodName()}_To_${target.toConvertMethodName()}'; static String constructNullableConvertMethodName({ required DartType source, diff --git a/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart index b606802d..e94bd41a 100644 --- a/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/value_assignment_builder.dart @@ -75,6 +75,16 @@ class ValueAssignmentBuilder { target: assignment.targetType, convertMethodArgument: rightSide, ), + // Type converter for primitive type. + TypeConverterBuilder( + assignment: assignment, + mapperConfig: mapperConfig, + mapping: mapping, + usedNullableMethodCallback: usedNullableMethodCallback, + source: assignment.sourceType!, + target: assignment.targetType, + convertMethodArgument: rightSide, + ), ]; // Try to assign value using one of assignment builder. @@ -84,6 +94,9 @@ class ValueAssignmentBuilder { } } + // Primitive types (based on DartTypeExtension.isPrimitiveType) + + // When null. if (fieldMapping?.whenNullExpression != null) { return rightSide.ifNullThen(fieldMapping!.whenNullExpression!); } diff --git a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart index 48df1689..bc73fcc8 100644 --- a/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart +++ b/packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart @@ -11,13 +11,13 @@ import 'package:auto_mappr/src/helpers/run_zoned_auto_mappr.dart'; import 'package:auto_mappr/src/models/auto_mappr_options.dart'; import 'package:auto_mappr/src/models/models.dart'; import 'package:auto_mappr/src/models/type_converter.dart'; -import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as annotation; import 'package:build/build.dart'; import 'package:collection/collection.dart'; import 'package:source_gen/source_gen.dart'; /// Code generator to generate implemented mapping classes. -class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { +class AutoMapprGenerator extends GeneratorForAnnotation<annotation.AutoMappr> { final BuilderOptions builderOptions; // Constants for AutoMappr. @@ -156,8 +156,8 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { TypeMapping( source: sourceType, target: targetType, - fieldMappings: fieldMappings, - converters: [...globalConverters, ..._toTypeConverters(mapTypeConverters)], + fieldMappings: fieldMappings ?? [], + typeConverters: [..._toTypeConverters(mapTypeConverters), ...globalConverters], whenSourceIsNullExpression: whenSourceIsNull, constructor: constructor, ignoreFieldNull: ignoreFieldNull, @@ -166,7 +166,7 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { TypeMapping( source: targetType, target: sourceType, - fieldMappings: fieldMappings, + fieldMappings: fieldMappings ?? [], whenSourceIsNullExpression: whenSourceIsNull, constructor: constructor, ignoreFieldNull: ignoreFieldNull, @@ -216,7 +216,7 @@ class AutoMapprGenerator extends GeneratorForAnnotation<AutoMappr> { return TypeConverter( source: sourceType, target: targetType, - converter: converter.getField(typeConverterFieldConverter)?.toCodeExpression(), + converter: converter.getField(typeConverterFieldConverter)!.toFunctionValue()!, ); }).toList(); } diff --git a/packages/auto_mappr/lib/src/helpers/di.dart b/packages/auto_mappr/lib/src/helpers/di.dart deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/auto_mappr/lib/src/models/source_assignment.dart b/packages/auto_mappr/lib/src/models/source_assignment.dart index 3e6fc7a1..be9447f1 100644 --- a/packages/auto_mappr/lib/src/models/source_assignment.dart +++ b/packages/auto_mappr/lib/src/models/source_assignment.dart @@ -5,6 +5,7 @@ import 'package:analyzer/dart/element/type.dart'; import 'package:auto_mappr/src/extensions/dart_type_extension.dart'; import 'package:auto_mappr/src/helpers/emitter_helper.dart'; import 'package:auto_mappr/src/models/models.dart'; +import 'package:auto_mappr/src/models/type_converter.dart'; import 'package:code_builder/code_builder.dart' show Expression, literalList, literalMap, literalNull, literalSet; class ConstructorAssignment { @@ -22,6 +23,8 @@ class SourceAssignment { final ConstructorAssignment? targetConstructorParam; final PropertyAccessorElement? targetField; + final List<TypeConverter> typeConverters; + /// Field mapping. /// /// Like filed 'name' from 'userName' etc. @@ -39,6 +42,7 @@ class SourceAssignment { required this.sourceField, required this.targetField, this.targetConstructorParam, + this.typeConverters = const [], this.fieldMapping, }); diff --git a/packages/auto_mappr/lib/src/models/type_converter.dart b/packages/auto_mappr/lib/src/models/type_converter.dart index b6f60e6d..cbce2712 100644 --- a/packages/auto_mappr/lib/src/models/type_converter.dart +++ b/packages/auto_mappr/lib/src/models/type_converter.dart @@ -1,11 +1,11 @@ +import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; -import 'package:code_builder/code_builder.dart'; import 'package:equatable/equatable.dart'; class TypeConverter extends Equatable { final DartType source; final DartType target; - final Expression? converter; + final ExecutableElement converter; @override List<Object?> get props => [source, target, converter]; @@ -15,4 +15,29 @@ class TypeConverter extends Equatable { required this.target, required this.converter, }); + + @override + String toString() { + final sourceX = source.getDisplayString(withNullability: true); + final targetX = target.getDisplayString(withNullability: true); + + return 'typeConverter $sourceX -> $targetX'; + } + + bool canBeUsed({ + required DartType mappingSource, + required DartType mappingTarget, + }) { + return _isConverterSubtype(source, mappingSource) && _isConverterSubtype(target, mappingTarget); + } + + bool _isConverterSubtype(DartType self, DartType other) { + // Same type. + if (self == other) return true; + + // Other must be subtype of self. + // + // When [self] is Object, it is always success. + return self.element?.library?.typeSystem.leastUpperBound(self, other) == self; + } } diff --git a/packages/auto_mappr/lib/src/models/type_mapping.dart b/packages/auto_mappr/lib/src/models/type_mapping.dart index ce8edae6..180859b6 100644 --- a/packages/auto_mappr/lib/src/models/type_mapping.dart +++ b/packages/auto_mappr/lib/src/models/type_mapping.dart @@ -11,8 +11,8 @@ import 'package:equatable/equatable.dart'; class TypeMapping extends Equatable { final InterfaceType source; final InterfaceType target; - final List<FieldMapping>? fieldMappings; - final List<TypeConverter>? converters; + final List<FieldMapping> fieldMappings; + final List<TypeConverter> typeConverters; final Expression? whenSourceIsNullExpression; final String? constructor; final bool? ignoreFieldNull; @@ -25,7 +25,7 @@ class TypeMapping extends Equatable { source, target, fieldMappings, - converters, + typeConverters, whenSourceIsNullExpression, constructor, ignoreFieldNull, @@ -36,8 +36,8 @@ class TypeMapping extends Equatable { required this.source, required this.target, required this.ignoreFieldNull, - this.fieldMappings, - this.converters, + this.fieldMappings = const [], + this.typeConverters = const [], this.whenSourceIsNullExpression, this.constructor, }); @@ -59,11 +59,11 @@ class TypeMapping extends Equatable { return whenSourceIsNullExpression != null; } - bool hasFieldMapping(String field) => fieldMappings?.any((x) => x.field == field) ?? false; + bool hasFieldMapping(String field) => fieldMappings.any((x) => x.field == field); - FieldMapping? getFieldMapping(String field) => fieldMappings?.firstWhereOrNull((x) => x.field == field); + FieldMapping? getFieldMapping(String field) => fieldMappings.firstWhereOrNull((x) => x.field == field); - FieldMapping? tryGetFieldMapping(String field) => fieldMappings?.firstWhereOrNull((x) => x.field == field); + FieldMapping? tryGetFieldMapping(String field) => fieldMappings.firstWhereOrNull((x) => x.field == field); bool fieldShouldBeIgnored(String field) => hasFieldMapping(field) && (getFieldMapping(field)?.ignore ?? false); diff --git a/packages/auto_mappr/test/integration/fixture/type_converters.dart b/packages/auto_mappr/test/integration/fixture/type_converters.dart new file mode 100644 index 00000000..3b893270 --- /dev/null +++ b/packages/auto_mappr/test/integration/fixture/type_converters.dart @@ -0,0 +1,163 @@ +// ignore_for_file: prefer-named-boolean-parameters, avoid_positional_boolean_parameters + +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; +import 'package:equatable/equatable.dart'; + +import 'type_converters.auto_mappr.dart'; +import 'type_converters/module_alpha.dart'; + +@AutoMappr( + [ + MapType<PrimitivesDto, Primitives>( + converters: [TypeConverter<Object, String>(Mappr.objectToString)], + ), + MapType<NormalFieldDto, NormalField>( + converters: [TypeConverter<int, Value<int>>(Mappr.intToValueInt)], + ), + MapType<InListDto, InList>(), + MapType<InMapDto, InMap>(), + MapType<IncludesDto, Includes>(), + ], + converters: [ + TypeConverter<String, Value<String>>(Mappr.stringToValueString), + TypeConverter<Object, Value<Object>>(Mappr.objectToValueObject2), + ], + includes: [MapprAlpha()], +) +class Mappr extends $Mappr { + const Mappr(); + + static String objectToString<T extends Object>(T source) { + return '--- $source ---'; + } + + static Value<T> objectToValueObject<T extends Object>(T source) { + return Value<T>(source); + } + + static Value<Object> objectToValueObject2(Object source) { + if (source is int) { + return Value<int>(source); + } + + return Value(source); + } + + static Value<int> intToValueInt(int source) { + return Value(source); + } + + static Value<String> stringToValueString(String source) { + return Value(source); + } +} + +// Primitives. + +class PrimitivesDto { + final int alpha; + final bool beta; + + const PrimitivesDto({required this.alpha, required this.beta}); +} + +class Primitives with EquatableMixin { + final String alpha; + final String beta; + + @override + List<Object?> get props => [alpha, beta]; + + const Primitives(this.alpha, this.beta); +} + +// Fields. + +class NormalFieldDto { + final int xInt; + final String xString; + final bool normalBool; + + const NormalFieldDto({required this.xInt, required this.xString, required this.normalBool}); +} + +class NormalField with EquatableMixin { + final Value<int> xInt; + final Value<String> xString; + final bool normalBool; + + @override + List<Object?> get props => [xInt, xString, normalBool]; + + const NormalField(this.xInt, this.xString, this.normalBool); +} + +// In list. + +class InListDto { + final List<int> xInt; + final String xString; + final bool normalBool; + + const InListDto({required this.xInt, required this.xString, required this.normalBool}); +} + +class InList with EquatableMixin { + final List<Value<int>> xInt; + final Value<String> xString; + final bool normalBool; + + @override + List<Object?> get props => [xInt, xString, normalBool]; + + const InList(this.xInt, this.xString, this.normalBool); +} + +// In map. + +class InMapDto { + final Map<String, int> alpha; + final Map<String, int> beta; + final Map<String, int> gama; + + const InMapDto({required this.alpha, required this.beta, required this.gama}); +} + +class InMap with EquatableMixin { + final Map<Value<String>, int> alpha; + final Map<String, Value<int>> beta; + final Map<Value<String>, Value<int>> gama; + + @override + List<Object?> get props => [alpha, beta, gama]; + + const InMap(this.alpha, this.beta, this.gama); +} + +// Includes. + +class IncludesDto { + final int alpha; + + const IncludesDto({required this.alpha}); +} + +class Includes with EquatableMixin { + final bool alpha; + + @override + List<Object?> get props => [alpha]; + + const Includes(this.alpha); +} + +// Box + +class Value<T> with EquatableMixin { + final T value; + + @override + List<Object?> get props => [value]; + + const Value(this.value); +} diff --git a/packages/auto_mappr/test/integration/fixture/type_converters/module_alpha.dart b/packages/auto_mappr/test/integration/fixture/type_converters/module_alpha.dart new file mode 100644 index 00000000..31a52d59 --- /dev/null +++ b/packages/auto_mappr/test/integration/fixture/type_converters/module_alpha.dart @@ -0,0 +1,12 @@ +import 'package:auto_mappr_annotation/auto_mappr_annotation.dart'; + +import 'module_alpha.auto_mappr.dart'; + +@AutoMappr([], converters: [TypeConverter<int, bool>(MapprAlpha.intToBool)]) +class MapprAlpha extends $MapprAlpha { + const MapprAlpha(); + + static bool intToBool(int source) { + return source == 1; + } +} diff --git a/packages/auto_mappr/test/integration/type_converters_test.dart b/packages/auto_mappr/test/integration/type_converters_test.dart new file mode 100644 index 00000000..c4f3725c --- /dev/null +++ b/packages/auto_mappr/test/integration/type_converters_test.dart @@ -0,0 +1,75 @@ +import 'package:test/test.dart'; + +import 'fixture/type_converters.dart' as fixture; + +void main() { + late final fixture.Mappr mappr; + + setUpAll(() { + mappr = const fixture.Mappr(); + }); + + test('primitives', () { + const dto = fixture.PrimitivesDto(alpha: 123456, beta: false); + final converted = mappr.convert<fixture.PrimitivesDto, fixture.Primitives>(dto); + + expect(converted, equals(const fixture.Primitives('--- 123456 ---', '--- false ---'))); + }); + + test('fields', () { + const dto = fixture.NormalFieldDto(xInt: 5, xString: 'Command', normalBool: true); + final converted = mappr.convert<fixture.NormalFieldDto, fixture.NormalField>(dto); + + expect(converted, equals(const fixture.NormalField(fixture.Value<int>(5), fixture.Value('Command'), true))); + }); + + test('list', () { + const dto = fixture.InListDto(xInt: [789, 5, 1], xString: 'Dunno', normalBool: false); + final converted = mappr.convert<fixture.InListDto, fixture.InList>(dto); + + expect( + converted, + equals( + const fixture.InList( + [fixture.Value<int>(789), fixture.Value<int>(5), fixture.Value<int>(1)], + fixture.Value('Dunno'), + false, + ), + ), + ); + }); + + test('map', () { + const dto = fixture.InMapDto( + alpha: {'aaa': 123, 'bbb': 456}, + beta: {'ccc': 789, 'ddd': 741}, + gama: {'eee': 852, 'fff': 963}, + ); + final converted = mappr.convert<fixture.InMapDto, fixture.InMap>(dto); + + expect( + converted, + equals( + fixture.InMap( + {const fixture.Value('aaa'): 123, const fixture.Value('bbb'): 456}, + {'ccc': const fixture.Value(789), 'ddd': const fixture.Value(741)}, + {const fixture.Value('eee'): const fixture.Value(852), const fixture.Value('fff'): const fixture.Value(963)}, + ), + ), + ); + }); + + test('includes', () { + const dto = fixture.IncludesDto(alpha: 1); + final converted = mappr.convert<fixture.IncludesDto, fixture.Includes>(dto); + + expect(converted, equals(const fixture.Includes(true))); + }); + + test('includes 2', () { + const dto = fixture.IncludesDto(alpha: 2); + final converted = mappr.convert<fixture.IncludesDto, fixture.Includes>(dto); + + expect(converted, equals(const fixture.Includes(false))); + }); +} diff --git a/packages/auto_mappr_annotation/lib/auto_mappr_annotation.dart b/packages/auto_mappr_annotation/lib/auto_mappr_annotation.dart index 22784c00..28ba0560 100644 --- a/packages/auto_mappr_annotation/lib/auto_mappr_annotation.dart +++ b/packages/auto_mappr_annotation/lib/auto_mappr_annotation.dart @@ -7,3 +7,4 @@ export 'src/field.dart'; export 'src/iterable_nullable_extension.dart'; export 'src/map_extension.dart'; export 'src/map_type.dart'; +export 'src/type_converter.dart'; From cdeb43698df64e6caaf0854086795f4a9b1d6498 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 11 Sep 2023 13:37:14 +0200 Subject: [PATCH 32/48] Update README priority --- packages/auto_mappr/README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/auto_mappr/README.md b/packages/auto_mappr/README.md index a68d6902..f61ba4a0 100644 --- a/packages/auto_mappr/README.md +++ b/packages/auto_mappr/README.md @@ -650,7 +650,13 @@ there are `TypeConverter`s that help you with that. Boxing, `String` to `DateTime`, and stuff like that, `TypeConverter`s are your friend. Note since type converters are only used internally, you cannot in any way use them using the `.convert()` method. -Note that global type converters are also "absorbed" when including a module. + +Global type converters are also "absorbed" from included modules. +To make the priority crystal clear: + +1. (local) type converters from `MapType`, in order +1. (global) type converters from `AutoMappr`, in order +1. (global included) type converters from `included` modules, in order Use `MapType` for most of the things. Use `TypeConverter` only for cases that cannot be solve otherwise. @@ -686,7 +692,7 @@ note that you have to either return the correct type with correct type parameter or initialize it inside correctly. It cannot be cast successfully otherwise. Therefore if you need a method that converts `"any"` to `Value("any")`, -and to make it work of `int` and `String`, +and to make it work for `int` and `String`, it must look like one of these: ```dart From aa56926c4afa09e61190d13eac370cf413cb81e7 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 11 Sep 2023 13:39:02 +0200 Subject: [PATCH 33/48] Bump version to beta2 --- packages/auto_mappr/CHANGELOG.md | 2 +- packages/auto_mappr/pubspec.yaml | 4 ++-- packages/auto_mappr_annotation/CHANGELOG.md | 2 +- packages/auto_mappr_annotation/pubspec.yaml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/auto_mappr/CHANGELOG.md b/packages/auto_mappr/CHANGELOG.md index ffb69485..dadb50e1 100644 --- a/packages/auto_mappr/CHANGELOG.md +++ b/packages/auto_mappr/CHANGELOG.md @@ -1,6 +1,6 @@ [//]: # (## Unreleased) -## Unreleased +## 2.0.0-beta2 - Add type converters, use `converters` on `AutoMappr` or `MapType`. [#119](https://github.com/netglade/auto_mappr/pull/119) ## 2.0.0-beta1 diff --git a/packages/auto_mappr/pubspec.yaml b/packages/auto_mappr/pubspec.yaml index 7c38a8ec..e7a20e1f 100644 --- a/packages/auto_mappr/pubspec.yaml +++ b/packages/auto_mappr/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr description: Code generation for mapping between different objects with ease. -version: 2.0.0-beta1 +version: 2.0.0-beta2 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues screenshots: @@ -13,7 +13,7 @@ environment: dependencies: # TODO: Support analyzer same way as json_serializable https://github.com/google/json_serializable.dart/pull/1333 analyzer: ">=5.4.0 <7.0.0" - auto_mappr_annotation: ^2.0.0-beta1 + auto_mappr_annotation: ^2.0.0-beta2 build: ^2.3.1 built_collection: ^5.1.1 code_builder: ^4.4.0 diff --git a/packages/auto_mappr_annotation/CHANGELOG.md b/packages/auto_mappr_annotation/CHANGELOG.md index ca1f930f..0f2ce292 100644 --- a/packages/auto_mappr_annotation/CHANGELOG.md +++ b/packages/auto_mappr_annotation/CHANGELOG.md @@ -1,6 +1,6 @@ [//]: # (## Unreleased) -## Unreleased +## 2.0.0-beta2 - Add type converters, use `converters` on `AutoMappr` or `MapType`. [#119](https://github.com/netglade/auto_mappr/pull/119) ## 2.0.0-beta1 diff --git a/packages/auto_mappr_annotation/pubspec.yaml b/packages/auto_mappr_annotation/pubspec.yaml index f30d5f06..b31761a6 100644 --- a/packages/auto_mappr_annotation/pubspec.yaml +++ b/packages/auto_mappr_annotation/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr_annotation description: Annotations for the auto_mappr code-generator of mapping between objects with ease. -version: 2.0.0-beta1 +version: 2.0.0-beta2 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues From f3a121be2e24738519770fb203012a63b4197d94 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 11 Sep 2023 14:32:53 +0200 Subject: [PATCH 34/48] Update lints --- examples/drift/lib/mappr.auto_mappr.dart | 2 +- examples/example/lib/enum.auto_mappr.dart | 2 +- .../example/lib/equatable.auto_mappr.dart | 2 +- examples/example/lib/nested.auto_mappr.dart | 2 +- examples/example/lib/nullable.auto_mappr.dart | 2 +- examples/example/lib/rename.auto_mappr.dart | 2 +- .../lib/freezed_example.auto_mappr.dart | 2 +- examples/injectable/lib/mappr.auto_mappr.dart | 2 +- .../lib/serializable.auto_mappr.dart | 2 +- .../fixture/json_serializable.auto_mappr.dart | 2 +- .../example/lib/mappr.auto_mappr.dart | 22 +++++++++---------- .../lib/src/builder/auto_mappr_builder.dart | 3 ++- 12 files changed, 23 insertions(+), 22 deletions(-) diff --git a/examples/drift/lib/mappr.auto_mappr.dart b/examples/drift/lib/mappr.auto_mappr.dart index d7a8b69e..a31ec4b5 100644 --- a/examples/drift/lib/mappr.auto_mappr.dart +++ b/examples/drift/lib/mappr.auto_mappr.dart @@ -4,7 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: type=lint +// ignore_for_file: type=lint, unnecessary_cast, unused_local_variable // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; diff --git a/examples/example/lib/enum.auto_mappr.dart b/examples/example/lib/enum.auto_mappr.dart index d0f030da..c1c90492 100644 --- a/examples/example/lib/enum.auto_mappr.dart +++ b/examples/example/lib/enum.auto_mappr.dart @@ -4,7 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: type=lint +// ignore_for_file: type=lint, unnecessary_cast, unused_local_variable // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; diff --git a/examples/example/lib/equatable.auto_mappr.dart b/examples/example/lib/equatable.auto_mappr.dart index 7a3c2591..018399df 100644 --- a/examples/example/lib/equatable.auto_mappr.dart +++ b/examples/example/lib/equatable.auto_mappr.dart @@ -4,7 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: type=lint +// ignore_for_file: type=lint, unnecessary_cast, unused_local_variable // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; diff --git a/examples/example/lib/nested.auto_mappr.dart b/examples/example/lib/nested.auto_mappr.dart index 97db1d3b..7bc1de54 100644 --- a/examples/example/lib/nested.auto_mappr.dart +++ b/examples/example/lib/nested.auto_mappr.dart @@ -4,7 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: type=lint +// ignore_for_file: type=lint, unnecessary_cast, unused_local_variable // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; diff --git a/examples/example/lib/nullable.auto_mappr.dart b/examples/example/lib/nullable.auto_mappr.dart index a66328f1..15855f48 100644 --- a/examples/example/lib/nullable.auto_mappr.dart +++ b/examples/example/lib/nullable.auto_mappr.dart @@ -4,7 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: type=lint +// ignore_for_file: type=lint, unnecessary_cast, unused_local_variable // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i2; diff --git a/examples/example/lib/rename.auto_mappr.dart b/examples/example/lib/rename.auto_mappr.dart index 0926d97b..c1c49985 100644 --- a/examples/example/lib/rename.auto_mappr.dart +++ b/examples/example/lib/rename.auto_mappr.dart @@ -4,7 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: type=lint +// ignore_for_file: type=lint, unnecessary_cast, unused_local_variable // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; diff --git a/examples/freezed/lib/freezed_example.auto_mappr.dart b/examples/freezed/lib/freezed_example.auto_mappr.dart index e1999c0d..569c0bd9 100644 --- a/examples/freezed/lib/freezed_example.auto_mappr.dart +++ b/examples/freezed/lib/freezed_example.auto_mappr.dart @@ -4,7 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: type=lint +// ignore_for_file: type=lint, unnecessary_cast, unused_local_variable // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; diff --git a/examples/injectable/lib/mappr.auto_mappr.dart b/examples/injectable/lib/mappr.auto_mappr.dart index 6e9123c3..eac09338 100644 --- a/examples/injectable/lib/mappr.auto_mappr.dart +++ b/examples/injectable/lib/mappr.auto_mappr.dart @@ -4,7 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: type=lint +// ignore_for_file: type=lint, unnecessary_cast, unused_local_variable // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; diff --git a/examples/json_serializable/lib/serializable.auto_mappr.dart b/examples/json_serializable/lib/serializable.auto_mappr.dart index 35b76e2b..9d58f240 100644 --- a/examples/json_serializable/lib/serializable.auto_mappr.dart +++ b/examples/json_serializable/lib/serializable.auto_mappr.dart @@ -4,7 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: type=lint +// ignore_for_file: type=lint, unnecessary_cast, unused_local_variable // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; diff --git a/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart b/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart index 91310fc8..9ebc5566 100644 --- a/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart +++ b/examples/json_serializable/test/fixture/json_serializable.auto_mappr.dart @@ -4,7 +4,7 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: type=lint +// ignore_for_file: type=lint, unnecessary_cast, unused_local_variable // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; diff --git a/packages/auto_mappr/example/lib/mappr.auto_mappr.dart b/packages/auto_mappr/example/lib/mappr.auto_mappr.dart index 6ea88f78..ab771404 100644 --- a/packages/auto_mappr/example/lib/mappr.auto_mappr.dart +++ b/packages/auto_mappr/example/lib/mappr.auto_mappr.dart @@ -4,14 +4,14 @@ // AutoMapprGenerator // ************************************************************************** -// ignore_for_file: type=lint +// ignore_for_file: type=lint, unnecessary_cast, unused_local_variable // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_mappr_annotation/auto_mappr_annotation.dart' as _i1; import 'mappr.dart' as _i2; -/// {@template package:auto_mappr_example/mappr.dart} +/// {@template asset:auto_mappr/example/lib/mappr.dart} /// Available mappings: /// - `UserDto` → `User`. /// {@endtemplate} @@ -22,7 +22,7 @@ class $Mappr implements _i1.AutoMapprInterface { List<_i1.AutoMapprInterface> get _delegates => const []; /// {@macro AutoMapprInterface:canConvert} - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override bool canConvert<SOURCE, TARGET>({bool recursive = true}) { final sourceTypeOf = _typeOf<SOURCE>(); @@ -44,7 +44,7 @@ class $Mappr implements _i1.AutoMapprInterface { } /// {@macro AutoMapprInterface:convert} - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override TARGET convert<SOURCE, TARGET>(SOURCE? model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -60,7 +60,7 @@ class $Mappr implements _i1.AutoMapprInterface { } /// {@macro AutoMapprInterface:tryConvert} - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override TARGET? tryConvert<SOURCE, TARGET>(SOURCE? model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -79,7 +79,7 @@ class $Mappr implements _i1.AutoMapprInterface { } /// {@macro AutoMapprInterface:convertIterable} - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override Iterable<TARGET> convertIterable<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -98,7 +98,7 @@ class $Mappr implements _i1.AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override Iterable<TARGET?> tryConvertIterable<SOURCE, TARGET>( Iterable<SOURCE?> model) { @@ -115,7 +115,7 @@ class $Mappr implements _i1.AutoMapprInterface { } /// {@macro AutoMapprInterface:convertList} - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override List<TARGET> convertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -134,7 +134,7 @@ class $Mappr implements _i1.AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override List<TARGET?> tryConvertList<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -150,7 +150,7 @@ class $Mappr implements _i1.AutoMapprInterface { } /// {@macro AutoMapprInterface:convertSet} - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override Set<TARGET> convertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { @@ -169,7 +169,7 @@ class $Mappr implements _i1.AutoMapprInterface { /// /// When an item in the source iterable is null, uses `whenSourceIsNull` if defined or null /// - /// {@macro package:auto_mappr_example/mappr.dart} + /// {@macro asset:auto_mappr/example/lib/mappr.dart} @override Set<TARGET?> tryConvertSet<SOURCE, TARGET>(Iterable<SOURCE?> model) { if (canConvert<SOURCE, TARGET>(recursive: false)) { diff --git a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart index 449d5f45..892ce834 100644 --- a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart +++ b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart @@ -15,8 +15,9 @@ class AutoMapprBuilder { static const List<String> fileIgnores = [ // ignore everything - // ignore: unnecessary-trailing-comma 'type=lint', + 'unused_local_variable', + 'unnecessary_cast', ]; const AutoMapprBuilder({ From 9839ca5ce7034eff617e5f84267a6430b7ce026b Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Mon, 11 Sep 2023 14:59:48 +0200 Subject: [PATCH 35/48] Fix review --- .../assignments/nested_object_mixin.dart | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart b/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart index 82e73190..3f7f984b 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/nested_object_mixin.dart @@ -12,7 +12,7 @@ import 'package:source_gen/source_gen.dart'; mixin NestedObjectMixin on AssignmentBuilderBase { /// Assigns nested object as either: /// - default value - /// - call to already generated mapping between two typ`es + /// - call to already generated mapping between two types /// /// If [convertMethodArgument] is null, uses a tear off call instead. Expression assignNestedObject({ @@ -48,27 +48,6 @@ mixin NestedObjectMixin on AssignmentBuilderBase { return typeConvertersBuilder.buildAssignment(); } - // if (assignment.typeConverters - // .firstWhereOrNull((converter) => converter.canBeUsed(mappingSource: source, mappingTarget: target)) - // case final converter?) { - // // Call. - // if (convertMethodArgument != null) { - // final targetRefer = EmitterHelper.current.typeRefer(type: target); - - // return EmitterHelper.current - // .refer(converter.converter.referCallString, converter.converter.library.identifier) - // .call([convertMethodArgument]).asA(targetRefer); - // } - - // final sourceEmitted = EmitterHelper.current.typeReferEmitted(type: source); - // final targetEmitted = EmitterHelper.current.typeReferEmitted(type: target); - - // // Tear-off. - // return EmitterHelper.current - // .refer(converter.converter.referCallString, converter.converter.library.identifier) - // .asA(refer('$targetEmitted Function($sourceEmitted)')); - // } - // Unknown mapping. if (nestedMapping == null) { final sourceName = assignment.sourceField?.getDisplayString(withNullability: true); From 5b2cd3ac29b5d773cf5de7a4665043ff482d6e99 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Thu, 14 Sep 2023 09:09:08 +0200 Subject: [PATCH 36/48] Update README.md --- packages/auto_mappr/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/auto_mappr/README.md b/packages/auto_mappr/README.md index f61ba4a0..841adaa0 100644 --- a/packages/auto_mappr/README.md +++ b/packages/auto_mappr/README.md @@ -49,6 +49,8 @@ Heavily inspired by [C# AutoMapper][auto_mapper_net_link]. - [Generics](#generics) - [Library import aliases](#library-import-aliases) - [Modules](#modules) + - [Including](#including) + - [Delegating](#delegating) - [Reverse mapping](#reverse-mapping) - [Records](#records) - [Works with `equatable`](#works-with-equatable) From 6d100ab0524eaf2d2021aee544d8ec740226fb15 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 15 Sep 2023 14:22:41 +0200 Subject: [PATCH 37/48] Bump versions to 2.0.0 --- examples/drift/pubspec.yaml | 4 ++-- examples/example/pubspec.yaml | 4 ++-- examples/freezed/pubspec.yaml | 4 ++-- examples/injectable/pubspec.yaml | 4 ++-- examples/json_serializable/pubspec.yaml | 4 ++-- packages/auto_mappr/CHANGELOG.md | 7 +++++++ packages/auto_mappr/example/pubspec.yaml | 4 ++-- packages/auto_mappr/pubspec.yaml | 4 ++-- packages/auto_mappr_annotation/CHANGELOG.md | 5 +++++ packages/auto_mappr_annotation/pubspec.yaml | 2 +- 10 files changed, 27 insertions(+), 15 deletions(-) diff --git a/examples/drift/pubspec.yaml b/examples/drift/pubspec.yaml index 10ff61c0..ffa45dd5 100644 --- a/examples/drift/pubspec.yaml +++ b/examples/drift/pubspec.yaml @@ -7,12 +7,12 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^1.2.0 + auto_mappr_annotation: ^2.0.0 drift: ^2.7.0 equatable: ^2.0.5 dev_dependencies: - auto_mappr: ^1.6.0 + auto_mappr: ^2.0.0 build_runner: ^2.0.0 drift_dev: ^2.7.0 netglade_analysis: ^4.2.0 diff --git a/examples/example/pubspec.yaml b/examples/example/pubspec.yaml index d4a1ae55..53669132 100644 --- a/examples/example/pubspec.yaml +++ b/examples/example/pubspec.yaml @@ -7,11 +7,11 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^1.2.0 + auto_mappr_annotation: ^2.0.0 equatable: ^2.0.5 dev_dependencies: - auto_mappr: ^1.3.0 + auto_mappr: ^2.0.0 build_runner: ^2.0.0 netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/examples/freezed/pubspec.yaml b/examples/freezed/pubspec.yaml index 2faceeac..35833e70 100644 --- a/examples/freezed/pubspec.yaml +++ b/examples/freezed/pubspec.yaml @@ -7,12 +7,12 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^1.2.0 + auto_mappr_annotation: ^2.0.0 equatable: ^2.0.5 freezed_annotation: ^2.2.0 dev_dependencies: - auto_mappr: ^1.6.0 + auto_mappr: ^2.0.0 build_runner: ^2.0.0 freezed: ^2.3.2 netglade_analysis: ^4.2.0 diff --git a/examples/injectable/pubspec.yaml b/examples/injectable/pubspec.yaml index b6963415..60675b0e 100644 --- a/examples/injectable/pubspec.yaml +++ b/examples/injectable/pubspec.yaml @@ -7,13 +7,13 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^1.2.0 + auto_mappr_annotation: ^2.0.0 equatable: ^2.0.5 get_it: ^7.3.0 injectable: ^2.1.1 dev_dependencies: - auto_mappr: ^1.6.0 + auto_mappr: ^2.0.0 build_runner: ^2.0.0 injectable_generator: ^2.1.5 netglade_analysis: ^4.2.0 diff --git a/examples/json_serializable/pubspec.yaml b/examples/json_serializable/pubspec.yaml index de12a25c..15489698 100644 --- a/examples/json_serializable/pubspec.yaml +++ b/examples/json_serializable/pubspec.yaml @@ -7,11 +7,11 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^1.2.0 + auto_mappr_annotation: ^2.0.0 json_annotation: ^4.8.1 dev_dependencies: - auto_mappr: ^1.6.0 + auto_mappr: ^2.0.0 build_runner: ^2.0.0 json_serializable: ^6.6.1 netglade_analysis: ^4.2.0 diff --git a/packages/auto_mappr/CHANGELOG.md b/packages/auto_mappr/CHANGELOG.md index dadb50e1..dc19e98b 100644 --- a/packages/auto_mappr/CHANGELOG.md +++ b/packages/auto_mappr/CHANGELOG.md @@ -1,5 +1,12 @@ [//]: # (## Unreleased) +## 2.0.0 +- **Breaking**: Allow "absorbing" modules using `includes` on `@AutoMappr`. Previous `modules` is now `delegates`. [#117](https://github.com/netglade/auto_mappr/pull/117) +- **Breaking**: Remove shared AutoMappr builder that used PartBuilder, now `.auto_mappr.dart` is generated using LibraryBuilder. [#117](https://github.com/netglade/auto_mappr/pull/117) +- Add type converters, use `converters` on `AutoMappr` or `MapType`. [#119](https://github.com/netglade/auto_mappr/pull/119) +- Add a `reverse` option on `MapType`, which includes the reverse mapping. [#115](https://github.com/netglade/auto_mappr/pull/115) +- Add a support for Dart 3 and Records feature. [#116](https://github.com/netglade/auto_mappr/pull/116) + ## 2.0.0-beta2 - Add type converters, use `converters` on `AutoMappr` or `MapType`. [#119](https://github.com/netglade/auto_mappr/pull/119) diff --git a/packages/auto_mappr/example/pubspec.yaml b/packages/auto_mappr/example/pubspec.yaml index 3c5d8dd3..b4ec6ae6 100644 --- a/packages/auto_mappr/example/pubspec.yaml +++ b/packages/auto_mappr/example/pubspec.yaml @@ -7,11 +7,11 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^1.1.0 + auto_mappr_annotation: ^2.0.0 equatable: ^2.0.5 dev_dependencies: - auto_mappr: ^1.3.0 + auto_mappr: ^2.0.0 build_runner: ^2.0.0 netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/packages/auto_mappr/pubspec.yaml b/packages/auto_mappr/pubspec.yaml index e7a20e1f..c0e8cf32 100644 --- a/packages/auto_mappr/pubspec.yaml +++ b/packages/auto_mappr/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr description: Code generation for mapping between different objects with ease. -version: 2.0.0-beta2 +version: 2.0.0 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues screenshots: @@ -13,7 +13,7 @@ environment: dependencies: # TODO: Support analyzer same way as json_serializable https://github.com/google/json_serializable.dart/pull/1333 analyzer: ">=5.4.0 <7.0.0" - auto_mappr_annotation: ^2.0.0-beta2 + auto_mappr_annotation: ^2.0.0 build: ^2.3.1 built_collection: ^5.1.1 code_builder: ^4.4.0 diff --git a/packages/auto_mappr_annotation/CHANGELOG.md b/packages/auto_mappr_annotation/CHANGELOG.md index 0f2ce292..c9cff628 100644 --- a/packages/auto_mappr_annotation/CHANGELOG.md +++ b/packages/auto_mappr_annotation/CHANGELOG.md @@ -1,5 +1,10 @@ [//]: # (## Unreleased) +## 2.0.0 +- Adhere to netglade_analysis 4.0.0. [#111](https://github.com/netglade/auto_mappr/pull/111) +- Add `reverse` option to `MapType`. [#115](https://github.com/netglade/auto_mappr/pull/115) +- Add type converters, use `converters` on `AutoMappr` or `MapType`. [#119](https://github.com/netglade/auto_mappr/pull/119) + ## 2.0.0-beta2 - Add type converters, use `converters` on `AutoMappr` or `MapType`. [#119](https://github.com/netglade/auto_mappr/pull/119) diff --git a/packages/auto_mappr_annotation/pubspec.yaml b/packages/auto_mappr_annotation/pubspec.yaml index b31761a6..838c72da 100644 --- a/packages/auto_mappr_annotation/pubspec.yaml +++ b/packages/auto_mappr_annotation/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr_annotation description: Annotations for the auto_mappr code-generator of mapping between objects with ease. -version: 2.0.0-beta2 +version: 2.0.0 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues From 87470d73635c7ceacda52e84bbf446e7ffc47c82 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 15 Sep 2023 14:31:45 +0200 Subject: [PATCH 38/48] Add melos bootstrap to ci --- .github/workflows/ci.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fc5dadd6..2ffadb05 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,6 +15,9 @@ jobs: - uses: dart-lang/setup-dart@v1 - uses: bluefireteam/melos-action@v2 + - name: Melos bootstrap + run: melos bootstrap + - name: Generate AutoMappr files run: melos run gen:build-all From c09856b9b909a5ef3f76a0cd909ffdbd57683bd3 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 15 Sep 2023 14:40:40 +0200 Subject: [PATCH 39/48] Update example package --- .github/workflows/ci.yaml | 3 --- packages/auto_mappr/example/pubspec.yaml | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2ffadb05..fc5dadd6 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,9 +15,6 @@ jobs: - uses: dart-lang/setup-dart@v1 - uses: bluefireteam/melos-action@v2 - - name: Melos bootstrap - run: melos bootstrap - - name: Generate AutoMappr files run: melos run gen:build-all diff --git a/packages/auto_mappr/example/pubspec.yaml b/packages/auto_mappr/example/pubspec.yaml index b4ec6ae6..1609c240 100644 --- a/packages/auto_mappr/example/pubspec.yaml +++ b/packages/auto_mappr/example/pubspec.yaml @@ -11,7 +11,8 @@ dependencies: equatable: ^2.0.5 dev_dependencies: - auto_mappr: ^2.0.0 + auto_mappr: + path: ../ build_runner: ^2.0.0 netglade_analysis: ^4.2.0 test: ^1.16.0 From 9827d4863ed6550500c9c70ad15a9972c20330a1 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 15 Sep 2023 14:47:01 +0200 Subject: [PATCH 40/48] WTF this should work --- packages/auto_mappr/example/pubspec.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/auto_mappr/example/pubspec.yaml b/packages/auto_mappr/example/pubspec.yaml index 1609c240..b4ec6ae6 100644 --- a/packages/auto_mappr/example/pubspec.yaml +++ b/packages/auto_mappr/example/pubspec.yaml @@ -11,8 +11,7 @@ dependencies: equatable: ^2.0.5 dev_dependencies: - auto_mappr: - path: ../ + auto_mappr: ^2.0.0 build_runner: ^2.0.0 netglade_analysis: ^4.2.0 test: ^1.16.0 From 3d868d530aadcab7423f894a16a130a8fbcc5cdf Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 15 Sep 2023 16:16:47 +0200 Subject: [PATCH 41/48] Use range in annotations --- .github/dependabot.yaml | 5 +++++ melos.yaml | 4 ---- .../src/builder/assignments/record_assignment_builder.dart | 2 -- packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart | 1 - packages/auto_mappr_annotation/example/pubspec.yaml | 3 +-- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 746b52cb..0f104c28 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -46,6 +46,11 @@ updates: directory: "/examples/freezed" schedule: interval: "weekly" + + - package-ecosystem: "pub" + directory: "/examples/injectable" + schedule: + interval: "weekly" - package-ecosystem: "pub" directory: "/examples/json_serializable" diff --git a/melos.yaml b/melos.yaml index db661e5d..b01c7a06 100644 --- a/melos.yaml +++ b/melos.yaml @@ -5,10 +5,6 @@ packages: - packages/*/example - examples/* -command: - bootstrap: - usePubspecOverrides: true - scripts: # ANALYZING diff --git a/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart b/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart index 064111f1..10484e6c 100644 --- a/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart +++ b/packages/auto_mappr/lib/src/builder/assignments/record_assignment_builder.dart @@ -1,5 +1,3 @@ -// ignore_for_file: avoid-shadowing - import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart' as type; import 'package:auto_mappr/src/builder/assignments/assignment_builder_base.dart'; diff --git a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart index 892ce834..56c58d22 100644 --- a/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart +++ b/packages/auto_mappr/lib/src/builder/auto_mappr_builder.dart @@ -115,7 +115,6 @@ class AutoMapprBuilder { ).buildMethod(), // Generates nullable mapping method only when nullable method is used. - // ignore: avoid-shadowing for (final mapping in config.mappers.where(nullableMappings.contains)) MappingMethodBuilder(config, mapping: mapping, nullable: true).buildMethod(), ]; diff --git a/packages/auto_mappr_annotation/example/pubspec.yaml b/packages/auto_mappr_annotation/example/pubspec.yaml index 250c3f1c..8c4234cf 100644 --- a/packages/auto_mappr_annotation/example/pubspec.yaml +++ b/packages/auto_mappr_annotation/example/pubspec.yaml @@ -7,8 +7,7 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: - path: ../ + auto_mappr_annotation: ^2.0.0 dev_dependencies: build_runner: ^2.0.0 From eaa5f4ddfcbcd314c9df1d522dee29376e8a80c9 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 15 Sep 2023 16:22:23 +0200 Subject: [PATCH 42/48] Update --- packages/auto_mappr/example/pubspec.yaml | 2 +- packages/auto_mappr_annotation/example/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/auto_mappr/example/pubspec.yaml b/packages/auto_mappr/example/pubspec.yaml index b4ec6ae6..011f1001 100644 --- a/packages/auto_mappr/example/pubspec.yaml +++ b/packages/auto_mappr/example/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: none environment: - sdk: ">=2.18.7 <4.0.0" + sdk: ^3.0.0 dependencies: auto_mappr_annotation: ^2.0.0 diff --git a/packages/auto_mappr_annotation/example/pubspec.yaml b/packages/auto_mappr_annotation/example/pubspec.yaml index 8c4234cf..cba7aa45 100644 --- a/packages/auto_mappr_annotation/example/pubspec.yaml +++ b/packages/auto_mappr_annotation/example/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: none environment: - sdk: ">=2.18.7 <4.0.0" + sdk: ^3.0.0 dependencies: auto_mappr_annotation: ^2.0.0 From aa2b79b9d763a727ce22cee794a9187dc2266c0a Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 15 Sep 2023 16:23:47 +0200 Subject: [PATCH 43/48] Try ** --- melos.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/melos.yaml b/melos.yaml index b01c7a06..05541012 100644 --- a/melos.yaml +++ b/melos.yaml @@ -1,9 +1,8 @@ name: auto_mappr_workspace packages: - - packages/* - - packages/*/example - - examples/* + - packages/** + - examples/** scripts: # ANALYZING From 4739af6af8f7e7e95e830181dfac537aad5e30c3 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 15 Sep 2023 16:28:48 +0200 Subject: [PATCH 44/48] Update --- melos.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/melos.yaml b/melos.yaml index 05541012..d030bd96 100644 --- a/melos.yaml +++ b/melos.yaml @@ -1,8 +1,9 @@ name: auto_mappr_workspace packages: - - packages/** - - examples/** + - packages/* + - examples/* + - packages/*/example scripts: # ANALYZING From 99cade5dec4f045aaa8da25e3b4c947d0f0e9911 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 15 Sep 2023 23:25:44 +0200 Subject: [PATCH 45/48] Try minor bump --- examples/drift/pubspec.yaml | 4 ++-- examples/example/pubspec.yaml | 4 ++-- examples/freezed/pubspec.yaml | 4 ++-- examples/injectable/pubspec.yaml | 4 ++-- examples/json_serializable/pubspec.yaml | 4 ++-- melos.yaml | 2 +- packages/auto_mappr/example/pubspec.yaml | 4 ++-- packages/auto_mappr/pubspec.yaml | 4 ++-- packages/auto_mappr_annotation/example/pubspec.yaml | 2 +- packages/auto_mappr_annotation/pubspec.yaml | 2 +- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/examples/drift/pubspec.yaml b/examples/drift/pubspec.yaml index ffa45dd5..f2a08b85 100644 --- a/examples/drift/pubspec.yaml +++ b/examples/drift/pubspec.yaml @@ -7,12 +7,12 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^2.0.0 + auto_mappr_annotation: ^1.42.0 drift: ^2.7.0 equatable: ^2.0.5 dev_dependencies: - auto_mappr: ^2.0.0 + auto_mappr: ^1.42.0 build_runner: ^2.0.0 drift_dev: ^2.7.0 netglade_analysis: ^4.2.0 diff --git a/examples/example/pubspec.yaml b/examples/example/pubspec.yaml index 53669132..e1acf569 100644 --- a/examples/example/pubspec.yaml +++ b/examples/example/pubspec.yaml @@ -7,11 +7,11 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^2.0.0 + auto_mappr_annotation: ^1.42.0 equatable: ^2.0.5 dev_dependencies: - auto_mappr: ^2.0.0 + auto_mappr: ^1.42.0 build_runner: ^2.0.0 netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/examples/freezed/pubspec.yaml b/examples/freezed/pubspec.yaml index 35833e70..c549de64 100644 --- a/examples/freezed/pubspec.yaml +++ b/examples/freezed/pubspec.yaml @@ -7,12 +7,12 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^2.0.0 + auto_mappr_annotation: ^1.42.0 equatable: ^2.0.5 freezed_annotation: ^2.2.0 dev_dependencies: - auto_mappr: ^2.0.0 + auto_mappr: ^1.42.0 build_runner: ^2.0.0 freezed: ^2.3.2 netglade_analysis: ^4.2.0 diff --git a/examples/injectable/pubspec.yaml b/examples/injectable/pubspec.yaml index 60675b0e..1f242b2f 100644 --- a/examples/injectable/pubspec.yaml +++ b/examples/injectable/pubspec.yaml @@ -7,13 +7,13 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^2.0.0 + auto_mappr_annotation: ^1.42.0 equatable: ^2.0.5 get_it: ^7.3.0 injectable: ^2.1.1 dev_dependencies: - auto_mappr: ^2.0.0 + auto_mappr: ^1.42.0 build_runner: ^2.0.0 injectable_generator: ^2.1.5 netglade_analysis: ^4.2.0 diff --git a/examples/json_serializable/pubspec.yaml b/examples/json_serializable/pubspec.yaml index 15489698..6a173df2 100644 --- a/examples/json_serializable/pubspec.yaml +++ b/examples/json_serializable/pubspec.yaml @@ -7,11 +7,11 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^2.0.0 + auto_mappr_annotation: ^1.42.0 json_annotation: ^4.8.1 dev_dependencies: - auto_mappr: ^2.0.0 + auto_mappr: ^1.42.0 build_runner: ^2.0.0 json_serializable: ^6.6.1 netglade_analysis: ^4.2.0 diff --git a/melos.yaml b/melos.yaml index d030bd96..b01c7a06 100644 --- a/melos.yaml +++ b/melos.yaml @@ -2,8 +2,8 @@ name: auto_mappr_workspace packages: - packages/* - - examples/* - packages/*/example + - examples/* scripts: # ANALYZING diff --git a/packages/auto_mappr/example/pubspec.yaml b/packages/auto_mappr/example/pubspec.yaml index 011f1001..853a2edb 100644 --- a/packages/auto_mappr/example/pubspec.yaml +++ b/packages/auto_mappr/example/pubspec.yaml @@ -7,11 +7,11 @@ environment: sdk: ^3.0.0 dependencies: - auto_mappr_annotation: ^2.0.0 + auto_mappr_annotation: ^1.42.0 equatable: ^2.0.5 dev_dependencies: - auto_mappr: ^2.0.0 + auto_mappr: ^1.42.0 build_runner: ^2.0.0 netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/packages/auto_mappr/pubspec.yaml b/packages/auto_mappr/pubspec.yaml index c0e8cf32..6a5af540 100644 --- a/packages/auto_mappr/pubspec.yaml +++ b/packages/auto_mappr/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr description: Code generation for mapping between different objects with ease. -version: 2.0.0 +version: 1.42.0 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues screenshots: @@ -13,7 +13,7 @@ environment: dependencies: # TODO: Support analyzer same way as json_serializable https://github.com/google/json_serializable.dart/pull/1333 analyzer: ">=5.4.0 <7.0.0" - auto_mappr_annotation: ^2.0.0 + auto_mappr_annotation: ^1.42.0 build: ^2.3.1 built_collection: ^5.1.1 code_builder: ^4.4.0 diff --git a/packages/auto_mappr_annotation/example/pubspec.yaml b/packages/auto_mappr_annotation/example/pubspec.yaml index cba7aa45..500b8460 100644 --- a/packages/auto_mappr_annotation/example/pubspec.yaml +++ b/packages/auto_mappr_annotation/example/pubspec.yaml @@ -7,7 +7,7 @@ environment: sdk: ^3.0.0 dependencies: - auto_mappr_annotation: ^2.0.0 + auto_mappr_annotation: ^1.42.0 dev_dependencies: build_runner: ^2.0.0 diff --git a/packages/auto_mappr_annotation/pubspec.yaml b/packages/auto_mappr_annotation/pubspec.yaml index 838c72da..0b65cbef 100644 --- a/packages/auto_mappr_annotation/pubspec.yaml +++ b/packages/auto_mappr_annotation/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr_annotation description: Annotations for the auto_mappr code-generator of mapping between objects with ease. -version: 2.0.0 +version: 1.42.0 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues From 7c79cf16f22ddc4845a0ba0ee29f7ac94e35cd63 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 15 Sep 2023 23:33:34 +0200 Subject: [PATCH 46/48] Get bump major back --- examples/drift/pubspec.yaml | 4 ++-- examples/example/pubspec.yaml | 4 ++-- examples/freezed/pubspec.yaml | 4 ++-- examples/injectable/pubspec.yaml | 4 ++-- examples/json_serializable/pubspec.yaml | 4 ++-- packages/auto_mappr/example/pubspec.yaml | 4 ++-- packages/auto_mappr/pubspec.yaml | 4 ++-- packages/auto_mappr_annotation/example/pubspec.yaml | 2 +- packages/auto_mappr_annotation/pubspec.yaml | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/drift/pubspec.yaml b/examples/drift/pubspec.yaml index f2a08b85..ffa45dd5 100644 --- a/examples/drift/pubspec.yaml +++ b/examples/drift/pubspec.yaml @@ -7,12 +7,12 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^1.42.0 + auto_mappr_annotation: ^2.0.0 drift: ^2.7.0 equatable: ^2.0.5 dev_dependencies: - auto_mappr: ^1.42.0 + auto_mappr: ^2.0.0 build_runner: ^2.0.0 drift_dev: ^2.7.0 netglade_analysis: ^4.2.0 diff --git a/examples/example/pubspec.yaml b/examples/example/pubspec.yaml index e1acf569..53669132 100644 --- a/examples/example/pubspec.yaml +++ b/examples/example/pubspec.yaml @@ -7,11 +7,11 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^1.42.0 + auto_mappr_annotation: ^2.0.0 equatable: ^2.0.5 dev_dependencies: - auto_mappr: ^1.42.0 + auto_mappr: ^2.0.0 build_runner: ^2.0.0 netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/examples/freezed/pubspec.yaml b/examples/freezed/pubspec.yaml index c549de64..35833e70 100644 --- a/examples/freezed/pubspec.yaml +++ b/examples/freezed/pubspec.yaml @@ -7,12 +7,12 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^1.42.0 + auto_mappr_annotation: ^2.0.0 equatable: ^2.0.5 freezed_annotation: ^2.2.0 dev_dependencies: - auto_mappr: ^1.42.0 + auto_mappr: ^2.0.0 build_runner: ^2.0.0 freezed: ^2.3.2 netglade_analysis: ^4.2.0 diff --git a/examples/injectable/pubspec.yaml b/examples/injectable/pubspec.yaml index 1f242b2f..60675b0e 100644 --- a/examples/injectable/pubspec.yaml +++ b/examples/injectable/pubspec.yaml @@ -7,13 +7,13 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^1.42.0 + auto_mappr_annotation: ^2.0.0 equatable: ^2.0.5 get_it: ^7.3.0 injectable: ^2.1.1 dev_dependencies: - auto_mappr: ^1.42.0 + auto_mappr: ^2.0.0 build_runner: ^2.0.0 injectable_generator: ^2.1.5 netglade_analysis: ^4.2.0 diff --git a/examples/json_serializable/pubspec.yaml b/examples/json_serializable/pubspec.yaml index 6a173df2..15489698 100644 --- a/examples/json_serializable/pubspec.yaml +++ b/examples/json_serializable/pubspec.yaml @@ -7,11 +7,11 @@ environment: sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^1.42.0 + auto_mappr_annotation: ^2.0.0 json_annotation: ^4.8.1 dev_dependencies: - auto_mappr: ^1.42.0 + auto_mappr: ^2.0.0 build_runner: ^2.0.0 json_serializable: ^6.6.1 netglade_analysis: ^4.2.0 diff --git a/packages/auto_mappr/example/pubspec.yaml b/packages/auto_mappr/example/pubspec.yaml index 853a2edb..011f1001 100644 --- a/packages/auto_mappr/example/pubspec.yaml +++ b/packages/auto_mappr/example/pubspec.yaml @@ -7,11 +7,11 @@ environment: sdk: ^3.0.0 dependencies: - auto_mappr_annotation: ^1.42.0 + auto_mappr_annotation: ^2.0.0 equatable: ^2.0.5 dev_dependencies: - auto_mappr: ^1.42.0 + auto_mappr: ^2.0.0 build_runner: ^2.0.0 netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/packages/auto_mappr/pubspec.yaml b/packages/auto_mappr/pubspec.yaml index 6a5af540..c0e8cf32 100644 --- a/packages/auto_mappr/pubspec.yaml +++ b/packages/auto_mappr/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr description: Code generation for mapping between different objects with ease. -version: 1.42.0 +version: 2.0.0 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues screenshots: @@ -13,7 +13,7 @@ environment: dependencies: # TODO: Support analyzer same way as json_serializable https://github.com/google/json_serializable.dart/pull/1333 analyzer: ">=5.4.0 <7.0.0" - auto_mappr_annotation: ^1.42.0 + auto_mappr_annotation: ^2.0.0 build: ^2.3.1 built_collection: ^5.1.1 code_builder: ^4.4.0 diff --git a/packages/auto_mappr_annotation/example/pubspec.yaml b/packages/auto_mappr_annotation/example/pubspec.yaml index 500b8460..cba7aa45 100644 --- a/packages/auto_mappr_annotation/example/pubspec.yaml +++ b/packages/auto_mappr_annotation/example/pubspec.yaml @@ -7,7 +7,7 @@ environment: sdk: ^3.0.0 dependencies: - auto_mappr_annotation: ^1.42.0 + auto_mappr_annotation: ^2.0.0 dev_dependencies: build_runner: ^2.0.0 diff --git a/packages/auto_mappr_annotation/pubspec.yaml b/packages/auto_mappr_annotation/pubspec.yaml index 0b65cbef..838c72da 100644 --- a/packages/auto_mappr_annotation/pubspec.yaml +++ b/packages/auto_mappr_annotation/pubspec.yaml @@ -1,6 +1,6 @@ name: auto_mappr_annotation description: Annotations for the auto_mappr code-generator of mapping between objects with ease. -version: 1.42.0 +version: 2.0.0 repository: https://github.com/netglade/auto_mappr issue_tracker: https://github.com/netglade/auto_mappr/issues From 13ff73c06132d4a63e1e67b7536d76bc19023952 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 15 Sep 2023 23:38:32 +0200 Subject: [PATCH 47/48] Reset packages/*/example --- packages/auto_mappr/example/pubspec.yaml | 6 +++--- packages/auto_mappr_annotation/example/pubspec.yaml | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/auto_mappr/example/pubspec.yaml b/packages/auto_mappr/example/pubspec.yaml index 011f1001..3c5d8dd3 100644 --- a/packages/auto_mappr/example/pubspec.yaml +++ b/packages/auto_mappr/example/pubspec.yaml @@ -4,14 +4,14 @@ version: 1.0.0 publish_to: none environment: - sdk: ^3.0.0 + sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^2.0.0 + auto_mappr_annotation: ^1.1.0 equatable: ^2.0.5 dev_dependencies: - auto_mappr: ^2.0.0 + auto_mappr: ^1.3.0 build_runner: ^2.0.0 netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/packages/auto_mappr_annotation/example/pubspec.yaml b/packages/auto_mappr_annotation/example/pubspec.yaml index cba7aa45..250c3f1c 100644 --- a/packages/auto_mappr_annotation/example/pubspec.yaml +++ b/packages/auto_mappr_annotation/example/pubspec.yaml @@ -4,10 +4,11 @@ version: 1.0.0 publish_to: none environment: - sdk: ^3.0.0 + sdk: ">=2.18.7 <4.0.0" dependencies: - auto_mappr_annotation: ^2.0.0 + auto_mappr_annotation: + path: ../ dev_dependencies: build_runner: ^2.0.0 From e21312593c53b2d1d0cc5017bfd853797992f541 Mon Sep 17 00:00:00 2001 From: Honza Bittner <git@tenhobi.dev> Date: Fri, 15 Sep 2023 23:48:20 +0200 Subject: [PATCH 48/48] Put package/*/example bump back --- packages/auto_mappr/example/pubspec.yaml | 6 +++--- packages/auto_mappr_annotation/example/pubspec.yaml | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/auto_mappr/example/pubspec.yaml b/packages/auto_mappr/example/pubspec.yaml index 3c5d8dd3..011f1001 100644 --- a/packages/auto_mappr/example/pubspec.yaml +++ b/packages/auto_mappr/example/pubspec.yaml @@ -4,14 +4,14 @@ version: 1.0.0 publish_to: none environment: - sdk: ">=2.18.7 <4.0.0" + sdk: ^3.0.0 dependencies: - auto_mappr_annotation: ^1.1.0 + auto_mappr_annotation: ^2.0.0 equatable: ^2.0.5 dev_dependencies: - auto_mappr: ^1.3.0 + auto_mappr: ^2.0.0 build_runner: ^2.0.0 netglade_analysis: ^4.2.0 test: ^1.16.0 diff --git a/packages/auto_mappr_annotation/example/pubspec.yaml b/packages/auto_mappr_annotation/example/pubspec.yaml index 250c3f1c..cba7aa45 100644 --- a/packages/auto_mappr_annotation/example/pubspec.yaml +++ b/packages/auto_mappr_annotation/example/pubspec.yaml @@ -4,11 +4,10 @@ version: 1.0.0 publish_to: none environment: - sdk: ">=2.18.7 <4.0.0" + sdk: ^3.0.0 dependencies: - auto_mappr_annotation: - path: ../ + auto_mappr_annotation: ^2.0.0 dev_dependencies: build_runner: ^2.0.0