diff --git a/packages/orm/angel_orm/lib/src/builder.dart b/packages/orm/angel_orm/lib/src/builder.dart index a27ee4ac..313d1257 100644 --- a/packages/orm/angel_orm/lib/src/builder.dart +++ b/packages/orm/angel_orm/lib/src/builder.dart @@ -1,4 +1,3 @@ -import 'dart:convert'; import 'package:intl/intl.dart' show DateFormat; import 'query.dart'; diff --git a/packages/serialize/angel_serialize_generator/CHANGELOG.md b/packages/serialize/angel_serialize_generator/CHANGELOG.md index a13163e2..fb4515c4 100644 --- a/packages/serialize/angel_serialize_generator/CHANGELOG.md +++ b/packages/serialize/angel_serialize_generator/CHANGELOG.md @@ -2,7 +2,13 @@ ## 4.1.2 -* Fixed `toMap` method generator +* Fixed `toMap` method generation +* Fixed `fromMape` method generation +* Updated generator to add `const []` to `List` type args in the contructor +* Updated generator to product non nullable aware code +* Removed redudant null checking in the generated code +* Refactored away nullable code +* Added logging to facilitate tracing the code generation via `-verbose` flag ## 4.1.1 @@ -34,6 +40,7 @@ ## 4.0.0 * Migrated to support Dart SDK 2.12.x NNBD +* Importing `Optional` package is required for the ORM model ## 3.0.0 diff --git a/packages/serialize/angel_serialize_generator/lib/angel3_serialize_generator.dart b/packages/serialize/angel_serialize_generator/lib/angel3_serialize_generator.dart index 86c84406..fe805804 100644 --- a/packages/serialize/angel_serialize_generator/lib/angel3_serialize_generator.dart +++ b/packages/serialize/angel_serialize_generator/lib/angel3_serialize_generator.dart @@ -155,6 +155,16 @@ bool isModelClass(DartType? t) { } } +bool isListType(DartType t) { + return const TypeChecker.fromRuntime(List).isAssignableFromType(t) && + !const TypeChecker.fromRuntime(Uint8List).isAssignableFromType(t); +} + +bool isMapType(DartType t) { + return const TypeChecker.fromRuntime(Map).isAssignableFromType(t) && + !const TypeChecker.fromRuntime(Uint8List).isAssignableFromType(t); +} + bool isListOrMapType(DartType t) { return (const TypeChecker.fromRuntime(List).isAssignableFromType(t) || const TypeChecker.fromRuntime(Map).isAssignableFromType(t)) && diff --git a/packages/serialize/angel_serialize_generator/lib/model.dart b/packages/serialize/angel_serialize_generator/lib/model.dart index 22c245ee..e74051ac 100644 --- a/packages/serialize/angel_serialize_generator/lib/model.dart +++ b/packages/serialize/angel_serialize_generator/lib/model.dart @@ -120,6 +120,7 @@ class JsonModelGenerator extends GeneratorForAnnotation { ..type = convertTypeReference(param.type))); } + // Generate intializers for (var field in ctx.fields) { if (!shouldBeConstant(ctx) && isListOrMapType(field.type)) { var typeName = const TypeChecker.fromRuntime(List) @@ -133,9 +134,15 @@ class JsonModelGenerator extends GeneratorForAnnotation { defaultValue = dartObjectToString(existingDefault); } - constructor.initializers.add(Code(''' - this.${field.name} = + if (field.type.nullabilitySuffix != NullabilitySuffix.question) { + constructor.initializers.add(Code(''' + ${field.name} = + $typeName.unmodifiable(${field.name})''')); + } else { + constructor.initializers.add(Code(''' + ${field.name} = $typeName.unmodifiable(${field.name} ?? $defaultValue)''')); + } } } @@ -152,18 +159,30 @@ class JsonModelGenerator extends GeneratorForAnnotation { var existingDefault = ctx.defaults[field.name]; if (existingDefault != null) { - b.defaultTo = Code(dartObjectToString(existingDefault)!); + var d = dartObjectToString(existingDefault); + if (d != null) { + b.defaultTo = Code(d); + } } + //log.fine( + // 'Constructor => ${field.name} ${field.type.nullabilitySuffix}'); if (!isListOrMapType(field.type)) { b.toThis = true; + } else if (isListType(field.type)) { + if (!b.toThis) { + b.type = convertTypeReference(field.type); + } + b.defaultTo = Code('const []'); } else if (!b.toThis) { b.type = convertTypeReference(field.type); + } else { + log.fine('Contructor: ${field.name} pass through'); } - if (ctx.requiredFields.containsKey(field.name) && - b.defaultTo == null || - (field.type.nullabilitySuffix != NullabilitySuffix.question)) { + if ((ctx.requiredFields.containsKey(field.name) || + field.type.nullabilitySuffix != NullabilitySuffix.question) && + b.defaultTo == null) { //b.annotations.add(CodeExpression(Code('required'))); b.required = true; } diff --git a/packages/serialize/angel_serialize_generator/lib/serialize.dart b/packages/serialize/angel_serialize_generator/lib/serialize.dart index ed610efa..17ca6b26 100644 --- a/packages/serialize/angel_serialize_generator/lib/serialize.dart +++ b/packages/serialize/angel_serialize_generator/lib/serialize.dart @@ -52,7 +52,7 @@ class SerializerGenerator extends GeneratorForAnnotation { var pascal = ctx.modelClassNameRecase.pascalCase.replaceAll('?', ''); var camel = ctx.modelClassNameRecase.camelCase.replaceAll('?', ''); - //log.fine('Pascal = $pascal, camel = $camel'); + log.info('Generating ${pascal}Serializer'); if (ctx.constructorParameters.isEmpty) { file.body.add(Code(''' @@ -189,9 +189,14 @@ class ${pascal}Decoder extends Converter { if (name.startsWith('_')) name = name.substring(1); var rc = ReCase(name); var m = serializerToMap(rc, 'm'); - serializedRepresentation = ''' - model.${field.name} - ?.map((m) => $m).toList()'''; + + var question = + (field.type.nullabilitySuffix == NullabilitySuffix.question) + ? '?' + : ''; + serializedRepresentation = + 'model.${field.name}$question.map((m) => $m).toList()'; + log.fine('serializedRepresentation => $serializedRepresentation'); } else if (isMapToModelType(type)) { var rc = ReCase( type.typeArguments[1].getDisplayString(withNullability: true)); @@ -201,10 +206,15 @@ class ${pascal}Decoder extends Converter { ${serializerToMap(rc, 'model.${field.name}[key]')}; })'''; } else if (type.element.isEnum) { + var convert = + (field.type.nullabilitySuffix == NullabilitySuffix.question) + ? '!' + : ''; + serializedRepresentation = ''' - model.${field.name} == null ? - null - : ${type.getDisplayString(withNullability: true)}.values.indexOf(model.${field.name}) + model.${field.name} != null ? + ${type.getDisplayString(withNullability: false)}.values.indexOf(model.${field.name}$convert) + : null '''; } else if (const TypeChecker.fromRuntime(Uint8List) .isAssignableFromType(type)) { @@ -280,6 +290,12 @@ class ${pascal}Decoder extends Converter { var deserializedRepresentation = "map['$alias'] as ${typeToString(type)}"; + if (type.nullabilitySuffix == NullabilitySuffix.question) { + deserializedRepresentation += '?'; + } + + //log.fine( + // 'deserializedRepresentation => $deserializedRepresentation, type => $type, nullcheck => ${type.nullabilitySuffix}'); var defaultValue = 'null'; var existingDefault = ctx.defaults[field.name];