@@ -2,6 +2,7 @@ import 'dart:async';
22import 'dart:convert' ;
33
44import 'package:analyzer/dart/element/element.dart' ;
5+ import 'package:analyzer/dart/element/type.dart' ;
56import 'package:build/build.dart' ;
67import 'package:objectbox/objectbox.dart' as obx;
78import 'package:objectbox/src/bindings/bindings.dart' ;
@@ -91,7 +92,7 @@ class EntityResolver extends Builder {
9192 }
9293
9394 int fieldType, flags = 0 ;
94- int propUid, indexUid ;
95+ int propUid;
9596
9697 if (_idChecker.hasAnnotationOfExact (f)) {
9798 if (hasIdProperty) {
@@ -141,72 +142,19 @@ class EntityResolver extends Builder {
141142 }
142143 }
143144
144- // Index and unique index.
145- final indexAnnotation = _indexChecker.firstAnnotationOfExact (f);
146- final hasUniqueAnnotation = _uniqueChecker.hasAnnotationOfExact (f);
147- if (indexAnnotation != null || hasUniqueAnnotation) {
148- // Throw if property type does not support any index.
149- if (fieldType == OBXPropertyType .Float || fieldType == OBXPropertyType .Double || fieldType == OBXPropertyType .ByteVector ) {
150- throw InvalidGenerationSourceError (
151- "in target ${elementBare .name }: @Index/@Unique is not supported for type '${f .type .toString ()}' of field '${f .name }'" );
152- }
153-
154- // TODO Throw if index used on Id property.
155-
156-
157- // If available use index type from annotation.
158- var indexFlag;
159- if (indexAnnotation != null ) {
160- indexFlag = indexAnnotation.getField ('flag' ).toIntValue ();
161- if (indexFlag != null &&
162- (indexFlag != OBXPropertyFlag .INDEXED
163- || indexFlag != OBXPropertyFlag .INDEX_HASH
164- || indexFlag != OBXPropertyFlag .INDEX_HASH64 )) {
165- throw InvalidGenerationSourceError (
166- 'in target ${elementBare .name }: @Index flag must be one of [OBXPropertyFlag.INDEXED, OBXPropertyFlag.INDEX_HASH, OBXPropertyFlag.INDEX_HASH64] or none for auto-detection' );
167- }
168- }
169-
170- // Fall back to index type based on property type.
171- final supportsHashIndex = fieldType == OBXPropertyType .String ;
172- if (indexFlag == null ) {
173- if (supportsHashIndex) {
174- indexFlag = OBXPropertyFlag .INDEX_HASH ;
175- } else {
176- indexFlag = OBXPropertyFlag .INDEXED ;
177- }
178- }
179-
180- // Throw if HASH or HASH64 is not supported by property type.
181- if (! supportsHashIndex &&
182- (indexFlag == OBXPropertyFlag .INDEX_HASH ||
183- indexFlag == OBXPropertyFlag .INDEX_HASH64 )) {
184- throw InvalidGenerationSourceError (
185- "in target ${elementBare .name }: a hash index is not supported for type '${f .type .toString ()}' of field '${f .name }'" );
186- }
187-
188- flags | = indexFlag;
189- if (hasUniqueAnnotation) {
190- flags | = OBXPropertyFlag .UNIQUE ;
191- }
192- }
193-
194145 // create property (do not use readEntity.createProperty in order to avoid generating new ids)
195- final prop =
196- ModelProperty ( IdUid . empty (), f.name, fieldType, flags, entity);
146+ final prop = ModelProperty ( IdUid . empty (), f.name, fieldType,
147+ flags : flags, entity : entity);
197148
198- // TODO test on @Property(...) that uses the proper flags for index
199- final isIndexer = flags.isIndexer;
200-
201- if (isIndexer) {
202- prop.indexId = indexUid == null ? IdUid .empty () : IdUid (0 , indexUid);
203- }
149+ // Index and unique annotation.
150+ final indexTypeStr =
151+ processAnnotationIndexUnique (f, fieldType, elementBare, prop);
204152
205153 if (propUid != null ) prop.id.uid = propUid;
206154 entity.properties.add (prop);
207155
208156 log.info (
209- ' ${ isIndexer ? "index " : "" } property ${prop .name }(${prop .id }) type:${prop .type } flags:${prop .flags }' );
157+ ' property ${prop .name }(${prop .id }) type:${prop .type } flags:${prop .flags } ${ prop . hasIndexFlag () ? "index:${ indexTypeStr }" : "" }' );
210158 }
211159
212160 // some checks on the entity's integrity
@@ -217,4 +165,84 @@ class EntityResolver extends Builder {
217165
218166 return entity;
219167 }
168+
169+ String processAnnotationIndexUnique (FieldElement f, int fieldType,
170+ Element elementBare, obx.ModelProperty prop) {
171+ obx.IndexType indexType;
172+
173+ final indexAnnotation = _indexChecker.firstAnnotationOfExact (f);
174+ final hasUniqueAnnotation = _uniqueChecker.hasAnnotationOfExact (f);
175+ if (indexAnnotation == null && ! hasUniqueAnnotation) return null ;
176+
177+ // Throw if property type does not support any index.
178+ if (fieldType == OBXPropertyType .Float ||
179+ fieldType == OBXPropertyType .Double ||
180+ fieldType == OBXPropertyType .ByteVector ) {
181+ throw InvalidGenerationSourceError (
182+ "in target ${elementBare .name }: @Index/@Unique is not supported for type '${f .type .toString ()}' of field '${f .name }'" );
183+ }
184+
185+ if (prop.hasFlag (OBXPropertyFlags .ID )) {
186+ throw InvalidGenerationSourceError (
187+ 'in target ${elementBare .name }: @Index/@Unique is not supported for ID field ${f .name }. IDs are unique by definition and automatically indexed' );
188+ }
189+
190+ // If available use index type from annotation.
191+ if (indexAnnotation != null && ! indexAnnotation.isNull) {
192+ // find out @Index(type:) value - its an enum IndexType
193+ final indexTypeField = indexAnnotation.getField ('type' );
194+ if (! indexTypeField.isNull) {
195+ final indexTypeEnumValues = (indexTypeField.type as InterfaceType )
196+ .element
197+ .fields
198+ .where ((f) => f.isEnumConstant)
199+ .toList ();
200+
201+ // Find the index of the matching enum constant.
202+ for (var i = 0 ; i < indexTypeEnumValues.length; i++ ) {
203+ if (indexTypeEnumValues[i].computeConstantValue () == indexTypeField) {
204+ indexType = obx.IndexType .values[i];
205+ break ;
206+ }
207+ }
208+ }
209+ }
210+
211+ // Fall back to index type based on property type.
212+ final supportsHashIndex = fieldType == OBXPropertyType .String ;
213+ if (indexType == null ) {
214+ if (supportsHashIndex) {
215+ indexType = obx.IndexType .hash;
216+ } else {
217+ indexType = obx.IndexType .value;
218+ }
219+ }
220+
221+ // Throw if HASH or HASH64 is not supported by property type.
222+ if (! supportsHashIndex &&
223+ (indexType == obx.IndexType .hash ||
224+ indexType == obx.IndexType .hash64)) {
225+ throw InvalidGenerationSourceError (
226+ "in target ${elementBare .name }: a hash index is not supported for type '${f .type .toString ()}' of field '${f .name }'" );
227+ }
228+
229+ if (hasUniqueAnnotation) {
230+ prop.flags | = OBXPropertyFlags .UNIQUE ;
231+ }
232+
233+ switch (indexType) {
234+ case obx.IndexType .value:
235+ prop.flags | = OBXPropertyFlags .INDEXED ;
236+ return 'value' ;
237+ case obx.IndexType .hash:
238+ prop.flags | = OBXPropertyFlags .INDEX_HASH ;
239+ return 'hash' ;
240+ case obx.IndexType .hash64:
241+ prop.flags | = OBXPropertyFlags .INDEX_HASH64 ;
242+ return 'hash64' ;
243+ default :
244+ throw InvalidGenerationSourceError (
245+ 'in target ${elementBare .name }: invalid index type: $indexType ' );
246+ }
247+ }
220248}
0 commit comments