mirror of https://github.com/AMT-Cheif/drift.git
Refactor generator: Extract common operations
This commit is contained in:
parent
33682a0ad1
commit
53d57d6a96
|
@ -54,18 +54,13 @@ class TableWithoutPK extends Table {
|
||||||
|
|
||||||
@UseMoor(
|
@UseMoor(
|
||||||
tables: [TodosTable, Categories, Users, SharedTodos, TableWithoutPK],
|
tables: [TodosTable, Categories, Users, SharedTodos, TableWithoutPK],
|
||||||
|
daos: [SomeDao],
|
||||||
queries: [
|
queries: [
|
||||||
Sql(
|
Sql(
|
||||||
'allTodosWithCategory',
|
'allTodosWithCategory',
|
||||||
'SELECT t.*, c.id as catId, c."desc" as catDesc '
|
'SELECT t.*, c.id as catId, c."desc" as catDesc '
|
||||||
'FROM todos t INNER JOIN categories c ON c.id = t.category',
|
'FROM todos t INNER JOIN categories c ON c.id = t.category',
|
||||||
),
|
),
|
||||||
Sql(
|
|
||||||
'todosForUser',
|
|
||||||
'SELECT t.* FROM todos t '
|
|
||||||
'INNER JOIN shared_todos st ON st.todo = t.id '
|
|
||||||
'INNER JOIN users u ON u.id = st.user '
|
|
||||||
'WHERE u.id = :user'),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
class TodoDb extends _$TodoDb {
|
class TodoDb extends _$TodoDb {
|
||||||
|
@ -77,3 +72,18 @@ class TodoDb extends _$TodoDb {
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 1;
|
int get schemaVersion => 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseDao(
|
||||||
|
tables: [Users, SharedTodos, TodosTable],
|
||||||
|
queries: [
|
||||||
|
Sql(
|
||||||
|
'todosForUser',
|
||||||
|
'SELECT t.* FROM todos t '
|
||||||
|
'INNER JOIN shared_todos st ON st.todo = t.id '
|
||||||
|
'INNER JOIN users u ON u.id = st.user '
|
||||||
|
'WHERE u.id = :user'),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
class SomeDao extends DatabaseAccessor<TodoDb> with _$SomeDaoMixin {
|
||||||
|
SomeDao(TodoDb db) : super(db);
|
||||||
|
}
|
||||||
|
|
|
@ -1024,21 +1024,6 @@ class AllTodosWithCategoryResult {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class TodosForUserResult {
|
|
||||||
final int id;
|
|
||||||
final String title;
|
|
||||||
final String content;
|
|
||||||
final DateTime targetDate;
|
|
||||||
final int category;
|
|
||||||
TodosForUserResult({
|
|
||||||
this.id,
|
|
||||||
this.title,
|
|
||||||
this.content,
|
|
||||||
this.targetDate,
|
|
||||||
this.category,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class _$TodoDb extends GeneratedDatabase {
|
abstract class _$TodoDb extends GeneratedDatabase {
|
||||||
_$TodoDb(QueryExecutor e) : super(const SqlTypeSystem.withDefaults(), e);
|
_$TodoDb(QueryExecutor e) : super(const SqlTypeSystem.withDefaults(), e);
|
||||||
$TodosTableTable _todosTable;
|
$TodosTableTable _todosTable;
|
||||||
|
@ -1052,6 +1037,8 @@ abstract class _$TodoDb extends GeneratedDatabase {
|
||||||
$TableWithoutPKTable _tableWithoutPK;
|
$TableWithoutPKTable _tableWithoutPK;
|
||||||
$TableWithoutPKTable get tableWithoutPK =>
|
$TableWithoutPKTable get tableWithoutPK =>
|
||||||
_tableWithoutPK ??= $TableWithoutPKTable(this);
|
_tableWithoutPK ??= $TableWithoutPKTable(this);
|
||||||
|
SomeDao _someDao;
|
||||||
|
SomeDao get someDao => _someDao ??= SomeDao(this as TodoDb);
|
||||||
AllTodosWithCategoryResult _rowToAllTodosWithCategoryResult(QueryRow row) {
|
AllTodosWithCategoryResult _rowToAllTodosWithCategoryResult(QueryRow row) {
|
||||||
return AllTodosWithCategoryResult(
|
return AllTodosWithCategoryResult(
|
||||||
id: row.readInt('id'),
|
id: row.readInt('id'),
|
||||||
|
@ -1081,38 +1068,17 @@ abstract class _$TodoDb extends GeneratedDatabase {
|
||||||
}).map((rows) => rows.map(_rowToAllTodosWithCategoryResult).toList());
|
}).map((rows) => rows.map(_rowToAllTodosWithCategoryResult).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
TodosForUserResult _rowToTodosForUserResult(QueryRow row) {
|
|
||||||
return TodosForUserResult(
|
|
||||||
id: row.readInt('id'),
|
|
||||||
title: row.readString('title'),
|
|
||||||
content: row.readString('content'),
|
|
||||||
targetDate: row.readDateTime('target_date'),
|
|
||||||
category: row.readInt('category'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<TodosForUserResult>> todosForUser(int user) {
|
|
||||||
return customSelect(
|
|
||||||
'SELECT t.* FROM todos t INNER JOIN shared_todos st ON st.todo = t.id INNER JOIN users u ON u.id = st.user WHERE u.id = :user',
|
|
||||||
variables: [
|
|
||||||
Variable.withInt(user),
|
|
||||||
]).then((rows) => rows.map(_rowToTodosForUserResult).toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<List<TodosForUserResult>> watchTodosForUser(int user) {
|
|
||||||
return customSelectStream(
|
|
||||||
'SELECT t.* FROM todos t INNER JOIN shared_todos st ON st.todo = t.id INNER JOIN users u ON u.id = st.user WHERE u.id = :user',
|
|
||||||
variables: [
|
|
||||||
Variable.withInt(user),
|
|
||||||
],
|
|
||||||
readsFrom: {
|
|
||||||
users,
|
|
||||||
todosTable,
|
|
||||||
sharedTodos
|
|
||||||
}).map((rows) => rows.map(_rowToTodosForUserResult).toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<TableInfo> get allTables =>
|
List<TableInfo> get allTables =>
|
||||||
[todosTable, categories, users, sharedTodos, tableWithoutPK];
|
[todosTable, categories, users, sharedTodos, tableWithoutPK];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// DaoGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
mixin _$SomeDaoMixin on DatabaseAccessor<TodoDb> {
|
||||||
|
$UsersTable get users => db.users;
|
||||||
|
$SharedTodosTable get sharedTodos => db.sharedTodos;
|
||||||
|
$TodosTableTable get todosTable => db.todosTable;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:build/build.dart';
|
import 'package:build/build.dart';
|
||||||
import 'package:moor_generator/src/dao_generator.dart';
|
import 'package:moor_generator/src/dao_generator.dart';
|
||||||
import 'package:moor_generator/src/options.dart';
|
import 'package:moor_generator/src/options.dart';
|
||||||
|
import 'package:moor_generator/src/shared_state.dart';
|
||||||
import 'package:source_gen/source_gen.dart';
|
import 'package:source_gen/source_gen.dart';
|
||||||
import 'package:moor_generator/src/moor_generator.dart';
|
import 'package:moor_generator/src/moor_generator.dart';
|
||||||
|
|
||||||
|
@ -8,7 +9,7 @@ Builder moorBuilder(BuilderOptions options) {
|
||||||
final writeFromString =
|
final writeFromString =
|
||||||
options.config['write_from_json_string_constructor'] as bool ?? false;
|
options.config['write_from_json_string_constructor'] as bool ?? false;
|
||||||
final parsedOptions = MoorOptions(writeFromString);
|
final parsedOptions = MoorOptions(writeFromString);
|
||||||
|
final state = SharedState(parsedOptions);
|
||||||
|
|
||||||
return SharedPartBuilder(
|
return SharedPartBuilder([MoorGenerator(state), DaoGenerator()], 'moor');
|
||||||
[MoorGenerator(parsedOptions), DaoGenerator()], 'moor');
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:analyzer/dart/element/type.dart';
|
|
||||||
import 'package:moor/moor.dart';
|
import 'package:moor/moor.dart';
|
||||||
import 'package:analyzer/dart/analysis/results.dart';
|
import 'package:analyzer/dart/analysis/results.dart';
|
||||||
import 'package:analyzer/src/dart/analysis/results.dart'; // ignore: implementation_imports
|
import 'package:analyzer/src/dart/analysis/results.dart'; // ignore: implementation_imports
|
||||||
|
@ -10,6 +9,7 @@ import 'package:moor_generator/src/model/specified_table.dart';
|
||||||
import 'package:moor_generator/src/options.dart';
|
import 'package:moor_generator/src/options.dart';
|
||||||
import 'package:moor_generator/src/parser/column_parser.dart';
|
import 'package:moor_generator/src/parser/column_parser.dart';
|
||||||
import 'package:moor_generator/src/parser/table_parser.dart';
|
import 'package:moor_generator/src/parser/table_parser.dart';
|
||||||
|
import 'package:moor_generator/src/shared_state.dart';
|
||||||
import 'package:moor_generator/src/writer/database_writer.dart';
|
import 'package:moor_generator/src/writer/database_writer.dart';
|
||||||
import 'package:source_gen/source_gen.dart';
|
import 'package:source_gen/source_gen.dart';
|
||||||
|
|
||||||
|
@ -17,18 +17,10 @@ import 'model/sql_query.dart';
|
||||||
import 'parser/sql/sql_parser.dart';
|
import 'parser/sql/sql_parser.dart';
|
||||||
|
|
||||||
class MoorGenerator extends GeneratorForAnnotation<UseMoor> {
|
class MoorGenerator extends GeneratorForAnnotation<UseMoor> {
|
||||||
//final Map<String, ParsedLibraryResult> _astForLibs = {};
|
final SharedState state;
|
||||||
final ErrorStore errors = ErrorStore();
|
MoorOptions get options => state.options;
|
||||||
final MoorOptions options;
|
|
||||||
|
|
||||||
TableParser tableParser;
|
MoorGenerator(this.state);
|
||||||
ColumnParser columnParser;
|
|
||||||
|
|
||||||
final tableTypeChecker = const TypeChecker.fromRuntime(Table);
|
|
||||||
|
|
||||||
final Map<DartType, SpecifiedTable> _foundTables = {};
|
|
||||||
|
|
||||||
MoorGenerator(this.options);
|
|
||||||
|
|
||||||
ElementDeclarationResult loadElementDeclaration(Element element) {
|
ElementDeclarationResult loadElementDeclaration(Element element) {
|
||||||
/*final result = _astForLibs.putIfAbsent(element.library.name, () {
|
/*final result = _astForLibs.putIfAbsent(element.library.name, () {
|
||||||
|
@ -52,29 +44,30 @@ class MoorGenerator extends GeneratorForAnnotation<UseMoor> {
|
||||||
.toList();
|
.toList();
|
||||||
final queries = annotation.peek('queries')?.listValue ?? [];
|
final queries = annotation.peek('queries')?.listValue ?? [];
|
||||||
|
|
||||||
tableParser ??= TableParser(this);
|
state.tableParser ??= TableParser(this);
|
||||||
columnParser ??= ColumnParser(this);
|
state.columnParser ??= ColumnParser(this);
|
||||||
|
|
||||||
final tablesForThisDb = <SpecifiedTable>[];
|
final tablesForThisDb = <SpecifiedTable>[];
|
||||||
var resolvedQueries = <SqlQuery>[];
|
var resolvedQueries = <SqlQuery>[];
|
||||||
|
|
||||||
for (var table in tableTypes) {
|
for (var table in tableTypes) {
|
||||||
if (!tableTypeChecker.isAssignableFrom(table.element)) {
|
if (!state.tableTypeChecker.isAssignableFrom(table.element)) {
|
||||||
errors.add(MoorError(
|
state.errors.add(MoorError(
|
||||||
critical: true,
|
critical: true,
|
||||||
message: 'The type $table is not a moor table',
|
message: 'The type $table is not a moor table',
|
||||||
affectedElement: element));
|
affectedElement: element));
|
||||||
} else {
|
} else {
|
||||||
final specifiedTable = tableParser.parse(table.element as ClassElement);
|
final specifiedTable =
|
||||||
_foundTables[table] = specifiedTable;
|
state.tableParser.parse(table.element as ClassElement);
|
||||||
|
state.foundTables[table] = specifiedTable;
|
||||||
tablesForThisDb.add(specifiedTable);
|
tablesForThisDb.add(specifiedTable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errors.errors.isNotEmpty) {
|
if (state.errors.errors.isNotEmpty) {
|
||||||
print('Warning: There were some errors while running moor_generator:');
|
print('Warning: There were some errors while running moor_generator:');
|
||||||
|
|
||||||
for (var error in errors.errors) {
|
for (var error in state.errors.errors) {
|
||||||
print(error.message);
|
print(error.message);
|
||||||
|
|
||||||
if (error.affectedElement != null) {
|
if (error.affectedElement != null) {
|
||||||
|
@ -82,17 +75,17 @@ class MoorGenerator extends GeneratorForAnnotation<UseMoor> {
|
||||||
print('${span.start.toolString}\n${span.highlight()}');
|
print('${span.start.toolString}\n${span.highlight()}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errors.errors.clear();
|
state.errors.errors.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queries.isNotEmpty) {
|
if (queries.isNotEmpty) {
|
||||||
final parser = SqlParser(options, tablesForThisDb, queries)..parse();
|
final parser = SqlParser(options, tablesForThisDb, queries)..parse();
|
||||||
errors.errors.addAll(parser.errors);
|
state.errors.errors.addAll(parser.errors);
|
||||||
|
|
||||||
resolvedQueries = parser.foundQueries;
|
resolvedQueries = parser.foundQueries;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_foundTables.isEmpty) return '';
|
if (tablesForThisDb.isEmpty) return '';
|
||||||
|
|
||||||
final specifiedDb = SpecifiedDatabase(
|
final specifiedDb = SpecifiedDatabase(
|
||||||
element as ClassElement, tablesForThisDb, daoTypes, resolvedQueries);
|
element as ClassElement, tablesForThisDb, daoTypes, resolvedQueries);
|
||||||
|
|
|
@ -52,7 +52,7 @@ class ColumnParser extends ParserBase {
|
||||||
final expr = returnExpressionOfMethod(getter);
|
final expr = returnExpressionOfMethod(getter);
|
||||||
|
|
||||||
if (!(expr is FunctionExpressionInvocation)) {
|
if (!(expr is FunctionExpressionInvocation)) {
|
||||||
generator.errors.add(MoorError(
|
generator.state.errors.add(MoorError(
|
||||||
affectedElement: getter.declaredElement,
|
affectedElement: getter.declaredElement,
|
||||||
message: _errorMessage,
|
message: _errorMessage,
|
||||||
critical: true,
|
critical: true,
|
||||||
|
@ -84,7 +84,7 @@ class ColumnParser extends ParserBase {
|
||||||
switch (methodName) {
|
switch (methodName) {
|
||||||
case _methodNamed:
|
case _methodNamed:
|
||||||
if (foundExplicitName != null) {
|
if (foundExplicitName != null) {
|
||||||
generator.errors.add(
|
generator.state.errors.add(
|
||||||
MoorError(
|
MoorError(
|
||||||
critical: false,
|
critical: false,
|
||||||
affectedElement: getter.declaredElement,
|
affectedElement: getter.declaredElement,
|
||||||
|
@ -97,7 +97,7 @@ class ColumnParser extends ParserBase {
|
||||||
|
|
||||||
foundExplicitName =
|
foundExplicitName =
|
||||||
readStringLiteral(remainingExpr.argumentList.arguments.first, () {
|
readStringLiteral(remainingExpr.argumentList.arguments.first, () {
|
||||||
generator.errors.add(
|
generator.state.errors.add(
|
||||||
MoorError(
|
MoorError(
|
||||||
critical: false,
|
critical: false,
|
||||||
affectedElement: getter.declaredElement,
|
affectedElement: getter.declaredElement,
|
||||||
|
@ -133,7 +133,7 @@ class ColumnParser extends ParserBase {
|
||||||
case _methodCustomConstraint:
|
case _methodCustomConstraint:
|
||||||
foundCustomConstraint =
|
foundCustomConstraint =
|
||||||
readStringLiteral(remainingExpr.argumentList.arguments.first, () {
|
readStringLiteral(remainingExpr.argumentList.arguments.first, () {
|
||||||
generator.errors.add(
|
generator.state.errors.add(
|
||||||
MoorError(
|
MoorError(
|
||||||
critical: false,
|
critical: false,
|
||||||
affectedElement: getter.declaredElement,
|
affectedElement: getter.declaredElement,
|
||||||
|
|
|
@ -18,7 +18,7 @@ class ParserBase {
|
||||||
final body = method.body;
|
final body = method.body;
|
||||||
|
|
||||||
if (!(body is ExpressionFunctionBody)) {
|
if (!(body is ExpressionFunctionBody)) {
|
||||||
generator.errors.add(MoorError(
|
generator.state.errors.add(MoorError(
|
||||||
affectedElement: method.declaredElement,
|
affectedElement: method.declaredElement,
|
||||||
critical: true,
|
critical: true,
|
||||||
message:
|
message:
|
||||||
|
|
|
@ -58,7 +58,7 @@ class TableParser extends ParserBase {
|
||||||
tableNameDeclaration.node as MethodDeclaration);
|
tableNameDeclaration.node as MethodDeclaration);
|
||||||
|
|
||||||
final tableName = readStringLiteral(returnExpr, () {
|
final tableName = readStringLiteral(returnExpr, () {
|
||||||
generator.errors.add(MoorError(
|
generator.state.errors.add(MoorError(
|
||||||
critical: true,
|
critical: true,
|
||||||
message:
|
message:
|
||||||
'This getter must return a string literal, and do nothing more',
|
'This getter must return a string literal, and do nothing more',
|
||||||
|
@ -79,7 +79,7 @@ class TableParser extends ParserBase {
|
||||||
as MethodDeclaration;
|
as MethodDeclaration;
|
||||||
final body = ast.body;
|
final body = ast.body;
|
||||||
if (body is! ExpressionFunctionBody) {
|
if (body is! ExpressionFunctionBody) {
|
||||||
generator.errors.add(MoorError(
|
generator.state.errors.add(MoorError(
|
||||||
affectedElement: primaryKeyGetter,
|
affectedElement: primaryKeyGetter,
|
||||||
message: 'This must return a set literal using the => syntax!'));
|
message: 'This must return a set literal using the => syntax!'));
|
||||||
return null;
|
return null;
|
||||||
|
@ -103,7 +103,7 @@ class TableParser extends ParserBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
generator.errors.add(MoorError(
|
generator.state.errors.add(MoorError(
|
||||||
affectedElement: primaryKeyGetter,
|
affectedElement: primaryKeyGetter,
|
||||||
message: 'This must return a set literal!'));
|
message: 'This must return a set literal!'));
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ class TableParser extends ParserBase {
|
||||||
final node = generator.loadElementDeclaration(field.getter).node
|
final node = generator.loadElementDeclaration(field.getter).node
|
||||||
as MethodDeclaration;
|
as MethodDeclaration;
|
||||||
|
|
||||||
return generator.columnParser.parse(node, field.getter);
|
return generator.state.columnParser.parse(node, field.getter);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import 'package:analyzer/dart/element/type.dart';
|
||||||
|
import 'package:moor/moor.dart' show Table;
|
||||||
|
import 'package:moor_generator/src/parser/column_parser.dart';
|
||||||
|
import 'package:moor_generator/src/parser/table_parser.dart';
|
||||||
|
import 'package:source_gen/source_gen.dart';
|
||||||
|
|
||||||
|
import 'errors.dart';
|
||||||
|
import 'model/specified_table.dart';
|
||||||
|
import 'options.dart';
|
||||||
|
|
||||||
|
/// Information that is needed for both the regular generator and the dao
|
||||||
|
/// generator. Kept in sync so it only needs to be evaluated once.
|
||||||
|
class SharedState {
|
||||||
|
final ErrorStore errors = ErrorStore();
|
||||||
|
final MoorOptions options;
|
||||||
|
|
||||||
|
TableParser tableParser;
|
||||||
|
ColumnParser columnParser;
|
||||||
|
|
||||||
|
final tableTypeChecker = const TypeChecker.fromRuntime(Table);
|
||||||
|
|
||||||
|
final Map<DartType, SpecifiedTable> foundTables = {};
|
||||||
|
|
||||||
|
SharedState(this.options);
|
||||||
|
}
|
|
@ -4,12 +4,14 @@ import 'package:moor_generator/src/options.dart';
|
||||||
import 'package:moor_generator/src/parser/column_parser.dart';
|
import 'package:moor_generator/src/parser/column_parser.dart';
|
||||||
import 'package:moor_generator/src/parser/table_parser.dart';
|
import 'package:moor_generator/src/parser/table_parser.dart';
|
||||||
import 'package:moor_generator/src/moor_generator.dart';
|
import 'package:moor_generator/src/moor_generator.dart';
|
||||||
|
import 'package:moor_generator/src/shared_state.dart';
|
||||||
import 'package:test_api/test_api.dart';
|
import 'package:test_api/test_api.dart';
|
||||||
import 'package:build_test/build_test.dart';
|
import 'package:build_test/build_test.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
LibraryElement testLib;
|
LibraryElement testLib;
|
||||||
MoorGenerator generator;
|
MoorGenerator generator;
|
||||||
|
SharedState state;
|
||||||
|
|
||||||
setUpAll(() async {
|
setUpAll(() async {
|
||||||
testLib = await resolveSource(r'''
|
testLib = await resolveSource(r'''
|
||||||
|
@ -51,8 +53,9 @@ void main() async {
|
||||||
});
|
});
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
generator = MoorGenerator(const MoorOptions.defaults());
|
state = SharedState(const MoorOptions.defaults());
|
||||||
generator
|
generator = MoorGenerator(state);
|
||||||
|
state
|
||||||
..columnParser = ColumnParser(generator)
|
..columnParser = ColumnParser(generator)
|
||||||
..tableParser = TableParser(generator);
|
..tableParser = TableParser(generator);
|
||||||
});
|
});
|
||||||
|
@ -74,7 +77,7 @@ void main() async {
|
||||||
test('should not parse for complex methods', () async {
|
test('should not parse for complex methods', () async {
|
||||||
TableParser(generator).parse(testLib.getType('WrongName'));
|
TableParser(generator).parse(testLib.getType('WrongName'));
|
||||||
|
|
||||||
expect(generator.errors.errors, isNotEmpty);
|
expect(state.errors.errors, isNotEmpty);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue