Skip to content

Commit c75a328

Browse files
committed
converter for enum is supported
1 parent 9a7f5d7 commit c75a328

File tree

9 files changed

+223
-65
lines changed

9 files changed

+223
-65
lines changed

packages/nitrite/lib/src/repository/annotations.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class Entity {
4242
/// Specifies nitrite code generators to generate
4343
/// the code for [EntityConverter] implementation of
4444
/// the marked class.
45-
@Target({TargetKind.classType})
45+
@Target({TargetKind.classType, TargetKind.enumType})
4646
class Convertable {
4747
/// Specifies the generated class name, default is empty.
4848
/// If empty, it will generate the class with name

packages/nitrite/lib/src/repository/entity.dart

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,26 @@ class EntityId {
4242
}
4343

4444
var filters = <Filter>[];
45-
for (var field in _embeddedFields) {
46-
var filterField = "$_fieldName${NitriteConfig.fieldSeparator}$field";
47-
var fieldValue = document[field];
48-
filters.add(where(filterField).eq(fieldValue));
45+
if (_embeddedFields.length == 1 && document is! Document) {
46+
// in case of single embedded field, the value is directly passed
47+
// as the value of the field
48+
var filterField =
49+
"$_fieldName${NitriteConfig.fieldSeparator}${_embeddedFields[0]}";
50+
51+
var nitriteFilter = where(filterField).eq(document);
52+
nitriteFilter.objectFilter = true;
53+
return nitriteFilter;
54+
} else {
55+
for (var field in _embeddedFields) {
56+
var filterField = "$_fieldName${NitriteConfig.fieldSeparator}$field";
57+
var fieldValue = document[field];
58+
filters.add(where(filterField).eq(fieldValue));
59+
}
60+
61+
var nitriteFilter = and(filters) as NitriteFilter;
62+
nitriteFilter.objectFilter = true;
63+
return nitriteFilter;
4964
}
50-
51-
var nitriteFilter = and(filters) as NitriteFilter;
52-
nitriteFilter.objectFilter = true;
53-
return nitriteFilter;
5465
} else {
5566
return where(_fieldName).eq(value);
5667
}
@@ -65,15 +76,26 @@ class EntityId {
6576
}
6677

6778
var filters = <Filter>[];
68-
for (var field in _embeddedFields) {
69-
var filterField = "$_fieldName${NitriteConfig.fieldSeparator}$field";
70-
var fieldValue = document[field];
71-
filters.add(where(filterField).eq(fieldValue));
79+
if (_embeddedFields.length == 1 && document is! Document) {
80+
// in case of single embedded field, the value is directly passed
81+
// as the value of the field
82+
var filterField =
83+
"$_fieldName${NitriteConfig.fieldSeparator}${_embeddedFields[0]}";
84+
85+
var nitriteFilter = where(filterField).eq(document);
86+
nitriteFilter.objectFilter = true;
87+
return nitriteFilter;
88+
} else {
89+
for (var field in _embeddedFields) {
90+
var filterField = "$_fieldName${NitriteConfig.fieldSeparator}$field";
91+
var fieldValue = document[field];
92+
filters.add(where(filterField).eq(fieldValue));
93+
}
94+
95+
var nitriteFilter = and(filters) as NitriteFilter;
96+
nitriteFilter.objectFilter = true;
97+
return nitriteFilter;
7298
}
73-
74-
var nitriteFilter = and(filters) as NitriteFilter;
75-
nitriteFilter.objectFilter = true;
76-
return nitriteFilter;
7799
} else {
78100
if (isNitriteId) {
79101
return where(docId).eq(id.idValue);

packages/nitrite_generator/lib/src/common.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,14 @@ class EntityInfo {
4545
class ConverterInfo {
4646
final String className;
4747
final String converterName;
48+
final bool isEnum;
4849
final List<FieldInfo> fieldInfoList;
4950
final List<PropertyInfo> propertyInfoList;
5051
final ConstructorInfo constructorInfo;
5152

5253
ConverterInfo(this.className,
5354
[this.converterName = "",
55+
this.isEnum = false,
5456
this.fieldInfoList = const [],
5557
this.propertyInfoList = const [],
5658
this.constructorInfo = const ConstructorInfo()]);

packages/nitrite_generator/lib/src/converter_generator.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ class ConverterGenerator extends GeneratorForAnnotation<Convertable> {
1717
generateForAnnotatedElement(
1818
Element element, ConstantReader annotation, BuildStep buildStep) {
1919
// @Convertable is class level annotation only.
20-
if (element is! ClassElement) {
20+
if (element is! ClassElement && element is! EnumElement) {
2121
throw InvalidGenerationSourceError(
22-
'`@Convertable` can only be used on classes.',
22+
'`@Convertable` can only be used on classes or enums.',
2323
element: element,
2424
);
2525
}
2626

2727
// parse the metadata from the annotation
28-
var converterParser = ConverterParser(element);
28+
var converterParser = ConverterParser(element as InterfaceElement);
2929
var converter = converterParser.parse();
3030

3131
final library = Library((builder) {

packages/nitrite_generator/lib/src/converter_parser.dart

Lines changed: 81 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,41 +9,68 @@ import 'package:nitrite_generator/src/type_validator.dart';
99
import 'package:source_gen/source_gen.dart';
1010

1111
class ConverterParser extends Parser<ConverterInfo> {
12-
final ClassElement _classElement;
12+
final InterfaceElement _element;
1313

14-
ConverterParser(this._classElement);
14+
ConverterParser(this._element);
1515

1616
@override
1717
ConverterInfo parse() {
18-
var className = _getClassName();
18+
if (_element is ClassElement) {
19+
var className = _getClassName();
1920

20-
// generated class name
21-
var converterName = _getConverterName();
21+
// generated class name
22+
var converterName = _getConverterName();
2223

23-
// constructor information
24-
var ctorInfo = _getConstructorInfo();
24+
// constructor information
25+
var ctorInfo = _getConstructorInfo();
2526

26-
// field information
27-
var fieldInfoList = _getFieldInfoList();
27+
// field information
28+
var fieldInfoList = _getFieldInfoList();
2829

29-
// property information
30-
var propertyInfoList = _getPropertyInfoList();
30+
// property information
31+
var propertyInfoList = _getPropertyInfoList();
3132

32-
// validate the class and filter out duplicate information
33-
_validateConverter(ctorInfo, propertyInfoList, fieldInfoList);
33+
// validate the class and filter out duplicate information
34+
_validateConverter(ctorInfo, propertyInfoList, fieldInfoList);
3435

35-
return ConverterInfo(
36-
className, converterName, fieldInfoList, propertyInfoList, ctorInfo);
36+
return ConverterInfo(
37+
className,
38+
converterName,
39+
false,
40+
fieldInfoList,
41+
propertyInfoList,
42+
ctorInfo,
43+
);
44+
} else if (_element is EnumElement) {
45+
// enum class name
46+
var className = _getClassName();
47+
48+
// generated class name
49+
var converterName = _getConverterName();
50+
51+
return ConverterInfo(
52+
className,
53+
converterName,
54+
true,
55+
[],
56+
[],
57+
);
58+
} else {
59+
throw InvalidGenerationSourceError(
60+
'`@Convertable` can only be used on classes or enums.',
61+
element: _element,
62+
);
63+
}
3764
}
3865

3966
String _getConverterName() {
40-
var converterName = _classElement
67+
var converterName = _element
4168
.getAnnotation(Convertable)
4269
?.getField(ConverterField.className)
4370
?.toStringValue();
4471

4572
if (converterName == null || converterName.isEmpty) {
46-
return '${_classElement.displayName}Converter';
73+
return '${_element.displayName}Converter';
4774
} else {
4875
return converterName;
4976
}
@@ -87,43 +114,52 @@ class ConverterParser extends Parser<ConverterInfo> {
87114
}
88115

89116
String _getClassName() {
90-
// check mixin
91-
if (_classElement.mixins.isNotEmpty) {
92-
/*
117+
if (_element is ClassElement) {
118+
// check mixin
119+
if (_element.isMixinClass) {
120+
/*
93121
* mixin A {
94122
* String? a;
95123
* }
96124
*
97125
* 1. mixins can not be instantiated
98126
* */
99127

100-
throw InvalidGenerationSourceError(
101-
'`@Convertable` can not be used with mixins.',
102-
element: _classElement,
103-
);
104-
}
128+
throw InvalidGenerationSourceError(
129+
'`@Convertable` can not be used with mixins.',
130+
element: _element,
131+
);
132+
}
105133

106-
if (_classElement.isAbstract) {
107-
/*
134+
if (_element.isAbstract) {
135+
/*
108136
* abstract class A {
109137
* String? a;
110138
* }
111139
*
112140
* 1. abstract class can not be instantiated
113141
* */
114142

143+
throw InvalidGenerationSourceError(
144+
'`@Convertable` can not be used on abstract class.',
145+
element: _element,
146+
);
147+
}
148+
149+
return _element.displayName;
150+
} else if (_element is EnumElement) {
151+
return _element.displayName;
152+
} else {
115153
throw InvalidGenerationSourceError(
116-
'`@Convertable` can not be used on abstract class.',
117-
element: _classElement,
154+
'`@Convertable` can only be used on classes or enums.',
155+
element: _element,
118156
);
119157
}
120-
121-
return _classElement.displayName;
122158
}
123159

124160
ConstructorInfo _getConstructorInfo() {
125161
// check for valid constructors
126-
var constructors = _classElement.constructors;
162+
var constructors = _element.constructors;
127163
var validConstructors = constructors.where((ctor) =>
128164
ctor.isPublic &&
129165
ctor.name.isEmpty &&
@@ -162,7 +198,7 @@ class ConverterParser extends Parser<ConverterInfo> {
162198
'`@Convertable` can only be used on class which has at least '
163199
'one public constructor which is either a default constructor or one '
164200
'with all optional/named parameters.',
165-
element: _classElement,
201+
element: _element,
166202
);
167203
}
168204

@@ -201,7 +237,7 @@ class ConverterParser extends Parser<ConverterInfo> {
201237

202238
List<FieldInfo> _getFieldInfoList() {
203239
var fieldInfos = <FieldInfo>{};
204-
var fieldElements = _classElement.fields;
240+
var fieldElements = _element.fields;
205241
for (var element in fieldElements) {
206242
if (_isValidField(element)) {
207243
// find out if alias is provided
@@ -220,7 +256,7 @@ class ConverterParser extends Parser<ConverterInfo> {
220256
}
221257

222258
// get field details from parents
223-
var supertypes = _classElement.allSupertypes;
259+
var supertypes = _element.allSupertypes;
224260
for (var type in supertypes) {
225261
// use recursion to scan the hierarchy
226262
var superParser = ConverterParser(type.element as ClassElement);
@@ -235,7 +271,7 @@ class ConverterParser extends Parser<ConverterInfo> {
235271

236272
List<PropertyInfo> _getPropertyInfoList() {
237273
var propInfos = <PropertyInfo>{};
238-
var accessors = _classElement.accessors;
274+
var accessors = _element.accessors;
239275

240276
for (var accessor in accessors) {
241277
// validate valid type
@@ -261,7 +297,7 @@ class ConverterParser extends Parser<ConverterInfo> {
261297
throw InvalidGenerationSourceError(
262298
'A getter accessor must be defined for corresponding setter '
263299
'${accessor.displayName}',
264-
element: _classElement);
300+
element: _element);
265301
}
266302

267303
if (accessor.isGetter) {
@@ -326,7 +362,7 @@ class ConverterParser extends Parser<ConverterInfo> {
326362
}
327363

328364
// get property info from parents
329-
var supertypes = _classElement.allSupertypes;
365+
var supertypes = _element.allSupertypes;
330366
for (var type in supertypes) {
331367
// use recursion to scan the hierarchy
332368
var superParser = ConverterParser(type.element as ClassElement);
@@ -363,7 +399,7 @@ class ConverterParser extends Parser<ConverterInfo> {
363399
throw InvalidGenerationSourceError(
364400
'A class with a constructor having all positional optional '
365401
'parameters should not have a final field.',
366-
element: _classElement);
402+
element: _element);
367403
}
368404
}
369405

@@ -385,7 +421,7 @@ class ConverterParser extends Parser<ConverterInfo> {
385421
'A class with a constructor having all named parameters '
386422
'should have all the fields\' names matching with the name of the '
387423
'constructor parameters.',
388-
element: _classElement);
424+
element: _element);
389425
}
390426
}
391427

@@ -397,10 +433,10 @@ class ConverterParser extends Parser<ConverterInfo> {
397433

398434
throw InvalidGenerationSourceError(
399435
'No suitable constructor found for the class '
400-
'${_classElement.displayName}. A class should have at least one public '
436+
'${_element.displayName}. A class should have at least one public '
401437
'constructor which is either a default constructor or one with all '
402438
'optional/named parameters.',
403-
element: _classElement);
439+
element: _element);
404440
}
405441

406442
for (var fieldInfo in fieldInfoList) {
@@ -430,7 +466,7 @@ class ConverterParser extends Parser<ConverterInfo> {
430466
throw InvalidGenerationSourceError(
431467
'A required named constructor parameter ${ctorParam.paramName} '
432468
'with non-nullable type cannot be ignored',
433-
element: _classElement);
469+
element: _element);
434470
} else {
435471
// if nullable set null during constructor call
436472
fieldInfo.setNull = true;
@@ -466,7 +502,7 @@ class ConverterParser extends Parser<ConverterInfo> {
466502

467503
throw InvalidGenerationSourceError(
468504
'Getter accessor is not defined for ${propInfo.setterFieldName}',
469-
element: _classElement);
505+
element: _element);
470506
}
471507

472508
if (propInfo.setterFieldName.isEmpty) {
@@ -480,7 +516,7 @@ class ConverterParser extends Parser<ConverterInfo> {
480516

481517
throw InvalidGenerationSourceError(
482518
'Setter accessor is not defined for ${propInfo.getterFieldName}',
483-
element: _classElement);
519+
element: _element);
484520
}
485521
}
486522
}

0 commit comments

Comments
 (0)