From d7225ad9a51acb776b1db2d28ad6d23c07bde6b9 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Sat, 21 Dec 2019 22:44:52 +0100 Subject: [PATCH] Support inheritance for daos (#285) --- moor_generator/CHANGELOG.md | 5 ++ .../lib/src/analyzer/dart/use_dao_parser.dart | 6 ++- .../src/analyzer/runner/steps/parse_dart.dart | 6 ++- .../lib/src/backends/build/moor_builder.dart | 22 ++++---- .../integration/dao_inheritance_test.dart | 54 +++++++++++++++++++ .../{ => integration}/integration_test.dart | 34 ++++-------- .../test/analyzer/integration/utils.dart | 33 ++++++++++++ 7 files changed, 123 insertions(+), 37 deletions(-) create mode 100644 moor_generator/test/analyzer/integration/dao_inheritance_test.dart rename moor_generator/test/analyzer/{ => integration}/integration_test.dart (77%) create mode 100644 moor_generator/test/analyzer/integration/utils.dart diff --git a/moor_generator/CHANGELOG.md b/moor_generator/CHANGELOG.md index bc995a67..f9a41c05 100644 --- a/moor_generator/CHANGELOG.md +++ b/moor_generator/CHANGELOG.md @@ -1,3 +1,8 @@ +## unreleased + +- Experimental new CLI tool (`pub run moor_generator`). Not useful at the moment +- Support inheritance when defining daos ([#285](https://github.com/simolus3/moor/issues/285)) + ## 2.1.1 - Fix a crash when using common table expressions in custom statements diff --git a/moor_generator/lib/src/analyzer/dart/use_dao_parser.dart b/moor_generator/lib/src/analyzer/dart/use_dao_parser.dart index 804a5cd0..0603db5e 100644 --- a/moor_generator/lib/src/analyzer/dart/use_dao_parser.dart +++ b/moor_generator/lib/src/analyzer/dart/use_dao_parser.dart @@ -8,8 +8,10 @@ class UseDaoParser { /// If [element] has a `@UseDao` annotation, parses the database model /// declared by that class and the referenced tables. Future parseDao(ClassElement element, ConstantReader annotation) async { - final dbType = element.supertype; - if (dbType.name != 'DatabaseAccessor') { + final dbType = element.allSupertypes + .firstWhere((i) => i.name == 'DatabaseAccessor', orElse: () => null); + + if (dbType == null) { step.reportError(ErrorInDartCode( affectedElement: element, severity: Severity.criticalError, diff --git a/moor_generator/lib/src/analyzer/runner/steps/parse_dart.dart b/moor_generator/lib/src/analyzer/runner/steps/parse_dart.dart index c74ad520..5967b12e 100644 --- a/moor_generator/lib/src/analyzer/runner/steps/parse_dart.dart +++ b/moor_generator/lib/src/analyzer/runner/steps/parse_dart.dart @@ -34,12 +34,14 @@ class ParseDartStep extends Step { } else { for (final annotation in _useMoorChecker.annotationsOf(declaredClass)) { final reader = ConstantReader(annotation); - databases.add(await parseDatabase(declaredClass, reader)); + final database = await parseDatabase(declaredClass, reader); + if (database != null) databases.add(database); } for (final annotation in _useDaoChecker.annotationsOf(declaredClass)) { final reader = ConstantReader(annotation); - daos.add(await parseDao(declaredClass, reader)); + final dao = await parseDao(declaredClass, reader); + if (dao != null) daos.add(dao); } } } diff --git a/moor_generator/lib/src/backends/build/moor_builder.dart b/moor_generator/lib/src/backends/build/moor_builder.dart index 8ed4e93d..e2c63aae 100644 --- a/moor_generator/lib/src/backends/build/moor_builder.dart +++ b/moor_generator/lib/src/backends/build/moor_builder.dart @@ -1,6 +1,7 @@ import 'package:build/build.dart'; import 'package:moor_generator/src/analyzer/options.dart'; import 'package:moor_generator/src/analyzer/runner/results.dart'; +import 'package:moor_generator/src/analyzer/runner/task.dart'; import 'package:moor_generator/src/analyzer/session.dart'; import 'package:moor_generator/src/backends/build/build_backend.dart'; import 'package:moor_generator/src/backends/build/generators/dao_generator.dart'; @@ -34,17 +35,20 @@ class MoorBuilder extends SharedPartBuilder { Writer createWriter() => Writer(options); Future analyzeDartFile(BuildStep step) async { - final backend = BuildBackend(); - final backendTask = backend.createTask(step); - final session = MoorSession(backend, options: options); + Task task; + try { + final backend = BuildBackend(); + final backendTask = backend.createTask(step); + final session = MoorSession(backend, options: options); - final input = session.registerFile(step.inputId.uri); - final task = session.startTask(backendTask); - await task.runTask(); + final input = session.registerFile(step.inputId.uri); + task = session.startTask(backendTask); + await task.runTask(); - task.printErrors(); - - return input.currentResult as ParsedDartFile; + return input.currentResult as ParsedDartFile; + } finally { + task.printErrors(); + } } } diff --git a/moor_generator/test/analyzer/integration/dao_inheritance_test.dart b/moor_generator/test/analyzer/integration/dao_inheritance_test.dart new file mode 100644 index 00000000..3c0da70f --- /dev/null +++ b/moor_generator/test/analyzer/integration/dao_inheritance_test.dart @@ -0,0 +1,54 @@ +import 'package:moor_generator/src/analyzer/runner/results.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + test('supports inheritance for daos', () async { + final state = TestState.withContent({ + 'a|lib/database.dart': r''' +import 'package:moor/moor.dart'; + +class Products extends Table { + IntColumn get id => integer().autoIncrement()(); + TextColumn get name => text()(); +} + +@UseMoor(tables: [Products], daos: [ProductsDao]) +class MyDatabase {} + +abstract class BaseDao + extends DatabaseAccessor { + + final TableInfo _table; + + BaseDao(MyDatabase db, this._table): super(db); + + Future insertOne(Insertable value) => into(_table).insert(value); + + Future> selectAll() => select(_table).get(); +} + +abstract class BaseProductsDao extends BaseDao { + BaseProductsDao(MyDatabase db): super(db, db.products); +} + +@UseDao(tables: [ProductTable]) +class ProductsDao extends BaseProductsDao with _$ProductDaoMixin { + ProductsDao(MyDatabase db): super(db); +} + ''', + }); + + await state.runTask('package:a/database.dart'); + final file = state.file('package:a/database.dart'); + + expect(file.isAnalyzed, isTrue); + expect(file.errors.errors, isEmpty); + + final dao = (file.currentResult as ParsedDartFile).declaredDaos.single; + expect(dao.dbClass.name, 'MyDatabase'); + + state.backend.finish(); + }); +} diff --git a/moor_generator/test/analyzer/integration_test.dart b/moor_generator/test/analyzer/integration/integration_test.dart similarity index 77% rename from moor_generator/test/analyzer/integration_test.dart rename to moor_generator/test/analyzer/integration/integration_test.dart index 8d4157d8..f6c130b5 100644 --- a/moor_generator/test/analyzer/integration_test.dart +++ b/moor_generator/test/analyzer/integration/integration_test.dart @@ -1,22 +1,17 @@ -import 'package:build/build.dart'; import 'package:moor_generator/moor_generator.dart'; import 'package:moor_generator/src/analyzer/runner/file_graph.dart'; import 'package:moor_generator/src/analyzer/runner/results.dart'; -import 'package:moor_generator/src/analyzer/runner/task.dart'; -import 'package:moor_generator/src/analyzer/session.dart'; import 'package:moor_generator/src/model/sql_query.dart'; import 'package:test/test.dart'; -import '../utils/test_backend.dart'; +import 'utils.dart'; void main() { - TestBackend backend; - MoorSession session; + TestState state; setUpAll(() { - backend = TestBackend( - { - AssetId.parse('test_lib|lib/database.dart'): r''' + state = TestState.withContent({ + 'test_lib|lib/database.dart': r''' import 'package:moor/moor.dart'; import 'another.dart'; // so that the resolver picks it up @@ -38,9 +33,8 @@ class UsedLanguages extends Table { }, ) class Database {} - ''', - AssetId.parse('test_lib|lib/tables.moor'): r''' + 'test_lib|lib/tables.moor': r''' import 'another.dart'; CREATE TABLE reference_test ( @@ -57,7 +51,7 @@ findLibraries: SELECT * FROM libraries WHERE name LIKE ?; joinTest: SELECT * FROM reference_test r INNER JOIN libraries l ON l.id = r.library; ''', - AssetId.parse('test_lib|lib/another.dart'): r''' + 'test_lib|lib/another.dart': r''' import 'package:moor/moor.dart'; class ProgrammingLanguages extends Table { @@ -66,27 +60,19 @@ class ProgrammingLanguages extends Table { IntColumn get popularity => integer().named('ieee_index').nullable()(); } ''', - }, - ); - session = MoorSession(backend); + }); }); tearDownAll(() { - backend.finish(); + state.backend.finish(); }); - Task task; - setUp(() async { - final backendTask = - backend.startTask(Uri.parse('package:test_lib/database.dart')); - task = session.startTask(backendTask); - await task.runTask(); + await state.runTask('package:test_lib/database.dart'); }); test('resolves tables and queries', () { - final file = - session.registerFile(Uri.parse('package:test_lib/database.dart')); + final file = state.file('package:test_lib/database.dart'); expect(file.state, FileState.analyzed); expect(file.errors.errors, isEmpty); diff --git a/moor_generator/test/analyzer/integration/utils.dart b/moor_generator/test/analyzer/integration/utils.dart new file mode 100644 index 00000000..b32f6b09 --- /dev/null +++ b/moor_generator/test/analyzer/integration/utils.dart @@ -0,0 +1,33 @@ +import 'package:build/build.dart'; +import 'package:moor_generator/src/analyzer/runner/file_graph.dart'; +import 'package:moor_generator/src/analyzer/runner/task.dart'; +import 'package:moor_generator/src/analyzer/session.dart'; + +import '../../utils/test_backend.dart'; + +class TestState { + TestBackend backend; + MoorSession session; + + TestState(this.backend, this.session); + + factory TestState.withContent(Map content) { + final backend = TestBackend({ + for (final entry in content.entries) + AssetId.parse(entry.key): entry.value, + }); + final session = MoorSession(backend); + return TestState(backend, session); + } + + Future runTask(String entrypointUri) async { + final backendTask = backend.startTask(Uri.parse(entrypointUri)); + final task = session.startTask(backendTask); + await task.runTask(); + return task; + } + + FoundFile file(String uri) { + return session.registerFile(Uri.parse(uri)); + } +}