mirror of https://github.com/AMT-Cheif/drift.git
Allow named constructors in custom row classes
This commit is contained in:
parent
e05e8fe07e
commit
5f7c20d4eb
|
@ -144,9 +144,15 @@ class UseRowClass {
|
|||
/// or types with arguments, are not allowed.
|
||||
final Type type;
|
||||
|
||||
/// The name of the constructor to use.
|
||||
///
|
||||
/// When this option is not set, the default (unnamed) constructor will be
|
||||
/// used to map database rows to the desired row class.
|
||||
final String constructor;
|
||||
|
||||
/// Customize the class used by moor to hold an instance of an annotated
|
||||
/// table.
|
||||
///
|
||||
/// For details, see the overall documentation on [UseRowClass].
|
||||
const UseRowClass(this.type);
|
||||
const UseRowClass(this.type, {this.constructor = ''});
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ class SharedTodos extends Table {
|
|||
|
||||
const _uuid = Uuid();
|
||||
|
||||
@UseRowClass(CustomRowClass)
|
||||
@UseRowClass(CustomRowClass, constructor: 'map')
|
||||
class TableWithoutPK extends Table {
|
||||
IntColumn get notReallyAnId => integer()();
|
||||
RealColumn get someFloat => real()();
|
||||
|
@ -74,9 +74,13 @@ class CustomRowClass implements Insertable<CustomRowClass> {
|
|||
|
||||
final String? notFromDb;
|
||||
|
||||
CustomRowClass(this.notReallyAnId, double someFloat,
|
||||
{required this.custom, this.notFromDb})
|
||||
: anotherName = someFloat; // ignore: prefer_initializing_formals
|
||||
CustomRowClass._(
|
||||
this.notReallyAnId, this.anotherName, this.custom, this.notFromDb);
|
||||
|
||||
factory CustomRowClass.map(int notReallyAnId, double someFloat,
|
||||
{required MyCustomObject custom, String? notFromDb}) {
|
||||
return CustomRowClass._(notReallyAnId, someFloat, custom, notFromDb);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
|
|
|
@ -1205,7 +1205,7 @@ class $TableWithoutPKTable extends TableWithoutPK
|
|||
@override
|
||||
CustomRowClass map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
|
||||
return CustomRowClass(
|
||||
return CustomRowClass.map(
|
||||
const IntType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}not_really_an_id'])!,
|
||||
const RealType()
|
||||
|
|
|
@ -30,9 +30,8 @@ void main() {
|
|||
|
||||
test('can insert floating point values', () async {
|
||||
// regression test for https://github.com/simolus3/moor/issues/30
|
||||
await db
|
||||
.into(db.tableWithoutPK)
|
||||
.insert(CustomRowClass(42, 3.1415, custom: MyCustomObject('custom')));
|
||||
await db.into(db.tableWithoutPK).insert(
|
||||
CustomRowClass.map(42, 3.1415, custom: MyCustomObject('custom')));
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO table_without_p_k '
|
||||
|
|
|
@ -4,14 +4,17 @@ import 'package:analyzer/dart/element/type.dart';
|
|||
import 'package:moor_generator/moor_generator.dart';
|
||||
import 'package:moor_generator/src/analyzer/errors.dart';
|
||||
|
||||
ExistingRowClass /*?*/ validateExistingClass(
|
||||
List<MoorColumn> columns, ClassElement desiredClass, ErrorSink errors) {
|
||||
final ctor = desiredClass.unnamedConstructor;
|
||||
ExistingRowClass /*?*/ validateExistingClass(List<MoorColumn> columns,
|
||||
ClassElement desiredClass, String constructor, ErrorSink errors) {
|
||||
final ctor = desiredClass.getNamedConstructor(constructor);
|
||||
|
||||
if (ctor == null) {
|
||||
errors.report(ErrorInDartCode(
|
||||
affectedElement: desiredClass,
|
||||
message: 'The desired data class must have an unnamed constructor',
|
||||
));
|
||||
final msg = constructor == ''
|
||||
? 'The desired data class must have an unnamed constructor'
|
||||
: 'The desired data class does not have a constructor named '
|
||||
'$constructor';
|
||||
|
||||
errors.report(ErrorInDartCode(affectedElement: desiredClass, message: msg));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ class TableParser {
|
|||
|
||||
String name;
|
||||
ClassElement existingClass;
|
||||
String constructorInExistingClass;
|
||||
|
||||
if (dataClassName != null) {
|
||||
name = dataClassName.getField('name').toStringValue();
|
||||
|
@ -79,6 +80,8 @@ class TableParser {
|
|||
|
||||
if (useRowClass != null) {
|
||||
final type = useRowClass.getField('type').toTypeValue();
|
||||
constructorInExistingClass =
|
||||
useRowClass.getField('constructor').toStringValue();
|
||||
|
||||
if (type is InterfaceType) {
|
||||
existingClass = type.element;
|
||||
|
@ -93,7 +96,8 @@ class TableParser {
|
|||
|
||||
final verified = existingClass == null
|
||||
? null
|
||||
: validateExistingClass(columns, existingClass, base.step.errors);
|
||||
: validateExistingClass(columns, existingClass,
|
||||
constructorInExistingClass, base.step.errors);
|
||||
return _DataClassInformation(name, verified);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,16 @@ class RowClass {
|
|||
RowClass.create();
|
||||
}
|
||||
@UseRowClass(RowClass)
|
||||
class TableClass extends Table {}
|
||||
''',
|
||||
'a|lib/invalid_no_named_constructor.dart': '''
|
||||
import 'package:moor/moor.dart';
|
||||
|
||||
class RowClass {
|
||||
RowClass();
|
||||
RowClass.create();
|
||||
}
|
||||
@UseRowClass(RowClass, constructor: 'create2')
|
||||
class TableClass extends Table {}
|
||||
''',
|
||||
'a|lib/mismatching_type.dart': '''
|
||||
|
@ -79,6 +89,16 @@ class TableClass extends Table {
|
|||
);
|
||||
});
|
||||
|
||||
test('when no constructor with the right name exists', () async {
|
||||
final file =
|
||||
await state.analyze('package:a/invalid_no_named_constructor.dart');
|
||||
expect(
|
||||
file.errors.errors,
|
||||
contains(isA<ErrorInDartCode>().having((e) => e.message, 'message',
|
||||
contains('does not have a constructor named create2'))),
|
||||
);
|
||||
});
|
||||
|
||||
test('when a parameter has a mismatching type', () async {
|
||||
final file = await state.analyze('package:a/mismatching_type.dart');
|
||||
expect(
|
||||
|
|
Loading…
Reference in New Issue