From af36c3b33900429340b218d5dcf6fc5f7d7f1c92 Mon Sep 17 00:00:00 2001 From: "thomashii@dukefirehawk.com" Date: Sun, 2 May 2021 19:33:32 +0800 Subject: [PATCH] Migrated angel_orm_generator --- CHANGELOG.md | 4 +- .../orm/angel_orm_generator/example/main.dart | 18 +-- .../angel_orm_generator/example/main.g.dart | 117 +++++++++--------- .../lib/src/migration_generator.dart | 43 ++++--- .../lib/src/orm_build_context.dart | 68 +++++----- .../lib/src/orm_generator.dart | 96 +++++++------- .../angel_orm_generator/lib/src/readers.dart | 30 ++--- packages/orm/angel_orm_generator/pubspec.yaml | 47 +++---- 8 files changed, 214 insertions(+), 209 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f1f5787..28d66ce5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,8 +31,8 @@ * Created basic-sdk-2.12.x_nnbd template (1/1 test passed) <= Milestone 1 * 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 (0/0 tests passed) -* Updated angel_migration to 3.0.0 (0/0 tests passed) +* Migrated angel_orm to 3.0.0 (0/0 tests passed) +* Migrated angel_migration to 3.0.0 (0/0 tests passed) * Added inflection2 and migrated to 1.0.0 (28/32 tests passed) * Updated angel_orm_generator to 3.0.0 (in progress) * Updated angel_migration_runner to 3.0.0 (in progress) diff --git a/packages/orm/angel_orm_generator/example/main.dart b/packages/orm/angel_orm_generator/example/main.dart index b81ac762..84421f81 100644 --- a/packages/orm/angel_orm_generator/example/main.dart +++ b/packages/orm/angel_orm_generator/example/main.dart @@ -8,12 +8,12 @@ part 'main.g.dart'; main() async { var query = EmployeeQuery() - ..where.firstName.equals('Rich') - ..where.lastName.equals('Person') - ..orWhere((w) => w.salary.greaterThanOrEqualTo(75000)) + ..where!.firstName.equals('Rich') + ..where!.lastName.equals('Person') + ..orWhere((w) => w!.salary.greaterThanOrEqualTo(75000)) ..join('companies', 'company_id', 'id'); - var richPerson = await query.getOne(_FakeExecutor()); + var richPerson = await (query.getOne(_FakeExecutor()) as FutureOr); print(richPerson.toJson()); } @@ -22,7 +22,7 @@ class _FakeExecutor extends QueryExecutor { @override Future> query( - String tableName, String query, Map substitutionValues, + String tableName, String? query, Map substitutionValues, [returningFields]) async { var now = DateTime.now(); print( @@ -41,12 +41,12 @@ class _FakeExecutor extends QueryExecutor { @orm @serializable abstract class _Employee extends Model { - String get firstName; + String? get firstName; - String get lastName; + String? get lastName; @Column(indexType: IndexType.unique) - String uniqueId; + String? uniqueId; - double get salary; + double? get salary; } diff --git a/packages/orm/angel_orm_generator/example/main.g.dart b/packages/orm/angel_orm_generator/example/main.g.dart index a87e89f2..78717b64 100644 --- a/packages/orm/angel_orm_generator/example/main.g.dart +++ b/packages/orm/angel_orm_generator/example/main.g.dart @@ -8,9 +8,9 @@ part of 'main.dart'; class EmployeeMigration extends Migration { @override - up(Schema schema) { + void up(Schema schema) { schema.create('employees', (table) { - table.serial('id')..primaryKey(); + table.serial('id').primaryKey(); table.timeStamp('created_at'); table.timeStamp('updated_at'); table.varChar('unique_id'); @@ -21,7 +21,7 @@ class EmployeeMigration extends Migration { } @override - down(Schema schema) { + void down(Schema schema) { schema.drop('employees'); } } @@ -30,8 +30,8 @@ class EmployeeMigration extends Migration { // OrmGenerator // ************************************************************************** -class EmployeeQuery extends Query { - EmployeeQuery({Set trampoline}) { +class EmployeeQuery extends Query { + EmployeeQuery({Set? trampoline}) { trampoline ??= Set(); trampoline.add(tableName); _where = EmployeeQueryWhere(this); @@ -40,7 +40,7 @@ class EmployeeQuery extends Query { @override final EmployeeQueryValues values = EmployeeQueryValues(); - EmployeeQueryWhere _where; + EmployeeQueryWhere? _where; @override get casts { @@ -66,7 +66,7 @@ class EmployeeQuery extends Query { } @override - EmployeeQueryWhere get where { + EmployeeQueryWhere? get where { return _where; } @@ -75,15 +75,15 @@ class EmployeeQuery extends Query { return EmployeeQueryWhere(this); } - static Employee parseRow(List row) { + static Employee? parseRow(List row) { if (row.every((x) => x == null)) return null; var model = Employee( - id: (row[0] as String), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime), - uniqueId: (row[3] as String), - firstName: (row[4] as String), - lastName: (row[5] as String), + id: (row[0] as String?), + createdAt: (row[1] as DateTime?), + updatedAt: (row[2] as DateTime?), + uniqueId: (row[3] as String?), + firstName: (row[4] as String?), + lastName: (row[5] as String?), salary: double.tryParse(row[6].toString())); return model; } @@ -130,41 +130,41 @@ class EmployeeQueryValues extends MapQueryValues { return {'salary': 'decimal'}; } - String get id { - return (values['id'] as String); + String? get id { + return (values['id'] as String?); } - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); + set id(String? value) => values['id'] = value; + DateTime? get createdAt { + return (values['created_at'] as DateTime?); } - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); + set createdAt(DateTime? value) => values['created_at'] = value; + DateTime? get updatedAt { + return (values['updated_at'] as DateTime?); } - set updatedAt(DateTime value) => values['updated_at'] = value; - String get uniqueId { - return (values['unique_id'] as String); + set updatedAt(DateTime? value) => values['updated_at'] = value; + String? get uniqueId { + return (values['unique_id'] as String?); } - set uniqueId(String value) => values['unique_id'] = value; - String get firstName { - return (values['first_name'] as String); + set uniqueId(String? value) => values['unique_id'] = value; + String? get firstName { + return (values['first_name'] as String?); } - set firstName(String value) => values['first_name'] = value; - String get lastName { - return (values['last_name'] as String); + set firstName(String? value) => values['first_name'] = value; + String? get lastName { + return (values['last_name'] as String?); } - set lastName(String value) => values['last_name'] = value; - double get salary { + set lastName(String? value) => values['last_name'] = value; + double? get salary { return double.tryParse((values['salary'] as String)); } - set salary(double value) => values['salary'] = value.toString(); + set salary(double? value) => values['salary'] = value.toString(); void copyFrom(Employee model) { id = model.id; createdAt = model.createdAt; @@ -193,36 +193,36 @@ class Employee extends _Employee { /// 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 uniqueId; + String? uniqueId; @override - final String firstName; + final String? firstName; @override - final String lastName; + final String? lastName; @override - final double salary; + final double? salary; Employee copyWith( - {String id, - DateTime createdAt, - DateTime updatedAt, - String uniqueId, - String firstName, - String lastName, - double salary}) { + {String? id, + DateTime? createdAt, + DateTime? updatedAt, + String? uniqueId, + String? firstName, + String? lastName, + double? salary}) { return Employee( id: id ?? this.id, createdAt: createdAt ?? this.createdAt, @@ -284,32 +284,29 @@ class EmployeeSerializer extends Codec { const EmployeeSerializer(); @override - get encoder => const EmployeeEncoder(); + EmployeeEncoder get encoder => const EmployeeEncoder(); @override - get decoder => const EmployeeDecoder(); + EmployeeDecoder get decoder => const EmployeeDecoder(); static Employee fromMap(Map map) { return Employee( - 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, - uniqueId: map['unique_id'] as String, - firstName: map['first_name'] as String, - lastName: map['last_name'] as String, - salary: map['salary'] as double); + uniqueId: map['unique_id'] as String?, + firstName: map['first_name'] as String?, + lastName: map['last_name'] as String?, + salary: map['salary'] as double?); } static Map toMap(_Employee model) { - if (model == null) { - return null; - } return { 'id': model.id, 'created_at': model.createdAt?.toIso8601String(), diff --git a/packages/orm/angel_orm_generator/lib/src/migration_generator.dart b/packages/orm/angel_orm_generator/lib/src/migration_generator.dart index 25cc6c69..1649a4ce 100644 --- a/packages/orm/angel_orm_generator/lib/src/migration_generator.dart +++ b/packages/orm/angel_orm_generator/lib/src/migration_generator.dart @@ -29,7 +29,7 @@ class MigrationGenerator extends GeneratorForAnnotation { const MigrationGenerator({this.autoSnakeCaseNames = true}); @override - Future generateForAnnotatedElement( + Future generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep) async { if (element is! ClassElement) { throw 'Only classes can be annotated with @ORM().'; @@ -43,20 +43,19 @@ class MigrationGenerator extends GeneratorForAnnotation { } var resolver = await buildStep.resolver; - var ctx = await buildOrmContext({}, element as ClassElement, annotation, - buildStep, resolver, autoSnakeCaseNames != false); - var lib = generateMigrationLibrary( - ctx, element as ClassElement, resolver, buildStep); + var ctx = await buildOrmContext({}, element, annotation, buildStep, + resolver, autoSnakeCaseNames != false); + var lib = generateMigrationLibrary(ctx, element, resolver, buildStep); if (lib == null) return null; return DartFormatter().format(lib.accept(DartEmitter()).toString()); } - Library generateMigrationLibrary(OrmBuildContext ctx, ClassElement element, + Library generateMigrationLibrary(OrmBuildContext? ctx, ClassElement element, Resolver resolver, BuildStep buildStep) { return Library((lib) { lib.body.add(Class((clazz) { clazz - ..name = '${ctx.buildContext.modelClassName}Migration' + ..name = '${ctx!.buildContext.modelClassName}Migration' ..extend = refer('Migration') ..methods .addAll([buildUpMigration(ctx, lib), buildDownMigration(ctx)]); @@ -64,10 +63,10 @@ class MigrationGenerator extends GeneratorForAnnotation { }); } - Method buildUpMigration(OrmBuildContext ctx, LibraryBuilder lib) { + Method buildUpMigration(OrmBuildContext? ctx, LibraryBuilder lib) { return Method((meth) { var autoIdAndDateFields = const TypeChecker.fromRuntime(Model) - .isAssignableFromType(ctx.buildContext.clazz.thisType); + .isAssignableFromType(ctx!.buildContext.clazz.thisType); meth ..name = 'up' ..annotations.add(refer('override')) @@ -80,7 +79,7 @@ class MigrationGenerator extends GeneratorForAnnotation { ..body = Block((closureBody) { var table = refer('table'); - List dup = []; + List dup = []; ctx.columns.forEach((name, col) { // Skip custom-expression columns. if (col.hasExpression) return; @@ -103,7 +102,7 @@ class MigrationGenerator extends GeneratorForAnnotation { (autoIdAndDateFields != false && name == 'id'))) { // Check for relationships that might duplicate for (var rName in ctx.relations.keys) { - var relationship = ctx.relations[rName]; + var relationship = ctx.relations[rName]!; if (relationship.localKey == key) return; } } @@ -111,7 +110,7 @@ class MigrationGenerator extends GeneratorForAnnotation { dup.add(key); } - String methodName; + String? methodName; List positional = [literal(key)]; Map named = {}; @@ -159,13 +158,13 @@ class MigrationGenerator extends GeneratorForAnnotation { if (col.length == null) { methodName = 'declare'; provColumn = columnTypeType.newInstance([ - literal(col.type.name), + literal(col.type!.name), ]); } else { methodName = 'declareColumn'; provColumn = colType.newInstance([], { 'type': columnTypeType.newInstance([ - literal(col.type.name), + literal(col.type!.name), ]), 'length': literal(col.length), }); @@ -183,10 +182,10 @@ class MigrationGenerator extends GeneratorForAnnotation { if (defaultValue != null && !defaultValue.isNull) { var type = defaultValue.type; - Expression defaultExpr; + Expression? defaultExpr; if (const TypeChecker.fromRuntime(RawSql) - .isAssignableFromType(defaultValue.type)) { + .isAssignableFromType(defaultValue.type!)) { var value = ConstantReader(defaultValue).read('value').stringValue; defaultExpr = @@ -195,7 +194,7 @@ class MigrationGenerator extends GeneratorForAnnotation { // Default to enum index. try { var index = - ConstantReader(defaultValue).read('index')?.intValue; + ConstantReader(defaultValue).read('index').intValue; if (index != null) defaultExpr = literalNum(index); } catch (_) { // Extremely weird error occurs here: `Not an instance of int`. @@ -203,7 +202,7 @@ class MigrationGenerator extends GeneratorForAnnotation { } } else { defaultExpr = CodeExpression( - Code(dartObjectToString(defaultValue)), + Code(dartObjectToString(defaultValue)!), ); } @@ -250,7 +249,7 @@ class MigrationGenerator extends GeneratorForAnnotation { var columnTypeType = refer('ColumnType'); var key = relationship.localKey; var keyType = relationship - .foreign.columns[relationship.foreignKey].type.name; + .foreign!.columns[relationship.foreignKey!]!.type!.name; var field = table.property('declare').call([ literal(key), @@ -284,7 +283,7 @@ class MigrationGenerator extends GeneratorForAnnotation { }); } - Method buildDownMigration(OrmBuildContext ctx) { + Method buildDownMigration(OrmBuildContext? ctx) { return Method((b) { b ..name = 'down' @@ -293,7 +292,7 @@ class MigrationGenerator extends GeneratorForAnnotation { ..body = Block((b) { var named = {}; - if (ctx.relations.values.any((r) => + if (ctx!.relations.values.any((r) => r.type == RelationshipType.hasOne || r.type == RelationshipType.hasMany || r.isManyToMany)) { @@ -302,7 +301,7 @@ class MigrationGenerator extends GeneratorForAnnotation { b.addExpression(_schema .property('drop') - .call([literalString(ctx.tableName)], named)); + .call([literalString(ctx.tableName!)], named)); }); }); } diff --git a/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart b/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart index 6dc2a731..a2bc1279 100644 --- a/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart +++ b/packages/orm/angel_orm_generator/lib/src/orm_build_context.dart @@ -10,6 +10,7 @@ import 'package:angel_serialize_generator/angel_serialize_generator.dart'; import 'package:angel_serialize_generator/build_context.dart'; import 'package:angel_serialize_generator/context.dart'; import 'package:build/build.dart'; +import 'package:collection/collection.dart' show IterableExtension; import 'package:inflection2/inflection2.dart'; import 'package:recase/recase.dart'; import 'package:source_gen/source_gen.dart'; @@ -19,21 +20,21 @@ import 'readers.dart'; bool isHasRelation(Relationship r) => r.type == RelationshipType.hasOne || r.type == RelationshipType.hasMany; -bool isSpecialId(OrmBuildContext ctx, FieldElement field) { +bool isSpecialId(OrmBuildContext? ctx, FieldElement field) { return // field is ShimFieldImpl && field is! RelationFieldImpl && (field.name == 'id' && const TypeChecker.fromRuntime(Model) - .isAssignableFromType(ctx.buildContext.clazz.thisType)); + .isAssignableFromType(ctx!.buildContext.clazz.thisType)); } Element _findElement(FieldElement field) { return (field.setter == null ? field.getter : field) ?? field; } -FieldElement findPrimaryFieldInList( - OrmBuildContext ctx, Iterable fields) { +FieldElement? findPrimaryFieldInList( + OrmBuildContext? ctx, Iterable fields) { for (var field_ in fields) { var field = field_ is RelationFieldImpl ? field_.originalField : field_; var element = _findElement(field); @@ -51,39 +52,38 @@ FieldElement findPrimaryFieldInList( } } - var specialId = - fields.firstWhere((f) => isSpecialId(ctx, f), orElse: () => null); + var specialId = fields.firstWhereOrNull((f) => isSpecialId(ctx, f)); // print( // 'Special ID on ${ctx.buildContext.originalClassName} => ${specialId?.name}'); return specialId; } -Future buildOrmContext( +Future buildOrmContext( Map cache, ClassElement clazz, ConstantReader annotation, BuildStep buildStep, Resolver resolver, - bool autoSnakeCaseNames, + bool? autoSnakeCaseNames, {bool heedExclude = true}) async { // Check for @generatedSerializable // ignore: unused_local_variable - DartObject generatedSerializable; + DartObject? generatedSerializable; while ((generatedSerializable = const TypeChecker.fromRuntime(GeneratedSerializable) .firstAnnotationOf(clazz)) != null) { - clazz = clazz.supertype.element; + clazz = clazz.supertype!.element; } - var id = clazz.location.components.join('-'); + var id = clazz.location!.components.join('-'); if (cache.containsKey(id)) { return cache[id]; } - var buildCtx = await buildContext( - clazz, annotation, buildStep, resolver, autoSnakeCaseNames, - heedExclude: heedExclude); + var buildCtx = await (buildContext( + clazz, annotation, buildStep, resolver, autoSnakeCaseNames!, + heedExclude: heedExclude) as FutureOr); var ormAnnotation = reviveORMAnnotation(annotation); // print( // 'tableName (${annotation.objectValue.type.name}) => ${ormAnnotation.tableName} from ${clazz.name} (${annotation.revive().namedArguments})'); @@ -98,7 +98,7 @@ Future buildOrmContext( // Read all fields for (var field in buildCtx.fields) { // Check for column annotation... - Column column; + Column? column; var element = _findElement(field); var columnAnnotation = columnTypeChecker.firstAnnotationOf(element); // print('${element.name} => $columnAnnotation'); @@ -134,7 +134,7 @@ Future buildOrmContext( // Try to find a relationship var el = _findElement(field); - el ??= field; + //el ??= field; var ann = relationshipTypeChecker.firstAnnotationOf(el); if (ann != null) { @@ -146,7 +146,7 @@ Future buildOrmContext( var foreignTable = cr.peek('foreignTable')?.stringValue; var cascadeOnDelete = cr.peek('cascadeOnDelete')?.boolValue == true; var through = cr.peek('through')?.typeValue; - OrmBuildContext foreign, throughContext; + OrmBuildContext? foreign, throughContext; if (foreignTable == null) { // if (!isModelClass(field.type) && @@ -166,7 +166,7 @@ Future buildOrmContext( const TypeChecker.fromRuntime(List) .isAssignableFromType(refType) && refType.typeArguments.length == 1) { - refType = (refType as InterfaceType).typeArguments[0]; + refType = refType.typeArguments[0]; } var modelType = firstModelAncestor(refType) ?? refType; @@ -175,7 +175,7 @@ Future buildOrmContext( cache, modelType.element as ClassElement, ConstantReader(const TypeChecker.fromRuntime(Orm) - .firstAnnotationOf(modelType.element)), + .firstAnnotationOf(modelType.element!)), buildStep, resolver, autoSnakeCaseNames); @@ -186,14 +186,14 @@ Future buildOrmContext( cache, through.element, ConstantReader(const TypeChecker.fromRuntime(Serializable) - .firstAnnotationOf(modelType.element)), + .firstAnnotationOf(modelType.element!)), buildStep, resolver, autoSnakeCaseNames); } var ormAnn = const TypeChecker.fromRuntime(Orm) - .firstAnnotationOf(modelType.element); + .firstAnnotationOf(modelType.element!); if (ormAnn != null) { foreignTable = @@ -201,7 +201,7 @@ Future buildOrmContext( } foreignTable ??= - pluralize(foreign.buildContext.modelClassNameRecase.snakeCase); + pluralize(foreign!.buildContext.modelClassNameRecase.snakeCase); } on StackOverflowError { throw UnsupportedError( 'There is an infinite cycle between ${clazz.name} and ${field.type.name}. This triggered a stack overflow.'); @@ -233,7 +233,7 @@ Future buildOrmContext( foreignKey ??= '${rc.snakeCase}_$localKey'; } else if (type == RelationshipType.belongsTo) { foreignKey ??= - ctx.buildContext.resolveFieldName(keyName(foreign, 'foreign key')); + ctx.buildContext.resolveFieldName(keyName(foreign!, 'foreign key')); localKey ??= '${rcc.snakeCase}_$foreignKey'; } @@ -271,7 +271,7 @@ Future buildOrmContext( // 'foreignKey=$foreignKey, localKey=$localKey'); if (relation.type == RelationshipType.belongsTo) { - var name = ReCase(relation.localKey).camelCase; + var name = ReCase(relation.localKey!).camelCase; ctx.buildContext.aliases[name] = relation.localKey; if (!ctx.effectiveFields.any((f) => f.name == field.name)) { @@ -290,7 +290,7 @@ Future buildOrmContext( ctx.relations[field.name] = relation; } else { - if (column?.type == null) { + if (column.type == null) { throw 'Cannot infer SQL column type for field "${ctx.buildContext.originalClassName}.${field.name}" with type "${field.type.displayName}".'; } @@ -315,7 +315,7 @@ Future buildOrmContext( return ctx; } -ColumnType inferColumnType(DartType type) { +ColumnType? inferColumnType(DartType type) { if (const TypeChecker.fromRuntime(String).isAssignableFromType(type)) { return ColumnType.varChar; } @@ -345,18 +345,18 @@ ColumnType inferColumnType(DartType type) { } Column reviveColumn(ConstantReader cr) { - ColumnType columnType; + ColumnType? columnType; var indexTypeObj = cr.peek('indexType')?.objectValue; indexTypeObj ??= cr.revive().namedArguments['indexType']; var columnObj = - cr.peek('type')?.objectValue?.getField('name')?.toStringValue(); + cr.peek('type')?.objectValue.getField('name')?.toStringValue(); var indexType = IndexType.values[ indexTypeObj?.getField('index')?.toIntValue() ?? IndexType.none.index]; if (const TypeChecker.fromRuntime(PrimaryKey) - .isAssignableFromType(cr.objectValue.type)) { + .isAssignableFromType(cr.objectValue.type!)) { indexType = IndexType.primaryKey; } @@ -365,7 +365,7 @@ Column reviveColumn(ConstantReader cr) { } return Column( - isNullable: cr.peek('isNullable')?.boolValue, + isNullable: cr.peek('isNullable')?.boolValue ?? false, length: cr.peek('length')?.intValue, type: columnType, indexType: indexType, @@ -378,7 +378,7 @@ const TypeChecker relationshipTypeChecker = class OrmBuildContext { final BuildContext buildContext; final Orm ormAnnotation; - final String tableName; + final String? tableName; final Map columns = {}; final List effectiveFields = []; @@ -411,13 +411,13 @@ class RelationFieldImpl extends ShimFieldImpl { String get originalFieldName => originalField.name; - PropertyAccessorElement get getter => originalField.getter; + PropertyAccessorElement? get getter => originalField.getter; } -InterfaceType firstModelAncestor(DartType type) { +InterfaceType? firstModelAncestor(DartType? type) { if (type is InterfaceType) { if (type.superclass != null && - const TypeChecker.fromRuntime(Model).isExactlyType(type.superclass)) { + const TypeChecker.fromRuntime(Model).isExactlyType(type.superclass!)) { return type; } else { return type.superclass == null diff --git a/packages/orm/angel_orm_generator/lib/src/orm_generator.dart b/packages/orm/angel_orm_generator/lib/src/orm_generator.dart index 5bf32ffc..23d209b4 100644 --- a/packages/orm/angel_orm_generator/lib/src/orm_generator.dart +++ b/packages/orm/angel_orm_generator/lib/src/orm_generator.dart @@ -31,7 +31,7 @@ TypeReference futureOf(String type) { /// Builder that generates `.orm.g.dart`, with an abstract `FooOrm` class. class OrmGenerator extends GeneratorForAnnotation { - final bool autoSnakeCaseNames; + final bool? autoSnakeCaseNames; OrmGenerator({this.autoSnakeCaseNames}); @@ -48,7 +48,7 @@ class OrmGenerator extends GeneratorForAnnotation { } } - Library buildOrmLibrary(AssetId inputId, OrmBuildContext ctx) { + Library buildOrmLibrary(AssetId inputId, OrmBuildContext? ctx) { return Library((lib) { // Create `FooQuery` class // Create `FooQueryWhere` class @@ -58,9 +58,9 @@ class OrmGenerator extends GeneratorForAnnotation { }); } - Class buildQueryClass(OrmBuildContext ctx) { + Class buildQueryClass(OrmBuildContext? ctx) { return Class((clazz) { - var rc = ctx.buildContext.modelClassNameRecase; + var rc = ctx!.buildContext.modelClassNameRecase; var queryWhereType = refer('${rc.pascalCase}QueryWhere'); clazz ..name = '${rc.pascalCase}Query' @@ -80,7 +80,7 @@ class OrmGenerator extends GeneratorForAnnotation { ..annotations.add(refer('override')) ..type = MethodType.getter ..body = Block((b) { - var args = {}; + var args = {}; for (var field in ctx.effectiveFields) { var name = ctx.buildContext.resolveFieldName(field.name); @@ -113,7 +113,7 @@ class OrmGenerator extends GeneratorForAnnotation { ..annotations.add(refer('override')) ..type = MethodType.getter ..body = Block((b) { - b.addExpression(literalString(ctx.tableName).returned); + b.addExpression(literalString(ctx.tableName!).returned); }); })); @@ -126,7 +126,7 @@ class OrmGenerator extends GeneratorForAnnotation { ..body = Block((b) { var names = ctx.effectiveFields .map((f) => - literalString(ctx.buildContext.resolveFieldName(f.name))) + literalString(ctx.buildContext.resolveFieldName(f.name)!)) .toList(); b.addExpression(literalConstList(names).returned); }); @@ -168,7 +168,7 @@ class OrmGenerator extends GeneratorForAnnotation { ..name = 'row' ..type = refer('List'))) ..body = Block((b) { - int i = 0; + var i = 0; var args = {}; for (var field in ctx.effectiveFields) { @@ -211,12 +211,12 @@ class OrmGenerator extends GeneratorForAnnotation { RelationshipType.belongsTo, RelationshipType.hasMany ].contains(relation.type)) return; - var foreign = relation.foreign; + var foreign = relation.foreign!; var skipToList = refer('row') .property('skip') .call([literalNum(i)]) .property('take') - .call([literalNum(relation.foreign.effectiveFields.length)]) + .call([literalNum(relation.foreign!.effectiveFields.length)]) .property('toList') .call([]); var parsed = refer( @@ -236,7 +236,7 @@ class OrmGenerator extends GeneratorForAnnotation { var blockStr = block.accept(DartEmitter()); var ifStr = 'if (row.length > $i) { $blockStr }'; b.statements.add(Code(ifStr)); - i += relation.foreign.effectiveFields.length; + i += relation.foreign!.effectiveFields.length; }); b.addExpression(refer('model').returned); @@ -277,10 +277,10 @@ class OrmGenerator extends GeneratorForAnnotation { // Add any manual SQL expressions. ctx.columns.forEach((name, col) { - if (col != null && col.hasExpression) { + if (col.hasExpression) { var lhs = refer('expressions').index( - literalString(ctx.buildContext.resolveFieldName(name))); - var rhs = literalString(col.expression); + literalString(ctx.buildContext.resolveFieldName(name)!)); + var rhs = literalString(col.expression!); b.addExpression(lhs.assign(rhs)); } }); @@ -301,13 +301,15 @@ class OrmGenerator extends GeneratorForAnnotation { // If this is a many-to-many, add the fields from the other object. - var additionalStrs = relation.foreign.effectiveFields.map((f) => - relation.foreign.buildContext.resolveFieldName(f.name)); - var additionalFields = additionalStrs.map(literalString); + var additionalStrs = relation.foreign!.effectiveFields.map( + (f) => relation.foreign!.buildContext + .resolveFieldName(f.name)); + var additionalFields = additionalStrs + .map(literalString as Expression Function(String?)); var joinArgs = [relation.localKey, relation.foreignKey] - .map(literalString) - .toList(); + .map(literalString as Function(String?)) + .toList() as List; // In the case of a many-to-many, we don't generate a subquery field, // as it easily leads to stack overflows. @@ -318,10 +320,10 @@ class OrmGenerator extends GeneratorForAnnotation { // FROM users // LEFT JOIN role_users ON role_users.user_id=users.id) var foreignFields = additionalStrs - .map((f) => '${relation.foreign.tableName}.$f'); + .map((f) => '${relation.foreign!.tableName}.$f'); var b = StringBuffer('(SELECT '); // role_users.role_id - b.write('${relation.throughContext.tableName}'); + b.write('${relation.throughContext!.tableName}'); b.write('.${relation.foreignKey}'); // , b.write(foreignFields.isEmpty @@ -329,39 +331,39 @@ class OrmGenerator extends GeneratorForAnnotation { : ', ' + foreignFields.join(', ')); // FROM users b.write(' FROM '); - b.write(relation.foreign.tableName); + b.write(relation.foreign!.tableName); // LEFT JOIN role_users - b.write(' LEFT JOIN ${relation.throughContext.tableName}'); + b.write(' LEFT JOIN ${relation.throughContext!.tableName}'); // Figure out which field on the "through" table points to users (foreign). var throughRelation = - relation.throughContext.relations.values.firstWhere((e) { - return e.foreignTable == relation.foreign.tableName; + relation.throughContext!.relations.values.firstWhere((e) { + return e.foreignTable == relation.foreign!.tableName; }, orElse: () { // _Role has a many-to-many to _User through _RoleUser, but // _RoleUser has no relation pointing to _User. var b = StringBuffer(); b.write(ctx.buildContext.modelClassName); b.write('has a many-to-many relationship to '); - b.write(relation.foreign.buildContext.modelClassName); + b.write(relation.foreign!.buildContext.modelClassName); b.write(' through '); b.write( - relation.throughContext.buildContext.modelClassName); + relation.throughContext!.buildContext.modelClassName); b.write(', but '); b.write( - relation.throughContext.buildContext.modelClassName); + relation.throughContext!.buildContext.modelClassName); b.write('has no relation pointing to '); - b.write(relation.foreign.buildContext.modelClassName); + b.write(relation.foreign!.buildContext.modelClassName); b.write('.'); throw b.toString(); }); // ON role_users.user_id=users.id) b.write(' ON '); - b.write('${relation.throughContext.tableName}'); + b.write('${relation.throughContext!.tableName}'); b.write('.'); b.write(throughRelation.localKey); b.write('='); - b.write(relation.foreign.tableName); + b.write(relation.foreign!.tableName); b.write('.'); b.write(throughRelation.foreignKey); b.write(')'); @@ -377,7 +379,7 @@ class OrmGenerator extends GeneratorForAnnotation { // There'll be a private `_field`, and then a getter, named `field`, // that returns the subquery object. var foreignQueryType = refer( - foreign.buildContext.modelClassNameRecase.pascalCase + + foreign!.buildContext.modelClassNameRecase.pascalCase + 'Query'); clazz ..fields.add(Field((b) => b @@ -415,7 +417,7 @@ class OrmGenerator extends GeneratorForAnnotation { if (manyToMany.isNotEmpty) { var outExprs = manyToMany.map((e) { - var foreignTableName = e.value.throughContext.tableName; + var foreignTableName = e.value.throughContext!.tableName; return CodeExpression(Code(''' (!( trampoline.contains('${ctx.tableName}') @@ -495,9 +497,9 @@ class OrmGenerator extends GeneratorForAnnotation { }); } - Class buildWhereClass(OrmBuildContext ctx) { + Class buildWhereClass(OrmBuildContext? ctx) { return Class((clazz) { - var rc = ctx.buildContext.modelClassNameRecase; + var rc = ctx!.buildContext.modelClassNameRecase; clazz ..name = '${rc.pascalCase}QueryWhere' ..extend = refer('QueryWhere'); @@ -519,7 +521,7 @@ class OrmGenerator extends GeneratorForAnnotation { // Add builders for each field for (var field in ctx.effectiveNormalFields) { - var name = field.name; + String? name = field.name; var args = []; DartType type; Reference builderType; @@ -535,7 +537,9 @@ class OrmGenerator extends GeneratorForAnnotation { isSpecialId(ctx, field)) { builderType = TypeReference((b) => b ..symbol = 'NumericSqlExpressionBuilder' - ..types.add(refer(isSpecialId(ctx, field) ? 'int' : type.name))); + ..types.add(refer(isSpecialId(ctx, field) + ? 'int' + : type.getDisplayString(withNullability: true)))); } else if (type is InterfaceType && type.element.isEnum) { builderType = TypeReference((b) => b ..symbol = 'EnumSqlExpressionBuilder' @@ -555,7 +559,7 @@ class OrmGenerator extends GeneratorForAnnotation { .isAssignableFromType(type)) { builderType = refer('ListSqlExpressionBuilder'); } else if (ctx.relations.containsKey(field.name)) { - var relation = ctx.relations[field.name]; + var relation = ctx.relations[field.name]!; if (relation.type != RelationshipType.belongsTo) { continue; } else { @@ -566,7 +570,7 @@ class OrmGenerator extends GeneratorForAnnotation { } } else { throw UnsupportedError( - 'Cannot generate ORM code for field of type ${field.type.name}.'); + 'Cannot generate ORM code for field of type ${field.type.getDisplayString(withNullability: false)}.'); } clazz.fields.add(Field((b) { @@ -579,7 +583,7 @@ class OrmGenerator extends GeneratorForAnnotation { refer(field.name) .assign(builderType.newInstance([ refer('query'), - literalString(ctx.buildContext.resolveFieldName(field.name)) + literalString(ctx.buildContext.resolveFieldName(field.name)!) ].followedBy(args))) .code, ); @@ -597,9 +601,9 @@ class OrmGenerator extends GeneratorForAnnotation { }); } - Class buildValuesClass(OrmBuildContext ctx) { + Class buildValuesClass(OrmBuildContext? ctx) { return Class((clazz) { - var rc = ctx.buildContext.modelClassNameRecase; + var rc = ctx!.buildContext.modelClassNameRecase; clazz ..name = '${rc.pascalCase}QueryValues' ..extend = refer('MapQueryValues'); @@ -611,7 +615,7 @@ class OrmGenerator extends GeneratorForAnnotation { ..annotations.add(refer('override')) ..type = MethodType.getter ..body = Block((b) { - var args = {}; + var args = {}; for (var field in ctx.effectiveFields) { var fType = field.type; @@ -637,7 +641,7 @@ class OrmGenerator extends GeneratorForAnnotation { var type = convertTypeReference(field.type); clazz.methods.add(Method((b) { - var value = refer('values').index(literalString(name)); + var value = refer('values').index(literalString(name!)); if (fType is InterfaceType && fType.element.isEnum) { var asInt = value.asA(refer('int')); @@ -682,7 +686,7 @@ class OrmGenerator extends GeneratorForAnnotation { ..name = 'value' ..type = type)) ..body = - refer('values').index(literalString(name)).assign(value).code; + refer('values').index(literalString(name!)).assign(value).code; })); } @@ -709,7 +713,7 @@ class OrmGenerator extends GeneratorForAnnotation { var prop = refer('model').property(original); // Add only if present var target = refer('values').index(literalString( - ctx.buildContext.resolveFieldName(field.name))); + ctx.buildContext.resolveFieldName(field.name)!)); var foreign = field.relationship.throughContext ?? field.relationship.foreign; var foreignField = field.relationship.findForeignField(ctx); diff --git a/packages/orm/angel_orm_generator/lib/src/readers.dart b/packages/orm/angel_orm_generator/lib/src/readers.dart index bef5f0f2..7b169676 100644 --- a/packages/orm/angel_orm_generator/lib/src/readers.dart +++ b/packages/orm/angel_orm_generator/lib/src/readers.dart @@ -20,21 +20,21 @@ class ColumnReader { bool get isNullable => reader.peek('isNullable')?.boolValue ?? true; - int get length => reader.peek('length')?.intValue; + int? get length => reader.peek('length')?.intValue; - DartObject get defaultValue => reader.peek('defaultValue')?.objectValue; + DartObject? get defaultValue => reader.peek('defaultValue')?.objectValue; } class RelationshipReader { final int type; - final String localKey; - final String foreignKey; - final String foreignTable; - final bool cascadeOnDelete; - final DartType through; - final OrmBuildContext foreign; - final OrmBuildContext throughContext; - final JoinType joinType; + final String? localKey; + final String? foreignKey; + final String? foreignTable; + final bool? cascadeOnDelete; + final DartType? through; + final OrmBuildContext? foreign; + final OrmBuildContext? throughContext; + final JoinType? joinType; const RelationshipReader(this.type, {this.localKey, @@ -72,16 +72,16 @@ class RelationshipReader { orElse: () { throw '${ctx.buildContext.clazz.name} has no field that maps to the name "$localKey", ' 'but it has a @HasMany() relation that expects such a field.'; - }); + } as FieldElement Function()?); } - FieldElement findForeignField(OrmBuildContext ctx) { - var foreign = throughContext ?? this.foreign; + FieldElement findForeignField(OrmBuildContext? ctx) { + var foreign = throughContext ?? this.foreign!; return foreign.effectiveFields.firstWhere( (f) => foreign.buildContext.resolveFieldName(f.name) == foreignKey, orElse: () { throw '${foreign.buildContext.clazz.name} has no field that maps to the name "$foreignKey", ' - 'but ${ctx.buildContext.clazz.name} has a @HasMany() relation that expects such a field.'; - }); + 'but ${ctx!.buildContext.clazz.name} has a @HasMany() relation that expects such a field.'; + } as FieldElement Function()?); } } diff --git a/packages/orm/angel_orm_generator/pubspec.yaml b/packages/orm/angel_orm_generator/pubspec.yaml index c2e9a7b8..556c33f9 100644 --- a/packages/orm/angel_orm_generator/pubspec.yaml +++ b/packages/orm/angel_orm_generator/pubspec.yaml @@ -4,54 +4,59 @@ description: Code generators for Angel's ORM. Generates query builder classes. homepage: https://github.com/dukefirehawk/angel publish_to: none environment: - sdk: '>=2.10.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: - analyzer: ">=0.35.0 <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 angel_orm: git: url: https://github.com/dukefirehawk/angel.git - ref: sdk-2.12.x + ref: sdk-2.12.x_nnbd path: packages/orm/angel_orm angel_serialize_generator: git: url: https://github.com/dukefirehawk/angel.git - ref: sdk-2.12.x + ref: sdk-2.12.x_nnbd path: packages/serialize/angel_serialize_generator - build: ^1.0.0 - build_config: ^0.4.0 - code_builder: ^3.0.0 - dart_style: ^1.0.0 - inflection2: ^0.4.2 - meta: ^1.0.0 - path: ^1.0.0 - recase: ^3.0.1 - source_gen: ^0.9.0 + inflection2: + git: + url: https://github.com/dukefirehawk/angel.git + ref: sdk-2.12.x_nnbd + path: packages/inflection2 + build: ^2.0.1 + build_config: ^1.0.0 + code_builder: ^4.0.0 + dart_style: ^2.0.1 + meta: ^1.3.0 + path: ^1.8.0 + recase: ^4.0.0 + source_gen: ^1.0.0 + collection: ^1.15.0-nullsafety.4 dev_dependencies: angel_framework: git: url: https://github.com/dukefirehawk/angel.git - ref: sdk-2.12.x + ref: sdk-2.12.x_nnbd path: packages/framework angel_migration: git: url: https://github.com/dukefirehawk/angel.git - ref: sdk-2.12.x + ref: sdk-2.12.x_nnbd path: packages/orm/angel_migration #angel_test: ^1.0.0 - build_runner: ^1.11.5 - collection: ^1.0.0 + build_runner: ^2.0.1 + collection: ^1.15.0 pedantic: ^1.11.0 - postgres: ^2.2.0 + postgres: ^2.3.2 # git: # url: https://github.com/dukefirehawk/postgresql-dart - test: ^1.16.5 + test: ^1.17.3