Skip to content

Commit 446e906

Browse files
committed
instantiated empty target
1 parent 4e65c2e commit 446e906

File tree

6 files changed

+112
-11
lines changed

6 files changed

+112
-11
lines changed

generator/lib/src/dartstruct_generator.dart

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'package:analyzer/dart/element/element.dart';
22
import 'package:build/src/builder/build_step.dart';
33
import 'package:code_builder/code_builder.dart';
44
import 'package:dart_style/dart_style.dart';
5+
import 'package:dartstruct_generator/src/name_provider.dart';
56
import 'package:source_gen/source_gen.dart';
67
import 'package:dartstruct/dartstruct.dart';
78
import './extensions/extensions.dart';
@@ -29,21 +30,24 @@ class DartStructGenerator extends GeneratorForAnnotation<Mapper> {
2930
);
3031
}
3132

32-
final classBuilder = ClassBuilder()
33-
..name = '${classElement.displayName}Impl'
34-
..abstract = false
35-
..extend = refer(classElement.displayName)
36-
..methods.addAll(classElement.methods.where((method) => method.isAbstract).map(_generateMethod));
33+
final nameProvider = NameProvider(classElement);
3734

38-
final mapperImpl = classBuilder.build();
35+
36+
final mapperImpl = Class((builder) {
37+
builder
38+
..name = '${classElement.displayName}Impl'
39+
..abstract = false
40+
..extend = refer(classElement.displayName)
41+
..methods.addAll(classElement.methods.where((method) => method.isAbstract).map((method) => _generateMethod(method, nameProvider.forMethod(method))));
42+
});
3943

4044
final code = '${mapperImpl.accept(_emitter)}';
4145

4246
return _formatter.format(code);
4347

4448
}
4549

46-
Method _generateMethod(MethodElement method) {
50+
Method _generateMethod(MethodElement method, NameProvider nameProvider) {
4751

4852
if (method.parameters.isEmpty) {
4953
throw InvalidGenerationSourceError('Method must provide an argument',
@@ -95,13 +99,25 @@ class DartStructGenerator extends GeneratorForAnnotation<Mapper> {
9599
);
96100
}
97101

102+
if (returnType.isDynamic) {
103+
throw InvalidGenerationSourceError('Dynamic type is not supported',
104+
element: method
105+
);
106+
}
107+
108+
if (!returnType.hasEmptyConstructor) {
109+
throw InvalidGenerationSourceError('Return type must provide an empty parameters constructor',
110+
element: method.returnType.element
111+
);
112+
}
113+
98114
return Method((builder) {
99115
builder
100116
..annotations.add(CodeExpression(Code('override')))
101117
..name = method.displayName
102118
..requiredParameters.add(_generateSourceParameter(source))
103119
..returns = refer(returnType.element.displayName)
104-
..body = _generateMethodBody(method);
120+
..body = _generateMethodBody(method, nameProvider);
105121
});
106122
}
107123

@@ -113,8 +129,19 @@ class DartStructGenerator extends GeneratorForAnnotation<Mapper> {
113129
});
114130
}
115131

116-
Code _generateMethodBody(MethodElement methodElement) {
117-
return Code('return null;');
132+
Code _generateMethodBody(MethodElement methodElement, NameProvider nameProvider) {
133+
134+
print(nameProvider);
135+
136+
final targetType = methodElement.returnType;
137+
138+
final targetName = nameProvider.provideVariableName(targetType);
139+
140+
return Block((builder) {
141+
builder
142+
..addExpression(refer(targetType.element.displayName).newInstance([]).assignFinal(targetName))
143+
..addExpression(refer(targetName).returned);
144+
});
118145
}
119146

120147
}

generator/lib/src/extensions/dart_type_extension.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:analyzer/dart/element/element.dart';
12
import 'package:analyzer/dart/element/type.dart';
23

34
extension DartTypeExtension on DartType {
@@ -16,4 +17,27 @@ extension DartTypeExtension on DartType {
1617

1718
bool get isCollection => isDartCoreMap || isDartCoreList || isDartCoreSet;
1819

20+
bool get hasEmptyConstructor {
21+
22+
if (element is ClassElement) {
23+
final classElement = element as ClassElement;
24+
25+
for (final constructor in classElement.constructors) {
26+
27+
final hasRequiredParameter = constructor.parameters.any(_isRequiredParameter);
28+
29+
if (!hasRequiredParameter) {
30+
return true;
31+
}
32+
33+
}
34+
}
35+
36+
return false;
37+
38+
}
39+
40+
bool _isRequiredParameter(ParameterElement parameterElement) {
41+
return parameterElement.isRequiredNamed || parameterElement.isRequiredPositional || parameterElement.hasRequired;
42+
}
1943
}

generator/lib/src/name_provider.dart

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import 'package:analyzer/dart/element/element.dart';
2+
import 'package:analyzer/dart/element/type.dart';
3+
import 'package:recase/recase.dart';
4+
5+
class NameProvider {
6+
List<String> _names;
7+
8+
NameProvider(ClassElement classElement) {
9+
_names = [
10+
classElement.displayName,
11+
...classElement.accessors.map((accessor) => accessor.displayName).toSet(),
12+
...classElement.methods.map((method) => method.displayName),
13+
...classElement.constructors.map((constructor) => constructor.displayName).toSet()
14+
];
15+
}
16+
17+
NameProvider._privateConstructor(List<String> names) {
18+
_names = [ ...names ];
19+
}
20+
21+
NameProvider forMethod(MethodElement methodElement) {
22+
return NameProvider._privateConstructor([
23+
..._names,
24+
...methodElement.parameters.map((parameter) => parameter.displayName)
25+
]);
26+
}
27+
28+
String provideVariableName(DartType type) {
29+
30+
final displayName = type.element.displayName;
31+
32+
final name = ReCase(displayName).camelCase;
33+
34+
var nameWithIndex = name;
35+
var counter = 1;
36+
37+
while(_names.contains(nameWithIndex)) {
38+
nameWithIndex = '$name$counter';
39+
counter++;
40+
}
41+
42+
_names.add(nameWithIndex);
43+
44+
return nameWithIndex;
45+
46+
}
47+
}

generator/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ dependencies:
1111
code_builder: ^3.2.1
1212
dart_style: ^1.3.3
1313
analyzer: ^0.39.5
14+
recase: ^3.0.0
1415
dartstruct:
1516
path: ../core
1617

integration_tests/test/empty_method_mapper/empty_method_mapper.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class Model {
1010
class Dto {
1111
String field;
1212
}
13+
1314
@Mapper()
1415
abstract class EmptyMethodMapper {
1516

integration_tests/test/empty_method_mapper/empty_method_mapper_test.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ void main() {
1010
});
1111

1212
test('Should return null', () {
13-
expect(EmptyMethodMapper.INSTANCE, isNotNull);
13+
final model = Model()..field = 'test';
14+
expect(EmptyMethodMapper.INSTANCE.modelToDto(model), isNotNull);
1415
});
1516

1617
});

0 commit comments

Comments
 (0)