2017-09-15 00:36:28 +00:00
|
|
|
import 'dart:async';
|
2017-06-20 22:13:04 +00:00
|
|
|
import 'package:analyzer/dart/element/element.dart';
|
|
|
|
import 'package:analyzer/dart/element/type.dart';
|
|
|
|
import 'package:analyzer/src/dart/element/element.dart';
|
|
|
|
import 'package:angel_serialize/angel_serialize.dart';
|
|
|
|
import 'package:build/build.dart';
|
|
|
|
import 'package:path/path.dart' as p;
|
|
|
|
import 'package:recase/recase.dart';
|
2017-09-15 00:20:36 +00:00
|
|
|
import 'package:source_gen/source_gen.dart';
|
2017-06-20 22:13:04 +00:00
|
|
|
import 'context.dart';
|
|
|
|
|
2017-09-15 00:20:36 +00:00
|
|
|
const TypeChecker aliasTypeChecker = const TypeChecker.fromRuntime(Alias);
|
|
|
|
|
|
|
|
const TypeChecker excludeTypeChecker = const TypeChecker.fromRuntime(Exclude);
|
|
|
|
|
|
|
|
const TypeChecker serializableTypeChecker =
|
2017-09-15 00:36:28 +00:00
|
|
|
const TypeChecker.fromRuntime(Serializable);
|
2017-09-15 00:20:36 +00:00
|
|
|
|
2017-06-20 22:13:04 +00:00
|
|
|
// TODO: Should add id, createdAt, updatedAt...
|
2017-09-15 00:36:28 +00:00
|
|
|
Future<BuildContext> buildContext(
|
2017-06-20 22:13:04 +00:00
|
|
|
ClassElement clazz,
|
|
|
|
Serializable annotation,
|
|
|
|
BuildStep buildStep,
|
|
|
|
Resolver resolver,
|
|
|
|
bool autoSnakeCaseNames,
|
|
|
|
bool autoIdAndDateFields,
|
2017-09-15 00:36:28 +00:00
|
|
|
{bool heedExclude: true}) async {
|
2017-06-20 22:13:04 +00:00
|
|
|
var ctx = new BuildContext(annotation,
|
|
|
|
originalClassName: clazz.name,
|
|
|
|
sourceFilename: p.basename(buildStep.inputId.path));
|
2017-09-15 00:36:28 +00:00
|
|
|
var lib = await resolver.libraryFor(buildStep.inputId);
|
2017-06-20 22:13:04 +00:00
|
|
|
List<String> fieldNames = [];
|
|
|
|
|
|
|
|
for (var field in clazz.fields) {
|
|
|
|
if (field.getter != null && field.setter != null) {
|
|
|
|
fieldNames.add(field.name);
|
|
|
|
// Skip if annotated with @exclude
|
2017-09-15 00:20:36 +00:00
|
|
|
var excludeAnnotation = excludeTypeChecker.firstAnnotationOf(field);
|
2017-06-20 22:13:04 +00:00
|
|
|
if (excludeAnnotation != null) continue;
|
|
|
|
// Check for alias
|
2017-09-15 00:20:36 +00:00
|
|
|
Alias alias;
|
|
|
|
var aliasAnn = aliasTypeChecker.firstAnnotationOf(field);
|
|
|
|
|
|
|
|
if (aliasAnn != null) {
|
|
|
|
alias = new Alias(aliasAnn.getField('name').toStringValue());
|
|
|
|
}
|
2017-06-20 22:13:04 +00:00
|
|
|
|
|
|
|
if (alias?.name?.isNotEmpty == true) {
|
|
|
|
ctx.aliases[field.name] = alias.name;
|
|
|
|
} else if (autoSnakeCaseNames != false) {
|
|
|
|
ctx.aliases[field.name] = new ReCase(field.name).snakeCase;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.fields.add(field);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (autoIdAndDateFields != false) {
|
|
|
|
if (!fieldNames.contains('id')) {
|
|
|
|
var idField = new _ShimField('id', lib.context.typeProvider.stringType);
|
|
|
|
ctx.fields.insert(0, idField);
|
|
|
|
ctx.shimmed['id'] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
DartType dateTime;
|
2017-09-15 00:36:28 +00:00
|
|
|
for (var key in ['createdAt', 'updatedAt']) {
|
2017-06-20 22:13:04 +00:00
|
|
|
if (!fieldNames.contains(key)) {
|
|
|
|
if (dateTime == null) {
|
2017-09-15 00:36:28 +00:00
|
|
|
var coreLib =
|
|
|
|
await resolver.libraries.singleWhere((lib) => lib.isDartCore);
|
2017-06-20 22:13:04 +00:00
|
|
|
var dt = coreLib.getType('DateTime');
|
|
|
|
dateTime = dt.type;
|
|
|
|
}
|
|
|
|
|
|
|
|
var field = new _ShimField(key, dateTime);
|
|
|
|
ctx.aliases[key] = new ReCase(key).snakeCase;
|
|
|
|
ctx.fields.add(field);
|
|
|
|
ctx.shimmed[key] = true;
|
|
|
|
}
|
2017-09-15 00:36:28 +00:00
|
|
|
}
|
|
|
|
;
|
2017-06-20 22:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
class _ShimField extends FieldElementImpl {
|
|
|
|
@override
|
|
|
|
final DartType type;
|
|
|
|
_ShimField(String name, this.type) : super(name, -1);
|
|
|
|
}
|