2018-12-31 01:18:44 +00:00
|
|
|
import 'package:analyzer/dart/constant/value.dart';
|
2017-06-20 22:13:04 +00:00
|
|
|
import 'package:analyzer/dart/element/element.dart';
|
2019-01-09 19:25:05 +00:00
|
|
|
import 'package:analyzer/dart/element/type.dart';
|
2017-07-10 15:15:09 +00:00
|
|
|
import 'package:angel_serialize/angel_serialize.dart';
|
2018-02-27 20:03:58 +00:00
|
|
|
import 'package:code_builder/code_builder.dart';
|
2018-02-27 19:42:06 +00:00
|
|
|
import 'package:recase/recase.dart';
|
2018-02-28 00:46:35 +00:00
|
|
|
import 'package:source_gen/source_gen.dart';
|
2017-06-20 22:13:04 +00:00
|
|
|
|
2018-02-27 19:20:39 +00:00
|
|
|
/// A base context for building serializable classes.
|
2017-06-20 22:13:04 +00:00
|
|
|
class BuildContext {
|
2018-02-27 19:42:06 +00:00
|
|
|
ReCase _modelClassNameRecase;
|
2018-02-27 20:03:58 +00:00
|
|
|
TypeReference _modelClassType;
|
2018-02-27 19:42:06 +00:00
|
|
|
|
2018-05-15 19:11:12 +00:00
|
|
|
/// A map of fields that are absolutely required, and error messages for when they are absent.
|
|
|
|
final Map<String, String> requiredFields = {};
|
|
|
|
|
2018-02-27 19:20:39 +00:00
|
|
|
/// A map of field names to resolved names from `@Alias()` declarations.
|
2017-06-20 22:13:04 +00:00
|
|
|
final Map<String, String> aliases = {};
|
2018-02-27 19:20:39 +00:00
|
|
|
|
2018-12-31 01:18:44 +00:00
|
|
|
/// A map of field names to their default values.
|
|
|
|
final Map<String, DartObject> defaults = {};
|
|
|
|
|
2019-01-07 00:56:05 +00:00
|
|
|
/// A map of fields to their related information.
|
2019-01-09 19:25:05 +00:00
|
|
|
final Map<String, SerializableFieldMirror> fieldInfo = {};
|
2019-01-07 00:56:05 +00:00
|
|
|
|
2018-02-28 00:36:53 +00:00
|
|
|
/// A map of fields that have been marked as to be excluded from serialization.
|
2019-01-07 00:56:05 +00:00
|
|
|
// ignore: deprecated_member_use
|
2018-03-02 18:38:41 +00:00
|
|
|
final Map<String, Exclude> excluded = {};
|
2018-02-28 00:36:53 +00:00
|
|
|
|
2018-02-27 19:20:39 +00:00
|
|
|
/// A map of "synthetic" fields, i.e. `id` and `created_at` injected automatically.
|
2017-06-20 22:13:04 +00:00
|
|
|
final Map<String, bool> shimmed = {};
|
2018-02-27 19:20:39 +00:00
|
|
|
|
2018-02-28 00:50:16 +00:00
|
|
|
final bool autoIdAndDateFields, autoSnakeCaseNames;
|
|
|
|
|
2017-06-20 22:13:04 +00:00
|
|
|
final String originalClassName, sourceFilename;
|
2018-02-27 19:20:39 +00:00
|
|
|
|
|
|
|
/// The fields declared on the original class.
|
2017-06-20 22:13:04 +00:00
|
|
|
final List<FieldElement> fields = [];
|
2018-02-27 19:20:39 +00:00
|
|
|
|
2018-05-13 17:23:40 +00:00
|
|
|
final List<ParameterElement> constructorParameters = [];
|
|
|
|
|
2018-02-28 00:46:35 +00:00
|
|
|
final ConstantReader annotation;
|
2018-02-27 19:20:39 +00:00
|
|
|
|
2018-05-15 19:16:46 +00:00
|
|
|
final ClassElement clazz;
|
|
|
|
|
2019-01-07 00:56:05 +00:00
|
|
|
/// Any annotations to include in the generated class.
|
|
|
|
final List<DartObject> includeAnnotations;
|
|
|
|
|
2018-02-27 19:20:39 +00:00
|
|
|
/// The name of the field that identifies data of this model type.
|
2017-06-20 22:13:04 +00:00
|
|
|
String primaryKeyName = 'id';
|
|
|
|
|
2018-05-15 19:16:46 +00:00
|
|
|
BuildContext(this.annotation, this.clazz,
|
2018-02-28 00:50:16 +00:00
|
|
|
{this.originalClassName,
|
|
|
|
this.sourceFilename,
|
|
|
|
this.autoSnakeCaseNames,
|
2019-01-07 00:56:05 +00:00
|
|
|
this.autoIdAndDateFields,
|
2019-04-30 15:44:01 +00:00
|
|
|
this.includeAnnotations = const <DartObject>[]});
|
2017-06-20 22:13:04 +00:00
|
|
|
|
2018-02-27 19:20:39 +00:00
|
|
|
/// The name of the generated class.
|
2017-06-20 22:13:04 +00:00
|
|
|
String get modelClassName => originalClassName.startsWith('_')
|
|
|
|
? originalClassName.substring(1)
|
|
|
|
: originalClassName;
|
|
|
|
|
2018-02-27 19:42:06 +00:00
|
|
|
/// A [ReCase] instance reflecting on the [modelClassName].
|
2018-02-27 20:03:58 +00:00
|
|
|
ReCase get modelClassNameRecase =>
|
2019-04-30 15:44:01 +00:00
|
|
|
_modelClassNameRecase ??= ReCase(modelClassName);
|
2018-02-27 20:03:58 +00:00
|
|
|
|
|
|
|
TypeReference get modelClassType =>
|
2019-04-30 15:44:01 +00:00
|
|
|
_modelClassType ??= TypeReference((b) => b.symbol = modelClassName);
|
2018-02-27 19:42:06 +00:00
|
|
|
|
2018-02-27 19:20:39 +00:00
|
|
|
/// The [FieldElement] pointing to the primary key.
|
|
|
|
FieldElement get primaryKeyField =>
|
|
|
|
fields.firstWhere((f) => f.name == primaryKeyName);
|
|
|
|
|
2018-05-15 19:33:57 +00:00
|
|
|
bool get importsPackageMeta {
|
|
|
|
return clazz.library.imports.any((i) => i.uri == 'package:meta/meta.dart');
|
|
|
|
}
|
|
|
|
|
2018-02-27 19:20:39 +00:00
|
|
|
/// Get the aliased name (if one is defined) for a field.
|
2017-06-20 22:13:04 +00:00
|
|
|
String resolveFieldName(String name) =>
|
|
|
|
aliases.containsKey(name) ? aliases[name] : name;
|
2019-01-09 19:25:05 +00:00
|
|
|
|
|
|
|
/// Finds the type that the field [name] should serialize to.
|
|
|
|
DartType resolveSerializedFieldType(String name) {
|
|
|
|
return fieldInfo[name]?.serializesTo ??
|
|
|
|
fields.firstWhere((f) => f.name == name).type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class SerializableFieldMirror {
|
|
|
|
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,
|
|
|
|
this.defaultValue,
|
|
|
|
this.serializer,
|
|
|
|
this.deserializer,
|
|
|
|
this.errorMessage,
|
|
|
|
this.isNullable,
|
|
|
|
this.canDeserialize,
|
|
|
|
this.canSerialize,
|
|
|
|
this.exclude,
|
|
|
|
this.serializesTo});
|
2017-06-20 22:13:04 +00:00
|
|
|
}
|