11import 'dart:async' ;
22
33import 'package:analyzer/dart/element/element.dart' ;
4- import 'package:analyzer/dart/element/type.dart' ;
54import 'package:build/build.dart' ;
65import 'package:code_builder/code_builder.dart' ;
76import 'package:collection/collection.dart' ;
87import 'package:dogs_core/dogs_core.dart' ;
9-
108import 'package:dogs_generator/dogs_generator.dart' ;
119import 'package:lyell_gen/lyell_gen.dart' ;
1210import 'package:source_gen/source_gen.dart' ;
@@ -29,20 +27,49 @@ class ConverterBuilder extends DogsAdapter<Serializable> {
2927 SubjectCodeContext codeContext) async {
3028 var emitter = DartEmitter ();
3129 var converterName = "${element .name }Converter" ;
30+
31+ String ? fallbackFieldName;
32+ final fieldValueMap =
33+ Map .fromEntries (element.fields.where ((e) => e.isEnumConstant).map ((e) {
34+ final actual = e.name;
35+ var serializedName = e.name;
36+
37+ final propertyName = propertyNameChecker.firstAnnotationOf (e);
38+ if (propertyName != null ) {
39+ serializedName =
40+ propertyName.getField ("name" )? .toStringValue () ?? serializedName;
41+ }
42+
43+ final enumProperty = enumPropertyChecker.firstAnnotationOf (e);
44+ if (enumProperty != null ) {
45+ serializedName =
46+ enumProperty.getField ("name" )? .toStringValue () ?? serializedName;
47+ if (enumProperty.getField ("fallback" )? .toBoolValue () ?? false ) {
48+ fallbackFieldName = actual;
49+ }
50+ }
51+
52+ return MapEntry (actual, serializedName);
53+ }));
54+
3255 var clazz = Class ((builder) {
3356 builder.name = converterName;
3457
3558 builder.extend = Reference (
3659 "$genAlias .GeneratedEnumDogConverter<${codeContext .typeName (element .thisType )}>" );
3760
61+ builder.constructors.add (Constructor ((builder) => builder
62+ ..initializers.add (Code (
63+ "super.structured(serialName: '${codeContext .typeName (element .thisType )}')" ))));
64+
3865 builder.methods.add (Method ((builder) => builder
3966 ..name = "values"
4067 ..type = MethodType .getter
4168 ..returns = Reference ("List<String>" )
4269 ..annotations.add (CodeExpression (Code ("override" )))
4370 ..lambda = true
4471 ..body = Code (
45- "${ codeContext . typeName ( element . thisType )}. values.map((e) => e.name).toList() " )));
72+ "[${ fieldValueMap . values .map ((e ) => "'${ sqsLiteralEscape ( e )}'" ). join ( "," )}] " )));
4673
4774 builder.methods.add (Method ((builder) => builder
4875 ..name = "toStr"
@@ -51,7 +78,12 @@ class ConverterBuilder extends DogsAdapter<Serializable> {
5178 "$genAlias .EnumToString<${codeContext .typeName (element .thisType )}> " )
5279 ..annotations.add (CodeExpression (Code ("override" )))
5380 ..lambda = true
54- ..body = Code ("(e) => e!.name" )));
81+ ..body = Code ("""
82+ (e) => switch(e) {
83+ ${fieldValueMap .entries .map ((e ) => "${codeContext .typeName (element .thisType )}.${e .key } => '${sqsLiteralEscape (e .value )}'," ).join ("\n " )}
84+ null => throw ArgumentError('Enum value cannot be null'),
85+ }
86+ """ )));
5587
5688 builder.methods.add (Method ((builder) => builder
5789 ..name = "fromStr"
@@ -60,8 +92,15 @@ class ConverterBuilder extends DogsAdapter<Serializable> {
6092 "$genAlias .EnumFromString<${codeContext .typeName (element .thisType )}> " )
6193 ..annotations.add (CodeExpression (Code ("override" )))
6294 ..lambda = true
63- ..body = Code (
64- "(e) => ${codeContext .typeName (element .thisType )}.values.firstWhereOrNullDogs((element) => element.name == e)" )));
95+ ..body = Code ("""
96+ (e) => switch(e) {
97+ ${fieldValueMap .entries .map ((e ) => "'${sqsLiteralEscape (e .value )}' => ${codeContext .typeName (element .thisType )}.${e .key }," ).join ("\n " )}
98+ _ => ${switch (fallbackFieldName ) {
99+ null => "null" ,
100+ _ => "${codeContext .typeName (element .thisType )}.$fallbackFieldName "
101+ }}
102+ }
103+ """ )));
65104 });
66105 codeContext.codeBuffer.writeln (clazz.accept (emitter));
67106 }
@@ -148,7 +187,8 @@ class ConverterBuilder extends DogsAdapter<Serializable> {
148187 log.severe ("""
149188Generic type variables for models are not supported.
150189If you wish to use class-level generics, please implement a TreeBaseConverterFactory for your base type.
151- """ .trim ());
190+ """
191+ .trim ());
152192 }
153193
154194 var referencedClassName = codeContext.className (element);
@@ -341,7 +381,8 @@ If you wish to use class-level generics, please implement a TreeBaseConverterFac
341381 builder.body = Code (bodyBuilder.toString ());
342382 }));
343383
344- var hasRebuildHook = TypeChecker .fromRuntime (PostRebuildHook ).isAssignableFromType (element.thisType);
384+ var hasRebuildHook = TypeChecker .fromRuntime (PostRebuildHook )
385+ .isAssignableFromType (element.thisType);
345386
346387 builder.methods.add (Method ((builder) => builder
347388 ..name = "build"
@@ -389,8 +430,7 @@ return instance;""")));
389430 ..type = MethodType .getter
390431 ..returns = Reference ("${element .name }\$ Copy" )
391432 ..body = Code ("toBuilder()" )
392- ..lambda = true
393- ));
433+ ..lambda = true ));
394434
395435 builder.methods.add (Method ((builder) => builder
396436 ..name = "toBuilder"
0 commit comments