From c841d0dc8e4ab773e95075afcce4d67cc1d17296 Mon Sep 17 00:00:00 2001 From: Petr Nymsa Date: Sun, 6 Nov 2022 11:41:32 +0100 Subject: [PATCH 1/2] chore(release): publish packages - smartstruct@1.4.0 - smartstruct_generator@1.4.0 --- example/pubspec.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/example/pubspec.yaml b/example/pubspec.yaml index c89a865..3a358d7 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -3,20 +3,20 @@ description: example version: 1.0.1 # homepage: https://www.example.com environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.17.0 <3.0.0" publish_to: none dependencies: freezed_annotation: ^2.1.0 injectable: ^1.5.3 - smartstruct: ^1.3.0 + smartstruct: ^1.4.0 dev_dependencies: build_runner: ^2.1.7 freezed: ^2.1.0+1 injectable_generator: ^1.5.3 - smartstruct_generator: ^1.3.0 + smartstruct_generator: ^1.4.0 #smartstruct_generator: # path: ../generator -dependency_overrides: - smartstruct: - path: ../smartstruct +# dependency_overrides: +# smartstruct: +# path: ../smartstruct From 1d594215f2e217b98cb0734b2132d418a46728bf Mon Sep 17 00:00:00 2001 From: Petr Nymsa Date: Sun, 13 Nov 2022 15:45:36 +0100 Subject: [PATCH 2/2] Optional static mapping --- .../function_mapping_static.dart | 50 +++++++++++++++++++ .../function_mapping_static.mapper.g.dart | 29 +++++++++++ generator/analysis_options.yaml | 4 -- .../lib/code_builders/assignment_builder.dart | 12 ++--- .../lib/code_builders/class_builder.dart | 4 +- .../lib/code_builders/method_builder.dart | 29 +++++------ generator/lib/mapper_config.dart | 5 +- smartstruct/lib/src/annotations.dart | 10 +++- 8 files changed, 114 insertions(+), 29 deletions(-) create mode 100644 example/lib/static_mapping/function_mapping_static.dart create mode 100644 example/lib/static_mapping/function_mapping_static.mapper.g.dart diff --git a/example/lib/static_mapping/function_mapping_static.dart b/example/lib/static_mapping/function_mapping_static.dart new file mode 100644 index 0000000..25289d3 --- /dev/null +++ b/example/lib/static_mapping/function_mapping_static.dart @@ -0,0 +1,50 @@ +import 'package:smartstruct/smartstruct.dart'; + +part 'function_mapping_static.mapper.g.dart'; + +// TARGET + +class Dog { + final String name; + final String breed; + final int age; + late AgeHolderTarget? model; + + Dog(this.name, this.breed, this.age); +} + +// SOURCE + +class DogModel { + final String name; + final int age; + + DogModel(this.name, this.age); +} + +class AgeHolderSource { + final int age; + AgeHolderSource(this.age); +} + +class AgeHolderTarget { + late int age; +} + +// This example uses static helper methods to map inner fields +@Mapper(useStaticMapping: false) +abstract class DogMapper { + static String breedCustom(DogModel model) => 'customBreed'; + + static AgeHolderSource? toAgeHolderSource(DogModel model) => + AgeHolderSource(model.age); + + static String fullNameWithAge(DogModel model) => model.name + '${model.age}'; + + @Mapping(source: fullNameWithAge, target: 'name') + @Mapping(source: breedCustom, target: 'breed') + @Mapping(source: toAgeHolderSource, target: 'model') + Dog fromDogModel(DogModel model); + + AgeHolderTarget fromAgeHolderSource(AgeHolderSource model); +} diff --git a/example/lib/static_mapping/function_mapping_static.mapper.g.dart b/example/lib/static_mapping/function_mapping_static.mapper.g.dart new file mode 100644 index 0000000..30cb016 --- /dev/null +++ b/example/lib/static_mapping/function_mapping_static.mapper.g.dart @@ -0,0 +1,29 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'function_mapping_static.dart'; + +// ************************************************************************** +// MapperGenerator +// ************************************************************************** + +class DogMapperImpl extends DogMapper { + DogMapperImpl() : super(); + + @override + Dog fromDogModel(DogModel model) { + final dog = Dog(DogMapper.fullNameWithAge(model), + DogMapper.breedCustom(model), model.age); + dog.model = () { + final tmp = DogMapper.toAgeHolderSource(model); + return tmp == null ? null : fromAgeHolderSource(tmp); + }(); + return dog; + } + + @override + AgeHolderTarget fromAgeHolderSource(AgeHolderSource model) { + final ageholdertarget = AgeHolderTarget(); + ageholdertarget.age = model.age; + return ageholdertarget; + } +} diff --git a/generator/analysis_options.yaml b/generator/analysis_options.yaml index 1118862..1776a13 100644 --- a/generator/analysis_options.yaml +++ b/generator/analysis_options.yaml @@ -1,5 +1,4 @@ include: package:lints/recommended.yaml - # For lint rules and documentation, see http://dart-lang.github.io/linter/lints. # Uncomment to specify additional rules. @@ -10,6 +9,3 @@ include: package:lints/recommended.yaml # analyzer: # exclude: # - path/to/excluded/files/** -analyzer: - enable-experiment: - - non-nullable diff --git a/generator/lib/code_builders/assignment_builder.dart b/generator/lib/code_builders/assignment_builder.dart index 13fd5b2..96b680d 100644 --- a/generator/lib/code_builders/assignment_builder.dart +++ b/generator/lib/code_builders/assignment_builder.dart @@ -27,8 +27,8 @@ Expression generateSourceFieldAssignment(SourceAssignment sourceAssignment, .map((sourceParam) => refer(sourceParam.displayName)); Expression expr = refer(sourceFunction.name); if (sourceFunction.isStatic && - sourceFunction.enclosingElement3.name != null) { - expr = refer(sourceFunction.enclosingElement3.name!) + sourceFunction.enclosingElement.name != null) { + expr = refer(sourceFunction.enclosingElement.name!) .property(sourceFunction.name); } sourceFieldAssignment = expr.call( @@ -191,11 +191,11 @@ Iterable _findMatchingMappingMethod(ClassElement classElement, if (met.parameters.isEmpty) { return false; } - final metReturnElement = met.returnType.element2; - final metParameterElement = met.parameters.first.type.element2; + final metReturnElement = met.returnType.element; + final metParameterElement = met.parameters.first.type.element; - final targetReturnElement = targetReturnType.element2; - final srcParameterElement = sourceParameterType.element2; + final targetReturnElement = targetReturnType.element; + final srcParameterElement = sourceParameterType.element; return metReturnElement == targetReturnElement && (metParameterElement == srcParameterElement); diff --git a/generator/lib/code_builders/class_builder.dart b/generator/lib/code_builders/class_builder.dart index c07d4de..8ad204a 100644 --- a/generator/lib/code_builders/class_builder.dart +++ b/generator/lib/code_builders/class_builder.dart @@ -30,6 +30,8 @@ List _generateStaticProxy( List _generateStaticMethods( ClassElement abstractClass, Map config) { + if (config['useStaticMapping'] == false) return []; + var staticMethods = abstractClass.methods .where( (method) => @@ -49,7 +51,7 @@ bool _shouldGenerateStaticMethod(MethodElement method) { } bool _isAbstractType(DartType type) { - final element = type.element2; + final element = type.element; if (element is! ClassElement) { return false; } diff --git a/generator/lib/code_builders/method_builder.dart b/generator/lib/code_builders/method_builder.dart index 8a6b6ef..8e38353 100644 --- a/generator/lib/code_builders/method_builder.dart +++ b/generator/lib/code_builders/method_builder.dart @@ -3,9 +3,9 @@ import 'dart:collection'; import 'package:analyzer/dart/element/element.dart'; import 'package:code_builder/code_builder.dart'; import 'package:smartstruct_generator/code_builders/parameter_copy.dart'; +import 'package:smartstruct_generator/mapper_config.dart'; import 'package:smartstruct_generator/models/RefChain.dart'; import 'package:smartstruct_generator/models/source_assignment.dart'; -import 'package:smartstruct_generator/mapper_config.dart'; import 'package:source_gen/source_gen.dart'; import 'assignment_builder.dart'; @@ -13,7 +13,7 @@ import 'assignment_builder.dart'; /// Generates the implemented mapper method by the given abstract [MethodElement]. Method buildMapperImplementation(Map config, MethodElement method, ClassElement abstractMapper) { - if (method.returnType.element2 == null) { + if (method.returnType.element == null) { throw InvalidGenerationSourceError( '${method.returnType} is not a valid return type', element: method, @@ -28,21 +28,20 @@ Method buildMapperImplementation(Map config, refer(method.returnType.getDisplayString(withNullability: true))); } - /// Generates the implemented mapper method by the given abstract [MethodElement]. 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))) + ..requiredParameters + .addAll(method.parameters.map((e) => copyParameter(e))) ..body = _generateBody(config, method, abstractMapper) ..returns = - refer(method.returnType.getDisplayString(withNullability: true)), + 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. @@ -51,7 +50,7 @@ Code _generateBody(Map config, MethodElement method, ClassElement abstractMapper) { final blockBuilder = BlockBuilder(); - final targetClass = method.returnType.element2 as ClassElement; + final targetClass = method.returnType.element as ClassElement; final sourceParams = method.parameters; @@ -161,7 +160,7 @@ List> _targetToSource( ClassElement target, MethodElement method, Map config) { - final sourceMap = {for (var e in sources) e.type.element2 as ClassElement: e}; + final sourceMap = {for (var e in sources) e.type.element as ClassElement: e}; final caseSensitiveFields = config['caseSensitiveFields']; final fieldMapper = caseSensitiveFields ? (a) => a : (a) => a.toUpperCase(); @@ -202,10 +201,11 @@ List> _targetToSource( 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); + + final refChain = RefChain.byPropNames( + sourceEntry.value, sourceValueList.sublist(1)); + targetToSource[matchedTarget] = + SourceAssignment.fromRefChain(refChain); } } else { targetToSource[f.name] = @@ -302,13 +302,14 @@ FieldElement? _findMatchingField( final foundField = potentielFinds.first; // foundField is not string if (_shouldSearchMoreFields(foundField)) { - final searchClazz = foundField.type.element2 as ClassElement; + final searchClazz = foundField.type.element as ClassElement; return _findMatchingField( sources.skip(1).toList(), _findFields(searchClazz)); } else { return foundField; } } + return null; } /// A search for a potential underlying should only be continued, if the field is not a primitive type (string, int, double etc) diff --git a/generator/lib/mapper_config.dart b/generator/lib/mapper_config.dart index 4682725..55487e3 100644 --- a/generator/lib/mapper_config.dart +++ b/generator/lib/mapper_config.dart @@ -10,7 +10,7 @@ class MapperConfig { static Map readMapperConfig( ConstantReader annotation, ClassElement mappingClass) { var mapper = - mappingClass.metadata[0].element!.enclosingElement3 as ClassElement; + mappingClass.metadata[0].element!.enclosingElement as ClassElement; final config = {}; for (final field in mapper.fields) { @@ -37,7 +37,8 @@ class MapperConfig { } static bool isIgnoreMapping(MethodElement method) { - final annotations = TypeChecker.fromRuntime(IgnoreMapping).annotationsOf(method); + final annotations = + TypeChecker.fromRuntime(IgnoreMapping).annotationsOf(method); return annotations.isNotEmpty; } } diff --git a/smartstruct/lib/src/annotations.dart b/smartstruct/lib/src/annotations.dart index d330d7e..edcd799 100644 --- a/smartstruct/lib/src/annotations.dart +++ b/smartstruct/lib/src/annotations.dart @@ -5,8 +5,14 @@ class Mapper { final bool useInjection; final bool caseSensitiveFields; final bool generateStaticProxy; + final bool useStaticMapping; - const Mapper({this.useInjection = false, this.caseSensitiveFields = false, this.generateStaticProxy = false}); + const Mapper({ + this.useInjection = false, + this.caseSensitiveFields = false, + this.generateStaticProxy = false, + this.useStaticMapping = true, + }); } const mapper = Mapper(); @@ -35,4 +41,4 @@ class Mapping { /// ``` class IgnoreMapping { const IgnoreMapping(); -} \ No newline at end of file +}