Skip to content

Commit 1b7480e

Browse files
committed
created conversion dictionary
1 parent 0326cde commit 1b7480e

10 files changed

+248
-9
lines changed

generator/lib/src/dartstruct_generator.dart

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
11
import 'package:analyzer/dart/element/element.dart';
2+
import 'package:analyzer/dart/element/type_system.dart';
3+
import 'package:build/build.dart';
24
import 'package:build/src/builder/build_step.dart';
35
import 'package:code_builder/code_builder.dart';
46
import 'package:dart_style/dart_style.dart';
57
import 'package:dartstruct_generator/src/name_provider.dart';
68
import 'package:logging/logging.dart';
79
import 'package:source_gen/source_gen.dart';
810
import 'package:dartstruct/dartstruct.dart';
9-
import './extensions/extensions.dart';
11+
import 'extensions/extensions.dart';
12+
import 'mappers/conversions/conversions.dart';
1013
import 'models/input_source.dart';
1114
import 'models/output_source.dart';
15+
import 'mappers/mappers.dart';
16+
import 'dart:core';
1217

1318
class DartStructGenerator extends GeneratorForAnnotation<Mapper> {
1419
final _emitter = DartEmitter();
1520
final _formatter = DartFormatter();
1621
final _logger = Logger('dartstruct');
22+
Conversions _conversions;
1723

1824
@override
19-
String generateForAnnotatedElement(Element element, ConstantReader annotation, BuildStep buildStep) {
25+
Future<String> generateForAnnotatedElement(Element element, ConstantReader annotation, BuildStep buildStep) async {
26+
27+
final dartCoreLibrary = await buildStep.resolver.findLibraryByName('dart.core');
28+
29+
_conversions = Conversions(dartCoreLibrary);
2030

2131
if (element is! ClassElement) {
2232
throw InvalidGenerationSourceError('${element.displayName} cannot be annotated with @Mapper',
@@ -174,18 +184,19 @@ class DartStructGenerator extends GeneratorForAnnotation<Mapper> {
174184

175185
Expression _getMapperExpression(FieldElement outputField, InputSource inputSource) {
176186

177-
final classElement = inputSource.type.element as ClassElement;
178-
final fieldName = outputField.displayName;
187+
MapperAdapter mapper = FieldMapperAdapter.create(inputSource, outputField.displayName);
179188

180-
final inputFieldElement = classElement.fields.firstWhere((field) => field.displayName == fieldName && field.getter != null, orElse: () => null);
189+
if (mapper == null) {
190+
return null;
191+
}
181192

182193

183-
if (inputFieldElement?.type == outputField.type) {
184-
return refer(inputSource.name).nullSafeProperty(fieldName);
194+
if (mapper.returnType != outputField.type && _conversions.canConvert(mapper.returnType, outputField.type)) {
195+
mapper = _conversions.convert(mapper.returnType, outputField.type, mapper);
196+
return mapper.expression;
185197
}
186198

187-
return null;
188-
199+
return mapper.expression;
189200

190201
}
191202

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import 'dart:collection';
2+
3+
import 'package:analyzer/dart/element/element.dart';
4+
import 'package:analyzer/dart/element/type.dart';
5+
import 'package:analyzer/dart/element/type_provider.dart';
6+
import 'package:dartstruct_generator/src/mappers/conversions/primitive_to_string_mapper.dart';
7+
import 'package:dartstruct_generator/src/mappers/conversions/string_to_num_mapper.dart';
8+
import 'package:dartstruct_generator/src/mappers/mappers.dart';
9+
import 'package:equatable/equatable.dart';
10+
import 'num_to_num_mapper.dart';
11+
12+
13+
class Conversions {
14+
15+
final Map<_ConvertionKey, _MapperFactory> _convertions = HashMap<_ConvertionKey, _MapperFactory>();
16+
17+
Conversions(LibraryElement dartCoreLibrary) {
18+
19+
DartType intType = dartCoreLibrary.getType('int').thisType;
20+
DartType doubleType = dartCoreLibrary.getType('double').thisType;
21+
DartType boolType = dartCoreLibrary.getType('bool').thisType;
22+
DartType numType = dartCoreLibrary.getType('num').thisType;
23+
DartType stringType = dartCoreLibrary.getType('String').thisType;
24+
25+
26+
// to string
27+
_addConvertion(intType, stringType, (parent) => PrimitiveToStringMapper(parent, stringType));
28+
_addConvertion(doubleType, stringType, (parent) => PrimitiveToStringMapper(parent, stringType));
29+
_addConvertion(boolType, stringType, (parent) => PrimitiveToStringMapper(parent, stringType));
30+
31+
// to int
32+
_addConvertion(numType, intType, (parent) => NumToNumMapper(parent, intType));
33+
_addConvertion(doubleType, intType, (parent) => NumToNumMapper(parent, intType));
34+
_addConvertion(stringType, intType, (parent) => StringToNumMapper(parent, intType));
35+
36+
// to double
37+
_addConvertion(numType, doubleType, (parent) => NumToNumMapper(parent, doubleType));
38+
_addConvertion(intType, doubleType, (parent) => NumToNumMapper(parent, doubleType));
39+
_addConvertion(stringType, doubleType, (parent) => StringToNumMapper(parent, doubleType));
40+
41+
// to num
42+
_addConvertion(intType, numType, (parent) => NumToNumMapper(parent, numType));
43+
_addConvertion(doubleType, numType, (parent) => NumToNumMapper(parent, numType));
44+
_addConvertion(stringType, numType, (parent) => StringToNumMapper(parent, numType));
45+
46+
}
47+
48+
bool canConvert(DartType from, DartType to) => _convertions.containsKey(_ConvertionKey(from, to));
49+
50+
MapperAdapter convert(DartType from, DartType to, MapperAdapter parent) => _convertions[_ConvertionKey(from, to)](parent);
51+
52+
void _addConvertion(DartType from, DartType to, _MapperFactory mapperFactory) {
53+
final key = _ConvertionKey(from, to);
54+
_convertions.putIfAbsent(key, () => mapperFactory);
55+
}
56+
57+
}
58+
59+
class _ConvertionKey extends Equatable {
60+
61+
final DartType from;
62+
final DartType to;
63+
64+
_ConvertionKey(this.from, this.to);
65+
66+
@override
67+
List<Object> get props => [from, to];
68+
69+
}
70+
71+
typedef _MapperFactory = MapperAdapter Function(MapperAdapter parent);
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import 'package:analyzer/dart/element/type.dart';
2+
import 'package:code_builder/src/specs/expression.dart';
3+
import 'package:dartstruct_generator/src/mappers/mappers.dart';
4+
5+
class NumToNumMapper implements MapperAdapter {
6+
7+
final MapperAdapter _mapper;
8+
final DartType _numType;
9+
10+
NumToNumMapper(this._mapper, this._numType);
11+
12+
@override
13+
Expression get expression {
14+
15+
final mapperExpression = _mapper.expression;
16+
17+
if (_numType.isDartCoreInt) {
18+
return mapperExpression.nullSafeProperty('toInt').call([]);
19+
}
20+
21+
if (_numType.isDartCoreDouble) {
22+
return mapperExpression.nullSafeProperty('toDouble').call([]);
23+
}
24+
25+
return mapperExpression;
26+
27+
}
28+
29+
@override
30+
DartType get returnType => _numType;
31+
32+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import 'package:analyzer/dart/element/type.dart';
2+
import 'package:code_builder/src/specs/expression.dart';
3+
import 'package:dartstruct_generator/src/mappers/mappers.dart';
4+
5+
class PrimitiveToStringMapper implements MapperAdapter {
6+
7+
final MapperAdapter _mapper;
8+
final DartType _stringType;
9+
10+
PrimitiveToStringMapper(this._mapper, this._stringType);
11+
12+
@override
13+
Expression get expression => _mapper.expression.nullSafeProperty('toString').call([]);
14+
15+
@override
16+
DartType get returnType => _stringType;
17+
18+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import 'package:analyzer/dart/element/type.dart';
2+
import 'package:code_builder/code_builder.dart';
3+
import 'package:code_builder/src/specs/expression.dart';
4+
import 'package:dartstruct_generator/src/mappers/mappers.dart';
5+
6+
class StringToNumMapper implements MapperAdapter {
7+
8+
final MapperAdapter _mapper;
9+
final DartType _numType;
10+
11+
StringToNumMapper(this._mapper, this._numType);
12+
13+
@override
14+
Expression get expression {
15+
16+
final mapperExpression = _mapper.expression;
17+
18+
if (_numType.isDartCoreInt) {
19+
return _parseExpression(mapperExpression, 'int');
20+
}
21+
22+
if (_numType.isDartCoreDouble) {
23+
return _parseExpression(mapperExpression, 'double');
24+
}
25+
26+
if (_numType.isDartCoreNum) {
27+
return _parseExpression(mapperExpression, 'num');
28+
}
29+
30+
return _mapper.expression;
31+
32+
}
33+
34+
Expression _parseExpression(Expression variable, String parseTo) {
35+
final nullValue = refer('null');
36+
return variable.equalTo(nullValue).conditional(nullValue, refer(parseTo).property('parse').call([variable]));
37+
}
38+
39+
@override
40+
DartType get returnType => _numType;
41+
42+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import 'package:analyzer/dart/element/element.dart';
2+
import 'package:analyzer/dart/element/type.dart';
3+
import 'package:code_builder/src/specs/expression.dart';
4+
import 'package:dartstruct_generator/src/models/input_source.dart';
5+
6+
import 'mappers.dart';
7+
8+
class FieldMapperAdapter implements MapperAdapter {
9+
final FieldElement _fieldElement;
10+
final MapperAdapter _mapper;
11+
12+
FieldMapperAdapter(this._mapper, this._fieldElement);
13+
14+
@override
15+
Expression get expression => _mapper.expression.nullSafeProperty(_fieldElement.displayName);
16+
17+
@override
18+
DartType get returnType => _fieldElement.type;
19+
20+
static FieldMapperAdapter create(InputSource input, String fieldName) {
21+
22+
MapperAdapter mapper = InputSourceMapperAdapter(input);
23+
24+
final classElement = input.type.element as ClassElement;
25+
26+
final inputFieldElement = classElement.fields.firstWhere((field) => field.displayName == fieldName && field.getter != null, orElse: () => null);
27+
28+
if (inputFieldElement == null) {
29+
return null;
30+
}
31+
32+
return FieldMapperAdapter(mapper, inputFieldElement);
33+
}
34+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import 'package:analyzer/dart/element/type.dart';
2+
import 'package:code_builder/code_builder.dart';
3+
import 'package:code_builder/src/specs/expression.dart';
4+
import 'package:dartstruct_generator/src/models/input_source.dart';
5+
6+
import 'mapper_adapter.dart';
7+
8+
class InputSourceMapperAdapter implements MapperAdapter {
9+
10+
final InputSource _source;
11+
12+
InputSourceMapperAdapter(this._source);
13+
14+
@override
15+
Expression get expression => refer(_source.name);
16+
17+
@override
18+
DartType get returnType => _source.type;
19+
20+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import 'package:analyzer/dart/element/type.dart';
2+
import 'package:code_builder/code_builder.dart';
3+
4+
abstract class MapperAdapter {
5+
Expression get expression;
6+
DartType get returnType;
7+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export 'mapper_adapter.dart';
2+
export 'input_source_mapper_adapter.dart';
3+
export 'field_mapper_adapter.dart';

generator/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ dependencies:
1313
analyzer: ^0.39.5
1414
recase: ^3.0.0
1515
logging: ^0.11.4
16+
equatable: ^1.1.1
1617
dartstruct:
1718
path: ../core
1819

0 commit comments

Comments
 (0)