Updated orm generator

This commit is contained in:
thomashii 2021-08-01 18:55:01 +08:00
parent 3fde227c94
commit 8885a6b1c3
7 changed files with 112 additions and 51 deletions

10
.gitignore vendored
View file

@ -40,11 +40,10 @@ pubspec.lock
## VsCode
.vscode/
#.vscode/*
#!.vscode/settings.json
#!.vscode/tasks.json
#!.vscode/launch.json
#!.vscode/extensions.json
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# IntelliJ
.idea/
@ -75,3 +74,4 @@ logs/
*.pem
.DS_Store
server_log.txt
ormapp/

View file

@ -2,15 +2,14 @@
## Short Term Goal
* Migrate all modules to support NNBD
* Fix issues and failed unit test
* ORM
* Fixing issues
* ORM source code generator
* OAuth2
* Proxy
* Update examples
* Update User Guide
* Update `Angel3` website
* Generate performance metric
* Update website
* Performance testing
## Long Term Goal

View file

@ -1,5 +1,13 @@
# Change Log
## 4.0.1
* Added `useNullSafetySyntax: true` to `DartEmitter`
* Updated `*Migration` class generator to produce NNBD code
* Updated `*Query` class generator to produce NNBD code
* Updated `*QueryWhere` class generator to produce NNBD code
* Updated `*QueryValues` class generator to produce NNBD code
## 4.0.0
* Fixed `BuildContext` cast error

View file

@ -1,6 +1,6 @@
# Angel3 ORM Generator
[![version](https://img.shields.io/badge/pub-v4.0.0-brightgreen)](https://pub.dartlang.org/packages/angel3_orm_generator)
[![version](https://img.shields.io/badge/pub-v4.0.1-brightgreen)](https://pub.dartlang.org/packages/angel3_orm_generator)
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)

View file

@ -45,17 +45,25 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
var resolver = buildStep.resolver;
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());
if (ctx == null) {
throw 'Invalid ORM build context';
}
Library generateMigrationLibrary(OrmBuildContext? ctx, ClassElement element,
// Create `FooMigration` class
var lib = generateMigrationLibrary(ctx, element, resolver, buildStep);
//if (lib == null) return null;
return DartFormatter()
.format(lib.accept(DartEmitter(useNullSafetySyntax: true)).toString());
}
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)]);
@ -63,12 +71,13 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
});
}
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'
..returns = refer('void')
..annotations.add(refer('override'))
..requiredParameters.add(_schemaParam);
@ -125,9 +134,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
switch (col.type) {
case ColumnType.varChar:
methodName = 'varChar';
if (col.length != null) {
named['length'] = literal(col.length);
}
break;
case ColumnType.serial:
methodName = 'serial';
@ -179,6 +186,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
}
var field = table.property(methodName).call(positional, named);
var cascade = <Expression>[];
var defaultValue = ctx.buildContext.defaults[name];
@ -226,12 +234,23 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
}
if (cascade.isNotEmpty) {
var b = StringBuffer()..writeln(field.accept(DartEmitter()));
var b = StringBuffer()
..writeln(
field.accept(DartEmitter(useNullSafetySyntax: true)));
if (cascade.length == 1) {
var ex = cascade[0];
b
..write('.')
..writeln(
ex.accept(DartEmitter(useNullSafetySyntax: true)));
} else {
for (var ex in cascade) {
b
..write('..')
..writeln(ex.accept(DartEmitter()));
..writeln(
ex.accept(DartEmitter(useNullSafetySyntax: true)));
}
}
field = CodeExpression(Code(b.toString()));
@ -290,6 +309,7 @@ class MigrationGenerator extends GeneratorForAnnotation<Orm> {
return Method((b) {
b
..name = 'down'
..returns = refer('void')
..annotations.add(refer('override'))
..requiredParameters.add(_schemaParam)
..body = Block((b) {

View file

@ -41,27 +41,39 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
if (element is ClassElement) {
var ctx = await buildOrmContext({}, element, annotation, buildStep,
buildStep.resolver, autoSnakeCaseNames);
if (ctx == null) {
throw 'Invalid ORM build context';
}
var lib = buildOrmLibrary(buildStep.inputId, ctx);
return lib.accept(DartEmitter()).toString();
return lib.accept(DartEmitter(useNullSafetySyntax: true)).toString();
} else {
throw 'The @Orm() annotation can only be applied to classes.';
}
}
Library buildOrmLibrary(AssetId inputId, OrmBuildContext? ctx) {
Library buildOrmLibrary(AssetId inputId, OrmBuildContext ctx) {
return Library((lib) {
// Create `FooQuery` class
// Create `FooQueryWhere` class
lib.body.add(buildQueryClass(ctx));
// Create `FooQueryWhere` class
lib.body.add(buildWhereClass(ctx));
// Create `FooQueryValues` class
lib.body.add(buildValuesClass(ctx));
});
}
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');
var nullableQueryWhereType = TypeReference((b) => b
..symbol = '${rc.pascalCase}QueryWhere'
..isNullable = true);
clazz
..name = '${rc.pascalCase}Query'
..extend = TypeReference((b) {
@ -78,6 +90,10 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
b
..name = 'casts'
..annotations.add(refer('override'))
..returns = TypeReference((b) => b
..symbol = 'Map'
..types.add(refer('String'))
..types.add(refer('String')))
..type = MethodType.getter
..body = Block((b) {
var args = <String?, Expression>{};
@ -110,6 +126,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
clazz.methods.add(Method((m) {
m
..name = 'tableName'
..returns = refer('String')
..annotations.add(refer('override'))
..type = MethodType.getter
..body = Block((b) {
@ -121,6 +138,10 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
clazz.methods.add(Method((m) {
m
..name = 'fields'
..returns = TypeReference((b) => b
..symbol = 'List'
..types.add(TypeReference(
(b) => b..symbol = 'String'))) //refer('List<String>')
..annotations.add(refer('override'))
..type = MethodType.getter
..body = Block((b) {
@ -136,7 +157,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
clazz.fields.add(Field((b) {
b
..name = '_where'
..type = queryWhereType;
..type = nullableQueryWhereType;
}));
// Add where getter
@ -144,10 +165,11 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
b
..name = 'where'
..type = MethodType.getter
..returns = queryWhereType
..returns = nullableQueryWhereType
..annotations.add(refer('override'))
..body = Block((b) => b.addExpression(refer('_where').returned));
}));
// newWhereClause()
clazz.methods.add(Method((b) {
b
@ -158,12 +180,14 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
queryWhereType.newInstance([refer('this')]).returned));
}));
// Add deserialize()
// Add parseRow()
clazz.methods.add(Method((m) {
m
..name = 'parseRow'
..static = true
..returns = ctx.buildContext.modelClassType
..returns = TypeReference((b) => b
..symbol = '${rc.pascalCase}'
..isNullable = true) //refer('${rc.pascalCase}?')
..requiredParameters.add(Parameter((b) => b
..name = 'row'
..type = refer('List')))
@ -225,7 +249,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
.call([skipToList]);
if (relation.type == RelationshipType.hasMany) {
parsed = literalList([parsed]);
var pp = parsed.accept(DartEmitter());
var pp = parsed.accept(DartEmitter(useNullSafetySyntax: true));
parsed = CodeExpression(
Code('$pp.where((x) => x != null).toList()'));
}
@ -233,7 +257,8 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
refer('model').property('copyWith').call([], {name: parsed});
var block =
Block((b) => b.addExpression(refer('model').assign(expr)));
var blockStr = block.accept(DartEmitter());
var blockStr =
block.accept(DartEmitter(useNullSafetySyntax: true));
var ifStr = 'if (row.length > $i) { $blockStr }';
b.statements.add(Code(ifStr));
i += relation.foreign!.effectiveFields.length;
@ -243,15 +268,19 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
});
}));
// deserialize
clazz.methods.add(Method((m) {
m
..name = 'deserialize'
..returns = refer('Optional<${rc.pascalCase}>')
..annotations.add(refer('override'))
..requiredParameters.add(Parameter((b) => b
..name = 'row'
..type = refer('List')))
..body = Block((b) {
b.addExpression(refer('parseRow').call([refer('row')]).returned);
b.addExpression(refer('Optional.ofNullable').call([
refer('parseRow').call([refer('row')])
]).returned);
});
}));
@ -261,17 +290,18 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
..optionalParameters.add(Parameter((b) => b
..named = true
..name = 'parent'
..type = refer('Query')))
..type = refer('Query?')))
..optionalParameters.add(Parameter((b) => b
..named = true
..name = 'trampoline'
..type = TypeReference((b) => b
..symbol = 'Set'
..types.add(refer('String')))))
..type = refer('Set<String>?')))
//TypeReference((b) => b
//..symbol = 'Set'
//..types.add(refer('String')))))
..initializers.add(Code('super(parent: parent)'))
..body = Block((b) {
b.statements.addAll([
Code('trampoline ??= Set();'),
Code('trampoline ??= <String>{};'),
Code('trampoline.add(tableName);'),
]);
@ -444,7 +474,8 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
if (ctx.relations.values.any((r) => r.type == RelationshipType.hasMany)) {
for (var methodName in const ['get', 'update', 'delete']) {
clazz.methods.add(Method((b) {
var type = ctx.buildContext.modelClassType.accept(DartEmitter());
var type = ctx.buildContext.modelClassType
.accept(DartEmitter(useNullSafetySyntax: true));
b
..name = methodName
..annotations.add(refer('override'))
@ -460,8 +491,8 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
// This is only allowed with lists.
var field =
ctx.buildContext.fields.firstWhere((f) => f.name == name);
var typeLiteral =
convertTypeReference(field.type).accept(DartEmitter());
var typeLiteral = convertTypeReference(field.type)
.accept(DartEmitter(useNullSafetySyntax: true));
merge.add('''
$name: $typeLiteral.from(l.$name ?? [])..addAll(model.$name ?? [])
''');
@ -497,9 +528,9 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
});
}
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');
@ -508,6 +539,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
clazz.methods.add(Method((m) {
m
..name = 'expressionBuilders'
..returns = refer('List<SqlExpressionBuilder>')
..annotations.add(refer('override'))
..type = MethodType.getter
..body = Block((b) {
@ -601,9 +633,10 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
});
}
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');
@ -612,6 +645,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
clazz.methods.add(Method((b) {
b
..name = 'casts'
..returns = refer('Map<String, String>')
..annotations.add(refer('override'))
..type = MethodType.getter
..body = Block((b) {
@ -725,10 +759,11 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
}
var cond = prop.notEqualTo(literalNull);
var condStr = cond.accept(DartEmitter());
var condStr =
cond.accept(DartEmitter(useNullSafetySyntax: true));
var blkStr =
Block((b) => b.addExpression(target.assign(parsedId)))
.accept(DartEmitter());
.accept(DartEmitter(useNullSafetySyntax: true));
var ifStmt = Code('if ($condStr) { $blkStr }');
b.statements.add(ifStmt);
}

View file

@ -1,5 +1,5 @@
name: angel3_orm_generator
version: 4.0.0
version: 4.0.1
description: Code generators for Angel3 ORM. Generates query builder classes.
homepage: https://angel3-framework.web.app/
repository: https://github.com/dukefirehawk/angel/tree/angel3/packages/orm/angel_orm_generator
@ -26,7 +26,6 @@ dependencies:
dev_dependencies:
angel3_framework: ^4.0.0
angel3_migration: ^4.0.0
#angel_test: ^1.0.0
build_runner: ^2.0.1
pedantic: ^1.11.0
postgres: ^2.3.2