Migrated angel_serialize_generator

This commit is contained in:
thomashii@dukefirehawk.com 2021-05-02 14:02:08 +08:00
parent 1d3d10fb4f
commit ed87d48c96
25 changed files with 346 additions and 340 deletions

View file

@ -29,8 +29,15 @@
* Added range_header and migrated to 3.0.0 (12/12 tests passed)
* Migrated static to 4.0.0 (1/1 test passed)
* Created basic-sdk-2.12.x_nnbd template (1/1 test passed)
* Updated angel_serialize to 4.0.0 (in progress)
* Updated angel_serialize_generator to 4.0.0 (in progress)
* Migrated angel_serialize to 4.0.0 (0/0 test passed)
* Migrated angel_serialize_generator to 4.0.0 (33/33 tests passed)
* Updated angel_orm to 3.0.0 (in progress)
* Updated angel_migration to 3.0.0 (in progress)
* Updated angel_orm_generator to 3.0.0 (in progress, use a fork of postgres)
* Updated angel_migration_runner to 3.0.0 (in progress)
* Updated angel_orm_test to 1.0.0 (in progress)
* Updated angel_orm_postgres to 2.0.0 (in progress)
* Update orm-sdk-2.12.x boilerplate (in progress)
# 3.0.0 (Non NNBD)
* Changed Dart SDK requirements for all packages to ">=2.10.0 <3.0.0"
@ -55,9 +62,9 @@
* Updated production to 2.0.0 (0/0 tests passed)
* Updated hot to 3.0.0 (0/0 tests passed)
* Updated static to 3.0.0 (12/12 tests passed)
* Update basic-sdk-2.12.x boilerplate
* Updated angel_serialize to 3.0.0
* Updated angel_serialize_generator to 3.0.0
* Update basic-sdk-2.12.x boilerplate (1/1 tests passed)
* Updated angel_serialize to 3.0.0 (0/0 tests passed)
* Updated angel_serialize_generator to 3.0.0 (33/33 tests passed)
* Updated angel_orm to 3.0.0
* Updated angel_migration to 3.0.0
* Updated angel_orm_generator to 3.0.0 (use a fork of postgres)

View file

@ -4,6 +4,6 @@ part 'main.g.dart';
@serializable
class _Todo {
String text;
bool completed;
String? text;
bool? completed;
}

View file

@ -11,12 +11,12 @@ class Todo extends _Todo {
Todo({this.text, this.completed});
@override
String text;
String? text;
@override
bool completed;
bool? completed;
Todo copyWith({String text, bool completed}) {
Todo copyWith({String? text, bool? completed}) {
return Todo(
text: text ?? this.text, completed: completed ?? this.completed);
}
@ -69,13 +69,10 @@ class TodoSerializer extends Codec<Todo, Map> {
get decoder => const TodoDecoder();
static Todo fromMap(Map map) {
return Todo(
text: map['text'] as String, completed: map['completed'] as bool);
text: map['text'] as String?, completed: map['completed'] as bool?);
}
static Map<String, dynamic> toMap(_Todo model) {
if (model == null) {
return null;
}
return {'text': model.text, 'completed': model.completed};
}
}

View file

@ -38,9 +38,9 @@ Builder typescriptDefinitionBuilder(_) {
}
/// Converts a [DartType] to a [TypeReference].
TypeReference convertTypeReference(DartType t) {
TypeReference convertTypeReference(DartType? t) {
return TypeReference((b) {
b..symbol = t.element?.displayName;
b.symbol = t!.element?.displayName;
if (t is InterfaceType) {
b.types.addAll(t.typeArguments.map(convertTypeReference));
@ -50,21 +50,21 @@ TypeReference convertTypeReference(DartType t) {
Expression convertObject(DartObject o) {
if (o.isNull) return literalNull;
if (o.toBoolValue() != null) return literalBool(o.toBoolValue());
if (o.toIntValue() != null) return literalNum(o.toIntValue());
if (o.toDoubleValue() != null) return literalNum(o.toDoubleValue());
if (o.toBoolValue() != null) return literalBool(o.toBoolValue()!);
if (o.toIntValue() != null) return literalNum(o.toIntValue()!);
if (o.toDoubleValue() != null) return literalNum(o.toDoubleValue()!);
if (o.toSymbolValue() != null) {
return CodeExpression(Code('#' + o.toSymbolValue()));
return CodeExpression(Code('#' + o.toSymbolValue()!));
}
if (o.toStringValue() != null) return literalString(o.toStringValue());
if (o.toStringValue() != null) return literalString(o.toStringValue()!);
if (o.toTypeValue() != null) return convertTypeReference(o.toTypeValue());
if (o.toListValue() != null) {
return literalList(o.toListValue().map(convertObject));
return literalList(o.toListValue()!.map(convertObject));
}
if (o.toMapValue() != null) {
return literalMap(o
.toMapValue()
.map((k, v) => MapEntry(convertObject(k), convertObject(v))));
.toMapValue()!
.map((k, v) => MapEntry(convertObject(k!), convertObject(v!))));
}
var rev = ConstantReader(o).revive();
@ -74,36 +74,48 @@ Expression convertObject(DartObject o) {
rev.namedArguments.map((k, v) => MapEntry(k, convertObject(v))));
}
String dartObjectToString(DartObject v) {
String? dartObjectToString(DartObject v) {
var type = v.type;
if (v.isNull) return 'null';
if (v.toBoolValue() != null) return v.toBoolValue().toString();
if (v.toIntValue() != null) return v.toIntValue().toString();
if (v.toDoubleValue() != null) return v.toDoubleValue().toString();
if (v.toSymbolValue() != null) return '#' + v.toSymbolValue();
if (v.toTypeValue() != null) return v.toTypeValue().name;
if (v.toBoolValue() != null) {
return v.toBoolValue().toString();
}
if (v.toIntValue() != null) {
return v.toIntValue().toString();
}
if (v.toDoubleValue() != null) {
return v.toDoubleValue().toString();
}
if (v.toSymbolValue() != null) {
return '#' + v.toSymbolValue()!;
}
if (v.toTypeValue() != null) {
return v.toTypeValue()!.getDisplayString(withNullability: true);
}
if (v.toListValue() != null) {
return 'const [' + v.toListValue().map(dartObjectToString).join(', ') + ']';
return 'const [' +
v.toListValue()!.map(dartObjectToString).join(', ') +
']';
}
if (v.toMapValue() != null) {
return 'const {' +
v.toMapValue().entries.map((entry) {
var k = dartObjectToString(entry.key);
var v = dartObjectToString(entry.value);
v.toMapValue()!.entries.map((entry) {
var k = dartObjectToString(entry.key!);
var v = dartObjectToString(entry.value!);
return '$k: $v';
}).join(', ') +
'}';
}
if (v.toStringValue() != null) {
return literalString(v.toStringValue()).accept(DartEmitter()).toString();
return literalString(v.toStringValue()!).accept(DartEmitter()).toString();
}
if (type is InterfaceType && type.element.isEnum) {
// Find the index of the enum, then find the member.
for (var field in type.element.fields) {
if (field.isEnumConstant && field.isStatic) {
var value = type.element.getField(field.name).computeConstantValue();
var value = type.element.getField(field.name)!.computeConstantValue();
if (value == v) {
return '${type.element?.displayName}.${field.name}';
return '${type.element.displayName}.${field.name}';
}
}
}
@ -113,14 +125,14 @@ String dartObjectToString(DartObject v) {
}
/// Determines if a type supports `package:angel_serialize`.
bool isModelClass(DartType t) {
bool isModelClass(DartType? t) {
if (t == null) return false;
if (serializableTypeChecker.hasAnnotationOf(t.element)) {
if (serializableTypeChecker.hasAnnotationOf(t.element!)) {
return true;
}
if (generatedSerializableTypeChecker.hasAnnotationOf(t.element)) {
if (generatedSerializableTypeChecker.hasAnnotationOf(t.element!)) {
return true;
}
@ -167,13 +179,13 @@ bool isAssignableToModel(DartType type) =>
const TypeChecker.fromRuntime(Model).isAssignableFromType(type);
/// Compute a [String] representation of a [type].
String typeToString(DartType type) {
String? typeToString(DartType type) {
if (type is InterfaceType) {
if (type.typeArguments.isEmpty) {
return type.element?.displayName;
return type.element.displayName;
}
var name = type.element?.displayName ?? '';
var name = type.element.displayName;
return name + '<' + type.typeArguments.map(typeToString).join(', ') + '>';
} else {

View file

@ -31,10 +31,14 @@ const TypeChecker generatedSerializableTypeChecker =
final Map<String, BuildContext> _cache = {};
/// Create a [BuildContext].
Future<BuildContext> buildContext(ClassElement clazz, ConstantReader annotation,
BuildStep buildStep, Resolver resolver, bool autoSnakeCaseNames,
Future<BuildContext?> buildContext(
ClassElement clazz,
ConstantReader annotation,
BuildStep buildStep,
Resolver resolver,
bool autoSnakeCaseNames,
{bool heedExclude = true}) async {
var id = clazz.location.components.join('-');
var id = clazz.location!.components.join('-');
if (_cache.containsKey(id)) {
return _cache[id];
}
@ -53,11 +57,11 @@ Future<BuildContext> buildContext(ClassElement clazz, ConstantReader annotation,
annotation.peek('includeAnnotations')?.listValue ?? <DartObject>[],
);
// var lib = await resolver.libraryFor(buildStep.inputId);
List<String> fieldNames = [];
var fieldNames = <String>[];
var fields = <FieldElement>[];
// Crawl for classes from parent classes.
void crawlClass(InterfaceType t) {
void crawlClass(InterfaceType? t) {
while (t != null) {
fields.insertAll(0, t.element.fields);
t.interfaces.forEach(crawlClass);
@ -74,8 +78,8 @@ Future<BuildContext> buildContext(ClassElement clazz, ConstantReader annotation,
}
if (field.getter != null &&
(field.setter != null || field.getter.isAbstract)) {
var el = field.setter == null ? field.getter : field;
(field.setter != null || field.getter!.isAbstract)) {
var el = field.setter == null ? field.getter! : field;
fieldNames.add(field.name);
// Check for @SerializableField
@ -100,11 +104,11 @@ Future<BuildContext> buildContext(ClassElement clazz, ConstantReader annotation,
ctx.requiredFields[field.name] = reason;
}
if (sField.exclude) {
if (sField.exclude!) {
// ignore: deprecated_member_use
ctx.excluded[field.name] = Exclude(
canSerialize: sField.canSerialize,
canDeserialize: sField.canDeserialize,
canSerialize: sField.canSerialize!,
canDeserialize: sField.canDeserialize!,
);
}
}
@ -156,17 +160,17 @@ Future<BuildContext> buildContext(ClassElement clazz, ConstantReader annotation,
// Check for alias
// ignore: deprecated_member_use
Alias alias;
Alias? alias;
var aliasAnn = aliasTypeChecker.firstAnnotationOf(el);
if (aliasAnn != null) {
// ignore: deprecated_member_use
alias = Alias(aliasAnn.getField('name').toStringValue());
alias = Alias(aliasAnn.getField('name')!.toStringValue()!);
foundNone = false;
}
if (alias?.name?.isNotEmpty == true) {
ctx.aliases[field.name] = alias.name;
if (alias?.name.isNotEmpty == true) {
ctx.aliases[field.name] = alias!.name;
} else if (autoSnakeCaseNames != false) {
ctx.aliases[field.name] = ReCase(field.name).snakeCase;
}
@ -234,7 +238,7 @@ Future<BuildContext> buildContext(ClassElement clazz, ConstantReader annotation,
// }
// Get constructor params, if any
ctx.constructorParameters.addAll(clazz.unnamedConstructor.parameters);
ctx.constructorParameters.addAll(clazz.unnamedConstructor!.parameters);
return ctx;
}

View file

@ -8,17 +8,17 @@ import 'package:source_gen/source_gen.dart';
/// A base context for building serializable classes.
class BuildContext {
ReCase _modelClassNameRecase;
TypeReference _modelClassType;
ReCase? _modelClassNameRecase;
TypeReference? _modelClassType;
/// A map of fields that are absolutely required, and error messages for when they are absent.
final Map<String, String> requiredFields = {};
/// A map of field names to resolved names from `@Alias()` declarations.
final Map<String, String> aliases = {};
final Map<String, String?> aliases = {};
/// A map of field names to their default values.
final Map<String, DartObject> defaults = {};
final Map<String, DartObject?> defaults = {};
/// A map of fields to their related information.
final Map<String, SerializableFieldMirror> fieldInfo = {};
@ -30,9 +30,9 @@ class BuildContext {
/// A map of "synthetic" fields, i.e. `id` and `created_at` injected automatically.
final Map<String, bool> shimmed = {};
final bool autoIdAndDateFields, autoSnakeCaseNames;
final bool? autoIdAndDateFields, autoSnakeCaseNames;
final String originalClassName, sourceFilename;
final String? originalClassName, sourceFilename;
/// The fields declared on the original class.
final List<FieldElement> fields = [];
@ -57,13 +57,13 @@ class BuildContext {
this.includeAnnotations = const <DartObject>[]});
/// The name of the generated class.
String get modelClassName => originalClassName.startsWith('_')
? originalClassName.substring(1)
String? get modelClassName => originalClassName!.startsWith('_')
? originalClassName!.substring(1)
: originalClassName;
/// A [ReCase] instance reflecting on the [modelClassName].
ReCase get modelClassNameRecase =>
_modelClassNameRecase ??= ReCase(modelClassName);
_modelClassNameRecase ??= ReCase(modelClassName!);
TypeReference get modelClassType =>
_modelClassType ??= TypeReference((b) => b.symbol = modelClassName);
@ -77,7 +77,7 @@ class BuildContext {
}
/// Get the aliased name (if one is defined) for a field.
String resolveFieldName(String name) =>
String? resolveFieldName(String name) =>
aliases.containsKey(name) ? aliases[name] : name;
/// Finds the type that the field [name] should serialize to.
@ -88,12 +88,12 @@ class BuildContext {
}
class SerializableFieldMirror {
final String alias;
final DartObject defaultValue;
final Symbol serializer, deserializer;
final String errorMessage;
final bool isNullable, canDeserialize, canSerialize, exclude;
final DartType serializesTo;
final String? alias;
final DartObject? defaultValue;
final Symbol? serializer, deserializer;
final String? errorMessage;
final bool? isNullable, canDeserialize, canSerialize, exclude;
final DartType? serializesTo;
SerializableFieldMirror(
{this.alias,

View file

@ -23,10 +23,10 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
/// Generate an extended model class.
void generateClass(
BuildContext ctx, LibraryBuilder file, ConstantReader annotation) {
BuildContext? ctx, LibraryBuilder file, ConstantReader annotation) {
file.body.add(Class((clazz) {
clazz
..name = ctx.modelClassNameRecase.pascalCase
..name = ctx!.modelClassNameRecase.pascalCase
..annotations.add(refer('generatedSerializable'));
for (var ann in ctx.includeAnnotations) {
@ -57,7 +57,7 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
for (var el in [field.getter, field]) {
if (el?.documentationComment != null) {
b.docs.addAll(el.documentationComment.split('\n'));
b.docs.addAll(el!.documentationComment!.split('\n'));
}
}
}));
@ -92,10 +92,10 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
/// Generate a constructor with named parameters.
void generateConstructor(
BuildContext ctx, ClassBuilder clazz, LibraryBuilder file) {
BuildContext? ctx, ClassBuilder clazz, LibraryBuilder file) {
clazz.constructors.add(Constructor((constructor) {
// Add all `super` params
constructor.constant = (ctx.clazz.unnamedConstructor?.isConst == true ||
constructor.constant = (ctx!.clazz.unnamedConstructor?.isConst == true ||
shouldBeConstant(ctx)) &&
ctx.fields.every((f) {
return f.setter == null && f is! ShimFieldImpl;
@ -113,7 +113,7 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
.isAssignableFromType(field.type)
? 'List'
: 'Map';
var defaultValue = typeName == 'List' ? '[]' : '{}';
String? defaultValue = typeName == 'List' ? '[]' : '{}';
var existingDefault = ctx.defaults[field.name];
if (existingDefault != null) {
@ -136,7 +136,7 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
var existingDefault = ctx.defaults[field.name];
if (existingDefault != null) {
b.defaultTo = Code(dartObjectToString(existingDefault));
b.defaultTo = Code(dartObjectToString(existingDefault)!);
}
if (!isListOrMapType(field.type)) {
@ -164,11 +164,11 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
/// Generate a `copyWith` method.
void generateCopyWithMethod(
BuildContext ctx, ClassBuilder clazz, LibraryBuilder file) {
BuildContext? ctx, ClassBuilder clazz, LibraryBuilder file) {
clazz.methods.add(Method((method) {
method
..name = 'copyWith'
..returns = ctx.modelClassType;
..returns = ctx!.modelClassType;
// Add all `super` params
if (ctx.constructorParameters.isNotEmpty) {
@ -204,12 +204,12 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
}));
}
static String generateEquality(DartType type, [bool nullable = false]) {
static String? generateEquality(DartType type, [bool nullable = false]) {
if (type is InterfaceType) {
if (const TypeChecker.fromRuntime(List).isAssignableFromType(type)) {
if (type.typeArguments.length == 1) {
var eq = generateEquality(type.typeArguments[0]);
return 'ListEquality<${type.typeArguments[0].element.name}>($eq)';
return 'ListEquality<${type.typeArguments[0].element!.name}>($eq)';
} else {
return 'ListEquality()';
}
@ -218,7 +218,7 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
if (type.typeArguments.length == 2) {
var keq = generateEquality(type.typeArguments[0]),
veq = generateEquality(type.typeArguments[1]);
return 'MapEquality<${type.typeArguments[0].element.name}, ${type.typeArguments[1].element.name}>(keys: $keq, values: $veq)';
return 'MapEquality<${type.typeArguments[0].element!.name}, ${type.typeArguments[1].element!.name}>(keys: $keq, values: $veq)';
} else {
return 'MapEquality()';
}
@ -239,7 +239,7 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
return (a, b) => '$eq.equals($a, $b)';
}
void generateHashCode(BuildContext ctx, ClassBuilder clazz) {
void generateHashCode(BuildContext? ctx, ClassBuilder clazz) {
clazz
..methods.add(Method((method) {
method
@ -248,20 +248,20 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
..returns = refer('int')
..annotations.add(refer('override'))
..body = refer('hashObjects')
.call([literalList(ctx.fields.map((f) => refer(f.name)))])
.call([literalList(ctx!.fields.map((f) => refer(f.name)))])
.returned
.statement;
}));
}
void generateToString(BuildContext ctx, ClassBuilder clazz) {
void generateToString(BuildContext? ctx, ClassBuilder clazz) {
clazz.methods.add(Method((b) {
b
..name = 'toString'
..returns = refer('String')
..annotations.add(refer('override'))
..body = Block((b) {
var buf = StringBuffer('\"${ctx.modelClassName}(');
var buf = StringBuffer('\"${ctx!.modelClassName}(');
var i = 0;
for (var field in ctx.fields) {
if (i++ > 0) buf.write(', ');
@ -274,14 +274,14 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
}
void generateEqualsOperator(
BuildContext ctx, ClassBuilder clazz, LibraryBuilder file) {
BuildContext? ctx, ClassBuilder clazz, LibraryBuilder file) {
clazz.methods.add(Method((method) {
method
..name = 'operator =='
..returns = Reference('bool')
..requiredParameters.add(Parameter((b) => b.name = 'other'));
var buf = ['other is ${ctx.originalClassName}'];
var buf = ['other is ${ctx!.originalClassName}'];
buf.addAll(ctx.fields.map((f) {
return generateComparator(f.type)('other.${f.name}', f.name);

View file

@ -6,7 +6,7 @@ class SerializerGenerator extends GeneratorForAnnotation<Serializable> {
const SerializerGenerator({this.autoSnakeCaseNames = true});
@override
Future<String> generateForAnnotatedElement(
Future<String?> generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) async {
if (element.kind != ElementKind.CLASS) {
throw 'Only classes can be annotated with a @Serializable() annotation.';
@ -25,7 +25,7 @@ class SerializerGenerator extends GeneratorForAnnotation<Serializable> {
}
var lib = Library((b) {
generateClass(serializers.map((s) => s.toIntValue()).toList(), ctx, b);
generateClass(serializers.map((s) => s.toIntValue()).toList(), ctx!, b);
generateFieldsClass(ctx, b);
});
@ -35,7 +35,7 @@ class SerializerGenerator extends GeneratorForAnnotation<Serializable> {
/// Generate a serializer class.
void generateClass(
List<int> serializers, BuildContext ctx, LibraryBuilder file) {
List<int?> serializers, BuildContext ctx, LibraryBuilder file) {
// Generate canonical codecs, etc.
var pascal = ctx.modelClassNameRecase.pascalCase,
camel = ctx.modelClassNameRecase.camelCase;
@ -105,7 +105,7 @@ class ${pascal}Decoder extends Converter<Map, ${pascal}> {
..requiredParameters.add(Parameter((b) {
b
..name = 'model'
..type = refer(ctx.originalClassName);
..type = refer(ctx.originalClassName!);
}));
var buf = StringBuffer();
@ -143,7 +143,7 @@ class ${pascal}Decoder extends Converter<Map, ${pascal}> {
}
if (ctx.fieldInfo[field.name]?.serializer != null) {
var name = MirrorSystem.getName(ctx.fieldInfo[field.name].serializer);
var name = MirrorSystem.getName(ctx.fieldInfo[field.name]!.serializer!);
serializedRepresentation = '$name(model.${field.name})';
}
@ -154,12 +154,12 @@ class ${pascal}Decoder extends Converter<Map, ${pascal}> {
// Serialize model classes via `XSerializer.toMap`
else if (isModelClass(type)) {
var rc = ReCase(type.name);
var rc = ReCase(type.name!);
serializedRepresentation =
'${serializerToMap(rc, 'model.${field.name}')}';
} else if (type is InterfaceType) {
if (isListOfModelType(type)) {
var name = type.typeArguments[0].name;
var name = type.typeArguments[0].name!;
if (name.startsWith('_')) name = name.substring(1);
var rc = ReCase(name);
var m = serializerToMap(rc, 'm');
@ -168,7 +168,7 @@ class ${pascal}Decoder extends Converter<Map, ${pascal}> {
?.map((m) => $m)
?.toList()''';
} else if (isMapToModelType(type)) {
var rc = ReCase(type.typeArguments[1].name);
var rc = ReCase(type.typeArguments[1].name!);
serializedRepresentation =
'''model.${field.name}.keys?.fold({}, (map, key) {
return map..[key] =
@ -255,7 +255,7 @@ class ${pascal}Decoder extends Converter<Map, ${pascal}> {
String deserializedRepresentation =
"map['$alias'] as ${typeToString(type)}";
var defaultValue = 'null';
String? defaultValue = 'null';
var existingDefault = ctx.defaults[field.name];
if (existingDefault != null) {
@ -266,7 +266,7 @@ class ${pascal}Decoder extends Converter<Map, ${pascal}> {
if (ctx.fieldInfo[field.name]?.deserializer != null) {
var name =
MirrorSystem.getName(ctx.fieldInfo[field.name].deserializer);
MirrorSystem.getName(ctx.fieldInfo[field.name]!.deserializer!);
deserializedRepresentation = "$name(map['$alias'])";
} else if (dateTimeTypeChecker.isAssignableFromType(type)) {
deserializedRepresentation = "map['$alias'] != null ? "
@ -276,20 +276,20 @@ class ${pascal}Decoder extends Converter<Map, ${pascal}> {
// Serialize model classes via `XSerializer.toMap`
else if (isModelClass(type)) {
var rc = ReCase(type.name);
var rc = ReCase(type.name!);
deserializedRepresentation = "map['$alias'] != null"
" ? ${rc.pascalCase}Serializer.fromMap(map['$alias'] as Map)"
" : $defaultValue";
} else if (type is InterfaceType) {
if (isListOfModelType(type)) {
var rc = ReCase(type.typeArguments[0].name);
var rc = ReCase(type.typeArguments[0].name!);
deserializedRepresentation = "map['$alias'] is Iterable"
" ? List.unmodifiable(((map['$alias'] as Iterable)"
".whereType<Map>())"
".map(${rc.pascalCase}Serializer.fromMap))"
" : $defaultValue";
} else if (isMapToModelType(type)) {
var rc = ReCase(type.typeArguments[1].name);
var rc = ReCase(type.typeArguments[1].name!);
deserializedRepresentation = '''
map['$alias'] is Map
? Map.unmodifiable((map['$alias'] as Map).keys.fold({}, (out, key) {
@ -359,11 +359,11 @@ class ${pascal}Decoder extends Converter<Map, ${pascal}> {
}));
}
void generateFieldsClass(BuildContext ctx, LibraryBuilder file) {
void generateFieldsClass(BuildContext? ctx, LibraryBuilder file) {
file.body.add(Class((clazz) {
clazz
..abstract = true
..name = '${ctx.modelClassNameRecase.pascalCase}Fields';
..name = '${ctx!.modelClassNameRecase.pascalCase}Fields';
clazz.fields.add(Field((b) {
b

View file

@ -13,13 +13,13 @@ class TypeScriptDefinitionBuilder implements Builder {
}
Future<String> compileToTypeScriptType(
BuildContext ctx,
BuildContext? ctx,
String fieldName,
DartType type,
List<String> refs,
List<CodeBuffer> ext,
BuildStep buildStep) async {
String typeScriptType = 'any';
var typeScriptType = 'any';
var types = const {
num: 'number',
@ -58,7 +58,7 @@ class TypeScriptDefinitionBuilder implements Builder {
);*/
typeScriptType =
ctx.modelClassNameRecase.pascalCase + ReCase(fieldName).pascalCase;
ctx!.modelClassNameRecase.pascalCase + ReCase(fieldName).pascalCase;
ext.add(CodeBuffer()
..writeln('interface $typeScriptType {')
@ -81,10 +81,11 @@ class TypeScriptDefinitionBuilder implements Builder {
if (!p.equals(sourcePath, targetPath)) {
var relative = p.relative(targetPath, from: sourcePath);
String ref;
String? ref;
if (type.element.source.uri.scheme == 'asset') {
var id = AssetId.resolve(type.element.source.uri.toString());
var id =
AssetId.resolve(Uri.parse(type.element.source.uri.toString()));
if (id.package != buildStep.inputId.package) {
ref = '/// <reference types="${id.package}" />';
}
@ -103,14 +104,14 @@ class TypeScriptDefinitionBuilder implements Builder {
if (!refs.contains(ref)) refs.add(ref);
}
var ctx = await buildContext(
var ctx = await (buildContext(
type.element,
ConstantReader(
serializableTypeChecker.firstAnnotationOf(type.element)),
buildStep,
buildStep.resolver,
autoSnakeCaseNames,
);
) as FutureOr<BuildContext>);
typeScriptType = ctx.modelClassNameRecase.pascalCase;
}
}
@ -120,7 +121,7 @@ class TypeScriptDefinitionBuilder implements Builder {
@override
Future build(BuildStep buildStep) async {
var contexts = <BuildContext>[];
var contexts = <BuildContext?>[];
LibraryReader lib;
try {
@ -159,7 +160,7 @@ class TypeScriptDefinitionBuilder implements Builder {
element.element as ClassElement,
element.annotation,
buildStep,
await buildStep.resolver,
buildStep.resolver,
autoSnakeCaseNames != false));
}
@ -181,7 +182,7 @@ class TypeScriptDefinitionBuilder implements Builder {
for (var ctx in contexts) {
// interface Bar { ... }
buf
..writeln('interface ${ctx.modelClassNameRecase.pascalCase} {')
..writeln('interface ${ctx!.modelClassNameRecase.pascalCase} {')
..indent();
var ext = <CodeBuffer>[];
@ -195,7 +196,11 @@ class TypeScriptDefinitionBuilder implements Builder {
ctx.resolveSerializedFieldType(field.name), refs, ext, buildStep);
// foo: string;
if (!ctx.requiredFields.containsKey(field.name)) alias += '?';
if (!ctx.requiredFields.containsKey(field.name)) {
if (alias != null) {
alias += '?';
}
}
buf.writeln('$alias: $typeScriptType;');
}

View file

@ -4,33 +4,37 @@ description: Model serialization generators, designed for use with Angel. Combin
homepage: https://github.com/dukefirehawk/angel
publish_to: none
environment:
sdk: '>=2.7.0 <3.0.0'
sdk: '>=2.12.0 <3.0.0'
dependencies:
analyzer: ">=0.27.1 <2.0.0"
analyzer: ^1.5.0
angel_model:
git:
url: https://github.com/dukefirehawk/angel.git
ref: sdk-2.12.x
ref: sdk-2.12.x_nnbd
path: packages/model
angel_serialize:
git:
url: https://github.com/dukefirehawk/angel.git
ref: sdk-2.12.x
ref: sdk-2.12.x_nnbd
path: packages/serialize/angel_serialize
build: ">=0.12.0 <2.0.0"
build_config: ">=0.3.0 <2.0.0"
code_buffer: ^1.0.0
code_builder: ^3.0.0
code_buffer:
git:
url: https://github.com/dukefirehawk/angel.git
ref: sdk-2.12.x_nnbd
path: packages/code_buffer
build: ^2.0.1
build_config: ^1.0.0
code_builder: ^4.0.0
meta: ^1.3.0
path: ^1.8.0
recase: ^3.0.1
source_gen: ^0.9.0
quiver: ^2.1.5
recase: ^4.0.0
source_gen: ^1.0.0
quiver: ^3.0.1
dev_dependencies:
build_runner: ^1.11.5
build_runner: ^2.0.1
collection: ^1.15.0
pedantic: ^1.11.0
test: ^1.16.5
test: ^1.17.3
# dependency_overrides:
# angel_serialize:
# path: ../angel_serialize

View file

@ -21,8 +21,8 @@ main() {
age: 51,
books: [deathlyHallows],
newestBook: deathlyHallows);
var serializedJkRowling = authorSerializer.encode(jkRowling);
var deathlyHallowsMap = bookSerializer.encode(deathlyHallows);
Map<dynamic, dynamic> serializedJkRowling = authorSerializer.encode(jkRowling);
Map<dynamic, dynamic>? deathlyHallowsMap = bookSerializer.encode(deathlyHallows);
print('J.K. Rowling: $jkRowling');
var library = Library(collection: {deathlyHallowsIsbn: deathlyHallows});
@ -31,30 +31,30 @@ main() {
group('serialization', () {
test('serialization sets proper fields', () {
expect(serializedDeathlyHallows['id'], deathlyHallows.id);
expect(serializedDeathlyHallows!['id'], deathlyHallows.id);
expect(serializedDeathlyHallows['author'], deathlyHallows.author);
expect(
serializedDeathlyHallows['description'], deathlyHallows.description);
expect(serializedDeathlyHallows['page_count'], deathlyHallows.pageCount);
expect(serializedDeathlyHallows['created_at'], isNull);
expect(serializedDeathlyHallows['updated_at'],
deathlyHallows.updatedAt.toIso8601String());
deathlyHallows.updatedAt!.toIso8601String());
});
test('can be mutated', () {
var b = deathlyHallows.copyWith();
b.author = 'Hey';
expect(b.author, 'Hey');
expect(b.toJson()[BookFields.author], 'Hey');
expect(b.toJson()![BookFields.author], 'Hey');
});
test('heeds @Alias', () {
expect(serializedDeathlyHallows['page_count'], deathlyHallows.pageCount);
expect(serializedDeathlyHallows!['page_count'], deathlyHallows.pageCount);
expect(serializedDeathlyHallows.keys, isNot(contains('pageCount')));
});
test('standard list', () {
expect(serializedDeathlyHallows['not_models'], deathlyHallows.notModels);
expect(serializedDeathlyHallows!['not_models'], deathlyHallows.notModels);
});
test('heeds @exclude', () {
@ -63,7 +63,7 @@ main() {
test('heeds canDeserialize', () {
var map = Map.from(serializedJkRowling)..['obscured'] = 'foo';
var author = authorSerializer.decode(map);
Author author = authorSerializer.decode(map);
expect(author.obscured, 'foo');
});
@ -112,7 +112,7 @@ main() {
group('deserialization', () {
test('deserialization sets proper fields', () {
var book = BookSerializer.fromMap(deathlyHallowsMap);
var book = BookSerializer.fromMap(deathlyHallowsMap!);
expect(book.id, deathlyHallows.id);
expect(book.author, deathlyHallows.author);
expect(book.description, deathlyHallows.description);
@ -126,7 +126,7 @@ main() {
var author = AuthorSerializer.fromMap(serializedJkRowling);
test('nested @serializable class is deserialized', () {
var newestBook = author.newestBook;
var newestBook = author.newestBook!;
expect(newestBook, isNotNull);
expect(newestBook.id, deathlyHallows.id);
expect(newestBook.pageCount, deathlyHallows.pageCount);
@ -148,7 +148,7 @@ main() {
var lib = LibrarySerializer.fromMap(serializedLibrary);
expect(lib.collection, allOf(isNotEmpty, hasLength(1)));
expect(lib.collection.keys.first, deathlyHallowsIsbn);
var book = lib.collection[deathlyHallowsIsbn];
var book = lib.collection[deathlyHallowsIsbn]!;
expect(book.id, deathlyHallows.id);
expect(book.author, deathlyHallows.author);
expect(book.description, deathlyHallows.description);

View file

@ -14,38 +14,38 @@ part 'book.g.dart';
],
)
abstract class _Book extends Model {
String author, title, description;
String? author, title, description;
/// The number of pages the book has.
int pageCount;
int? pageCount;
List<double> notModels;
List<double>? notModels;
@SerializableField(alias: 'camelCase', isNullable: true)
String camelCaseString;
String? camelCaseString;
}
@Serializable(serializers: Serializers.all)
abstract class _Author extends Model {
@SerializableField(isNullable: false)
String get name;
String? get name;
String get customMethod => 'hey!';
@SerializableField(
isNullable: false, errorMessage: 'Custom message for missing `age`')
int get age;
int? get age;
List<_Book> get books;
/// The newest book.
_Book get newestBook;
_Book? get newestBook;
@SerializableField(exclude: true, isNullable: true)
String get secret;
String? get secret;
@SerializableField(exclude: true, canDeserialize: true, isNullable: true)
String get obscured;
String? get obscured;
}
@Serializable(serializers: Serializers.all)
@ -61,9 +61,9 @@ abstract class _Bookmark extends Model {
List<int> get history;
@SerializableField(isNullable: false)
int get page;
int? get page;
String get comment;
String? get comment;
_Bookmark(this.book);
}

View file

@ -18,51 +18,51 @@ class Book extends _Book {
this.title,
this.description,
this.pageCount,
List<double> notModels,
List<double>? notModels,
this.camelCaseString})
: this.notModels = List.unmodifiable(notModels ?? []);
/// A unique identifier corresponding to this item.
@override
String id;
String? id;
/// The time at which this item was created.
@override
DateTime createdAt;
DateTime? createdAt;
/// The last time at which this item was updated.
@override
DateTime updatedAt;
DateTime? updatedAt;
@override
String author;
String? author;
@override
String title;
String? title;
@override
String description;
String? description;
/// The number of pages the book has.
@override
int pageCount;
int? pageCount;
@override
List<double> notModels;
List<double>? notModels;
@override
String camelCaseString;
String? camelCaseString;
Book copyWith(
{String id,
DateTime createdAt,
DateTime updatedAt,
String author,
String title,
String description,
int pageCount,
List<double> notModels,
String camelCaseString}) {
{String? id,
DateTime? createdAt,
DateTime? updatedAt,
String? author,
String? title,
String? description,
int? pageCount,
List<double>? notModels,
String? camelCaseString}) {
return Book(
id: id ?? this.id,
createdAt: createdAt ?? this.createdAt,
@ -106,10 +106,10 @@ class Book extends _Book {
@override
String toString() {
return "Book(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, author=$author, title=$title, description=$description, pageCount=$pageCount, notModels=$notModels, camelCaseString=$camelCaseString)";
return 'Book(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, author=$author, title=$title, description=$description, pageCount=$pageCount, notModels=$notModels, camelCaseString=$camelCaseString)';
}
Map<String, dynamic> toJson() {
Map<String, dynamic>? toJson() {
return BookSerializer.toMap(this);
}
}
@ -120,9 +120,9 @@ class Author extends _Author {
{this.id,
this.createdAt,
this.updatedAt,
@required this.name,
@required this.age,
List<_Book> books,
required this.name,
required this.age,
List<_Book>? books,
this.newestBook,
this.secret,
this.obscured})
@ -130,45 +130,45 @@ class Author extends _Author {
/// A unique identifier corresponding to this item.
@override
String id;
String? id;
/// The time at which this item was created.
@override
DateTime createdAt;
DateTime? createdAt;
/// The last time at which this item was updated.
@override
DateTime updatedAt;
DateTime? updatedAt;
@override
final String name;
final String? name;
@override
final int age;
final int? age;
@override
final List<_Book> books;
/// The newest book.
@override
final _Book newestBook;
final _Book? newestBook;
@override
final String secret;
final String? secret;
@override
final String obscured;
final String? obscured;
Author copyWith(
{String id,
DateTime createdAt,
DateTime updatedAt,
String name,
int age,
List<_Book> books,
_Book newestBook,
String secret,
String obscured}) {
{String? id,
DateTime? createdAt,
DateTime? updatedAt,
String? name,
int? age,
List<_Book>? books,
_Book? newestBook,
String? secret,
String? obscured}) {
return Author(
id: id ?? this.id,
createdAt: createdAt ?? this.createdAt,
@ -212,7 +212,7 @@ class Author extends _Author {
@override
String toString() {
return "Author(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, name=$name, age=$age, books=$books, newestBook=$newestBook, secret=$secret, obscured=$obscured)";
return 'Author(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, name=$name, age=$age, books=$books, newestBook=$newestBook, secret=$secret, obscured=$obscured)';
}
Map<String, dynamic> toJson() {
@ -223,29 +223,29 @@ class Author extends _Author {
@generatedSerializable
class Library extends _Library {
Library(
{this.id, this.createdAt, this.updatedAt, Map<String, _Book> collection})
: this.collection = Map.unmodifiable(collection ?? {});
{this.id, this.createdAt, this.updatedAt, Map<String, _Book>? collection})
: collection = Map.unmodifiable(collection ?? {});
/// A unique identifier corresponding to this item.
@override
String id;
String? id;
/// The time at which this item was created.
@override
DateTime createdAt;
DateTime? createdAt;
/// The last time at which this item was updated.
@override
DateTime updatedAt;
DateTime? updatedAt;
@override
final Map<String, _Book> collection;
Library copyWith(
{String id,
DateTime createdAt,
DateTime updatedAt,
Map<String, _Book> collection}) {
{String? id,
DateTime? createdAt,
DateTime? updatedAt,
Map<String, _Book>? collection}) {
return Library(
id: id ?? this.id,
createdAt: createdAt ?? this.createdAt,
@ -271,7 +271,7 @@ class Library extends _Library {
@override
String toString() {
return "Library(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, collection=$collection)";
return 'Library(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, collection=$collection)';
}
Map<String, dynamic> toJson() {
@ -285,40 +285,40 @@ class Bookmark extends _Bookmark {
{this.id,
this.createdAt,
this.updatedAt,
List<int> history,
@required this.page,
List<int>? history,
required this.page,
this.comment})
: this.history = List.unmodifiable(history ?? []),
: history = List.unmodifiable(history ?? []),
super(book);
/// A unique identifier corresponding to this item.
@override
String id;
String? id;
/// The time at which this item was created.
@override
DateTime createdAt;
DateTime? createdAt;
/// The last time at which this item was updated.
@override
DateTime updatedAt;
DateTime? updatedAt;
@override
final List<int> history;
@override
final int page;
final int? page;
@override
final String comment;
final String? comment;
Bookmark copyWith(_Book book,
{String id,
DateTime createdAt,
DateTime updatedAt,
List<int> history,
int page,
String comment}) {
{String? id,
DateTime? createdAt,
DateTime? updatedAt,
List<int>? history,
int? page,
String? comment}) {
return Bookmark(book,
id: id ?? this.id,
createdAt: createdAt ?? this.createdAt,
@ -346,7 +346,7 @@ class Bookmark extends _Bookmark {
@override
String toString() {
return "Bookmark(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, history=$history, page=$page, comment=$comment)";
return 'Bookmark(id=$id, createdAt=$createdAt, updatedAt=$updatedAt, history=$history, page=$page, comment=$comment)';
}
Map<String, dynamic> toJson() {
@ -360,11 +360,11 @@ class Bookmark extends _Bookmark {
const BookSerializer bookSerializer = BookSerializer();
class BookEncoder extends Converter<Book, Map> {
class BookEncoder extends Converter<Book, Map?> {
const BookEncoder();
@override
Map convert(Book model) => BookSerializer.toMap(model);
Map? convert(Book model) => BookSerializer.toMap(model);
}
class BookDecoder extends Converter<Map, Book> {
@ -374,37 +374,39 @@ class BookDecoder extends Converter<Map, Book> {
Book convert(Map map) => BookSerializer.fromMap(map);
}
class BookSerializer extends Codec<Book, Map> {
class BookSerializer extends Codec<Book, Map?> {
const BookSerializer();
@override
get encoder => const BookEncoder();
BookEncoder get encoder => const BookEncoder();
@override
get decoder => const BookDecoder();
BookDecoder get decoder => const BookDecoder();
static Book fromMap(Map map) {
return Book(
id: map['id'] as String,
id: map['id'] as String?,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime)
? (map['created_at'] as DateTime?)
: DateTime.parse(map['created_at'].toString()))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? (map['updated_at'] as DateTime)
? (map['updated_at'] as DateTime?)
: DateTime.parse(map['updated_at'].toString()))
: null,
author: map['author'] as String,
title: map['title'] as String,
description: map['description'] as String,
pageCount: map['page_count'] as int,
author: map['author'] as String?,
title: map['title'] as String?,
description: map['description'] as String?,
pageCount: map['page_count'] as int?,
notModels: map['not_models'] is Iterable
? (map['not_models'] as Iterable).cast<double>().toList()
: null,
camelCaseString: map['camelCase'] as String);
camelCaseString: map['camelCase'] as String?);
}
static Map<String, dynamic> toMap(_Book model) {
static Map<String, dynamic>? toMap(_Book? model) {
if (model == null) {
return null;
}
@ -474,32 +476,34 @@ class AuthorSerializer extends Codec<Author, Map> {
const AuthorSerializer();
@override
get encoder => const AuthorEncoder();
AuthorEncoder get encoder => const AuthorEncoder();
@override
get decoder => const AuthorDecoder();
AuthorDecoder get decoder => const AuthorDecoder();
static Author fromMap(Map map) {
if (map['name'] == null) {
throw FormatException("Missing required field 'name' on Author.");
}
if (map['age'] == null) {
throw FormatException("Custom message for missing `age`");
throw FormatException('Custom message for missing `age`');
}
return Author(
id: map['id'] as String,
id: map['id'] as String?,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime)
? (map['created_at'] as DateTime?)
: DateTime.parse(map['created_at'].toString()))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? (map['updated_at'] as DateTime)
? (map['updated_at'] as DateTime?)
: DateTime.parse(map['updated_at'].toString()))
: null,
name: map['name'] as String,
age: map['age'] as int,
name: map['name'] as String?,
age: map['age'] as int?,
books: map['books'] is Iterable
? List.unmodifiable(((map['books'] as Iterable).whereType<Map>())
.map(BookSerializer.fromMap))
@ -507,19 +511,16 @@ class AuthorSerializer extends Codec<Author, Map> {
newestBook: map['newest_book'] != null
? BookSerializer.fromMap(map['newest_book'] as Map)
: null,
obscured: map['obscured'] as String);
obscured: map['obscured'] as String?);
}
static Map<String, dynamic> toMap(_Author model) {
if (model == null) {
return null;
}
if (model.name == null) {
throw FormatException("Missing required field 'name' on Author.");
}
if (model.age == null) {
throw FormatException("Custom message for missing `age`");
throw FormatException('Custom message for missing `age`');
}
return {
@ -528,7 +529,7 @@ class AuthorSerializer extends Codec<Author, Map> {
'updated_at': model.updatedAt?.toIso8601String(),
'name': model.name,
'age': model.age,
'books': model.books?.map((m) => BookSerializer.toMap(m))?.toList(),
'books': model.books.map((m) => BookSerializer.toMap(m)).toList(),
'newest_book': BookSerializer.toMap(model.newestBook)
};
}
@ -586,20 +587,22 @@ class LibrarySerializer extends Codec<Library, Map> {
const LibrarySerializer();
@override
get encoder => const LibraryEncoder();
LibraryEncoder get encoder => const LibraryEncoder();
@override
get decoder => const LibraryDecoder();
LibraryDecoder get decoder => const LibraryDecoder();
static Library fromMap(Map map) {
return Library(
id: map['id'] as String,
id: map['id'] as String?,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime)
? (map['created_at'] as DateTime?)
: DateTime.parse(map['created_at'].toString()))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? (map['updated_at'] as DateTime)
? (map['updated_at'] as DateTime?)
: DateTime.parse(map['updated_at'].toString()))
: null,
collection: map['collection'] is Map
@ -613,14 +616,11 @@ class LibrarySerializer extends Codec<Library, Map> {
}
static Map<String, dynamic> toMap(_Library model) {
if (model == null) {
return null;
}
return {
'id': model.id,
'created_at': model.createdAt?.toIso8601String(),
'updated_at': model.updatedAt?.toIso8601String(),
'collection': model.collection.keys?.fold({}, (map, key) {
'collection': model.collection.keys.fold({}, (dynamic map, key) {
return map..[key] = BookSerializer.toMap(model.collection[key]);
})
};
@ -651,28 +651,25 @@ abstract class BookmarkSerializer {
}
return Bookmark(book,
id: map['id'] as String,
id: map['id'] as String?,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime)
? (map['created_at'] as DateTime?)
: DateTime.parse(map['created_at'].toString()))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? (map['updated_at'] as DateTime)
? (map['updated_at'] as DateTime?)
: DateTime.parse(map['updated_at'].toString()))
: null,
history: map['history'] is Iterable
? (map['history'] as Iterable).cast<int>().toList()
: null,
page: map['page'] as int,
comment: map['comment'] as String);
page: map['page'] as int?,
comment: map['comment'] as String?);
}
static Map<String, dynamic> toMap(_Bookmark model) {
if (model == null) {
return null;
}
if (model.page == null) {
throw FormatException("Missing required field 'page' on Bookmark.");
}

View file

@ -3,16 +3,16 @@ part 'game_pad_button.g.dart';
@serializable
abstract class _GamepadButton {
String get name;
int get radius;
String? get name;
int? get radius;
}
@serializable
class _Gamepad {
List<_GamepadButton> buttons;
List<_GamepadButton>? buttons;
Map<String, dynamic> dynamicMap;
Map<String, dynamic>? dynamicMap;
// ignore: unused_field
String _somethingPrivate;
String? _somethingPrivate;
}

View file

@ -11,12 +11,12 @@ class GamepadButton implements _GamepadButton {
const GamepadButton({this.name, this.radius});
@override
final String name;
final String? name;
@override
final int radius;
final int? radius;
GamepadButton copyWith({String name, int radius}) {
GamepadButton copyWith({String? name, int? radius}) {
return GamepadButton(
name: name ?? this.name, radius: radius ?? this.radius);
}
@ -44,18 +44,18 @@ class GamepadButton implements _GamepadButton {
@generatedSerializable
class Gamepad extends _Gamepad {
Gamepad({List<_GamepadButton> buttons, Map<String, dynamic> dynamicMap})
Gamepad({List<_GamepadButton>? buttons, Map<String, dynamic>? dynamicMap})
: this.buttons = List.unmodifiable(buttons ?? []),
this.dynamicMap = Map.unmodifiable(dynamicMap ?? {});
@override
List<_GamepadButton> buttons;
List<_GamepadButton>? buttons;
@override
Map<String, dynamic> dynamicMap;
Map<String, dynamic>? dynamicMap;
Gamepad copyWith(
{List<_GamepadButton> buttons, Map<String, dynamic> dynamicMap}) {
{List<_GamepadButton>? buttons, Map<String, dynamic>? dynamicMap}) {
return Gamepad(
buttons: buttons ?? this.buttons,
dynamicMap: dynamicMap ?? this.dynamicMap);
@ -115,13 +115,10 @@ class GamepadButtonSerializer extends Codec<GamepadButton, Map> {
get decoder => const GamepadButtonDecoder();
static GamepadButton fromMap(Map map) {
return GamepadButton(
name: map['name'] as String, radius: map['radius'] as int);
name: map['name'] as String?, radius: map['radius'] as int?);
}
static Map<String, dynamic> toMap(_GamepadButton model) {
if (model == null) {
return null;
}
return {'name': model.name, 'radius': model.radius};
}
}
@ -169,12 +166,9 @@ class GamepadSerializer extends Codec<Gamepad, Map> {
}
static Map<String, dynamic> toMap(_Gamepad model) {
if (model == null) {
return null;
}
return {
'buttons':
model.buttons?.map((m) => GamepadButtonSerializer.toMap(m))?.toList(),
model.buttons?.map((m) => GamepadButtonSerializer.toMap(m)).toList(),
'dynamic_map': model.dynamicMap
};
}

View file

@ -16,7 +16,7 @@ class Goat implements _Goat {
@override
final List<int> list;
Goat copyWith({int integer, List<int> list}) {
Goat copyWith({int? integer, List<int>? list}) {
return Goat(integer: integer ?? this.integer, list: list ?? this.list);
}
@ -70,16 +70,13 @@ class GoatSerializer extends Codec<Goat, Map> {
get decoder => const GoatDecoder();
static Goat fromMap(Map map) {
return Goat(
integer: map['integer'] as int ?? 34,
integer: map['integer'] as int? ?? 34,
list: map['list'] is Iterable
? (map['list'] as Iterable).cast<int>().toList()
: const [34, 35]);
}
static Map<String, dynamic> toMap(_Goat model) {
if (model == null) {
return null;
}
return {'integer': model.integer, 'list': model.list};
}
}

View file

@ -4,9 +4,9 @@ import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
part 'has_map.g.dart';
Map _fromString(v) => json.decode(v.toString()) as Map;
Map? _fromString(v) => json.decode(v.toString()) as Map?;
String _toString(Map v) => json.encode(v);
String _toString(Map? v) => json.encode(v);
@serializable
abstract class _HasMap {
@ -15,5 +15,5 @@ abstract class _HasMap {
deserializer: #_fromString,
isNullable: false,
serializesTo: String)
Map get value;
Map? get value;
}

View file

@ -8,12 +8,12 @@ part of 'has_map.dart';
@generatedSerializable
class HasMap implements _HasMap {
const HasMap({@required this.value});
const HasMap({required this.value});
@override
final Map<dynamic, dynamic> value;
final Map<dynamic, dynamic>? value;
HasMap copyWith({Map<dynamic, dynamic> value}) {
HasMap copyWith({Map<dynamic, dynamic>? value}) {
return HasMap(value: value ?? this.value);
}
@ -75,9 +75,6 @@ class HasMapSerializer extends Codec<HasMap, Map> {
}
static Map<String, dynamic> toMap(_HasMap model) {
if (model == null) {
return null;
}
if (model.value == null) {
throw FormatException("Missing required field 'value' on HasMap.");
}

View file

@ -4,15 +4,15 @@ part 'subclass.g.dart';
@serializable
class _Animal {
@notNull
String genus;
String? genus;
@notNull
String species;
String? species;
}
@serializable
class _Bird extends _Animal {
@DefaultsTo(false)
bool isSparrow;
bool? isSparrow;
}
var saxaulSparrow = Bird(

View file

@ -8,15 +8,15 @@ part of 'subclass.dart';
@generatedSerializable
class Animal extends _Animal {
Animal({@required this.genus, @required this.species});
Animal({required this.genus, required this.species});
@override
String genus;
String? genus;
@override
String species;
String? species;
Animal copyWith({String genus, String species}) {
Animal copyWith({String? genus, String? species}) {
return Animal(genus: genus ?? this.genus, species: species ?? this.species);
}
@ -41,18 +41,18 @@ class Animal extends _Animal {
@generatedSerializable
class Bird extends _Bird {
Bird({@required this.genus, @required this.species, this.isSparrow = false});
Bird({required this.genus, required this.species, this.isSparrow = false});
@override
String genus;
String? genus;
@override
String species;
String? species;
@override
bool isSparrow;
bool? isSparrow;
Bird copyWith({String genus, String species, bool isSparrow}) {
Bird copyWith({String? genus, String? species, bool? isSparrow}) {
return Bird(
genus: genus ?? this.genus,
species: species ?? this.species,
@ -118,13 +118,10 @@ class AnimalSerializer extends Codec<Animal, Map> {
}
return Animal(
genus: map['genus'] as String, species: map['species'] as String);
genus: map['genus'] as String?, species: map['species'] as String?);
}
static Map<String, dynamic> toMap(_Animal model) {
if (model == null) {
return null;
}
if (model.genus == null) {
throw FormatException("Missing required field 'genus' on Animal.");
}
@ -178,15 +175,12 @@ class BirdSerializer extends Codec<Bird, Map> {
}
return Bird(
genus: map['genus'] as String,
species: map['species'] as String,
isSparrow: map['is_sparrow'] as bool ?? false);
genus: map['genus'] as String?,
species: map['species'] as String?,
isSparrow: map['is_sparrow'] as bool? ?? false);
}
static Map<String, dynamic> toMap(_Bird model) {
if (model == null) {
return null;
}
if (model.genus == null) {
throw FormatException("Missing required field 'genus' on Bird.");
}

View file

@ -7,11 +7,11 @@ part 'with_enum.g.dart';
@serializable
abstract class _WithEnum {
@DefaultsTo(WithEnumType.b)
WithEnumType get type;
WithEnumType? get type;
List<int> get finalList;
List<int>? get finalList;
Uint8List get imageBytes;
Uint8List? get imageBytes;
}
enum WithEnumType { a, b, c }

View file

@ -11,16 +11,16 @@ class WithEnum implements _WithEnum {
const WithEnum({this.type = WithEnumType.b, this.finalList, this.imageBytes});
@override
final WithEnumType type;
final WithEnumType? type;
@override
final List<int> finalList;
final List<int>? finalList;
@override
final Uint8List imageBytes;
final Uint8List? imageBytes;
WithEnum copyWith(
{WithEnumType type, List<int> finalList, Uint8List imageBytes}) {
{WithEnumType? type, List<int>? finalList, Uint8List? imageBytes}) {
return WithEnum(
type: type ?? this.type,
finalList: finalList ?? this.finalList,
@ -80,7 +80,7 @@ class WithEnumSerializer extends Codec<WithEnum, Map> {
static WithEnum fromMap(Map map) {
return WithEnum(
type: map['type'] is WithEnumType
? (map['type'] as WithEnumType)
? (map['type'] as WithEnumType?)
: (map['type'] is int
? WithEnumType.values[map['type'] as int]
: WithEnumType.b),
@ -88,7 +88,7 @@ class WithEnumSerializer extends Codec<WithEnum, Map> {
? (map['final_list'] as Iterable).cast<int>().toList()
: null,
imageBytes: map['image_bytes'] is Uint8List
? (map['image_bytes'] as Uint8List)
? (map['image_bytes'] as Uint8List?)
: (map['image_bytes'] is Iterable<int>
? Uint8List.fromList(
(map['image_bytes'] as Iterable<int>).toList())
@ -99,15 +99,12 @@ class WithEnumSerializer extends Codec<WithEnum, Map> {
}
static Map<String, dynamic> toMap(_WithEnum model) {
if (model == null) {
return null;
}
return {
'type':
model.type == null ? null : WithEnumType.values.indexOf(model.type),
model.type == null ? null : WithEnumType.values.indexOf(model.type!),
'final_list': model.finalList,
'image_bytes':
model.imageBytes == null ? null : base64.encode(model.imageBytes)
model.imageBytes == null ? null : base64.encode(model.imageBytes!)
};
}
}

View file

@ -1,4 +0,0 @@
cd angel_serialize_generator
pub get
pub run build_runner build --delete-conflicting-outputs
pub run test

View file

@ -1,3 +1,9 @@
# 4.0.0
* Migrated to support Dart SDK 2.12.x NNBD
# 3.0.0
* Migrated to work with Dart SDK 2.12.x Non NNBD
# 2.0.2
* Deduplicate error messages.

View file

@ -1,7 +1,6 @@
name: angel_validate
description: Cross-platform request body validation library based on `matcher`.
version: 4.0.0
author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/validate
publish_to: none
environment: