Skip to content

Commit

Permalink
Merge pull request #192 from netglade/fix/consider-renames-for-setters
Browse files Browse the repository at this point in the history
Consider rename for target classes without ctors where setters are used
  • Loading branch information
tenhobi authored Mar 26, 2024
2 parents 6660bfd + cc4fbed commit 6c956ae
Show file tree
Hide file tree
Showing 22 changed files with 117 additions and 48 deletions.
10 changes: 4 additions & 6 deletions examples/drift/lib/db.drift.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,9 @@ class $TodosTable extends Todos with TableInfo<$TodosTable, Todo> {
@override
List<GeneratedColumn> get $columns => [id, title, content, category];
@override
String get aliasedName => _alias ?? actualTableName;
String get aliasedName => _alias ?? 'todos';
@override
String get actualTableName => $name;
static const String $name = 'todos';
String get actualTableName => 'todos';
@override
VerificationContext validateIntegrity(Insertable<Todo> instance,
{bool isInserting = false}) {
Expand Down Expand Up @@ -279,10 +278,9 @@ class $CategoriesTable extends Categories
@override
List<GeneratedColumn> get $columns => [id, description];
@override
String get aliasedName => _alias ?? actualTableName;
String get aliasedName => _alias ?? 'categories';
@override
String get actualTableName => $name;
static const String $name = 'categories';
String get actualTableName => 'categories';
@override
VerificationContext validateIntegrity(Insertable<Category> instance,
{bool isInserting = false}) {
Expand Down
1 change: 0 additions & 1 deletion examples/drift/lib/mappr.auto_mappr.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion examples/example/lib/enum.auto_mappr.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion examples/example/lib/equatable.auto_mappr.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion examples/example/lib/nested.auto_mappr.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion examples/example/lib/nullable.auto_mappr.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion examples/example/lib/rename.auto_mappr.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions examples/freezed/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
include: package:netglade_analysis/lints.yaml

analyzer:
exclude:
- "**/*.freezed.dart"
1 change: 0 additions & 1 deletion examples/freezed/lib/freezed_example.auto_mappr.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 18 additions & 19 deletions examples/freezed/lib/freezed_example.freezed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ part of 'freezed_example.dart';
T _$identity<T>(T value) => value;

final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');

/// @nodoc
mixin _$UserInfoUnion {
Expand Down Expand Up @@ -79,11 +79,11 @@ class _$UserInfoUnionCopyWithImpl<$Res, $Val extends UserInfoUnion>
}

/// @nodoc
abstract class _$$UserInfoImplCopyWith<$Res>
abstract class _$$UserInfoCopyWith<$Res>
implements $UserInfoUnionCopyWith<$Res> {
factory _$$UserInfoImplCopyWith(
_$UserInfoImpl value, $Res Function(_$UserInfoImpl) then) =
__$$UserInfoImplCopyWithImpl<$Res>;
factory _$$UserInfoCopyWith(
_$UserInfo value, $Res Function(_$UserInfo) then) =
__$$UserInfoCopyWithImpl<$Res>;
@override
@useResult
$Res call(
Expand All @@ -94,11 +94,10 @@ abstract class _$$UserInfoImplCopyWith<$Res>
}

/// @nodoc
class __$$UserInfoImplCopyWithImpl<$Res>
extends _$UserInfoUnionCopyWithImpl<$Res, _$UserInfoImpl>
implements _$$UserInfoImplCopyWith<$Res> {
__$$UserInfoImplCopyWithImpl(
_$UserInfoImpl _value, $Res Function(_$UserInfoImpl) _then)
class __$$UserInfoCopyWithImpl<$Res>
extends _$UserInfoUnionCopyWithImpl<$Res, _$UserInfo>
implements _$$UserInfoCopyWith<$Res> {
__$$UserInfoCopyWithImpl(_$UserInfo _value, $Res Function(_$UserInfo) _then)
: super(_value, _then);

@pragma('vm:prefer-inline')
Expand All @@ -109,7 +108,7 @@ class __$$UserInfoImplCopyWithImpl<$Res>
Object? updatedAt = null,
Object? primarySectionId = null,
}) {
return _then(_$UserInfoImpl(
return _then(_$UserInfo(
email: null == email
? _value.email
: email // ignore: cast_nullable_to_non_nullable
Expand All @@ -132,8 +131,8 @@ class __$$UserInfoImplCopyWithImpl<$Res>

/// @nodoc
class _$UserInfoImpl implements UserInfo {
_$UserInfoImpl(
class _$UserInfo implements UserInfo {
_$UserInfo(
{required this.email,
required this.loginIdentifier,
required this.updatedAt,
Expand All @@ -155,10 +154,10 @@ class _$UserInfoImpl implements UserInfo {
}

@override
bool operator ==(Object other) {
bool operator ==(dynamic other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$UserInfoImpl &&
other is _$UserInfo &&
(identical(other.email, email) || other.email == email) &&
(identical(other.loginIdentifier, loginIdentifier) ||
other.loginIdentifier == loginIdentifier) &&
Expand All @@ -175,16 +174,16 @@ class _$UserInfoImpl implements UserInfo {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$UserInfoImplCopyWith<_$UserInfoImpl> get copyWith =>
__$$UserInfoImplCopyWithImpl<_$UserInfoImpl>(this, _$identity);
_$$UserInfoCopyWith<_$UserInfo> get copyWith =>
__$$UserInfoCopyWithImpl<_$UserInfo>(this, _$identity);
}

abstract class UserInfo implements UserInfoUnion {
factory UserInfo(
{required final String email,
required final String loginIdentifier,
required final DateTime updatedAt,
final int primarySectionId}) = _$UserInfoImpl;
final int primarySectionId}) = _$UserInfo;

@override
String get email;
Expand All @@ -196,6 +195,6 @@ abstract class UserInfo implements UserInfoUnion {
int get primarySectionId;
@override
@JsonKey(ignore: true)
_$$UserInfoImplCopyWith<_$UserInfoImpl> get copyWith =>
_$$UserInfoCopyWith<_$UserInfo> get copyWith =>
throw _privateConstructorUsedError;
}
3 changes: 2 additions & 1 deletion examples/injectable/lib/getit.config.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion examples/injectable/lib/mappr.auto_mappr.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion packages/auto_mappr/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
[//]: # (## Unreleased)

## 2.4.0
- Fix nested types ignores settings about null values (whenNull and ignoreNull). [#191](https://github.com/netglade/auto_mappr/pull/191)
- Fix not considering renaming ("from") when mapping using setters. [#192](https://github.com/netglade/auto_mappr/pull/192)

## 2.3.0
- Support zero argument function in custom mapping [#169](https://github.com/netglade/auto_mappr/pull/169)
- Support zero argument function in custom mapping. [#169](https://github.com/netglade/auto_mappr/pull/169)

## 2.2.0
- Improve error messages. [#147](https://github.com/netglade/auto_mappr/pull/147)
Expand Down
2 changes: 1 addition & 1 deletion packages/auto_mappr/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ targets:
enabled: true
generate_for:
# include:
# - test/integration/fixture/type_converters/required_to_nullable.dart
# - test/integration/fixture/rename.dart
exclude:
- test/integration/error_fixture/**
options:
Expand Down
1 change: 0 additions & 1 deletion packages/auto_mappr/example/lib/mappr.auto_mappr.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -217,30 +217,60 @@ class ClassBodyBuilder extends MapBodyBuilderBase {
}) {
final targetSetters = mapping.target.getAllSetters();

final potentialSetterFields = sourceFields.keys.where((field) => !alreadyMapped.contains(field)).toList();
final fields = potentialSetterFields
.map((key) => sourceFields[key])
// Select only those who has not been mapped yet.
final potentialSetterFields = sourceFields.keys.where((field) {
final fieldMapping = mapping.tryGetFieldMappingFromFrom(field);
final from = fieldMapping?.field;

// If the field has a rename, check that.
if (from != null) {
return !alreadyMapped.contains(from);
}

// Or check it direclty.
return !alreadyMapped.contains(field);
}).toList();

final notMappedSourceFields = potentialSetterFields
.map((sourceKey) => sourceFields[sourceKey])
.whereNotNull()
// Use only those that match.
.where((accessor) => targetSetters.any((targetAccessor) => targetAccessor.displayName == accessor.displayName))
.where((accessor) {
final fieldMapping = mapping.tryGetFieldMappingFromFrom(accessor.name);
final from = fieldMapping?.field;

return
// Contains rename.
from != null ||
// Or matches directly.
targetSetters.any((targetAccessor) => targetAccessor.displayName == accessor.displayName);
})
// Skip ignored fields.
.where((accessor) => !mapping.fieldShouldBeIgnored(accessor.displayName))
.toList();

if (fields.isEmpty) {
if (notMappedSourceFields.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);

for (final sourceField in notMappedSourceFields) {
// Is there a rename?
final fieldMapping = mapping.tryGetFieldMappingFromFrom(sourceField.name);
final from = fieldMapping?.field;

// Rename or original field name.
final sourceFieldName = from ?? sourceField.name;
final targetField = targetClassGetters.firstWhereOrNull((field) => field.displayName == sourceFieldName);

// final targetField = targetClassSetters.firstWhereOrNull((field) => field.displayName == sourceField.displayName);
if (targetField == null) continue;

// Assign result.X = model.X
cascadedAssignments = cascadedAssignments.cascade(sourceField.displayName).assign(
cascadedAssignments = cascadedAssignments.cascade(sourceFieldName).assign(
ValueAssignmentBuilder(
mapperConfig: mapperConfig,
mapping: mapping,
Expand Down
2 changes: 2 additions & 0 deletions packages/auto_mappr/lib/src/models/type_mapping.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class TypeMapping extends Equatable {

FieldMapping? tryGetFieldMapping(String field) => fieldMappings.firstWhereOrNull((x) => x.field == field);

FieldMapping? tryGetFieldMappingFromFrom(String from) => fieldMappings.firstWhereOrNull((x) => x.from == from);

bool fieldShouldBeIgnored(String field) => hasFieldMapping(field) && (getFieldMapping(field)?.ignore ?? false);

@override
Expand Down
2 changes: 1 addition & 1 deletion packages/auto_mappr/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: auto_mappr
description: Code generation for mapping between different objects with ease.
version: 2.3.0
version: 2.4.0
repository: https://github.com/netglade/auto_mappr
issue_tracker: https://github.com/netglade/auto_mappr/issues
screenshots:
Expand Down
26 changes: 26 additions & 0 deletions packages/auto_mappr/test/integration/fixture/rename.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ import 'rename.auto_mappr.dart';
Field.custom('nameAndId', custom: Mappr.convertToNameAndIdNamed),
],
),
// no constructor with late fields
MapType<NoConstructorWithLateDto, NoConstructorWithLate>(
fields: [
Field('alpha', from: 'value'),
Field('beta', from: 'secondValue'),
],
),
])
class Mappr extends $Mappr {
static String convertToNameAndIdPositional(CustomPositionalDto? dto) => '${dto?.name} #${dto?.id}';
Expand Down Expand Up @@ -304,3 +311,22 @@ class CustomNamedDto {

const CustomNamedDto({required this.id, required this.name});
}

// No constructor with late fields.

class NoConstructorWithLateDto {
final int value;
final String secondValue;

const NoConstructorWithLateDto({required this.value, required this.secondValue});
}

class NoConstructorWithLate with EquatableMixin {
// ignore: avoid-unassigned-late-fields, will be set using Mappr
late int alpha;
// ignore: avoid-unassigned-late-fields, will be set using Mappr
late String beta;

@override
List<Object?> get props => [alpha, beta];
}
16 changes: 16 additions & 0 deletions packages/auto_mappr/test/integration/rename_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,20 @@ void main() {
expect(converted, equals(const fixture.CustomNamed(nameAndId: 'monitor #11')));
});
});

group('with no constructor and with late fields', () {
test('Renamed when using positional parameters', () {
const dto = fixture.NoConstructorWithLateDto(value: 42, secondValue: 'colosseum');
final converted = mappr.convert<fixture.NoConstructorWithLateDto, fixture.NoConstructorWithLate>(dto);

expect(
converted,
equals(
fixture.NoConstructorWithLate()
..alpha = 42
..beta = 'colosseum',
),
);
});
});
}

0 comments on commit 6c956ae

Please sign in to comment.