Serialize column constraints

This commit is contained in:
Simon Binder 2022-09-10 18:18:39 +02:00
parent eabf2a1e03
commit 97ed32f05a
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
8 changed files with 151 additions and 120 deletions

View File

@ -2,7 +2,27 @@
# which is what we want! Our builders depend on generated code, so they break the generated build script at the start of # which is what we want! Our builders depend on generated code, so they break the generated build script at the start of
# a build. # a build.
targets: targets:
analysis_results:
# Analysis result serialization is drift-internal and doesn't need any of
# the checks the default serialization builder runs on.
auto_apply_builders: false
sources:
- "lib/src/analysis/**"
builders:
json_serializable:
enabled: true
options:
checked: false
disallow_unrecognized_keys: false
any_map: true
field_rename: snake
explicit_to_json: true
source_gen:combining_builder:
enabled: false # Run in default target
$default: $default:
dependencies: [":analysis_results"]
builders: builders:
json_serializable: json_serializable:
options: options:
@ -11,6 +31,9 @@ targets:
disallow_unrecognized_keys: true disallow_unrecognized_keys: true
field_rename: snake field_rename: snake
explicit_to_json: true explicit_to_json: true
generate_for:
exclude:
- "lib/src/analysis/**" # using different options for those files
# https://simonbinder.eu/posts/build_directory_moves/#generating-into-a-directory-with-source_gen # https://simonbinder.eu/posts/build_directory_moves/#generating-into-a-directory-with-source_gen
source_gen:combining_builder: source_gen:combining_builder:
options: options:

View File

@ -8,6 +8,8 @@ import 'dart.dart';
import 'element.dart'; import 'element.dart';
import 'types.dart'; import 'types.dart';
part '../../generated/analysis/results/column.g.dart';
class DriftColumn implements HasType { class DriftColumn implements HasType {
@override @override
final DriftSqlType sqlType; final DriftSqlType sqlType;
@ -163,10 +165,16 @@ class UniqueColumn extends DriftColumnConstraint {
const UniqueColumn(); const UniqueColumn();
} }
@JsonSerializable()
class PrimaryKeyColumn extends DriftColumnConstraint { class PrimaryKeyColumn extends DriftColumnConstraint {
final bool isAutoIncrement; final bool isAutoIncrement;
PrimaryKeyColumn(this.isAutoIncrement); PrimaryKeyColumn(this.isAutoIncrement);
factory PrimaryKeyColumn.fromJson(Map json) =>
_$PrimaryKeyColumnFromJson(json);
Map<String, Object?> toJson() => _$PrimaryKeyColumnToJson(this);
} }
class ForeignKeyReference extends DriftColumnConstraint { class ForeignKeyReference extends DriftColumnConstraint {
@ -185,20 +193,33 @@ class ForeignKeyReference extends DriftColumnConstraint {
} }
} }
@JsonSerializable()
class ColumnGeneratedAs extends DriftColumnConstraint { class ColumnGeneratedAs extends DriftColumnConstraint {
final AnnotatedDartCode dartExpression; final AnnotatedDartCode dartExpression;
final bool stored; final bool stored;
ColumnGeneratedAs(this.dartExpression, this.stored); ColumnGeneratedAs(this.dartExpression, this.stored);
factory ColumnGeneratedAs.fromJson(Map json) =>
_$ColumnGeneratedAsFromJson(json);
Map<String, Object?> toJson() => _$ColumnGeneratedAsToJson(this);
} }
/// A column with a `CHECK()` generated from a Dart expression. /// A column with a `CHECK()` generated from a Dart expression.
@JsonSerializable()
class DartCheckExpression extends DriftColumnConstraint { class DartCheckExpression extends DriftColumnConstraint {
final AnnotatedDartCode dartExpression; final AnnotatedDartCode dartExpression;
DartCheckExpression(this.dartExpression); DartCheckExpression(this.dartExpression);
factory DartCheckExpression.fromJson(Map json) =>
_$DartCheckExpressionFromJson(json);
Map<String, Object?> toJson() => _$DartCheckExpressionToJson(this);
} }
@JsonSerializable()
class LimitingTextLength extends DriftColumnConstraint { class LimitingTextLength extends DriftColumnConstraint {
final int? minLength; final int? minLength;
@ -206,6 +227,11 @@ class LimitingTextLength extends DriftColumnConstraint {
LimitingTextLength({this.minLength, this.maxLength}); LimitingTextLength({this.minLength, this.maxLength});
factory LimitingTextLength.fromJson(Map json) =>
_$LimitingTextLengthFromJson(json);
Map<String, Object?> toJson() => _$LimitingTextLengthToJson(this);
@override @override
int get hashCode => minLength.hashCode ^ maxLength.hashCode; int get hashCode => minLength.hashCode ^ maxLength.hashCode;

View File

@ -75,15 +75,25 @@ class ElementSerializer {
Map<String, Object?> _serializeColumnConstraint( Map<String, Object?> _serializeColumnConstraint(
DriftColumnConstraint constraint) { DriftColumnConstraint constraint) {
if (constraint is ForeignKeyReference) { if (constraint is UniqueColumn) {
return {'type': 'unique'};
} else if (constraint is PrimaryKeyColumn) {
return {'type': 'primary', ...constraint.toJson()};
} else if (constraint is ForeignKeyReference) {
return { return {
'type': 'foreign_key', 'type': 'foreign_key',
'column': _serializeColumnReference(constraint.otherColumn), 'column': _serializeColumnReference(constraint.otherColumn),
'onUpdate': constraint.onUpdate?.name, 'onUpdate': constraint.onUpdate?.name,
'onDelete': constraint.onDelete?.name, 'onDelete': constraint.onDelete?.name,
}; };
} else if (constraint is ColumnGeneratedAs) {
return {'type': 'generated_as', ...constraint.toJson()};
} else if (constraint is DartCheckExpression) {
return {'type': 'check', ...constraint.toJson()};
} else if (constraint is LimitingTextLength) {
return {'type': 'limit_text_length', ...constraint.toJson()};
} else { } else {
throw UnimplementedError('Unsupported column constrain: $constraint'); throw UnimplementedError('Unsupported column constraint: $constraint');
} }
} }
@ -136,7 +146,7 @@ class _DartTypeSerializer extends TypeVisitor<Map<String, Object?>> {
return { return {
'kind': 'interface', 'kind': 'interface',
'suffix': type.nullabilitySuffix.name, 'suffix': type.nullabilitySuffix.name,
'library': type.element2.library.source.uri, 'library': type.element2.library.source.uri.toString(),
'element': type.element2.name, 'element': type.element2.name,
'instantiation': [ 'instantiation': [
for (final instantiation in type.typeArguments) for (final instantiation in type.typeArguments)
@ -329,6 +339,10 @@ abstract class ElementDeserializer {
final type = json['type'] as String; final type = json['type'] as String;
switch (type) { switch (type) {
case 'unique':
return const UniqueColumn();
case 'primary':
return PrimaryKeyColumn.fromJson(json);
case 'foreign_key': case 'foreign_key':
ReferenceAction? readAction(String? value) { ReferenceAction? readAction(String? value) {
return value == null ? null : ReferenceAction.values.byName(value); return value == null ? null : ReferenceAction.values.byName(value);
@ -339,6 +353,12 @@ abstract class ElementDeserializer {
readAction(json['onUpdate'] as String?), readAction(json['onUpdate'] as String?),
readAction(json['onDelete'] as String?), readAction(json['onDelete'] as String?),
); );
case 'generated_as':
return ColumnGeneratedAs.fromJson(json);
case 'check':
return DartCheckExpression.fromJson(json);
case 'limit_text_length':
return LimitingTextLength.fromJson(json);
default: default:
throw UnimplementedError('Unsupported constraint: $type'); throw UnimplementedError('Unsupported constraint: $type');
} }

View File

@ -7,36 +7,15 @@ part of '../../analysis/preprocess_drift.dart';
// ************************************************************************** // **************************************************************************
DriftPreprocessorResult _$DriftPreprocessorResultFromJson(Map json) => DriftPreprocessorResult _$DriftPreprocessorResultFromJson(Map json) =>
$checkedCreate( DriftPreprocessorResult._(
'DriftPreprocessorResult', Map<String, String>.from(
json, json['inline_dart_expressions_to_helper_field'] as Map),
($checkedConvert) { (json['declared_tables_and_views'] as List<dynamic>)
$checkKeys( .map((e) => e as String)
json, .toList(),
allowedKeys: const [ (json['imports'] as List<dynamic>)
'inline_dart_expressions_to_helper_field',
'declared_tables_and_views',
'imports'
],
);
final val = DriftPreprocessorResult._(
$checkedConvert('inline_dart_expressions_to_helper_field',
(v) => Map<String, String>.from(v as Map)),
$checkedConvert('declared_tables_and_views',
(v) => (v as List<dynamic>).map((e) => e as String).toList()),
$checkedConvert(
'imports',
(v) => (v as List<dynamic>)
.map((e) => Uri.parse(e as String)) .map((e) => Uri.parse(e as String))
.toList()), .toList(),
);
return val;
},
fieldKeyMap: const {
'inlineDartExpressionsToHelperField':
'inline_dart_expressions_to_helper_field',
'declaredTablesAndViews': 'declared_tables_and_views'
},
); );
Map<String, dynamic> _$DriftPreprocessorResultToJson( Map<String, dynamic> _$DriftPreprocessorResultToJson(

View File

@ -0,0 +1,49 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of '../../../analysis/results/column.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
PrimaryKeyColumn _$PrimaryKeyColumnFromJson(Map json) => PrimaryKeyColumn(
json['is_auto_increment'] as bool,
);
Map<String, dynamic> _$PrimaryKeyColumnToJson(PrimaryKeyColumn instance) =>
<String, dynamic>{
'is_auto_increment': instance.isAutoIncrement,
};
ColumnGeneratedAs _$ColumnGeneratedAsFromJson(Map json) => ColumnGeneratedAs(
AnnotatedDartCode.fromJson(json['dart_expression'] as Map),
json['stored'] as bool,
);
Map<String, dynamic> _$ColumnGeneratedAsToJson(ColumnGeneratedAs instance) =>
<String, dynamic>{
'dart_expression': instance.dartExpression.toJson(),
'stored': instance.stored,
};
DartCheckExpression _$DartCheckExpressionFromJson(Map json) =>
DartCheckExpression(
AnnotatedDartCode.fromJson(json['dart_expression'] as Map),
);
Map<String, dynamic> _$DartCheckExpressionToJson(
DartCheckExpression instance) =>
<String, dynamic>{
'dart_expression': instance.dartExpression.toJson(),
};
LimitingTextLength _$LimitingTextLengthFromJson(Map json) => LimitingTextLength(
minLength: json['min_length'] as int?,
maxLength: json['max_length'] as int?,
);
Map<String, dynamic> _$LimitingTextLengthToJson(LimitingTextLength instance) =>
<String, dynamic>{
'min_length': instance.minLength,
'max_length': instance.maxLength,
};

View File

@ -6,22 +6,11 @@ part of '../../../analysis/results/dart.dart';
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
DartTopLevelSymbol _$DartTopLevelSymbolFromJson(Map json) => $checkedCreate( DartTopLevelSymbol _$DartTopLevelSymbolFromJson(Map json) => DartTopLevelSymbol(
'DartTopLevelSymbol', json['lexeme'] as String,
json, json['import_uri'] == null
($checkedConvert) { ? null
$checkKeys( : Uri.parse(json['import_uri'] as String),
json,
allowedKeys: const ['lexeme', 'import_uri'],
);
final val = DartTopLevelSymbol(
$checkedConvert('lexeme', (v) => v as String),
$checkedConvert(
'import_uri', (v) => v == null ? null : Uri.parse(v as String)),
);
return val;
},
fieldKeyMap: const {'importUri': 'import_uri'},
); );
Map<String, dynamic> _$DartTopLevelSymbolToJson(DartTopLevelSymbol instance) => Map<String, dynamic> _$DartTopLevelSymbolToJson(DartTopLevelSymbol instance) =>

View File

@ -6,21 +6,9 @@ part of '../../../analysis/results/element.dart';
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
DriftElementId _$DriftElementIdFromJson(Map json) => $checkedCreate( DriftElementId _$DriftElementIdFromJson(Map json) => DriftElementId(
'DriftElementId', Uri.parse(json['library_uri'] as String),
json, json['name'] as String,
($checkedConvert) {
$checkKeys(
json,
allowedKeys: const ['library_uri', 'name'],
);
final val = DriftElementId(
$checkedConvert('library_uri', (v) => Uri.parse(v as String)),
$checkedConvert('name', (v) => v as String),
);
return val;
},
fieldKeyMap: const {'libraryUri': 'library_uri'},
); );
Map<String, dynamic> _$DriftElementIdToJson(DriftElementId instance) => Map<String, dynamic> _$DriftElementIdToJson(DriftElementId instance) =>
@ -29,21 +17,9 @@ Map<String, dynamic> _$DriftElementIdToJson(DriftElementId instance) =>
'name': instance.name, 'name': instance.name,
}; };
DriftDeclaration _$DriftDeclarationFromJson(Map json) => $checkedCreate( DriftDeclaration _$DriftDeclarationFromJson(Map json) => DriftDeclaration(
'DriftDeclaration', Uri.parse(json['source_uri'] as String),
json, json['offset'] as int,
($checkedConvert) {
$checkKeys(
json,
allowedKeys: const ['source_uri', 'offset'],
);
final val = DriftDeclaration(
$checkedConvert('source_uri', (v) => Uri.parse(v as String)),
$checkedConvert('offset', (v) => v as int),
);
return val;
},
fieldKeyMap: const {'sourceUri': 'source_uri'},
); );
Map<String, dynamic> _$DriftDeclarationToJson(DriftDeclaration instance) => Map<String, dynamic> _$DriftDeclarationToJson(DriftDeclaration instance) =>

View File

@ -6,47 +6,16 @@ part of '../../../analysis/results/result_sets.dart';
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
ExistingRowClass _$ExistingRowClassFromJson(Map json) => $checkedCreate( ExistingRowClass _$ExistingRowClassFromJson(Map json) => ExistingRowClass(
'ExistingRowClass', targetClass: AnnotatedDartCode.fromJson(json['target_class'] as Map),
json, targetType: AnnotatedDartCode.fromJson(json['target_type'] as Map),
($checkedConvert) { constructor: json['constructor'] as String,
$checkKeys( positionalColumns: (json['positional_columns'] as List<dynamic>)
json, .map((e) => e as String)
allowedKeys: const [ .toList(),
'target_class', namedColumns: Map<String, String>.from(json['named_columns'] as Map),
'target_type', generateInsertable: json['generate_insertable'] as bool? ?? false,
'constructor', isAsyncFactory: json['is_async_factory'] as bool? ?? false,
'is_async_factory',
'positional_columns',
'named_columns',
'generate_insertable'
],
);
final val = ExistingRowClass(
targetClass: $checkedConvert(
'target_class', (v) => AnnotatedDartCode.fromJson(v as Map)),
targetType: $checkedConvert(
'target_type', (v) => AnnotatedDartCode.fromJson(v as Map)),
constructor: $checkedConvert('constructor', (v) => v as String),
positionalColumns: $checkedConvert('positional_columns',
(v) => (v as List<dynamic>).map((e) => e as String).toList()),
namedColumns: $checkedConvert(
'named_columns', (v) => Map<String, String>.from(v as Map)),
generateInsertable: $checkedConvert(
'generate_insertable', (v) => v as bool? ?? false),
isAsyncFactory:
$checkedConvert('is_async_factory', (v) => v as bool? ?? false),
);
return val;
},
fieldKeyMap: const {
'targetClass': 'target_class',
'targetType': 'target_type',
'positionalColumns': 'positional_columns',
'namedColumns': 'named_columns',
'generateInsertable': 'generate_insertable',
'isAsyncFactory': 'is_async_factory'
},
); );
Map<String, dynamic> _$ExistingRowClassToJson(ExistingRowClass instance) => Map<String, dynamic> _$ExistingRowClassToJson(ExistingRowClass instance) =>