diff --git a/drift_dev/lib/src/analyzer/custom_row_class.dart b/drift_dev/lib/src/analyzer/custom_row_class.dart index c72b11a3..327c3607 100644 --- a/drift_dev/lib/src/analyzer/custom_row_class.dart +++ b/drift_dev/lib/src/analyzer/custom_row_class.dart @@ -129,12 +129,12 @@ void _checkType(ParameterElement element, MoorColumn column, Step step) { return; } - DartType expectedDartType; + DriftDartType expectedDartType; if (column.typeConverter != null) { expectedDartType = column.typeConverter!.mappedType; } else { - expectedDartType = provider.typeFor(column.type); + expectedDartType = DriftDartType.of(provider.typeFor(column.type)); } // BLOB columns should be stored in an Uint8List (or a supertype of that). @@ -146,7 +146,8 @@ void _checkType(ParameterElement element, MoorColumn column, Step step) { type.element.name == 'Uint8List' && type.element.library.name == 'dart.typed_data'; - if (!typesystem.isAssignableTo(expectedDartType, type) && + if (expectedDartType.type != null && + !typesystem.isAssignableTo(expectedDartType.type!, type) && !isAllowedUint8List) { error('Parameter must accept ' '${expectedDartType.getDisplayString(withNullability: true)}'); diff --git a/drift_dev/lib/src/analyzer/dart/column_parser.dart b/drift_dev/lib/src/analyzer/dart/column_parser.dart index 44dedbda..b015091f 100644 --- a/drift_dev/lib/src/analyzer/dart/column_parser.dart +++ b/drift_dev/lib/src/analyzer/dart/column_parser.dart @@ -70,7 +70,7 @@ class ColumnParser { Expression? foundDefaultExpression; Expression? clientDefaultExpression; Expression? createdTypeConverter; - DartType? typeConverterRuntime; + DriftDartType? typeConverterRuntime; ColumnGeneratedAs? generatedAs; var nullable = false; @@ -247,9 +247,22 @@ class ColumnParser { // the map method has a parameter type that resolved to the runtime // type of the custom object final type = remainingExpr.typeArgumentTypes!.single; - createdTypeConverter = expression; - typeConverterRuntime = type; + + // If converter type argument is dynamic, the referenced + // class is not exists yet. We assume it will be generated + if (type is DynamicType || + type is InterfaceType && + type.typeArguments.isNotEmpty && + type.typeArguments.single.isDynamic && + remainingExpr.typeArguments != null) { + typeConverterRuntime = DriftDartType( + name: remainingExpr.typeArguments!.arguments[0].toSource(), + nullabilitySuffix: NullabilitySuffix.none, + ); + } else { + typeConverterRuntime = DriftDartType.of(type); + } break; case _methodGenerated: Expression? generatedExpression; diff --git a/drift_dev/lib/src/analyzer/moor/create_table_reader.dart b/drift_dev/lib/src/analyzer/moor/create_table_reader.dart index 98e6d725..ea277d97 100644 --- a/drift_dev/lib/src/analyzer/moor/create_table_reader.dart +++ b/drift_dev/lib/src/analyzer/moor/create_table_reader.dart @@ -265,7 +265,9 @@ class CreateTableReader { final typeInDart = asTypeConverter.typeArguments.first; return UsedTypeConverter( - expression: code, mappedType: typeInDart, sqlType: sqlType); + expression: code, + mappedType: DriftDartType.of(typeInDart), + sqlType: sqlType); } Future _readDartType(String typeIdentifier) async { diff --git a/drift_dev/lib/src/model/types.dart b/drift_dev/lib/src/model/types.dart index 55dc61e8..10930a83 100644 --- a/drift_dev/lib/src/model/types.dart +++ b/drift_dev/lib/src/model/types.dart @@ -1,3 +1,5 @@ +import 'package:analyzer/dart/element/nullability_suffix.dart'; +import 'package:analyzer/dart/element/type.dart'; import 'package:drift_dev/src/model/model.dart'; import 'package:drift_dev/src/utils/type_utils.dart'; import 'package:drift_dev/writer.dart'; @@ -22,6 +24,55 @@ abstract class HasType { UsedTypeConverter? get typeConverter; } +class DriftDartType { + final DartType? type; + final String name; + final NullabilitySuffix nullabilitySuffix; + + const DriftDartType({ + this.type, + required this.name, + required this.nullabilitySuffix, + }); + + factory DriftDartType.of(DartType type) { + return DriftDartType( + type: type, + name: type.toString(), + nullabilitySuffix: type.nullabilitySuffix, + ); + } + + String getDisplayString({required bool withNullability}) { + if (type != null) { + return type!.getDisplayString(withNullability: withNullability); + } + + if (withNullability) { + switch (nullabilitySuffix) { + case NullabilitySuffix.question: + return '$name?'; + case NullabilitySuffix.star: + return '$name*'; + case NullabilitySuffix.none: + return '$name'; + } + } + return '$name'; + } + + String codeString([GenerationOptions options = const GenerationOptions()]) { + if (type != null) { + return type!.codeString(options); + } + + if (nullabilitySuffix == NullabilitySuffix.star) { + return getDisplayString(withNullability: false); + } + return getDisplayString(withNullability: options.nnbd); + } +} + extension OperationOnTypes on HasType { /// Whether this type is nullable in Dart bool get nullableInDart { diff --git a/drift_dev/lib/src/model/used_type_converter.dart b/drift_dev/lib/src/model/used_type_converter.dart index 1747f0ef..1181d577 100644 --- a/drift_dev/lib/src/model/used_type_converter.dart +++ b/drift_dev/lib/src/model/used_type_converter.dart @@ -21,7 +21,7 @@ class UsedTypeConverter { final String expression; /// The type that will be present at runtime. - final DartType mappedType; + final DriftDartType mappedType; /// The type that will be written to the database. final ColumnType sqlType; @@ -56,10 +56,11 @@ class UsedTypeConverter { return UsedTypeConverter( expression: 'const EnumIndexConverter<$className>($className.values)', - mappedType: creatingClass.instantiate( - typeArguments: const [], - nullabilitySuffix: - nullable ? NullabilitySuffix.question : NullabilitySuffix.none), + mappedType: DriftDartType( + name: creatingClass.name, + nullabilitySuffix: + nullable ? NullabilitySuffix.question : NullabilitySuffix.none, + ), sqlType: ColumnType.integer, ); } diff --git a/drift_dev/lib/src/writer/tables/table_writer.dart b/drift_dev/lib/src/writer/tables/table_writer.dart index de2c9842..f068feb9 100644 --- a/drift_dev/lib/src/writer/tables/table_writer.dart +++ b/drift_dev/lib/src/writer/tables/table_writer.dart @@ -1,7 +1,6 @@ import 'package:drift/sqlite_keywords.dart'; import 'package:drift_dev/moor_generator.dart'; import 'package:drift_dev/src/utils/string_escaper.dart'; -import 'package:drift_dev/src/utils/type_utils.dart'; import 'package:drift_dev/writer.dart'; import 'package:sqlparser/sqlparser.dart';