Backwards compatible attempt

This commit is contained in:
Alexander Wilde 2022-10-15 23:47:58 +01:00
parent ba28b51125
commit ff9d419559
9 changed files with 53 additions and 31 deletions

View File

@ -1,2 +1,3 @@
// This field is analyzed by drift_dev to easily obtain common types. // This field is analyzed by drift_dev to easily obtain common types.
export 'runtime/types/converters.dart' show TypeConverter, JsonTypeConverter; export 'runtime/types/converters.dart'
show TypeConverter, JsonTypeConverter, JsonTypeConverterWithDifferentTypes;

View File

@ -33,13 +33,9 @@ abstract class TypeConverter<D, S> {
/// to SQL (and vice-versa). /// to SQL (and vice-versa).
/// When a [BuildGeneralColumn.map] column (or a `MAPPED BY` constraint in /// When a [BuildGeneralColumn.map] column (or a `MAPPED BY` constraint in
/// `.drift` files) refers to a type converter that inherits from /// `.drift` files) refers to a type converter that inherits from
/// [JsonTypeConverter], it will also be used for the conversion from and to /// [JsonTypeConverterWithDifferentTypes], it will also be used for the conversion from and to
/// JSON. /// JSON.
abstract class JsonTypeConverter<D, S, J> extends TypeConverter<D, S> { mixin JsonTypeConverterWithDifferentTypes<D, S, J> on TypeConverter<D, S> {
/// Empty constant constructor so that subclasses can have a constant
/// constructor.
const JsonTypeConverter();
/// Map a value from the Data class to json. /// Map a value from the Data class to json.
/// ///
/// Defaults to doing the same conversion as for Dart -> SQL, [toSql]. /// Defaults to doing the same conversion as for Dart -> SQL, [toSql].
@ -56,9 +52,39 @@ abstract class JsonTypeConverter<D, S, J> extends TypeConverter<D, S> {
/// The returned type converter will use the [inner] type converter for non- /// The returned type converter will use the [inner] type converter for non-
/// null values. Further, `null` is mapped to `null` in both directions (from /// null values. Further, `null` is mapped to `null` in both directions (from
/// Dart to SQL and vice-versa). /// Dart to SQL and vice-versa).
static JsonTypeConverter<D?, S?, J?> static JsonTypeConverterWithDifferentTypes<D?, S?, J?>
asNullable<D, S extends Object, J extends Object>( asNullable<D, S extends Object, J extends Object>(
JsonTypeConverter<D, S, J> inner) { JsonTypeConverterWithDifferentTypes<D, S, J> inner) {
return _NullWrappingTypeConverterWithJson(inner);
}
}
/// A mixin for [TypeConverter]s that should also apply to drift's builtin
/// JSON serialization of data classes.
///
/// By default, a [TypeConverter] only applies to the serialization from Dart
/// to SQL (and vice-versa).
/// When a [BuildGeneralColumn.map] column (or a `MAPPED BY` constraint in
/// `.drift` files) refers to a type converter that inherits from
/// [JsonTypeConverter], it will also be used for the conversion from and to
/// JSON.
mixin JsonTypeConverter<D, S>
implements JsonTypeConverterWithDifferentTypes<D, S, S> {
@override
S toJson(D value) => toSql(value);
@override
D fromJson(S json) => fromSql(json);
/// Wraps an [inner] type converter that only considers non-nullable values
/// as a type converter that handles null values too.
///
/// The returned type converter will use the [inner] type converter for non-
/// null values. Further, `null` is mapped to `null` in both directions (from
/// Dart to SQL and vice-versa).
static JsonTypeConverterWithDifferentTypes<D?, S?, J?>
asNullable<D, S extends Object, J extends Object>(
JsonTypeConverterWithDifferentTypes<D, S, J> inner) {
return _NullWrappingTypeConverterWithJson(inner); return _NullWrappingTypeConverterWithJson(inner);
} }
} }
@ -157,8 +183,8 @@ class _NullWrappingTypeConverter<D, S extends Object>
class _NullWrappingTypeConverterWithJson<D, S extends Object, J extends Object> class _NullWrappingTypeConverterWithJson<D, S extends Object, J extends Object>
extends NullAwareTypeConverter<D, S> extends NullAwareTypeConverter<D, S>
implements JsonTypeConverter<D?, S?, J?> { implements JsonTypeConverterWithDifferentTypes<D?, S?, J?> {
final JsonTypeConverter<D, S, J> _inner; final JsonTypeConverterWithDifferentTypes<D, S, J> _inner;
const _NullWrappingTypeConverterWithJson(this._inner); const _NullWrappingTypeConverterWithJson(this._inner);

View File

@ -135,14 +135,8 @@ class CustomConverter extends TypeConverter<MyCustomObject, String> {
} }
class CustomJsonConverter extends CustomConverter class CustomJsonConverter extends CustomConverter
implements JsonTypeConverter<MyCustomObject, String, String> { with JsonTypeConverter<MyCustomObject, String> {
const CustomJsonConverter(); const CustomJsonConverter();
@override
MyCustomObject fromJson(String json) => fromSql(json);
@override
String toJson(MyCustomObject value) => toSql(value);
} }
abstract class CategoryTodoCountView extends View { abstract class CategoryTodoCountView extends View {

View File

@ -1373,10 +1373,11 @@ class $PureDefaultsTable extends PureDefaults
return $PureDefaultsTable(attachedDatabase, alias); return $PureDefaultsTable(attachedDatabase, alias);
} }
static JsonTypeConverter<MyCustomObject, String, String> $converter0 = static JsonTypeConverterWithDifferentTypes<MyCustomObject, String, String>
const CustomJsonConverter(); $converter0 = const CustomJsonConverter();
static JsonTypeConverter<MyCustomObject?, String?, String?> $converter0n = static JsonTypeConverterWithDifferentTypes<MyCustomObject?, String?, String?>
JsonTypeConverter.asNullable($converter0); $converter0n =
JsonTypeConverterWithDifferentTypes.asNullable($converter0);
} }
class CategoryTodoCountViewData extends DataClass { class CategoryTodoCountViewData extends DataClass {

View File

@ -181,7 +181,7 @@ UsedTypeConverter? readTypeConverter(
"potentially map to `null` which can't be stored in the database."); "potentially map to `null` which can't be stored in the database.");
} else if (!canBeSkippedForNulls) { } else if (!canBeSkippedForNulls) {
final alternative = appliesToJsonToo final alternative = appliesToJsonToo
? 'JsonTypeConverter.asNullable' ? 'JsonTypeConverterWithDifferentTypes.asNullable'
: 'NullAwareTypeConverter.wrap'; : 'NullAwareTypeConverter.wrap';
reportError('This column is nullable, but the type converter has a non-' reportError('This column is nullable, but the type converter has a non-'

View File

@ -27,18 +27,18 @@ class HelperLibrary {
} }
/// Converts the given Dart [type] into an instantiation of the /// Converts the given Dart [type] into an instantiation of the
/// `TypeConverter` class from drift. /// `JsonTypeConverter` class from drift.
/// ///
/// Returns `null` if [type] is not a subtype of `TypeConverter`. /// Returns `null` if [type] is not a subtype of `TypeConverter`.
InterfaceType? asJsonTypeConverter(DartType type) { InterfaceType? asJsonTypeConverter(DartType type) {
final converter = helperLibrary.exportNamespace.get('JsonTypeConverter') final converter = helperLibrary.exportNamespace
as InterfaceElement; .get('JsonTypeConverterWithDifferentTypes') as InterfaceElement;
return type.asInstanceOf(converter); return type.asInstanceOf(converter);
} }
bool isJsonAwareTypeConverter(DartType? type, LibraryElement context) { bool isJsonAwareTypeConverter(DartType? type, LibraryElement context) {
final jsonMixin = helperLibrary.exportNamespace.get('JsonTypeConverter') final jsonMixin = helperLibrary.exportNamespace
as InterfaceElement; .get('JsonTypeConverterWithDifferentTypes') as InterfaceElement;
final jsonConverterType = jsonMixin.instantiate( final jsonConverterType = jsonMixin.instantiate(
typeArguments: [ typeArguments: [
context.typeProvider.dynamicType, context.typeProvider.dynamicType,

View File

@ -143,7 +143,7 @@ class UsedTypeConverter {
if (makeNullable) jsonDartType += '?'; if (makeNullable) jsonDartType += '?';
if (alsoAppliesToJsonConversion) { if (alsoAppliesToJsonConversion) {
return 'JsonTypeConverter<${dartTypeCode(makeNullable)}, $sqlDartType, $jsonDartType>'; return 'JsonTypeConverterWithDifferentTypes<${dartTypeCode(makeNullable)}, $sqlDartType, $jsonDartType>';
} }
return 'TypeConverter<${dartTypeCode(makeNullable)}, $sqlDartType>'; return 'TypeConverter<${dartTypeCode(makeNullable)}, $sqlDartType>';
} }

View File

@ -336,7 +336,7 @@ class TableWriter extends TableOrViewWriter {
converter.converterNameInCode(makeNullable: true); converter.converterNameInCode(makeNullable: true);
final wrap = converter.alsoAppliesToJsonConversion final wrap = converter.alsoAppliesToJsonConversion
? 'JsonTypeConverter.asNullable' ? 'JsonTypeConverterWithDifferentTypes.asNullable'
: 'NullAwareTypeConverter.wrap'; : 'NullAwareTypeConverter.wrap';
final code = '$wrap(${converter.fieldName})'; final code = '$wrap(${converter.fieldName})';

View File

@ -15,7 +15,7 @@ void main() {
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
TypeConverter<String, String> withoutJson() => throw 'stub'; TypeConverter<String, String> withoutJson() => throw 'stub';
JsonTypeConverter<String, String, String> withJson() => throw 'stub'; JsonTypeConverter<String, String> withJson() => throw 'stub';
class Users extends Table { class Users extends Table {
TextColumn get foo => text().map(withoutJson())(); TextColumn get foo => text().map(withoutJson())();