diff --git a/example/lib/complete/complete.mapper.g.dart b/example/lib/complete/complete.mapper.g.dart index da3c2d5..2016c79 100644 --- a/example/lib/complete/complete.mapper.g.dart +++ b/example/lib/complete/complete.mapper.g.dart @@ -11,13 +11,20 @@ class ExampleMapperImpl extends ExampleMapper { ExampleMapperImpl() : super(); @override - BarTarget fromFoo(FooSource source, FooSourceTheSecond second) { + BarTarget fromFoo( + FooSource source, + FooSourceTheSecond second, + ) { final bartarget = BarTarget( - source.number, source.text, source.truthy, source.superText, - named: source.named, - namedTwoDiff: source.namedTwo, - list: source.list.map((x) => fromFooSub(x)).toList(), - secondTextOther: second.secondTextOther); + source.number, + source.text, + source.truthy, + source.superText, + named: source.named, + namedTwoDiff: source.namedTwo, + list: source.list.map((x) => fromFooSub(x)).toList(), + secondTextOther: second.secondTextOther, + ); bartarget.property = source.property; bartarget.propertyTwoDiff = source.propertyTwo; bartarget.nested = fromFooSub(source.nested); @@ -30,7 +37,10 @@ class ExampleMapperImpl extends ExampleMapper { @override BarNestedTarget fromFooSub(FooNestedSource source) { - final barnestedtarget = BarNestedTarget(source.text, source.number); + final barnestedtarget = BarNestedTarget( + source.text, + source.number, + ); return barnestedtarget; } } diff --git a/example/lib/constructor/constructor.mapper.g.dart b/example/lib/constructor/constructor.mapper.g.dart index a65bef5..cfc30b8 100644 --- a/example/lib/constructor/constructor.mapper.g.dart +++ b/example/lib/constructor/constructor.mapper.g.dart @@ -7,10 +7,17 @@ part of 'constructor.dart'; // ************************************************************************** class ConstructorMapperImpl extends ConstructorMapper { - ConstructorMapperImpl(String? optionalPos, String requiredPos, - {required String requiredNamed, String? optionalNamed}) - : super(optionalPos, requiredPos, - requiredNamed: requiredNamed, optionalNamed: optionalNamed); + ConstructorMapperImpl( + String? optionalPos, + String requiredPos, { + required String requiredNamed, + String? optionalNamed, + }) : super( + optionalPos, + requiredPos, + requiredNamed: requiredNamed, + optionalNamed: optionalNamed, + ); ConstructorMapperImpl.foo(String text) : super.foo(text); diff --git a/example/lib/dog_mapping/dog_mapping.dart b/example/lib/dog_mapping/dog_mapping.dart new file mode 100644 index 0000000..6e94f26 --- /dev/null +++ b/example/lib/dog_mapping/dog_mapping.dart @@ -0,0 +1,32 @@ +import 'package:smartstruct/smartstruct.dart'; +part 'dog_mapping.mapper.g.dart'; + +// TARGET + +class Dog { + final String name; + final String breed; + final int age; + + Dog(this.name, this.breed, this.age); +} + +// SOURCE + +class DogModel { + final String dogName; + final String breed; + + DogModel( + this.dogName, + this.breed, + ); +} + +/// Mapper showcasing explicit fieldmapping in case fields do not match their respective fieldnames +@Mapper() +abstract class DogMapper { + @Mapping(source: 'dogName', target: 'name') + @Mapping(source: 'age', target: 'age', isStraight: true) + Dog fromDogModel(DogModel model, int age); +} diff --git a/example/lib/dog_mapping/dog_mapping.mapper.g.dart b/example/lib/dog_mapping/dog_mapping.mapper.g.dart new file mode 100644 index 0000000..a20bfe0 --- /dev/null +++ b/example/lib/dog_mapping/dog_mapping.mapper.g.dart @@ -0,0 +1,24 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'dog_mapping.dart'; + +// ************************************************************************** +// MapperGenerator +// ************************************************************************** + +class DogMapperImpl extends DogMapper { + DogMapperImpl() : super(); + + @override + Dog fromDogModel( + DogModel model, + int age, + ) { + final dog = Dog( + model.dogName, + model.breed, + age, + ); + return dog; + } +} diff --git a/example/lib/field_mapping/field_mapping.mapper.g.dart b/example/lib/field_mapping/field_mapping.mapper.g.dart index 7c1729e..d2de23a 100644 --- a/example/lib/field_mapping/field_mapping.mapper.g.dart +++ b/example/lib/field_mapping/field_mapping.mapper.g.dart @@ -11,7 +11,11 @@ class DogMapperImpl extends DogMapper { @override Dog fromDogModel(DogModel model) { - final dog = Dog(model.dogName, model.breed, model.dogAge); + final dog = Dog( + model.dogName, + model.breed, + model.dogAge, + ); return dog; } } diff --git a/example/lib/freezed/freezed_mapper.mapper.g.dart b/example/lib/freezed/freezed_mapper.mapper.g.dart index 7e7e561..e5c7eaf 100644 --- a/example/lib/freezed/freezed_mapper.mapper.g.dart +++ b/example/lib/freezed/freezed_mapper.mapper.g.dart @@ -11,7 +11,10 @@ class FreezedMapperImpl extends FreezedMapper { @override FreezedTarget fromModel(FreezedSource model) { - final freezedtarget = FreezedTarget(model.name, model.age); + final freezedtarget = FreezedTarget( + model.name, + model.age, + ); return freezedtarget; } } @@ -21,8 +24,10 @@ class FreezedNamedMapperImpl extends FreezedNamedMapper { @override FreezedNamedTarget fromModel(FreezedNamedSource model) { - final freezednamedtarget = - FreezedNamedTarget(name: model.name, age: model.age); + final freezednamedtarget = FreezedNamedTarget( + name: model.name, + age: model.age, + ); return freezednamedtarget; } } diff --git a/example/lib/function_mapping/function_mapping.mapper.g.dart b/example/lib/function_mapping/function_mapping.mapper.g.dart index 3dcc84c..9b88779 100644 --- a/example/lib/function_mapping/function_mapping.mapper.g.dart +++ b/example/lib/function_mapping/function_mapping.mapper.g.dart @@ -11,8 +11,11 @@ class DogMapperImpl extends DogMapper { @override Dog fromDogModel(DogModel model) { - final dog = Dog(fullNameWithAge(model), DogMapper.breedCustom(model), - FunctionUtils.mapAge(model)); + final dog = Dog( + model.name, + DogMapper.breedCustom(model), + model.age, + ); return dog; } } diff --git a/example/lib/function_mapping/function_mapping_more.mapper.g.dart b/example/lib/function_mapping/function_mapping_more.mapper.g.dart index 22473e9..37e78a3 100644 --- a/example/lib/function_mapping/function_mapping_more.mapper.g.dart +++ b/example/lib/function_mapping/function_mapping_more.mapper.g.dart @@ -11,8 +11,11 @@ class DogMapperImpl extends DogMapper { @override Dog fromDogModel(DogModel model) { - final dog = - Dog(fullNameWithAge(model), DogMapper.breedCustom(model), model.age); + final dog = Dog( + model.name, + DogMapper.breedCustom(model), + model.age, + ); dog.model = () { final tmp = toAgeHolderSource(model); return tmp == null ? null : fromAgeHolderSource(tmp); diff --git a/example/lib/function_mapping/function_mapping_with_mapper.mapper.g.dart b/example/lib/function_mapping/function_mapping_with_mapper.mapper.g.dart index 47b8353..e519e97 100644 --- a/example/lib/function_mapping/function_mapping_with_mapper.mapper.g.dart +++ b/example/lib/function_mapping/function_mapping_with_mapper.mapper.g.dart @@ -11,8 +11,10 @@ class PassOnMapperFunctionMapperImpl extends PassOnMapperFunctionMapper { @override ComplexFunctionTarget fromSource(ComplexFunctionSource source) { - final complexfunctiontarget = - ComplexFunctionTarget(mapComplexSubSource(source, mapper: this)); + final complexfunctiontarget = ComplexFunctionTarget(mapComplexSubSource( + source, + mapper: this, + )); return complexfunctiontarget; } diff --git a/example/lib/inheritance/inheritance.mapper.g.dart b/example/lib/inheritance/inheritance.mapper.g.dart index a15924c..cf6ae21 100644 --- a/example/lib/inheritance/inheritance.mapper.g.dart +++ b/example/lib/inheritance/inheritance.mapper.g.dart @@ -12,7 +12,11 @@ class InheritanceMapperImpl extends InheritanceMapper { @override BarTarget fromFoo(FooSource source) { final bartarget = BarTarget( - source.subFoo, source.superFoo, source.mappable, source.superProp); + source.subFoo, + source.superFoo, + source.mappable, + source.superProp, + ); return bartarget; } } diff --git a/example/lib/injection/service_locator.config.dart b/example/lib/injection/service_locator.config.dart index 58e8028..50254bf 100644 --- a/example/lib/injection/service_locator.config.dart +++ b/example/lib/injection/service_locator.config.dart @@ -4,6 +4,7 @@ // InjectableConfigGenerator // ************************************************************************** +// ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:get_it/get_it.dart' as _i1; import 'package:injectable/injectable.dart' as _i2; @@ -12,9 +13,16 @@ import 'injectable_mapper.dart' as _i4; // ignore_for_file: unnecessary_lambdas // ignore_for_file: lines_longer_than_80_chars /// initializes the registration of provided dependencies inside of [GetIt] -_i1.GetIt $initGetIt(_i1.GetIt get, - {String? environment, _i2.EnvironmentFilter? environmentFilter}) { - final gh = _i2.GetItHelper(get, environment, environmentFilter); +_i1.GetIt $initGetIt( + _i1.GetIt get, { + String? environment, + _i2.EnvironmentFilter? environmentFilter, +}) { + final gh = _i2.GetItHelper( + get, + environment, + environmentFilter, + ); gh.lazySingleton<_i3.ExampleMapper>(() => _i3.ExampleMapperImpl()); gh.lazySingleton<_i4.InjectableNestedMapper>( () => _i4.InjectableNestedMapperImpl()); diff --git a/example/lib/list/list.mapper.g.dart b/example/lib/list/list.mapper.g.dart index ca7c2de..e2d8a31 100644 --- a/example/lib/list/list.mapper.g.dart +++ b/example/lib/list/list.mapper.g.dart @@ -11,8 +11,10 @@ class ListMapperImpl extends ListMapper { @override Target fromSource(Source source) { - final target = Target(source.intList.map((e) => e).toList(), - source.entryList.map((x) => fromSourceEntry(x)).toList()); + final target = Target( + source.intList.map((e) => e).toList(), + source.entryList.map((x) => fromSourceEntry(x)).toList(), + ); return target; } diff --git a/example/lib/mapper_inheritance/mapper_inheritance.mapper.g.dart b/example/lib/mapper_inheritance/mapper_inheritance.mapper.g.dart index c37770b..df7d535 100644 --- a/example/lib/mapper_inheritance/mapper_inheritance.mapper.g.dart +++ b/example/lib/mapper_inheritance/mapper_inheritance.mapper.g.dart @@ -16,7 +16,10 @@ class UserLoginContractFromEntityMapperImpl return null; } ; - final userlogincontract = UserLoginContract(entity.age, entity.id); + final userlogincontract = UserLoginContract( + entity.age, + entity.id, + ); return userlogincontract; } } @@ -31,7 +34,10 @@ class UserLoginContractFromEntityMapper2Impl return null; } ; - final userlogincontract2 = UserLoginContract2(entity.age, entity.id); + final userlogincontract2 = UserLoginContract2( + entity.age, + entity.id, + ); return userlogincontract2; } } diff --git a/example/lib/multi_constructor/multi_constructor.mapper.g.dart b/example/lib/multi_constructor/multi_constructor.mapper.g.dart index f2e0a02..03cca09 100644 --- a/example/lib/multi_constructor/multi_constructor.mapper.g.dart +++ b/example/lib/multi_constructor/multi_constructor.mapper.g.dart @@ -11,7 +11,10 @@ class MultiConMapperImpl extends MultiConMapper { @override MultiConTarget fromSource(MultiConSource source) { - final multicontarget = MultiConTarget.multi(source.text, source.number); + final multicontarget = MultiConTarget.multi( + source.text, + source.number, + ); return multicontarget; } } diff --git a/example/lib/multiple_sources/multiple_sources.mapper.g.dart b/example/lib/multiple_sources/multiple_sources.mapper.g.dart index 2c22145..c83c3cf 100644 --- a/example/lib/multiple_sources/multiple_sources.mapper.g.dart +++ b/example/lib/multiple_sources/multiple_sources.mapper.g.dart @@ -10,9 +10,21 @@ class MultipleSourcesMapperImpl extends MultipleSourcesMapper { MultipleSourcesMapperImpl() : super(); @override - Target fromSource(Source source, Source2 source2, Source3 source3) { - final target = Target(source.text1, source2.text2, source3.text3, - allText(source, source2, source3)); + Target fromSource( + Source source, + Source2 source2, + Source3 source3, + ) { + final target = Target( + source.text1, + source2.text2, + source3.text3, + allText( + source, + source2, + source3, + ), + ); return target; } } diff --git a/example/lib/nested/nested_mapping.mapper.g.dart b/example/lib/nested/nested_mapping.mapper.g.dart index 1b7e995..b0e445f 100644 --- a/example/lib/nested/nested_mapping.mapper.g.dart +++ b/example/lib/nested/nested_mapping.mapper.g.dart @@ -11,8 +11,11 @@ class UserMapperImpl extends UserMapper { @override User fromResponse(UserResponse response) { - final user = User(response.username, response.address.zipcode, - response.address.street.streetName); + final user = User( + response.username, + response.address.zipcode, + response.address.street.streetName, + ); return user; } } diff --git a/example/lib/static_mapping/static_mapping.mapper.g.dart b/example/lib/static_mapping/static_mapping.mapper.g.dart index 0750f5c..5ad5d06 100644 --- a/example/lib/static_mapping/static_mapping.mapper.g.dart +++ b/example/lib/static_mapping/static_mapping.mapper.g.dart @@ -11,12 +11,18 @@ class StaticMappingMapperImpl extends StaticMappingMapper { @override StaticMappingTarget fromSourceNormal(StaticMappingSource source) { - final staticmappingtarget = StaticMappingTarget(source.text, source.number); + final staticmappingtarget = StaticMappingTarget( + source.text, + source.number, + ); return staticmappingtarget; } } StaticMappingTarget _$fromSourceStatic(StaticMappingSource source) { - final staticmappingtarget = StaticMappingTarget(source.text, source.number); + final staticmappingtarget = StaticMappingTarget( + source.text, + source.number, + ); return staticmappingtarget; } diff --git a/example/lib/static_mapping/static_proxy.mapper.g.dart b/example/lib/static_mapping/static_proxy.mapper.g.dart index 5f559dd..a3fbcb8 100644 --- a/example/lib/static_mapping/static_proxy.mapper.g.dart +++ b/example/lib/static_mapping/static_proxy.mapper.g.dart @@ -11,7 +11,10 @@ class StaticMappingMapperImpl extends StaticMappingMapper { @override StaticProxyTarget fromSourceNormal(StaticMappingSource source) { - final staticproxytarget = StaticProxyTarget(source.text, source.number); + final staticproxytarget = StaticProxyTarget( + source.text, + source.number, + ); return staticproxytarget; } } diff --git a/example/pubspec.lock b/example/pubspec.lock index 238eee3..d31cab6 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -5,79 +5,79 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "47.0.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.7.0" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.1" + version: "2.3.1" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.7.0" + version: "2.9.0" build: dependency: transitive description: name: build - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.1" build_config: dependency: transitive description: name: build_config - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0" + version: "1.1.0" build_daemon: dependency: transitive description: name: build_daemon - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.0" build_resolvers: dependency: transitive description: name: build_resolvers - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.10" build_runner: dependency: "direct dev" description: name: build_runner - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.11" build_runner_core: dependency: transitive description: name: build_runner_core - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "7.2.2" + version: "7.2.4" built_collection: dependency: transitive description: name: built_collection - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "5.0.0" + version: "5.1.1" built_value: dependency: transitive description: @@ -91,238 +91,231 @@ packages: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "8.4.1" checked_yaml: dependency: transitive description: name: checked_yaml - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.1" code_builder: dependency: transitive description: name: code_builder - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "4.1.0" + version: "4.3.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.15.0" + version: "1.16.0" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.0" + version: "3.0.2" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.1" + version: "3.0.2" dart_style: dependency: transitive description: name: dart_style - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.4" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "6.1.1" + version: "6.1.4" fixnum: dependency: transitive description: name: fixnum - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0" + version: "1.0.1" freezed: dependency: "direct dev" description: name: freezed - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0+1" freezed_annotation: dependency: "direct main" description: name: freezed_annotation - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" frontend_server_client: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.0" + version: "2.1.3" get_it: dependency: transitive description: name: get_it - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "7.2.0" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.1" + version: "2.1.0" graphs: dependency: transitive description: name: graphs - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.0" + version: "2.1.0" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.1" + version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "4.0.0" + version: "4.0.1" injectable: dependency: "direct main" description: name: injectable - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.5.3" injectable_generator: dependency: "direct dev" description: name: injectable_generator - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.5.4" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0" + version: "1.0.3" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "0.6.3" + version: "0.6.4" json_annotation: dependency: transitive description: name: json_annotation - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "4.4.0" + version: "4.6.0" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.1" + version: "1.0.2" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "0.12.10" + version: "0.12.12" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.7.0" + version: "1.8.0" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0" + version: "1.0.2" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.0" + version: "2.1.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.1" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.11.0" + version: "1.8.2" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.5.0" + version: "1.5.1" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.0" + version: "2.1.1" pubspec_parse: dependency: transitive description: name: pubspec_parse - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0" + version: "1.2.1" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.4" + version: "1.3.2" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.1" + version: "1.0.2" smartstruct: dependency: "direct main" description: @@ -341,85 +334,85 @@ packages: dependency: transitive description: name: source_gen - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.5" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.1" + version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" stream_transform: dependency: transitive description: name: stream_transform - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.0" + version: "1.2.1" timing: dependency: transitive description: name: timing - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.3.0" + version: "1.3.1" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0" + version: "1.0.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.0" + version: "2.2.0" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.1.0" + version: "3.1.1" sdks: dart: ">=2.17.0 <3.0.0" diff --git a/generator/lib/code_builders/assignment_builder.dart b/generator/lib/code_builders/assignment_builder.dart index 082fe03..d7d18c4 100644 --- a/generator/lib/code_builders/assignment_builder.dart +++ b/generator/lib/code_builders/assignment_builder.dart @@ -17,124 +17,124 @@ import 'package:smartstruct_generator/models/source_assignment.dart'; /// fromSub(model.sub); /// ``` /// -Expression generateSourceFieldAssignment(SourceAssignment sourceAssignment, - ClassElement abstractMapper, VariableElement targetField) { +Expression generateSourceFieldAssignment( + SourceAssignment sourceAssignment, ClassElement abstractMapper, VariableElement targetField) { Expression sourceFieldAssignment; if (sourceAssignment.shouldUseFunction()) { final sourceFunction = sourceAssignment.function!; - final references = sourceAssignment.params! - .map((sourceParam) => refer(sourceParam.displayName)); + final references = + sourceAssignment.params!.map((sourceParam) => refer(sourceParam.displayName)); Expression expr = refer(sourceFunction.name); if (sourceFunction.isStatic && sourceFunction.enclosingElement3.name != null) { expr = refer(sourceFunction.enclosingElement3.name!) .property(sourceFunction.name); } - sourceFieldAssignment = expr.call([...references], makeNamedArgumentForStaticFunction(sourceFunction)); + sourceFieldAssignment = + expr.call([...references], makeNamedArgumentForStaticFunction(sourceFunction)); // The return of the function may be needed a nested mapping. sourceFieldAssignment = invokeNestedMappingForStaticFunction( - sourceFunction, - abstractMapper, - targetField, - sourceFieldAssignment); + sourceFunction, abstractMapper, targetField, sourceFieldAssignment); } else { // final sourceClass = sourceAssignment.sourceClass!; final sourceField = sourceAssignment.field!; - final sourceReference = refer(sourceAssignment.sourceName!); - sourceFieldAssignment = sourceReference.property(sourceField.name); - // list support - if (sourceAssignment.shouldAssignList(targetField.type)) { - final sourceListType = _getGenericTypes(sourceField.type).first; - final targetListType = _getGenericTypes(targetField.type).first; - final matchingMappingListMethods = _findMatchingMappingMethod( - abstractMapper, targetListType, sourceListType); - - // mapping expression, default is just the identity, - // for example for primitive types or objects that do not have their own mapping method - var expr = refer('(e) => e'); - var sourceIsNullable = sourceListType.nullabilitySuffix == NullabilitySuffix.question; - var targetIsNullable = targetListType.nullabilitySuffix == NullabilitySuffix.question; - var needTargetFilter = sourceIsNullable && !targetIsNullable; - if (matchingMappingListMethods.isNotEmpty) { - final nestedMapping = matchingMappingListMethods.first; - // expr = refer(nestedMapping.name); - final invokeStr = invokeNestedMappingFunction( - nestedMapping, - sourceIsNullable, - refer("x"), - refer("x"), - ).accept(DartEmitter()).toString(); - expr = refer(''' + //if the sourceAssignment isn't straight + if (!sourceAssignment.isStraight) { + final sourceReference = refer(sourceAssignment.sourceName!); + sourceFieldAssignment = sourceReference.property(sourceField.name); + // list support + if (sourceAssignment.shouldAssignList(targetField.type)) { + final sourceListType = _getGenericTypes(sourceField.type).first; + final targetListType = _getGenericTypes(targetField.type).first; + final matchingMappingListMethods = + _findMatchingMappingMethod(abstractMapper, targetListType, sourceListType); + + // mapping expression, default is just the identity, + // for example for primitive types or objects that do not have their own mapping method + var expr = refer('(e) => e'); + var sourceIsNullable = sourceListType.nullabilitySuffix == NullabilitySuffix.question; + var targetIsNullable = targetListType.nullabilitySuffix == NullabilitySuffix.question; + var needTargetFilter = sourceIsNullable && !targetIsNullable; + if (matchingMappingListMethods.isNotEmpty) { + final nestedMapping = matchingMappingListMethods.first; + // expr = refer(nestedMapping.name); + final invokeStr = invokeNestedMappingFunction( + nestedMapping, + sourceIsNullable, + refer("x"), + refer("x"), + ).accept(DartEmitter()).toString(); + expr = refer(''' (x) => $invokeStr '''); - final returnIsNullable = checkNestMappingReturnNullable(nestedMapping, sourceIsNullable); - needTargetFilter = !targetIsNullable && returnIsNullable; - } - - sourceFieldAssignment = - // source.{field}.map - sourceReference.property(sourceField.name) - .property('map') - // (expr) - .call([expr]); - - if(needTargetFilter) { - sourceFieldAssignment = sourceFieldAssignment.property("where").call([refer("(x) => x != null")]); - } - - if(sourceAssignment.needCollect(targetField.type)) { - sourceFieldAssignment = sourceFieldAssignment - //.toList() .toSet() - .property(sourceAssignment.collectInvoke(targetField.type)) - // .property('toList') - // .call([]) - ; - } - - if(needTargetFilter) { - sourceFieldAssignment = sourceFieldAssignment - .asA(refer(targetField.type.getDisplayString(withNullability: true))); - } - } else { - // found a mapping method in the class which will map the source to target - final matchingMappingMethods = _findMatchingMappingMethod( - abstractMapper, targetField.type, sourceField.type); - - // nested classes can be mapped with their own mapping methods - if (matchingMappingMethods.isNotEmpty) { - sourceFieldAssignment = invokeNestedMappingFunction( - matchingMappingMethods.first, - sourceAssignment.refChain!.isNullable, - refer(sourceAssignment.refChain!.refWithQuestion), - refer(sourceAssignment.refChain!.ref), - ); + final returnIsNullable = checkNestMappingReturnNullable(nestedMapping, sourceIsNullable); + needTargetFilter = !targetIsNullable && returnIsNullable; + } + + sourceFieldAssignment = + // source.{field}.map + sourceReference.property(sourceField.name).property('map') + // (expr) + .call([expr]); + + if (needTargetFilter) { + sourceFieldAssignment = + sourceFieldAssignment.property("where").call([refer("(x) => x != null")]); + } + + if (sourceAssignment.needCollect(targetField.type)) { + sourceFieldAssignment = sourceFieldAssignment + //.toList() .toSet() + .property(sourceAssignment.collectInvoke(targetField.type)) + // .property('toList') + // .call([]) + ; + } + + if (needTargetFilter) { + sourceFieldAssignment = sourceFieldAssignment + .asA(refer(targetField.type.getDisplayString(withNullability: true))); + } + } else { + // found a mapping method in the class which will map the source to target + final matchingMappingMethods = + _findMatchingMappingMethod(abstractMapper, targetField.type, sourceField.type); + + // nested classes can be mapped with their own mapping methods + if (matchingMappingMethods.isNotEmpty) { + sourceFieldAssignment = invokeNestedMappingFunction( + matchingMappingMethods.first, + sourceAssignment.refChain!.isNullable, + refer(sourceAssignment.refChain!.refWithQuestion), + refer(sourceAssignment.refChain!.ref), + ); + } } } + //if the sourceAssignment is straight + else { + sourceFieldAssignment = refer(sourceAssignment.sourceName!); + } } return sourceFieldAssignment; } Expression invokeNestedMappingFunction( - MethodElement method, + MethodElement method, bool sourceNullable, Expression refWithQuestion, Expression ref, ) { Expression sourceFieldAssignment; - if(method.parameters.first.isOptional) { + if (method.parameters.first.isOptional) { // The parameter can be null. - sourceFieldAssignment = refer(method.name) - .call([refWithQuestion]); + sourceFieldAssignment = refer(method.name).call([refWithQuestion]); } else { - sourceFieldAssignment = refer(method.name) - .call([ref]); - sourceFieldAssignment = checkNullExpression( - sourceNullable, - refWithQuestion, - sourceFieldAssignment - ); + sourceFieldAssignment = refer(method.name).call([ref]); + sourceFieldAssignment = + checkNullExpression(sourceNullable, refWithQuestion, sourceFieldAssignment); } return sourceFieldAssignment; } @@ -146,42 +146,37 @@ Expression invokeNestedMappingForStaticFunction( Expression sourceFieldAssignment, ) { final returnType = sourceFunction.returnType; - final matchingMappingMethods = _findMatchingMappingMethod( - abstractMapper, targetField.type, returnType); - if(matchingMappingMethods.isNotEmpty) { + final matchingMappingMethods = + _findMatchingMappingMethod(abstractMapper, targetField.type, returnType); + if (matchingMappingMethods.isNotEmpty) { final nestedMappingMethod = matchingMappingMethods.first; - if( - nestedMappingMethod.parameters.first.type.nullabilitySuffix != NullabilitySuffix.question && - sourceFunction.returnType.nullabilitySuffix == NullabilitySuffix.question - ) { + if (nestedMappingMethod.parameters.first.type.nullabilitySuffix != NullabilitySuffix.question && + sourceFunction.returnType.nullabilitySuffix == NullabilitySuffix.question) { final str = makeNullCheckCall( - sourceFieldAssignment.accept( - DartEmitter() - ).toString(), + sourceFieldAssignment.accept(DartEmitter()).toString(), nestedMappingMethod, ); sourceFieldAssignment = refer(str); } else { - sourceFieldAssignment = refer(matchingMappingMethods.first.name) - .call([sourceFieldAssignment]); + sourceFieldAssignment = + refer(matchingMappingMethods.first.name).call([sourceFieldAssignment]); } - } return sourceFieldAssignment; } /// Finds a matching Mapping Method in [classElement] /// which has the same return type as the given [targetReturnType] and same parametertype as the given [sourceParameterType] -Iterable _findMatchingMappingMethod(ClassElement classElement, - DartType targetReturnType, DartType sourceParameterType) { +Iterable _findMatchingMappingMethod( + ClassElement classElement, DartType targetReturnType, DartType sourceParameterType) { final matchingMappingMethods = classElement.methods.where((met) { // Sometimes the user is troubled by the nullability of these types. // So ingore the nullability of all the type for the nested mapping function is more easy to be matched. // The process of nullability is one duty for this library. - if(met.parameters.isEmpty) { - return false; + if (met.parameters.isEmpty) { + return false; } final metReturnElement = met.returnType.element2; final metParameterElement = met.parameters.first.type.element2; @@ -189,8 +184,7 @@ Iterable _findMatchingMappingMethod(ClassElement classElement, final targetReturnElement = targetReturnType.element2; final srcParameterElement = sourceParameterType.element2; - return metReturnElement == targetReturnElement && - (metParameterElement == srcParameterElement); + return metReturnElement == targetReturnElement && (metParameterElement == srcParameterElement); // return met.returnType == targetReturnType && // met.parameters.isNotEmpty && met.parameters.first.type == sourceParameterType; @@ -204,19 +198,17 @@ Iterable _getGenericTypes(DartType type) { // Sometimes we need to pass some variable to the static function just like "this pointer". // We can use the named parameters to implement the goal. -Map makeNamedArgumentForStaticFunction(ExecutableElement element) { - - final argumentMap = { - "mapper": "this", - "\$this": "this", - }; - final namedParameterList = element.parameters.where((p) => p.isNamed && argumentMap.containsKey(p.name)).toList(); - - return namedParameterList - .asMap().map((key, value) => MapEntry( - value.name, - refer(argumentMap[value.name]!) - )); +Map makeNamedArgumentForStaticFunction(ExecutableElement element) { + final argumentMap = { + "mapper": "this", + "\$this": "this", + }; + final namedParameterList = + element.parameters.where((p) => p.isNamed && argumentMap.containsKey(p.name)).toList(); + + return namedParameterList + .asMap() + .map((key, value) => MapEntry(value.name, refer(argumentMap[value.name]!))); } Expression checkNullExpression( @@ -224,11 +216,11 @@ Expression checkNullExpression( Expression sourceRef, Expression expression, ) { - if(needCheck) { + if (needCheck) { return sourceRef.equalTo(literalNull).conditional( - literalNull, - expression, - ); + literalNull, + expression, + ); } else { return expression; } @@ -238,7 +230,6 @@ makeNullCheckCall( String checkTarget, MethodElement method, ) { - final methodInvoke = refer(method.name).call([refer("tmp")]).accept(DartEmitter()).toString(); return ''' (){ @@ -249,13 +240,8 @@ makeNullCheckCall( } checkNestMappingReturnNullable(MethodElement method, bool inputNullable) { - final returnIsNullable = - (inputNullable && - method.parameters.first.type.nullabilitySuffix != NullabilitySuffix.question - ) || - ( - inputNullable && - method.returnType.nullabilitySuffix == NullabilitySuffix.question - ); - return returnIsNullable; -} \ No newline at end of file + final returnIsNullable = (inputNullable && + method.parameters.first.type.nullabilitySuffix != NullabilitySuffix.question) || + (inputNullable && method.returnType.nullabilitySuffix == NullabilitySuffix.question); + return returnIsNullable; +} diff --git a/generator/lib/code_builders/method_builder.dart b/generator/lib/code_builders/method_builder.dart index 8994a62..0a2c197 100644 --- a/generator/lib/code_builders/method_builder.dart +++ b/generator/lib/code_builders/method_builder.dart @@ -24,31 +24,26 @@ Method buildMapperImplementation(Map config, ..name = method.displayName ..requiredParameters.addAll(method.parameters.map((e) => copyParameter(e))) ..body = _generateBody(config, method, abstractMapper) - ..returns = - refer(method.returnType.getDisplayString(withNullability: true))); + ..returns = refer(method.returnType.getDisplayString(withNullability: true))); } - /// Generates the implemented mapper method by the given abstract [MethodElement]. -Method buildStaticMapperImplementation(Map config, - MethodElement method, ClassElement abstractMapper) { +Method buildStaticMapperImplementation( + Map config, MethodElement method, ClassElement abstractMapper) { return Method( - (b) => b + (b) => b ..name = '_\$${method.name}' ..requiredParameters.addAll(method.parameters.map((e) => copyParameter(e))) ..body = _generateBody(config, method, abstractMapper) - ..returns = - refer(method.returnType.getDisplayString(withNullability: true)), + ..returns = refer(method.returnType.getDisplayString(withNullability: true)), ); } - /// Generates the body for the mapping method. /// /// Uses the default constructor of the target mapping class to populate optional and required named and positional parameters. /// If the target class has any properties which were not set in the constructor, and are mappable by the source, they will be also mapped after initializing the target instance. -Code _generateBody(Map config, MethodElement method, - ClassElement abstractMapper) { +Code _generateBody(Map config, MethodElement method, ClassElement abstractMapper) { final blockBuilder = BlockBuilder(); final targetClass = method.returnType.element2 as ClassElement; @@ -69,8 +64,8 @@ Code _generateBody(Map config, MethodElement method, .where((targetField) => targetToSource.containsKey(targetField.name)) .forEach((targetField) { final sourceAssignment = targetToSource[targetField.name]!; - var sourceFieldAssignment = generateSourceFieldAssignment( - sourceAssignment, abstractMapper, targetField); + var sourceFieldAssignment = + generateSourceFieldAssignment(sourceAssignment, abstractMapper, targetField); if (targetField.isNamed) { namedArgs.putIfAbsent(targetField.name, () => sourceFieldAssignment); @@ -84,11 +79,8 @@ Code _generateBody(Map config, MethodElement method, // source.isOptional does not work for (final sourceParam in sourceParams) { - if (sourceParam.type - .getDisplayString(withNullability: true) - .endsWith('?')) { - blockBuilder.addExpression( - refer('if (${sourceParam.displayName} == null) { return null; }')); + if (sourceParam.type.getDisplayString(withNullability: true).endsWith('?')) { + blockBuilder.addExpression(refer('if (${sourceParam.displayName} == null) { return null; }')); } } // final output = Output(positionalArgs, {namedArgs}); @@ -100,15 +92,12 @@ Code _generateBody(Map config, MethodElement method, final fields = _findFields(targetClass); fields // .where((field) => !field.isFinal) // - .where( - (targetField) => targetToSource.containsKey(targetField.displayName)) + .where((targetField) => targetToSource.containsKey(targetField.displayName)) .map((targetField) { var sourceAssignment = targetToSource[targetField.displayName]!; - var sourceFieldAssignment = generateSourceFieldAssignment( - sourceAssignment, abstractMapper, targetField); - return refer(targetVarName) - .property(targetField.displayName) - .assign(sourceFieldAssignment); + var sourceFieldAssignment = + generateSourceFieldAssignment(sourceAssignment, abstractMapper, targetField); + return refer(targetVarName).property(targetField.displayName).assign(sourceFieldAssignment); }).forEach((expr) => blockBuilder.addExpression(expr)); blockBuilder.addExpression(refer(targetVarName).returned); @@ -117,8 +106,7 @@ Code _generateBody(Map config, MethodElement method, /// Chooses the constructor which will be used to instantiate the target class. ConstructorElement _chooseConstructor(ClassElement outputClass) { - ConstructorElement chosen = - outputClass.constructors.where((element) => !element.isFactory).first; + ConstructorElement chosen = outputClass.constructors.where((element) => !element.isFactory).first; for (var con in outputClass.constructors) { if (con.parameters.length >= chosen.parameters.length) { // choose the one with the most parameters @@ -148,11 +136,8 @@ List _findFields(ClassElement clazz) { return !field.isStatic && !field.isConst && !isAbstract; }; - final allSuperFields = allSuperclasses - .map((e) => e.fields) - .expand((e) => e) - .where(fieldFilter) - .toList(); + final allSuperFields = + allSuperclasses.map((e) => e.fields).expand((e) => e).where(fieldFilter).toList(); return [...clazz.fields, ...allSuperFields]; } @@ -162,11 +147,9 @@ List> _targetToSource( MethodElement method, Map config) { final sourceMap = {for (var e in sources) e.type.element2 as ClassElement: e}; - final caseSensitiveFields = config['caseSensitiveFields']; final fieldMapper = caseSensitiveFields ? (a) => a : (a) => a.toUpperCase(); - final equalsHashCode = - caseSensitiveFields ? (a) => a.hashCode : (a) => a.toUpperCase().hashCode; + final equalsHashCode = caseSensitiveFields ? (a) => a.hashCode : (a) => a.toUpperCase().hashCode; final mappingConfig = MapperConfig.readMappingConfig(method); // final customMappingConfig = MapperConfig.readCustomMappingConfig(method); @@ -174,77 +157,233 @@ List> _targetToSource( /// It is very usefull when you want to have caseInsensitive keys /// Contains data from @Mapping annotations var targetToSource = HashMap( - equals: (a, b) => fieldMapper(a) == fieldMapper(b), - hashCode: (a) => equalsHashCode(a)); + equals: (a, b) => fieldMapper(a) == fieldMapper(b), hashCode: (a) => equalsHashCode(a)); /// Contains data from @CustomMapping annotations var customTargetToSource = HashMap( - equals: (a, b) => fieldMapper(a) == fieldMapper(b), - hashCode: (a) => equalsHashCode(a)); - - final mappingStringConfig = _extractStringMappingConfig(mappingConfig); + equals: (a, b) => fieldMapper(a) == fieldMapper(b), hashCode: (a) => equalsHashCode(a)); + // get the return obj classElement + final returnClassElement = method.returnType.element as ClassElement; + //it's used to mark all fields of all method parameters whether it's added into the targetToSource array + final Map> ret = {}; + for (var source in sources) { + final List fields = _findFields(source.type.element as ClassElement); + ret[source] = {}; + fields.forEach((element) { + ret[source]![element] = false; + }); + } - for (final sourceEntry in sourceMap.entries) { - Map> matchedSourceClazzInSourceMapping = - _findMatchingSourceClazzInMappingMap( - mappingStringConfig, sourceEntry.value.displayName); - for (var f in _findFields(sourceEntry.key)) { - if (targetToSource.containsKey(f.name) && !caseSensitiveFields) { - final duplicatedKey = targetToSource.keys - .toList() - .firstWhere((k) => k.toUpperCase() == f.name.toUpperCase()); - throw InvalidGenerationSourceError( - 'Mapper got case insensitive fields and contains fields: ${f.name} and $duplicatedKey. If you use a case-sensitive mapper, make sure the fields are unique in a case insensitive way.', - todo: "Use case sensitive mapper or change field's names"); - } - if (matchedSourceClazzInSourceMapping.isNotEmpty && - _shouldSearchMoreFields(f)) { - for (var matchedTarget in matchedSourceClazzInSourceMapping.keys) { - final sourceValueList = - matchedSourceClazzInSourceMapping[matchedTarget]!; - final fieldClazz = f.type.element2 as ClassElement; - - final refChain = RefChain.byPropNames(sourceEntry.value, sourceValueList.sublist(1)); - targetToSource[matchedTarget] = SourceAssignment.fromRefChain(refChain); + //traverse all fields of the return obj + // because the key of targetToSource normally will be converted in the origin step + for (var returnClassType in _findFields(returnClassElement)) { + //traverse all `@Mapping` annotation + //it will handle all relations in all `@Mapping`s + for (var entry in mappingConfig.entries) { + //get the target attribute + final targetStr = entry.key; + //get the configuration object of the current `@mapping` + final mappingConfig = entry.value; + //if the current @mapping target is equals to the current field + //it likes we link the field to the mapping + if (targetStr == returnClassType.displayName) { + //if we need to ignore the attribute ,we will break the cycle, and find the next target field + if (mappingConfig.ignore) { + break; + } + //if we don't fill the attribute straightly + else if (!mappingConfig.isStraight) { + //the mapping source is a function + if (mappingConfig.source!.toFunctionValue() != null) { + targetToSource[targetStr] = SourceAssignment.fromFunction( + mappingConfig.source!.toFunctionValue()!, [...sources]); + break; + } + //the mapping source is a string + else if (mappingConfig.source!.toStringValue() != null) { + //we will find the relation between the mapping source and the current parameter + //we can get the map filled data when the mapping source only be cascade, it has the dot + Map> sourceValueMap = + _findMatchingSourceClazzInMappingConfig(mappingConfig, sources); + //we can find the cascade mapping string by the parameter + if (sourceValueMap.isNotEmpty) { + //the map just has one data + for (var entry in sourceValueMap.entries) { + final sourceValue = entry.key; + final sourceKey = sourceValue.type.element as ClassElement; + List matchList = entry.value; + //if the length of list is bigger than 1 + //In fact ,the situation must happen when the list isn't empty + if (matchList.isNotEmpty && matchList.length > 1) { + //get the filed element in the assigned parameter + final fieldElement = sourceKey.getField(matchList[1])!; + //the field class is the custom class + if (_shouldSearchMoreFields(fieldElement)) { + final refChain = RefChain.byPropNames(sourceValue, matchList.sublist(1)); + //we will use the targetStr as the key ,so we don't need to convert it like origin method + targetToSource[targetStr] = SourceAssignment.fromRefChain(refChain); + //mark the field + ret[sourceValue]![fieldElement] = true; + } + //the field class is the basic class + else { + //we will use the targetStr as the key ,so we don't need to convert it like origin method + targetToSource[targetStr] = + SourceAssignment.fromRefChain(RefChain([sourceValue, fieldElement])); + //mark the field + ret[sourceValue]![fieldElement] = true; + } + } + break; + } + } + //the map is empty shows the mapping source just be the field of the first method parameter + else { + //get the first method parameter + final sourceKey = sources[0].type.element as ClassElement; + final sourceValue = sources[0]; + //if it's sensitive to the field + if (!caseSensitiveFields) { + //get the field from the first method parameter + var fieldElement = sourceKey.getField(mappingConfig.source!.toStringValue()!)!; + targetToSource[targetStr] = + SourceAssignment.fromRefChain(RefChain([sources[0], fieldElement])); + //mark the field + ret[sourceValue]![fieldElement] = true; + } + //if it's not be sensitive to the field + else { + //find the assigned field in the first method parameter + for (var field in _findFields(sourceKey)) { + //it's same in the upper case + if (field.displayName.toUpperCase() == targetStr.toUpperCase()) { + targetToSource[targetStr] = + SourceAssignment.fromRefChain(RefChain([sources[0], field])); + //mark the field + ret[sourceValue]![field] = true; + break; + } + } + } + } + } + } + //if the mapping need to fill into the target straightly + else { + //find the assigned parameter + for (final source in sources) { + final sourceKey = source.type.element as ClassElement; + final sourceValue = source; + if (mappingConfig.source!.toStringValue() == sourceValue.displayName) { + targetToSource[targetStr] = + SourceAssignment.fromField(returnClassType, sourceValue.displayName); + break; + } + } } - } else { - targetToSource[f.name] = - SourceAssignment.fromRefChain(RefChain([sourceEntry.value, f])); + break; } } } - - /// If there are Mapping Annotations on the method, the source attribute of the source mapping class, - /// will be replaced with the source attribute of the given mapping config. - mappingConfig.forEach((targetField, mappingConfig) { - final sourceField = mappingConfig.source; - if (sourceField != null) { - if (sourceField.toFunctionValue() != null) { - targetToSource[targetField] = SourceAssignment.fromFunction( - sourceField.toFunctionValue()!, [...sources]); - } else if (sourceField.toStringValue() != null) { - final sourceFieldString = sourceField.toStringValue()!; - // sourceField exists in any sourceParam - if (targetToSource.containsKey(sourceFieldString)) { - // replace mapping target with mapping - targetToSource.putIfAbsent( - targetField, () => targetToSource[sourceFieldString]!); - targetToSource.remove(sourceFieldString); - } + //we have handled all @mapping configuration + //we need to add all field which isn't handled + for (var entry in ret.entries) { + var parameterElement = entry.key; + Map fields = entry.value; + for (var subEntry in fields.entries) { + var field = subEntry.key; + var isAdd = subEntry.value; + if (!isAdd) { + targetToSource[field.name] = + SourceAssignment.fromRefChain(RefChain([parameterElement, field])); } } - + } + //sometimes the ignore attribute don't appear in the result obj, but we also need to remove it + //like the 'CopyWith' + mappingConfig.forEach((targetField, mappingConfig) { if (mappingConfig.ignore) { targetToSource.remove(targetField); } }); + // for (final sourceEntry in sourceMap.entries) { + // Map> matchedSourceClazzInSourceMapping = + // _findMatchingSourceClazzInMappingMap( + // mappingStringConfig, sourceEntry.value.displayName); + // for (var f in _findFields(sourceEntry.key)) { + // if (targetToSource.containsKey(f.name) && !caseSensitiveFields) { + // final duplicatedKey = targetToSource.keys + // .toList() + // .firstWhere((k) => k.toUpperCase() == f.name.toUpperCase()); + // throw InvalidGenerationSourceError( + // 'Mapper got case insensitive fields and contains fields: ${f.name} and $duplicatedKey. If you use a case-sensitive mapper, make sure the fields are unique in a case insensitive way.', + // todo: "Use case sensitive mapper or change field's names"); + // } + // if (matchedSourceClazzInSourceMapping.isNotEmpty && + // _shouldSearchMoreFields(f)) { + // for (var matchedTarget in matchedSourceClazzInSourceMapping.keys) { + // final sourceValueList = + // matchedSourceClazzInSourceMapping[matchedTarget]!; + // final fieldClazz = f.type.element as ClassElement; + // final foundFields = _findFields(fieldClazz); + // + // final refChain = RefChain.byPropNames( + // sourceEntry.value, sourceValueList.sublist(1)); + // targetToSource[matchedTarget] = + // SourceAssignment.fromRefChain(refChain); + // + // // final matchingFieldForSourceValues = + // // _findMatchingField(sourceValueList.sublist(1), foundFields); + // // if (matchingFieldForSourceValues != null) { + // // final sourceRefer = sourceValueList + // // .sublist(0, sourceValueList.length - 1) + // // .join("."); + // // targetToSource[matchedTarget] = SourceAssignment.fromField( + // // matchingFieldForSourceValues, sourceRefer); + // // } else { + // // targetToSource[f.name] = + // // SourceAssignment.fromField(f, sourceEntry.value.displayName); + // // } + // } + // } else { + // targetToSource[f.name] = + // SourceAssignment.fromRefChain(RefChain([sourceEntry.value, f])); + // // targetToSource[f.name] = + // // SourceAssignment.fromField(f, sourceEntry.value.displayName); + // } + // } + // } + // + // /// If there are Mapping Annotations on the method, the source attribute of the source mapping class, + // /// will be replaced with the source attribute of the given mapping config. + // mappingConfig.forEach((targetField, mappingConfig) { + // final sourceField = mappingConfig.source; + // if (sourceField != null) { + // if (sourceField.toFunctionValue() != null) { + // targetToSource[targetField] = SourceAssignment.fromFunction( + // sourceField.toFunctionValue()!, [...sources]); + // } else if (sourceField.toStringValue() != null) { + // final sourceFieldString = sourceField.toStringValue()!; + // // sourceField exists in any sourceParam + // if (targetToSource.containsKey(sourceFieldString)) { + // // replace mapping target with mapping + // targetToSource.putIfAbsent( + // targetField, () => targetToSource[sourceFieldString]!); + // targetToSource.remove(sourceFieldString); + // } + // } + // } + // + // if (mappingConfig.ignore) { + // targetToSource.remove(targetField); + // } + // }); return [targetToSource, customTargetToSource]; } /// Extracts all Mapping Config Entries in [mappingConfig] which contains source mappings of type string -Map _extractStringMappingConfig( - Map mappingConfig) { +Map _extractStringMappingConfig(Map mappingConfig) { final mappingStringConfig = {}; mappingConfig.forEach((key, value) { if (value.source != null && value.source!.toStringValue() != null) { @@ -254,12 +393,27 @@ Map _extractStringMappingConfig( return mappingStringConfig; } +///find the relation between the parameter and the current mapping source +///if it pairs successfully, we will split the source string to a list +///Otherwise , we will return a empty map +///Obviously, we can find there is only one pair in the map +Map> _findMatchingSourceClazzInMappingConfig( + MappingConfig perMappingConfig, List sources) { + final sourceValueList = perMappingConfig.source!.toStringValue()!.split("."); + final sourceObj = sourceValueList[0]; + for (var source in sources) { + if (source.displayName == sourceObj) { + return {source: sourceValueList}; + } + } + return {}; +} + /// Searches for a matching class for every given [MappingConfig] in [mappingStringConfig], matched against the given [matchingSourceClazzName] /// For MappingConfigs including dot seperated clazz attributes, the first value before the first dot is matched against the given matchingSourceClazzName. /// Example: A MappingConfig containing "user.address.zipcode" would try to match against user List> _findMatchingSourceClazzInMapping( - Map mappingStringConfig, - String matchingSourceClazzName) { + Map mappingStringConfig, String matchingSourceClazzName) { List> matchedSourceClazzInSourceMapping = []; mappingStringConfig.forEach((key, value) { // clazz.attribute1.attribute1_1 @@ -273,8 +427,7 @@ List> _findMatchingSourceClazzInMapping( } Map> _findMatchingSourceClazzInMappingMap( - Map mappingStringConfig, - String matchingSourceClazzName) { + Map mappingStringConfig, String matchingSourceClazzName) { Map> ret = {}; mappingStringConfig.forEach((key, value) { // clazz.attribute1.attribute1_1 @@ -292,8 +445,7 @@ Map> _findMatchingSourceClazzInMappingMap( /// /// Example: [sources]="user,address,zipcode" with [fields]=address would identify address as a field, then continue searching in the address field for the zipcode field. /// If the address contains a field zipcode, the zipcode field is returned. -FieldElement? _findMatchingField( - List sources, List fields) { +FieldElement? _findMatchingField(List sources, List fields) { for (var source in sources) { final potentielFinds = fields.where((element) => element.name == source); if (potentielFinds.isEmpty) { diff --git a/generator/lib/mapper_config.dart b/generator/lib/mapper_config.dart index 4682725..ee754b3 100644 --- a/generator/lib/mapper_config.dart +++ b/generator/lib/mapper_config.dart @@ -30,8 +30,10 @@ class MapperConfig { final reader = ConstantReader(element); final sourceReader = reader.read('source'); config[reader.read('target').stringValue] = MappingConfig( - sourceReader.isNull ? null : sourceReader.objectValue, - reader.read('ignore').boolValue); + sourceReader.isNull ? null : sourceReader.objectValue, + reader.read('ignore').boolValue, + reader.read('isStraight').boolValue, + ); } return config; } @@ -45,6 +47,7 @@ class MapperConfig { class MappingConfig { final DartObject? source; final bool ignore; - - MappingConfig(this.source, this.ignore); + //you can use the attribute to judge whether need to fill target straightly + final bool isStraight; + MappingConfig(this.source, this.ignore, this.isStraight); } diff --git a/generator/lib/models/source_assignment.dart b/generator/lib/models/source_assignment.dart index c303b6b..858124d 100644 --- a/generator/lib/models/source_assignment.dart +++ b/generator/lib/models/source_assignment.dart @@ -5,13 +5,16 @@ import 'package:smartstruct_generator/models/RefChain.dart'; class SourceAssignment { FieldElement? field; String? sourceName; + //this attr is judge whether the parameter need to fill the target straightly + bool isStraight = false; ExecutableElement? function; List? params; RefChain? refChain; - SourceAssignment.fromField(this.field, this.sourceName); + //if you use the method to create the SourceAssignment, isStraight default will be true + SourceAssignment.fromField(this.field, this.sourceName, {this.isStraight = true}); SourceAssignment.fromFunction(this.function, this.params); SourceAssignment.fromRefChain(this.refChain) { sourceName = refChain!.removeLast().refWithQuestion; @@ -28,22 +31,22 @@ class SourceAssignment { } bool _isMapable(DartType type) { - if(_isCoreListLike(type)) { + if (_isCoreListLike(type)) { return true; } - if(type is! InterfaceType) { + if (type is! InterfaceType) { return false; } return type.allSupertypes.any(_isCoreListLike); } String collectInvoke(DartType type) { - if(type.isDartCoreList) { + if (type.isDartCoreList) { return "toList()"; - } else if(type.isDartCoreSet) { + } else if (type.isDartCoreSet) { return "toSet()"; - } + } throw "Unkown type ${type.getDisplayString(withNullability: false)}"; } diff --git a/smartstruct/lib/src/annotations.dart b/smartstruct/lib/src/annotations.dart index d330d7e..0715ba2 100644 --- a/smartstruct/lib/src/annotations.dart +++ b/smartstruct/lib/src/annotations.dart @@ -6,7 +6,10 @@ class Mapper { final bool caseSensitiveFields; final bool generateStaticProxy; - const Mapper({this.useInjection = false, this.caseSensitiveFields = false, this.generateStaticProxy = false}); + const Mapper( + {this.useInjection = false, + this.caseSensitiveFields = false, + this.generateStaticProxy = false}); } const mapper = Mapper(); @@ -18,7 +21,8 @@ class Mapping { final dynamic source; final String target; final bool ignore; - const Mapping({required this.target, this.source, this.ignore = false}); + final bool isStraight; + const Mapping({required this.target, this.source, this.ignore = false, this.isStraight = false}); } /// Annotate methods to indicate that you don't want smartstruct to generate a mapping implementation for you