Skip to content

Commit 0e3c0d7

Browse files
author
Ivan Dlugos
committed
add PropertyType to fine-tune stored type using @Property() annotation
1 parent 89bf491 commit 0e3c0d7

File tree

9 files changed

+281
-55
lines changed

9 files changed

+281
-55
lines changed

generator/integration-tests/basics/1.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,22 @@ void main() {
3535
expect(entity(model, 'D').flags, equals(OBXEntityFlags.SYNC_ENABLED));
3636
expect(entity(jsonModel, 'D').flags, equals(OBXEntityFlags.SYNC_ENABLED));
3737
});
38+
39+
test('types', () {
40+
expect(property(model, 'T.tBool').type, OBXPropertyType.Bool);
41+
expect(property(model, 'T.tByte').type, OBXPropertyType.Byte);
42+
expect(property(model, 'T.tShort').type, OBXPropertyType.Short);
43+
expect(property(model, 'T.tChar').type, OBXPropertyType.Char);
44+
expect(property(model, 'T.tInt').type, OBXPropertyType.Int);
45+
expect(property(model, 'T.tLong').type, OBXPropertyType.Long);
46+
expect(property(model, 'T.tFloat').type, OBXPropertyType.Float);
47+
expect(property(model, 'T.tDouble').type, OBXPropertyType.Double);
48+
expect(property(model, 'T.tString').type, OBXPropertyType.String);
49+
expect(property(model, 'T.tDate').type, OBXPropertyType.Date);
50+
expect(property(model, 'T.tDateNano').type, OBXPropertyType.DateNano);
51+
// expect(property(model, 'T.tByteVector1').type, OBXPropertyType.ByteVector);
52+
// expect(property(model, 'T.tByteVector2').type, OBXPropertyType.ByteVector);
53+
// expect(property(model, 'T.tByteVector3').type, OBXPropertyType.ByteVector);
54+
// expect(property(model, 'T.tStringVector').type, OBXPropertyType.StringVector);
55+
});
3856
}

generator/integration-tests/basics/lib/lib.dart

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:typed_data';
2+
13
import 'package:objectbox/objectbox.dart';
24
import 'objectbox.g.dart';
35
export 'other.dart';
@@ -27,3 +29,58 @@ class D {
2729

2830
D();
2931
}
32+
33+
@Entity()
34+
class T {
35+
@Id()
36+
int id;
37+
38+
// implicit PropertyType.bool
39+
bool tBool;
40+
41+
@Property(type: PropertyType.byte)
42+
int tByte;
43+
44+
@Property(type: PropertyType.short)
45+
int tShort;
46+
47+
@Property(type: PropertyType.char)
48+
int tChar;
49+
50+
@Property(type: PropertyType.int)
51+
int tInt;
52+
53+
// implicit PropertyType.long
54+
int tLong;
55+
56+
@Property(type: PropertyType.float)
57+
double tFloat;
58+
59+
// implicit PropertyType.double
60+
double tDouble;
61+
62+
// implicitly determined types
63+
String tString;
64+
65+
@Property(type: PropertyType.date)
66+
int tDate;
67+
68+
@Property(type: PropertyType.dateNano)
69+
int tDateNano;
70+
71+
// TODO
72+
// @Property(type: PropertyType.byteVector)
73+
// List<int> tByteVector1;
74+
75+
// TODO
76+
// @Property(type: PropertyType.byteVector)
77+
// Int8List tByteVector2;
78+
79+
// TODO
80+
// @Property(type: PropertyType.byteVector)
81+
// Uint8List tByteVector3;
82+
83+
// TODO
84+
// @Property(type: PropertyType.stringVector)
85+
// List<String> tStringVector;
86+
}

generator/lib/src/code_chunks.dart

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import "dart:convert";
2-
import "package:objectbox/src/modelinfo/index.dart";
3-
import "package:objectbox/src/bindings/bindings.dart" show OBXPropertyType;
4-
import "package:source_gen/source_gen.dart" show InvalidGenerationSourceError;
1+
import 'dart:convert';
2+
import 'package:objectbox/src/modelinfo/index.dart';
3+
import 'package:objectbox/src/bindings/bindings.dart';
4+
import 'package:source_gen/source_gen.dart' show InvalidGenerationSourceError;
55

66
class CodeChunks {
77
static String objectboxDart(ModelInfo model, List<String> imports) => """
@@ -52,46 +52,42 @@ class CodeChunks {
5252
String fieldType;
5353
switch (prop.type) {
5454
case OBXPropertyType.Bool:
55-
fieldType = "Boolean";
55+
fieldType = 'Boolean';
5656
break;
5757
case OBXPropertyType.String:
58-
fieldType = "String";
59-
break;
60-
float:
61-
case OBXPropertyType.Double:
62-
fieldType = "Double";
58+
fieldType = 'String';
6359
break;
6460
case OBXPropertyType.Float:
65-
continue float;
66-
integer:
67-
case OBXPropertyType.Int:
68-
fieldType = "Integer";
61+
case OBXPropertyType.Double:
62+
fieldType = 'Double';
6963
break;
7064
case OBXPropertyType.Byte:
71-
continue integer;
7265
case OBXPropertyType.Short:
73-
continue integer;
7466
case OBXPropertyType.Char:
75-
continue integer;
67+
case OBXPropertyType.Int:
7668
case OBXPropertyType.Long:
77-
continue integer;
69+
case OBXPropertyType.Date:
70+
case OBXPropertyType.DateNano:
71+
case OBXPropertyType.Relation:
72+
fieldType = 'Integer';
73+
break;
7874
default:
7975
throw InvalidGenerationSourceError(
80-
"Unsupported property type (${prop.type}): ${entity.name}.${name}");
76+
'Unsupported property type (${prop.type}): ${entity.name}.${name}');
8177
}
8278

83-
ret.add("""
84-
static final ${name} = Query${fieldType}Property(entityId:${entity.id.id}, propertyId:${prop.id.id}, obxType:${prop.type});
85-
""");
79+
ret.add('''
80+
static final ${prop.name} = Query${fieldType}Property(entityId:${entity.id.id}, propertyId:${prop.id.id}, obxType:${prop.type});
81+
''');
8682
}
8783
return ret.join();
8884
}
8985

9086
static String queryConditionClasses(ModelEntity entity) {
9187
// TODO add entity.id check to throw an error Box if the wrong entity.property is used
92-
return """
88+
return '''
9389
class ${entity.name}_ {
9490
${_queryConditionBuilder(entity)}
95-
}""";
91+
}''';
9692
}
9793
}

generator/lib/src/entity_resolver.dart

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import 'dart:async';
22
import 'dart:convert';
33

4+
import 'package:analyzer/dart/constant/value.dart';
45
import 'package:analyzer/dart/element/element.dart';
56
import 'package:analyzer/dart/element/type.dart';
67
import 'package:build/build.dart';
78
import 'package:objectbox/objectbox.dart' as obx;
89
import 'package:objectbox/src/bindings/bindings.dart';
10+
import 'package:objectbox/src/bindings/helpers.dart';
911
import 'package:objectbox/src/modelinfo/index.dart';
1012
import 'package:source_gen/source_gen.dart';
1113

@@ -67,8 +69,7 @@ class EntityResolver extends Builder {
6769
entity.flags |= OBXEntityFlags.SYNC_ENABLED;
6870
}
6971

70-
log.info('entity ${entity.name}(${entity.id}), sync=' +
71-
(entity.hasFlag(OBXEntityFlags.SYNC_ENABLED) ? 'ON' : 'OFF'));
72+
log.info(entity);
7273

7374
// getters, ... (anything else?)
7475
final readOnlyFields = <String, bool>{};
@@ -91,7 +92,8 @@ class EntityResolver extends Builder {
9192
continue;
9293
}
9394

94-
int fieldType, flags = 0;
95+
int fieldType;
96+
var flags = 0;
9597
int propUid;
9698

9799
if (_idChecker.hasAnnotationOfExact(f)) {
@@ -114,7 +116,8 @@ class EntityResolver extends Builder {
114116
} else if (_propertyChecker.hasAnnotationOfExact(f)) {
115117
final _propertyAnnotation = _propertyChecker.firstAnnotationOfExact(f);
116118
propUid = _propertyAnnotation.getField('uid').toIntValue();
117-
fieldType = _propertyAnnotation.getField('type').toIntValue();
119+
fieldType =
120+
propertyTypeFromAnnotation(_propertyAnnotation.getField('type'));
118121
flags = _propertyAnnotation.getField('flag').toIntValue() ?? 0;
119122
}
120123

@@ -147,14 +150,12 @@ class EntityResolver extends Builder {
147150
flags: flags, entity: entity);
148151

149152
// Index and unique annotation.
150-
final indexTypeStr =
151-
processAnnotationIndexUnique(f, fieldType, elementBare, prop);
153+
processAnnotationIndexUnique(f, fieldType, elementBare, prop);
152154

153155
if (propUid != null) prop.id.uid = propUid;
154156
entity.properties.add(prop);
155157

156-
log.info(
157-
' property ${prop.name}(${prop.id}) type:${prop.type} flags:${prop.flags} ${prop.hasIndexFlag() ? "index:${indexTypeStr}" : ""}');
158+
log.info(' ${prop}');
158159
}
159160

160161
// some checks on the entity's integrity
@@ -166,7 +167,7 @@ class EntityResolver extends Builder {
166167
return entity;
167168
}
168169

169-
String processAnnotationIndexUnique(FieldElement f, int fieldType,
170+
void processAnnotationIndexUnique(FieldElement f, int fieldType,
170171
Element elementBare, obx.ModelProperty prop) {
171172
obx.IndexType indexType;
172173

@@ -233,16 +234,35 @@ class EntityResolver extends Builder {
233234
switch (indexType) {
234235
case obx.IndexType.value:
235236
prop.flags |= OBXPropertyFlags.INDEXED;
236-
return 'value';
237+
break;
237238
case obx.IndexType.hash:
238239
prop.flags |= OBXPropertyFlags.INDEX_HASH;
239-
return 'hash';
240+
break;
240241
case obx.IndexType.hash64:
241242
prop.flags |= OBXPropertyFlags.INDEX_HASH64;
242-
return 'hash64';
243+
break;
243244
default:
244245
throw InvalidGenerationSourceError(
245246
'in target ${elementBare.name}: invalid index type: $indexType');
246247
}
247248
}
249+
250+
// find out @Property(type:) field value - its an enum PropertyType
251+
int /*?*/ propertyTypeFromAnnotation(DartObject typeField) {
252+
if (typeField.isNull) return null;
253+
final enumValues = (typeField.type as InterfaceType)
254+
.element
255+
.fields
256+
.where((f) => f.isEnumConstant)
257+
.toList();
258+
259+
// Find the index of the matching enum constant.
260+
for (var i = 0; i < enumValues.length; i++) {
261+
if (enumValues[i].computeConstantValue() == typeField) {
262+
return propertyTypeToOBXPropertyType(obx.PropertyType.values[i]);
263+
}
264+
}
265+
266+
return null;
267+
}
248268
}

lib/src/annotations.dart

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,65 @@ class Entity {
1313
///
1414
/// Use OBXPropertyType and OBXPropertyFlag values, resp. for type and flag.
1515
class Property {
16-
final int /*?*/ uid, type, flag;
16+
final int /*?*/ uid, flag;
17+
18+
/// Override dart type with an alternative ObjectBox property type
19+
final PropertyType /*?*/ type;
1720

1821
const Property({this.type, this.flag, this.uid});
1922
}
2023

24+
// Specify ObjectBox property type explicitly
25+
enum PropertyType {
26+
/// dart type=bool, size: 1-byte/8-bits
27+
/// no need to specify explicitly, just use `bool`
28+
// bool,
29+
30+
/// size: 1-byte/8-bits
31+
byte,
32+
33+
/// size: 2-bytes/16-bits
34+
short,
35+
36+
/// size: 1-byte/8-bits
37+
char,
38+
39+
/// size: 4-bytes/32-bits
40+
int,
41+
42+
/// dart type=int, size: 8-bytes/64-bits
43+
/// no need to specify explicitly, just use `int`
44+
// long,
45+
46+
/// size: 4-bytes/32-bits
47+
float,
48+
49+
/// dart type=double, size: 8-bytes/64-bits
50+
/// no need to specify explicitly, just use `double`
51+
// double,
52+
53+
/// dart type=String
54+
/// no need to specify explicitly, just use `String`
55+
// string,
56+
57+
/// Relation, currently not supported
58+
// relation,
59+
60+
/// Unix timestamp (milliseconds since 1970), size: 8-bytes/64-bits
61+
date,
62+
63+
/// Unix timestamp (nanoseconds since 1970), size: 8-bytes/64-bits
64+
dateNano,
65+
66+
/// dart type=Uint8List, currently not supported
67+
// byteVector,
68+
69+
/// dart type=List<String>, currently not supported
70+
// stringVector
71+
}
72+
2173
class Id {
22-
final int /*?*/ uid;
74+
final int /*?*/ uid; // TODO remove, use `Property(uid:)`
2375

2476
const Id({this.uid});
2577
}
@@ -44,6 +96,7 @@ class Transient {
4496
/// properties.
4597
class Index {
4698
final IndexType /*?*/ type;
99+
47100
const Index({this.type});
48101
}
49102

0 commit comments

Comments
 (0)