Fix nnbd generation around type converters (#968)

This commit is contained in:
Simon Binder 2020-12-14 15:13:59 +01:00
parent a749f38e2b
commit 5db10342b0
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
6 changed files with 32 additions and 15 deletions

View File

@ -289,8 +289,8 @@ class ConfigTable extends Table with TableInfo<ConfigTable, Config> {
return ConfigTable(_db, alias);
}
static TypeConverter<SyncType?, int?> $converter0 = const SyncTypeConverter();
static TypeConverter<SyncType?, int?> $converter1 =
static TypeConverter<SyncType, int> $converter0 = const SyncTypeConverter();
static TypeConverter<SyncType?, int> $converter1 =
const EnumIndexConverter<SyncType>(SyncType.values);
@override
bool get dontWriteConstraints => true;
@ -1614,7 +1614,7 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
readsFrom: {config}).map(config.mapFromRow);
}
Selectable<String> typeConverterVar(SyncType? var1, List<SyncType?> var2) {
Selectable<String> typeConverterVar(SyncType var1, List<SyncType?> var2) {
var $arrayStartIndex = 2;
final expandedvar2 = $expandVar($arrayStartIndex, var2.length);
$arrayStartIndex += var2.length;
@ -1623,7 +1623,7 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
variables: [
Variable<int>(ConfigTable.$converter0.mapToSql(var1)!),
for (var $ in var2)
Variable<int>(ConfigTable.$converter1.mapToSql($)!)
Variable<int?>(ConfigTable.$converter1.mapToSql($)!)
],
readsFrom: {
config

View File

@ -558,7 +558,7 @@ class $CategoriesTable extends Categories
return $CategoriesTable(_db, alias);
}
static TypeConverter<CategoryPriority, int?> $converter0 =
static TypeConverter<CategoryPriority, int> $converter0 =
const EnumIndexConverter<CategoryPriority>(CategoryPriority.values);
}
@ -1316,7 +1316,7 @@ class $TableWithoutPKTable extends TableWithoutPK
return $TableWithoutPKTable(_db, alias);
}
static TypeConverter<MyCustomObject, String?> $converter0 =
static TypeConverter<MyCustomObject, String> $converter0 =
const CustomConverter();
}

View File

@ -11,6 +11,7 @@ import 'package:moor_generator/src/model/used_type_converter.dart';
import 'package:moor_generator/src/utils/names.dart';
import 'package:moor_generator/src/utils/string_escaper.dart';
import 'package:moor_generator/src/utils/type_converter_hint.dart';
import 'package:moor_generator/src/utils/type_utils.dart';
import 'package:recase/recase.dart';
import 'package:sqlparser/sqlparser.dart';
@ -217,8 +218,11 @@ class CreateTableReader {
}
final interfaceType = type as InterfaceType;
// TypeConverter declares a "D mapToDart(S fromDb);". We need to know D
final typeInDart = interfaceType.getMethod('mapToDart').returnType;
final asTypeConverter = interfaceType.allSupertypes.firstWhere(
(type) => isFromMoor(type) && type.element.name == 'TypeConverter');
// TypeConverter<D, S>, where D is the type in Dart
final typeInDart = asTypeConverter.typeArguments.first;
return UsedTypeConverter(
expression: code, mappedType: typeInDart, sqlType: sqlType);

View File

@ -17,6 +17,11 @@ abstract class HasType {
}
extension OperationOnTypes on HasType {
/// Whether this type is nullable in Dart
bool get nullableInDart {
return nullable || typeConverter?.hasNullableDartType == true;
}
/// the Dart type of this column that can be handled by moors type mapping.
/// Basically the same as [dartTypeCode], minus custom types and nullability.
String get variableTypeName => dartTypeNames[type];
@ -30,7 +35,7 @@ extension OperationOnTypes on HasType {
/// This is the same as [dartTypeCode] but without custom types.
String variableTypeCode(
[GenerationOptions options = const GenerationOptions()]) {
final hasSuffix = nullable && options.nnbd;
final hasSuffix = nullableInDart && options.nnbd;
return hasSuffix ? '$variableTypeName?' : variableTypeName;
}
@ -39,7 +44,10 @@ extension OperationOnTypes on HasType {
/// [int].
String dartTypeCode([GenerationOptions options = const GenerationOptions()]) {
if (typeConverter != null) {
return typeConverter.mappedType?.codeString(options);
final needsSuffix = nullable && !typeConverter.hasNullableDartType;
final baseType = typeConverter.mappedType.codeString(options);
return needsSuffix ? '$baseType?' : baseType;
}
return variableTypeCode(options);

View File

@ -37,6 +37,9 @@ class UsedTypeConverter {
@required this.sqlType,
});
bool get hasNullableDartType =>
mappedType.nullabilitySuffix == NullabilitySuffix.question;
factory UsedTypeConverter.forEnumColumn(DartType enumType, bool nullable) {
if (enumType.element is! ClassElement) {
throw InvalidTypeForEnumConverterException('Not a class', enumType);
@ -61,7 +64,7 @@ class UsedTypeConverter {
/// A suitable typename to store an instance of the type converter used here.
String converterNameInCode(GenerationOptions options) {
final sqlDartType = options.nullableType(dartTypeNames[sqlType]);
final sqlDartType = dartTypeNames[sqlType];
return 'TypeConverter<${mappedType.codeString(options)}, $sqlDartType>';
}
}

View File

@ -176,15 +176,17 @@ class DataClassWriter {
for (var i = 0; i < table.columns.length; i++) {
final column = table.columns[i];
final last = i == table.columns.length - 1;
final isNullable = column.nullableInDart;
final typeName = column.dartTypeCode(scope.generationOptions);
if (wrapNullableInValue && column.nullable) {
if (wrapNullableInValue && isNullable) {
_buffer
..write('Value<$typeName> ${column.dartGetterName} ')
..write('= const Value.absent()');
} else if (!column.nullable && scope.generationOptions.nnbd) {
// We always write nullable types in the copyWith constructor, since all
// parameters are optional.
} else if (!isNullable && scope.generationOptions.nnbd) {
// We always use nullable parameters in copyWith, since all parameters
// are optional. The !isNullable check is there to avoid a duplicate
// question mark in the type name.
_buffer.write('$typeName? ${column.dartGetterName}');
} else {
_buffer.write('$typeName ${column.dartGetterName}');