mirror of https://github.com/AMT-Cheif/drift.git
✨ textEnum
This commit is contained in:
parent
0a5014a7b4
commit
e8ee29bb18
|
@ -139,7 +139,7 @@ abstract class Table extends HasResultSet {
|
|||
/// corresponding to the enum's index. Note that this can invalidate your data
|
||||
/// if you add another value to the enum class.
|
||||
@protected
|
||||
ColumnBuilder<int> intEnum<T>() => _isGenerated();
|
||||
ColumnBuilder<int> intEnum<T extends Enum>() => _isGenerated();
|
||||
|
||||
/// Use this as the body of a getter to declare a column that holds strings.
|
||||
/// Example (inside the body of a table class):
|
||||
|
@ -149,6 +149,13 @@ abstract class Table extends HasResultSet {
|
|||
@protected
|
||||
ColumnBuilder<String> text() => _isGenerated();
|
||||
|
||||
/// Creates a column to store an `enum` class [T].
|
||||
///
|
||||
/// In the database, the column will be represented as text corresponding to
|
||||
/// the name of the enum entries. Note that this can invalidate your data if
|
||||
/// you rename the entries of the enum class.
|
||||
ColumnBuilder<String> textEnum<T extends Enum>() => _isGenerated();
|
||||
|
||||
/// Use this as the body of a getter to declare a column that holds bools.
|
||||
/// Example (inside the body of a table class):
|
||||
/// ```
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import '../../dsl/dsl.dart';
|
||||
import '../data_class.dart';
|
||||
|
||||
|
@ -100,6 +101,26 @@ class EnumIndexConverter<T extends Enum> extends TypeConverter<T, int> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Implementation for an enum to string converter that uses the name of the
|
||||
/// enum as the value stored in the database.
|
||||
class EnumNameConverter<T extends Enum> extends TypeConverter<T, String> {
|
||||
/// All values of the enum.
|
||||
final List<T> values;
|
||||
|
||||
/// Constant default constructor.
|
||||
const EnumNameConverter(this.values);
|
||||
|
||||
@override
|
||||
T fromSql(String fromDb) {
|
||||
return values.byName(fromDb);
|
||||
}
|
||||
|
||||
@override
|
||||
String toSql(T value) {
|
||||
return value.name;
|
||||
}
|
||||
}
|
||||
|
||||
/// A type converter automatically mapping `null` values to `null` in both
|
||||
/// directions.
|
||||
///
|
||||
|
|
|
@ -15,7 +15,8 @@ import 'table.dart';
|
|||
|
||||
const String _startInt = 'integer';
|
||||
const String _startInt64 = 'int64';
|
||||
const String _startEnum = 'intEnum';
|
||||
const String _startIntEnum = 'intEnum';
|
||||
const String _startTextEnum = 'textEnum';
|
||||
const String _startString = 'text';
|
||||
const String _startBool = 'boolean';
|
||||
const String _startDateTime = 'dateTime';
|
||||
|
@ -25,7 +26,8 @@ const String _startReal = 'real';
|
|||
const Set<String> _starters = {
|
||||
_startInt,
|
||||
_startInt64,
|
||||
_startEnum,
|
||||
_startIntEnum,
|
||||
_startTextEnum,
|
||||
_startString,
|
||||
_startBool,
|
||||
_startDateTime,
|
||||
|
@ -349,20 +351,37 @@ class ColumnParser {
|
|||
);
|
||||
}
|
||||
|
||||
if (foundStartMethod == _startEnum) {
|
||||
if (foundStartMethod == _startIntEnum) {
|
||||
if (converter != null) {
|
||||
_resolver.reportError(DriftAnalysisError.forDartElement(
|
||||
element,
|
||||
'Using $_startEnum will apply a custom converter by default, '
|
||||
'Using $_startIntEnum will apply a custom converter by default, '
|
||||
"so you can't add an additional converter",
|
||||
));
|
||||
}
|
||||
|
||||
final enumType = remainingExpr.typeArgumentTypes![0];
|
||||
final enumType = remainingExpr.typeArgumentTypes!.first;
|
||||
converter = readEnumConverter(
|
||||
(msg) => _resolver.reportError(DriftAnalysisError.inDartAst(element,
|
||||
remainingExpr.typeArguments ?? remainingExpr.methodName, msg)),
|
||||
enumType,
|
||||
EnumType.intEnum,
|
||||
);
|
||||
} else if (foundStartMethod == _startTextEnum) {
|
||||
if (converter != null) {
|
||||
_resolver.reportError(DriftAnalysisError.forDartElement(
|
||||
element,
|
||||
'Using $_startTextEnum will apply a custom converter by default, '
|
||||
"so you can't add an additional converter",
|
||||
));
|
||||
}
|
||||
|
||||
final enumType = remainingExpr.typeArgumentTypes!.first;
|
||||
converter = readEnumConverter(
|
||||
(msg) => _resolver.reportError(DriftAnalysisError.inDartAst(element,
|
||||
remainingExpr.typeArguments ?? remainingExpr.methodName, msg)),
|
||||
enumType,
|
||||
EnumType.textEnum,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -427,7 +446,8 @@ class ColumnParser {
|
|||
_startString: DriftSqlType.string,
|
||||
_startInt: DriftSqlType.int,
|
||||
_startInt64: DriftSqlType.bigInt,
|
||||
_startEnum: DriftSqlType.int,
|
||||
_startIntEnum: DriftSqlType.int,
|
||||
_startTextEnum: DriftSqlType.string,
|
||||
_startDateTime: DriftSqlType.dateTime,
|
||||
_startBlob: DriftSqlType.blob,
|
||||
_startReal: DriftSqlType.double,
|
||||
|
|
|
@ -54,6 +54,7 @@ class DriftTableResolver extends LocalElementResolver<DiscoveredDriftTable> {
|
|||
AnnotatedDartCode? defaultArgument;
|
||||
|
||||
final typeName = column.definition?.typeName;
|
||||
|
||||
final enumMatch =
|
||||
typeName != null ? _enumRegex.firstMatch(typeName) : null;
|
||||
if (enumMatch != null) {
|
||||
|
@ -72,6 +73,9 @@ class DriftTableResolver extends LocalElementResolver<DiscoveredDriftTable> {
|
|||
(msg) => reportError(
|
||||
DriftAnalysisError.inDriftFile(column.definition ?? stmt, msg)),
|
||||
dartClass.classElement.thisType,
|
||||
column.type.type == BasicType.int
|
||||
? EnumType.intEnum
|
||||
: EnumType.textEnum,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,6 +160,11 @@ ExistingRowClass? validateExistingClass(
|
|||
);
|
||||
}
|
||||
|
||||
enum EnumType {
|
||||
intEnum,
|
||||
textEnum,
|
||||
}
|
||||
|
||||
AppliedTypeConverter? readTypeConverter(
|
||||
LibraryElement library,
|
||||
Expression dartExpression,
|
||||
|
@ -223,32 +228,39 @@ AppliedTypeConverter? readTypeConverter(
|
|||
|
||||
AppliedTypeConverter readEnumConverter(
|
||||
void Function(String) reportError,
|
||||
DartType enumType,
|
||||
DartType dartEnumType,
|
||||
EnumType columnEnumType,
|
||||
) {
|
||||
if (enumType is! InterfaceType) {
|
||||
reportError('Not a class: `$enumType`');
|
||||
if (dartEnumType is! InterfaceType) {
|
||||
reportError('Not a class: `$dartEnumType`');
|
||||
}
|
||||
|
||||
final creatingClass = enumType.element;
|
||||
final creatingClass = dartEnumType.element;
|
||||
if (creatingClass is! EnumElement) {
|
||||
reportError('Not an enum: `${creatingClass!.displayName}`');
|
||||
}
|
||||
|
||||
// `const EnumIndexConverter<EnumType>(EnumType.values)`
|
||||
// or
|
||||
// `const EnumNameConverter<EnumType>(EnumType.values)`
|
||||
final expression = AnnotatedDartCode.build((builder) {
|
||||
builder.addText('const ');
|
||||
if (columnEnumType == EnumType.intEnum) {
|
||||
builder.addSymbol('EnumIndexConverter', AnnotatedDartCode.drift);
|
||||
} else {
|
||||
builder.addSymbol('EnumNameConverter', AnnotatedDartCode.drift);
|
||||
}
|
||||
builder
|
||||
..addText('const ')
|
||||
..addSymbol('EnumIndexConverter', AnnotatedDartCode.drift)
|
||||
..addText('<')
|
||||
..addDartType(enumType)
|
||||
..addDartType(dartEnumType)
|
||||
..addText('>(')
|
||||
..addDartType(enumType)
|
||||
..addDartType(dartEnumType)
|
||||
..addText('.values)');
|
||||
});
|
||||
|
||||
return AppliedTypeConverter(
|
||||
expression: expression,
|
||||
dartType: enumType,
|
||||
dartType: dartEnumType,
|
||||
jsonType: null,
|
||||
sqlType: DriftSqlType.int,
|
||||
dartTypeIsNullable: false,
|
||||
|
|
Loading…
Reference in New Issue