Support inheritance for daos (#285)

This commit is contained in:
Simon Binder 2019-12-21 22:44:52 +01:00
parent 1f0ede967b
commit d7225ad9a5
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
7 changed files with 123 additions and 37 deletions

View File

@ -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

View File

@ -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<Dao> 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,

View File

@ -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);
}
}
}

View File

@ -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<ParsedDartFile> 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();
}
}
}

View File

@ -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<T extends Table, D extends DataClass>
extends DatabaseAccessor<MyDatabase> {
final TableInfo<T, D> _table;
BaseDao(MyDatabase db, this._table): super(db);
Future<void> insertOne(Insertable<T> value) => into(_table).insert(value);
Future<List<T>> selectAll() => select(_table).get();
}
abstract class BaseProductsDao extends BaseDao<Products, Product> {
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();
});
}

View File

@ -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);

View File

@ -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<String, String> 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<Task> 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));
}
}