Skip to content

Commit 03ee572

Browse files
committed
Optional static mapping
1 parent f8c1f2c commit 03ee572

File tree

8 files changed

+114
-29
lines changed

8 files changed

+114
-29
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import 'package:smartstruct/smartstruct.dart';
2+
3+
part 'function_mapping_static.mapper.g.dart';
4+
5+
// TARGET
6+
7+
class Dog {
8+
final String name;
9+
final String breed;
10+
final int age;
11+
late AgeHolderTarget? model;
12+
13+
Dog(this.name, this.breed, this.age);
14+
}
15+
16+
// SOURCE
17+
18+
class DogModel {
19+
final String name;
20+
final int age;
21+
22+
DogModel(this.name, this.age);
23+
}
24+
25+
class AgeHolderSource {
26+
final int age;
27+
AgeHolderSource(this.age);
28+
}
29+
30+
class AgeHolderTarget {
31+
late int age;
32+
}
33+
34+
// This example uses static helper methods to map inner fields
35+
@Mapper(useStaticMapping: false)
36+
abstract class DogMapper {
37+
static String breedCustom(DogModel model) => 'customBreed';
38+
39+
static AgeHolderSource? toAgeHolderSource(DogModel model) =>
40+
AgeHolderSource(model.age);
41+
42+
static String fullNameWithAge(DogModel model) => model.name + '${model.age}';
43+
44+
@Mapping(source: fullNameWithAge, target: 'name')
45+
@Mapping(source: breedCustom, target: 'breed')
46+
@Mapping(source: toAgeHolderSource, target: 'model')
47+
Dog fromDogModel(DogModel model);
48+
49+
AgeHolderTarget fromAgeHolderSource(AgeHolderSource model);
50+
}

example/lib/static_mapping/function_mapping_static.mapper.g.dart

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

generator/analysis_options.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
include: package:lints/recommended.yaml
2-
32
# For lint rules and documentation, see http://dart-lang.github.io/linter/lints.
43

54
# Uncomment to specify additional rules.
@@ -10,6 +9,3 @@ include: package:lints/recommended.yaml
109
# analyzer:
1110
# exclude:
1211
# - path/to/excluded/files/**
13-
analyzer:
14-
enable-experiment:
15-
- non-nullable

generator/lib/code_builders/assignment_builder.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ Expression generateSourceFieldAssignment(SourceAssignment sourceAssignment,
2727
.map((sourceParam) => refer(sourceParam.displayName));
2828
Expression expr = refer(sourceFunction.name);
2929
if (sourceFunction.isStatic &&
30-
sourceFunction.enclosingElement3.name != null) {
31-
expr = refer(sourceFunction.enclosingElement3.name!)
30+
sourceFunction.enclosingElement.name != null) {
31+
expr = refer(sourceFunction.enclosingElement.name!)
3232
.property(sourceFunction.name);
3333
}
3434
sourceFieldAssignment = expr.call(
@@ -191,11 +191,11 @@ Iterable<MethodElement> _findMatchingMappingMethod(ClassElement classElement,
191191
if (met.parameters.isEmpty) {
192192
return false;
193193
}
194-
final metReturnElement = met.returnType.element2;
195-
final metParameterElement = met.parameters.first.type.element2;
194+
final metReturnElement = met.returnType.element;
195+
final metParameterElement = met.parameters.first.type.element;
196196

197-
final targetReturnElement = targetReturnType.element2;
198-
final srcParameterElement = sourceParameterType.element2;
197+
final targetReturnElement = targetReturnType.element;
198+
final srcParameterElement = sourceParameterType.element;
199199

200200
return metReturnElement == targetReturnElement &&
201201
(metParameterElement == srcParameterElement);

generator/lib/code_builders/class_builder.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ List<Class> _generateStaticProxy(
3030

3131
List<Method> _generateStaticMethods(
3232
ClassElement abstractClass, Map<String, dynamic> config) {
33+
if (config['useStaticMapping'] == false) return [];
34+
3335
var staticMethods = abstractClass.methods
3436
.where(
3537
(method) =>
@@ -49,7 +51,7 @@ bool _shouldGenerateStaticMethod(MethodElement method) {
4951
}
5052

5153
bool _isAbstractType(DartType type) {
52-
final element = type.element2;
54+
final element = type.element;
5355
if (element is! ClassElement) {
5456
return false;
5557
}

generator/lib/code_builders/method_builder.dart

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@ import 'dart:collection';
33
import 'package:analyzer/dart/element/element.dart';
44
import 'package:code_builder/code_builder.dart';
55
import 'package:smartstruct_generator/code_builders/parameter_copy.dart';
6+
import 'package:smartstruct_generator/mapper_config.dart';
67
import 'package:smartstruct_generator/models/RefChain.dart';
78
import 'package:smartstruct_generator/models/source_assignment.dart';
8-
import 'package:smartstruct_generator/mapper_config.dart';
99
import 'package:source_gen/source_gen.dart';
1010

1111
import 'assignment_builder.dart';
1212

1313
/// Generates the implemented mapper method by the given abstract [MethodElement].
1414
Method buildMapperImplementation(Map<String, dynamic> config,
1515
MethodElement method, ClassElement abstractMapper) {
16-
if (method.returnType.element2 == null) {
16+
if (method.returnType.element == null) {
1717
throw InvalidGenerationSourceError(
1818
'${method.returnType} is not a valid return type',
1919
element: method,
@@ -28,21 +28,20 @@ Method buildMapperImplementation(Map<String, dynamic> config,
2828
refer(method.returnType.getDisplayString(withNullability: true)));
2929
}
3030

31-
3231
/// Generates the implemented mapper method by the given abstract [MethodElement].
3332
Method buildStaticMapperImplementation(Map<String, dynamic> config,
3433
MethodElement method, ClassElement abstractMapper) {
3534
return Method(
36-
(b) => b
35+
(b) => b
3736
..name = '_\$${method.name}'
38-
..requiredParameters.addAll(method.parameters.map((e) => copyParameter(e)))
37+
..requiredParameters
38+
.addAll(method.parameters.map((e) => copyParameter(e)))
3939
..body = _generateBody(config, method, abstractMapper)
4040
..returns =
41-
refer(method.returnType.getDisplayString(withNullability: true)),
41+
refer(method.returnType.getDisplayString(withNullability: true)),
4242
);
4343
}
4444

45-
4645
/// Generates the body for the mapping method.
4746
///
4847
/// 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<String, dynamic> config, MethodElement method,
5150
ClassElement abstractMapper) {
5251
final blockBuilder = BlockBuilder();
5352

54-
final targetClass = method.returnType.element2 as ClassElement;
53+
final targetClass = method.returnType.element as ClassElement;
5554

5655
final sourceParams = method.parameters;
5756

@@ -161,7 +160,7 @@ List<HashMap<String, SourceAssignment>> _targetToSource(
161160
ClassElement target,
162161
MethodElement method,
163162
Map<String, dynamic> config) {
164-
final sourceMap = {for (var e in sources) e.type.element2 as ClassElement: e};
163+
final sourceMap = {for (var e in sources) e.type.element as ClassElement: e};
165164

166165
final caseSensitiveFields = config['caseSensitiveFields'];
167166
final fieldMapper = caseSensitiveFields ? (a) => a : (a) => a.toUpperCase();
@@ -202,10 +201,11 @@ List<HashMap<String, SourceAssignment>> _targetToSource(
202201
for (var matchedTarget in matchedSourceClazzInSourceMapping.keys) {
203202
final sourceValueList =
204203
matchedSourceClazzInSourceMapping[matchedTarget]!;
205-
final fieldClazz = f.type.element2 as ClassElement;
206-
207-
final refChain = RefChain.byPropNames(sourceEntry.value, sourceValueList.sublist(1));
208-
targetToSource[matchedTarget] = SourceAssignment.fromRefChain(refChain);
204+
205+
final refChain = RefChain.byPropNames(
206+
sourceEntry.value, sourceValueList.sublist(1));
207+
targetToSource[matchedTarget] =
208+
SourceAssignment.fromRefChain(refChain);
209209
}
210210
} else {
211211
targetToSource[f.name] =
@@ -302,13 +302,14 @@ FieldElement? _findMatchingField(
302302
final foundField = potentielFinds.first;
303303
// foundField is not string
304304
if (_shouldSearchMoreFields(foundField)) {
305-
final searchClazz = foundField.type.element2 as ClassElement;
305+
final searchClazz = foundField.type.element as ClassElement;
306306
return _findMatchingField(
307307
sources.skip(1).toList(), _findFields(searchClazz));
308308
} else {
309309
return foundField;
310310
}
311311
}
312+
return null;
312313
}
313314

314315
/// A search for a potential underlying should only be continued, if the field is not a primitive type (string, int, double etc)

generator/lib/mapper_config.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class MapperConfig {
1010
static Map<String, dynamic> readMapperConfig(
1111
ConstantReader annotation, ClassElement mappingClass) {
1212
var mapper =
13-
mappingClass.metadata[0].element!.enclosingElement3 as ClassElement;
13+
mappingClass.metadata[0].element!.enclosingElement as ClassElement;
1414
final config = <String, dynamic>{};
1515

1616
for (final field in mapper.fields) {
@@ -37,7 +37,8 @@ class MapperConfig {
3737
}
3838

3939
static bool isIgnoreMapping(MethodElement method) {
40-
final annotations = TypeChecker.fromRuntime(IgnoreMapping).annotationsOf(method);
40+
final annotations =
41+
TypeChecker.fromRuntime(IgnoreMapping).annotationsOf(method);
4142
return annotations.isNotEmpty;
4243
}
4344
}

smartstruct/lib/src/annotations.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@ class Mapper {
55
final bool useInjection;
66
final bool caseSensitiveFields;
77
final bool generateStaticProxy;
8+
final bool useStaticMapping;
89

9-
const Mapper({this.useInjection = false, this.caseSensitiveFields = false, this.generateStaticProxy = false});
10+
const Mapper({
11+
this.useInjection = false,
12+
this.caseSensitiveFields = false,
13+
this.generateStaticProxy = false,
14+
this.useStaticMapping = true,
15+
});
1016
}
1117

1218
const mapper = Mapper();
@@ -35,4 +41,4 @@ class Mapping {
3541
/// ```
3642
class IgnoreMapping {
3743
const IgnoreMapping();
38-
}
44+
}

0 commit comments

Comments
 (0)