Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support constructor parameter default values #20

Merged
merged 11 commits into from
Sep 3, 2024
Merged
4 changes: 4 additions & 0 deletions hive/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.5.0+1

- Documentation updates for `HiveField` in support of `hive_ce_generator` changes

## 2.5.0

- Adds `Target` annotations to `HiveField` and `HiveType` to prevent invalid usage
Expand Down
2 changes: 2 additions & 0 deletions hive/lib/src/annotations/hive_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class HiveField {

/// The default value of this field for class hive types.
///
/// This value takes precedence over constructor parameter default values.
///
/// In enum hive types set `true` to use this enum value as default value
/// instead of null in null-safety.
///
Expand Down
2 changes: 1 addition & 1 deletion hive/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: hive_ce
description: Hive Community Edition - A spiritual continuation of Hive v2
version: 2.5.0
version: 2.5.0+1
homepage: https://github.com/IO-Design-Team/hive_ce/tree/main/hive
documentation: https://docs.hivedb.dev/

Expand Down
7 changes: 7 additions & 0 deletions hive_generator/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 1.5.0

- Supports constructor parameter default values
- No longer generates the `HiveRegistrar` if there are no adapters
- Removes unnecessary print statement in `HiveRegistrar` generator
- Bumps `analyzer` to `^6.5.0` to deal with deprecations

## 1.4.0

- Adds a generator to create a `HiveRegistrar` extension that allows registration of all generated `TypeAdapters` in one call
Expand Down
2 changes: 2 additions & 0 deletions hive_generator/example/lib/hive_registrar.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ extension HiveRegistrar on HiveInterface {
registerAdapter(Class2Adapter());
registerAdapter(EmptyClassAdapter());
registerAdapter(IterableClassAdapter());
registerAdapter(ConstructorDefaultsAdapter());
registerAdapter(NullableTypesAdapter());
registerAdapter(Enum1Adapter());
}
}
36 changes: 36 additions & 0 deletions hive_generator/example/lib/types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,39 @@ class IterableClass {
@HiveField(3)
final Set<List<String>> nestedSet;
}

@HiveType(typeId: 6)
class ConstructorDefaults {
ConstructorDefaults({
this.a = 42,
this.b = '42',
this.c = true,
DateTime? d,
}) : d = d ?? DateTime.now();

@HiveField(0)
final int a;

@HiveField(1, defaultValue: '6 * 7')
final String b;

@HiveField(2)
final bool c;

@HiveField(3)
final DateTime d;
}

@HiveType(typeId: 7)
class NullableTypes {
NullableTypes({this.a, this.b, this.c});

@HiveField(0)
final int? a;

@HiveField(1)
final String? b;

@HiveField(2)
final bool? c;
}
83 changes: 83 additions & 0 deletions hive_generator/example/lib/types.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 19 additions & 8 deletions hive_generator/lib/src/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,33 @@ import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';

/// TODO: Document this!
/// Metadata about a field in a class adapter
class AdapterField {
/// TODO: Document this!
/// The index of the field
///
/// Determines the order fields are read and written
final int index;

/// TODO: Document this!
/// The name of the field
final String name;

/// TODO: Document this!
/// The type of the field
final DartType type;

/// TODO: Document this!
final DartObject? defaultValue;
/// A default value provided by the field annotation
final DartObject? annotationDefault;

/// TODO: Document this!
AdapterField(this.index, this.name, this.type, this.defaultValue);
/// A default value provided by the constructor
final String? constructorDefault;

/// Constructor
AdapterField(
this.index,
this.name,
this.type,
this.annotationDefault,
this.constructorDefault,
);
}

/// TODO: Document this!
Expand Down
62 changes: 28 additions & 34 deletions hive_generator/lib/src/class_builder.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'dart:typed_data';

import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:hive_ce/hive.dart';
Expand Down Expand Up @@ -68,13 +67,7 @@ class ClassBuilder extends Builder {
if (param.isNamed) {
code.write('${param.name}: ');
}
code.write(
_value(
param.type,
'fields[${field.index}]',
field.defaultValue,
),
);
code.write(_value(param.type, field));
code.writeln(',');
fields.remove(field);
}
Expand All @@ -86,24 +79,33 @@ class ClassBuilder extends Builder {
// as initializing formals. We do so using cascades.
for (final field in fields) {
code.write('..${field.name} = ');
code.writeln(
_value(
field.type,
'fields[${field.index}]',
field.defaultValue,
),
);
code.writeln(_value(field.type, field));
}

code.writeln(';');

return code.toString();
}

String _value(DartType type, String variable, DartObject? defaultValue) {
String _value(DartType type, AdapterField field) {
final variable = 'fields[${field.index}]';
final value = _cast(type, variable);
if (defaultValue?.isNull != false) return value;
return '$variable == null ? ${constantToString(defaultValue!)} : $value';

final annotationDefaultIsNull = field.annotationDefault?.isNull ?? true;
final constructorDefaultIsNull = field.constructorDefault == null;

final String? defaultValue;
if (!annotationDefaultIsNull) {
defaultValue = constantToString(field.annotationDefault);
} else if (!constructorDefaultIsNull) {
defaultValue = field.constructorDefault;
} else {
defaultValue = null;
}

if (defaultValue == null) return value;

return '$variable == null ? $defaultValue : $value';
}

String _cast(DartType type, String variable) {
Expand All @@ -121,7 +123,7 @@ class ClassBuilder extends Builder {
} else if (type.isDartCoreDouble) {
return '($variable as num$suffix)$suffix.toDouble()';
} else {
return '$variable as ${_displayString(type)}';
return '$variable as ${type.getDisplayString()}';
}
}

Expand Down Expand Up @@ -152,7 +154,7 @@ class ClassBuilder extends Builder {

return '$suffix.map((e) => ${_cast(arg, 'e')})$cast';
} else {
return '$suffix.cast<${_displayString(arg)}>()';
return '$suffix.cast<${arg.getDisplayString()}>()';
}
}

Expand All @@ -165,8 +167,8 @@ class ClassBuilder extends Builder {
return '$suffix.map((dynamic k, dynamic v)=>'
'MapEntry(${_cast(arg1, 'k')},${_cast(arg2, 'v')}))';
} else {
return '$suffix.cast<${_displayString(arg1)}, '
'${_displayString(arg2)}>()';
return '$suffix.cast<${arg1.getDisplayString()}, '
'${arg2.getDisplayString()}>()';
}
}

Expand Down Expand Up @@ -212,16 +214,8 @@ String _accessorSuffixFromType(DartType type) {
/// Suffix to use when casting a value to [type].
/// $variable as $type$suffix
String _suffixFromType(DartType type) {
if (type.nullabilitySuffix == NullabilitySuffix.star) {
return '';
}
if (type.nullabilitySuffix == NullabilitySuffix.question) {
return '?';
}
return '';
}

String _displayString(DartType e) {
final suffix = _suffixFromType(e);
return '${e.getDisplayString()}$suffix';
return switch (type.nullabilitySuffix) {
NullabilitySuffix.question => '?',
_ => '',
};
}
2 changes: 1 addition & 1 deletion hive_generator/lib/src/enum_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class EnumBuilder extends Builder {
}

final defaultField = getters.firstWhere(
(it) => it.defaultValue?.toBoolValue() == true,
(it) => it.annotationDefault?.toBoolValue() == true,
orElse: () => getters.first,
);
code.writeln('''
Expand Down
7 changes: 5 additions & 2 deletions hive_generator/lib/src/registrar_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ class RegistrarBuilder implements Builder {

@override
Future<void> build(BuildStep buildStep) async {
final buffer = StringBuffer("import 'package:hive_ce/hive.dart';\n");

final uris = <String>[];
final adapters = <String>[];
await for (final input
Expand All @@ -26,6 +24,11 @@ class RegistrarBuilder implements Builder {
adapters.addAll((data['adapters'] as List).cast<String>());
}

// Do not create the registrar if there are no adapters
if (adapters.isEmpty) return;

final buffer = StringBuffer("import 'package:hive_ce/hive.dart';\n");

for (final uri in uris) {
buffer.writeln("import '$uri';");
}
Expand Down
Loading