From 53d57d6a96f52077e93bb636532d48bf0e932bff Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Sat, 29 Jun 2019 15:23:14 +0200 Subject: [PATCH] Refactor generator: Extract common operations --- moor/test/data/tables/todos.dart | 22 +++++-- moor/test/data/tables/todos.g.dart | 58 ++++--------------- moor_generator/lib/moor_generator.dart | 5 +- moor_generator/lib/src/moor_generator.dart | 39 +++++-------- .../lib/src/parser/column_parser.dart | 8 +-- moor_generator/lib/src/parser/parser.dart | 2 +- .../lib/src/parser/table_parser.dart | 8 +-- moor_generator/lib/src/shared_state.dart | 25 ++++++++ moor_generator/test/parser/parser_test.dart | 9 ++- 9 files changed, 87 insertions(+), 89 deletions(-) create mode 100644 moor_generator/lib/src/shared_state.dart diff --git a/moor/test/data/tables/todos.dart b/moor/test/data/tables/todos.dart index 18880d33..e182ce93 100644 --- a/moor/test/data/tables/todos.dart +++ b/moor/test/data/tables/todos.dart @@ -54,18 +54,13 @@ class TableWithoutPK extends Table { @UseMoor( tables: [TodosTable, Categories, Users, SharedTodos, TableWithoutPK], + daos: [SomeDao], queries: [ Sql( 'allTodosWithCategory', 'SELECT t.*, c.id as catId, c."desc" as catDesc ' '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 { @@ -77,3 +72,18 @@ class TodoDb extends _$TodoDb { @override 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 with _$SomeDaoMixin { + SomeDao(TodoDb db) : super(db); +} diff --git a/moor/test/data/tables/todos.g.dart b/moor/test/data/tables/todos.g.dart index 270adf6d..b57fe126 100644 --- a/moor/test/data/tables/todos.g.dart +++ b/moor/test/data/tables/todos.g.dart @@ -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 { _$TodoDb(QueryExecutor e) : super(const SqlTypeSystem.withDefaults(), e); $TodosTableTable _todosTable; @@ -1052,6 +1037,8 @@ abstract class _$TodoDb extends GeneratedDatabase { $TableWithoutPKTable _tableWithoutPK; $TableWithoutPKTable get tableWithoutPK => _tableWithoutPK ??= $TableWithoutPKTable(this); + SomeDao _someDao; + SomeDao get someDao => _someDao ??= SomeDao(this as TodoDb); AllTodosWithCategoryResult _rowToAllTodosWithCategoryResult(QueryRow row) { return AllTodosWithCategoryResult( id: row.readInt('id'), @@ -1081,38 +1068,17 @@ abstract class _$TodoDb extends GeneratedDatabase { }).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> 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> 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 List get allTables => [todosTable, categories, users, sharedTodos, tableWithoutPK]; } + +// ************************************************************************** +// DaoGenerator +// ************************************************************************** + +mixin _$SomeDaoMixin on DatabaseAccessor { + $UsersTable get users => db.users; + $SharedTodosTable get sharedTodos => db.sharedTodos; + $TodosTableTable get todosTable => db.todosTable; +} diff --git a/moor_generator/lib/moor_generator.dart b/moor_generator/lib/moor_generator.dart index 58b1c463..4cda6972 100644 --- a/moor_generator/lib/moor_generator.dart +++ b/moor_generator/lib/moor_generator.dart @@ -1,6 +1,7 @@ import 'package:build/build.dart'; import 'package:moor_generator/src/dao_generator.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:moor_generator/src/moor_generator.dart'; @@ -8,7 +9,7 @@ Builder moorBuilder(BuilderOptions options) { final writeFromString = options.config['write_from_json_string_constructor'] as bool ?? false; final parsedOptions = MoorOptions(writeFromString); + final state = SharedState(parsedOptions); - return SharedPartBuilder( - [MoorGenerator(parsedOptions), DaoGenerator()], 'moor'); + return SharedPartBuilder([MoorGenerator(state), DaoGenerator()], 'moor'); } diff --git a/moor_generator/lib/src/moor_generator.dart b/moor_generator/lib/src/moor_generator.dart index 32822e51..81be6771 100644 --- a/moor_generator/lib/src/moor_generator.dart +++ b/moor_generator/lib/src/moor_generator.dart @@ -1,4 +1,3 @@ -import 'package:analyzer/dart/element/type.dart'; import 'package:moor/moor.dart'; import 'package:analyzer/dart/analysis/results.dart'; 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/parser/column_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:source_gen/source_gen.dart'; @@ -17,18 +17,10 @@ import 'model/sql_query.dart'; import 'parser/sql/sql_parser.dart'; class MoorGenerator extends GeneratorForAnnotation { - //final Map _astForLibs = {}; - final ErrorStore errors = ErrorStore(); - final MoorOptions options; + final SharedState state; + MoorOptions get options => state.options; - TableParser tableParser; - ColumnParser columnParser; - - final tableTypeChecker = const TypeChecker.fromRuntime(Table); - - final Map _foundTables = {}; - - MoorGenerator(this.options); + MoorGenerator(this.state); ElementDeclarationResult loadElementDeclaration(Element element) { /*final result = _astForLibs.putIfAbsent(element.library.name, () { @@ -52,29 +44,30 @@ class MoorGenerator extends GeneratorForAnnotation { .toList(); final queries = annotation.peek('queries')?.listValue ?? []; - tableParser ??= TableParser(this); - columnParser ??= ColumnParser(this); + state.tableParser ??= TableParser(this); + state.columnParser ??= ColumnParser(this); final tablesForThisDb = []; var resolvedQueries = []; for (var table in tableTypes) { - if (!tableTypeChecker.isAssignableFrom(table.element)) { - errors.add(MoorError( + if (!state.tableTypeChecker.isAssignableFrom(table.element)) { + state.errors.add(MoorError( critical: true, message: 'The type $table is not a moor table', affectedElement: element)); } else { - final specifiedTable = tableParser.parse(table.element as ClassElement); - _foundTables[table] = specifiedTable; + final specifiedTable = + state.tableParser.parse(table.element as ClassElement); + state.foundTables[table] = specifiedTable; tablesForThisDb.add(specifiedTable); } } - if (errors.errors.isNotEmpty) { + if (state.errors.errors.isNotEmpty) { 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); if (error.affectedElement != null) { @@ -82,17 +75,17 @@ class MoorGenerator extends GeneratorForAnnotation { print('${span.start.toolString}\n${span.highlight()}'); } } - errors.errors.clear(); + state.errors.errors.clear(); } if (queries.isNotEmpty) { final parser = SqlParser(options, tablesForThisDb, queries)..parse(); - errors.errors.addAll(parser.errors); + state.errors.errors.addAll(parser.errors); resolvedQueries = parser.foundQueries; } - if (_foundTables.isEmpty) return ''; + if (tablesForThisDb.isEmpty) return ''; final specifiedDb = SpecifiedDatabase( element as ClassElement, tablesForThisDb, daoTypes, resolvedQueries); diff --git a/moor_generator/lib/src/parser/column_parser.dart b/moor_generator/lib/src/parser/column_parser.dart index 9ac3bb71..791be6a6 100644 --- a/moor_generator/lib/src/parser/column_parser.dart +++ b/moor_generator/lib/src/parser/column_parser.dart @@ -52,7 +52,7 @@ class ColumnParser extends ParserBase { final expr = returnExpressionOfMethod(getter); if (!(expr is FunctionExpressionInvocation)) { - generator.errors.add(MoorError( + generator.state.errors.add(MoorError( affectedElement: getter.declaredElement, message: _errorMessage, critical: true, @@ -84,7 +84,7 @@ class ColumnParser extends ParserBase { switch (methodName) { case _methodNamed: if (foundExplicitName != null) { - generator.errors.add( + generator.state.errors.add( MoorError( critical: false, affectedElement: getter.declaredElement, @@ -97,7 +97,7 @@ class ColumnParser extends ParserBase { foundExplicitName = readStringLiteral(remainingExpr.argumentList.arguments.first, () { - generator.errors.add( + generator.state.errors.add( MoorError( critical: false, affectedElement: getter.declaredElement, @@ -133,7 +133,7 @@ class ColumnParser extends ParserBase { case _methodCustomConstraint: foundCustomConstraint = readStringLiteral(remainingExpr.argumentList.arguments.first, () { - generator.errors.add( + generator.state.errors.add( MoorError( critical: false, affectedElement: getter.declaredElement, diff --git a/moor_generator/lib/src/parser/parser.dart b/moor_generator/lib/src/parser/parser.dart index 1b1b16bb..6dea15cc 100644 --- a/moor_generator/lib/src/parser/parser.dart +++ b/moor_generator/lib/src/parser/parser.dart @@ -18,7 +18,7 @@ class ParserBase { final body = method.body; if (!(body is ExpressionFunctionBody)) { - generator.errors.add(MoorError( + generator.state.errors.add(MoorError( affectedElement: method.declaredElement, critical: true, message: diff --git a/moor_generator/lib/src/parser/table_parser.dart b/moor_generator/lib/src/parser/table_parser.dart index 6d664aeb..9ec9f5dd 100644 --- a/moor_generator/lib/src/parser/table_parser.dart +++ b/moor_generator/lib/src/parser/table_parser.dart @@ -58,7 +58,7 @@ class TableParser extends ParserBase { tableNameDeclaration.node as MethodDeclaration); final tableName = readStringLiteral(returnExpr, () { - generator.errors.add(MoorError( + generator.state.errors.add(MoorError( critical: true, message: 'This getter must return a string literal, and do nothing more', @@ -79,7 +79,7 @@ class TableParser extends ParserBase { as MethodDeclaration; final body = ast.body; if (body is! ExpressionFunctionBody) { - generator.errors.add(MoorError( + generator.state.errors.add(MoorError( affectedElement: primaryKeyGetter, message: 'This must return a set literal using the => syntax!')); return null; @@ -103,7 +103,7 @@ class TableParser extends ParserBase { } } } else { - generator.errors.add(MoorError( + generator.state.errors.add(MoorError( affectedElement: primaryKeyGetter, message: 'This must return a set literal!')); } @@ -118,7 +118,7 @@ class TableParser extends ParserBase { final node = generator.loadElementDeclaration(field.getter).node as MethodDeclaration; - return generator.columnParser.parse(node, field.getter); + return generator.state.columnParser.parse(node, field.getter); }).toList(); } } diff --git a/moor_generator/lib/src/shared_state.dart b/moor_generator/lib/src/shared_state.dart new file mode 100644 index 00000000..7962f00e --- /dev/null +++ b/moor_generator/lib/src/shared_state.dart @@ -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 foundTables = {}; + + SharedState(this.options); +} diff --git a/moor_generator/test/parser/parser_test.dart b/moor_generator/test/parser/parser_test.dart index ec927a20..e213e5f6 100644 --- a/moor_generator/test/parser/parser_test.dart +++ b/moor_generator/test/parser/parser_test.dart @@ -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/table_parser.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:build_test/build_test.dart'; void main() async { LibraryElement testLib; MoorGenerator generator; + SharedState state; setUpAll(() async { testLib = await resolveSource(r''' @@ -51,8 +53,9 @@ void main() async { }); setUp(() { - generator = MoorGenerator(const MoorOptions.defaults()); - generator + state = SharedState(const MoorOptions.defaults()); + generator = MoorGenerator(state); + state ..columnParser = ColumnParser(generator) ..tableParser = TableParser(generator); }); @@ -74,7 +77,7 @@ void main() async { test('should not parse for complex methods', () async { TableParser(generator).parse(testLib.getType('WrongName')); - expect(generator.errors.errors, isNotEmpty); + expect(state.errors.errors, isNotEmpty); }); });