Fix nullability issues around record types

This commit is contained in:
Simon Binder 2023-01-27 17:12:49 +01:00
parent ba2a0280d3
commit bff8d6c6a1
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
4 changed files with 24 additions and 29 deletions

View File

@ -47,6 +47,7 @@ ExistingRowClass? validateExistingClass(
generateInsertable: generateInsertable,
knownDriftTypes: knownTypes,
typeProvider: library.typeProvider,
typeSystem: library.typeSystem,
);
}
@ -238,14 +239,17 @@ ExistingRowClass defaultRecordRowClass({
required List<DriftColumn> columns,
required bool generateInsertable,
required TypeProvider typeProvider,
required TypeSystem typeSystem,
required KnownDriftTypes knownDriftTypes,
}) {
final type = typeProvider.createRecordType(
positional: const [],
named: [
for (final column in columns)
MapEntry(column.nameInDart,
regularColumnType(typeProvider, knownDriftTypes, column)),
MapEntry(
column.nameInDart,
regularColumnType(
typeProvider, typeSystem, knownDriftTypes, column)),
],
);
@ -424,7 +428,8 @@ bool checkType(
if (typeConverter != null) {
expectedDartType = typeConverter.dartType;
if (typeConverter.canBeSkippedForNulls && columnIsNullable) {
expectedDartType = typeProvider.makeNullable(expectedDartType);
expectedDartType =
typeProvider.makeNullable(expectedDartType, typeSystem);
}
} else {
expectedDartType = typeProvider.typeFor(columnType, knownTypes);
@ -440,18 +445,25 @@ bool checkType(
}
DartType regularColumnType(
TypeProvider typeProvider, KnownDriftTypes knownTypes, HasType type) {
TypeProvider typeProvider,
TypeSystem typeSystem,
KnownDriftTypes knownTypes,
HasType type,
) {
final converter = type.typeConverter;
if (converter != null) {
var dartType = converter.dartType;
if (type.nullable && converter.canBeSkippedForNulls) {
return typeProvider.makeNullable(dartType);
return typeProvider.makeNullable(dartType, typeSystem);
} else {
return dartType;
}
} else {
final typeForNonNullable = typeProvider.typeFor(type.sqlType, knownTypes);
return type.nullable
? typeProvider.makeNullable(typeForNonNullable, typeSystem)
: typeForNonNullable;
}
return typeProvider.typeFor(type.sqlType, knownTypes);
}
extension on TypeProvider {
@ -499,24 +511,7 @@ extension CreateRecordType on TypeProvider {
);
}
DartType makeNullable(DartType type) {
if (type is InterfaceType) {
return type.element.instantiate(
typeArguments: type.typeArguments,
nullabilitySuffix: NullabilitySuffix.question,
);
} else if (type is NeverType) {
return nullType;
} else if (type is RecordType) {
return createRecordType(
positional: [for (final type in type.positionalFields) type.type],
named: [
for (final type in type.namedFields) MapEntry(type.name, type.type),
],
nullabilitySuffix: NullabilitySuffix.question,
);
} else {
return type;
}
DartType makeNullable(DartType type, TypeSystem typeSystem) {
return typeSystem.leastUpperBound(type, nullType);
}
}

View File

@ -578,7 +578,7 @@ class Users extends Table {
.having((e) => e.isRecord, 'isRecord', isTrue)
.having((e) => e.targetClass, 'targetClass', isNull)
.having((e) => e.targetType.toString(), 'targetType',
'({int id, String name, DateTime birthday})'),
'({DateTime birthday, int id, String name})'),
);
expect(table.nameOfRowClass, 'User');
}, skip: requireDart('3.0.0-dev'));

View File

@ -148,7 +148,7 @@ CREATE TABLE foo (
.having((e) => e.isRecord, 'isRecord', isTrue)
.having((e) => e.targetClass, 'targetClass', isNull)
.having((e) => e.targetType.toString(), 'targetType',
'({String foo, int? bar})'),
'({int? bar, String foo})'),
);
expect(table.nameOfRowClass, 'FooData');
}, skip: requireDart('3.0.0-dev'));

View File

@ -73,7 +73,7 @@ class Database {}
checkOutputs({
'a|lib/a.drift.dart': decodedMatches(allOf(
contains(
'typedef User = ({int id, String name, DateTime? birthDate});',
'typedef User = ({DateTime? birthDate, int id, String name});',
),
contains(
'return (id: attachedDatabase.typeMapping.read(DriftSqlType.int, data[\'\${effectivePrefix}id\'])!, '