@@ -6,8 +6,8 @@ import 'package:pubspec_parse/pubspec_parse.dart';
66import 'package:source_gen/source_gen.dart' show InvalidGenerationSourceError;
77
88class CodeChunks {
9- static String objectboxDart (
10- ModelInfo model, List < String > imports, Pubspec ? pubspec) =>
9+ static String objectboxDart (ModelInfo model, List < String > imports,
10+ Pubspec ? pubspec) =>
1111 """
1212 // GENERATED CODE - DO NOT MODIFY BY HAND
1313
@@ -35,7 +35,8 @@ class CodeChunks {
3535 ${defineModel (model )}
3636
3737 final bindings = <Type, EntityDefinition>{
38- ${model .entities .mapIndexed ((i , entity ) => "${entity .name }: ${entityBinding (i , entity )}" ).join (",\n " )}
38+ ${model .entities .mapIndexed ((i , entity ) => "${entity
39+ .name }: ${entityBinding (i , entity )}" ).join (",\n " )}
3940 };
4041
4142 return ModelDefinition(model, bindings);
@@ -53,9 +54,13 @@ class CodeChunks {
5354 int$nullableOperator fileMode,
5455 int$nullableOperator maxReaders,
5556 bool queriesCaseSensitiveDefault = true,
56- String$nullableOperator macosApplicationGroup})${obxFlutter ? ' async' : '' } =>
57+ String$nullableOperator macosApplicationGroup})${obxFlutter
58+ ? ' async'
59+ : '' } =>
5760 Store(getObjectBoxModel(),
58- directory: directory${obxFlutter ? ' ?? (await defaultStoreDirectory()).path' : '' },
61+ directory: directory${obxFlutter
62+ ? ' ?? (await defaultStoreDirectory()).path'
63+ : '' },
5964 maxDBSizeInKB: maxDBSizeInKB,
6065 fileMode: fileMode,
6166 maxReaders: maxReaders,
@@ -187,9 +192,11 @@ class CodeChunks {
187192 // Such ID must already be set, i.e. it could not have been assigned.
188193 return '''{
189194 if (object.${propertyFieldName (entity .idProperty )} != id) {
190- throw ArgumentError('Field ${entity .name }.${propertyFieldName (entity .idProperty )} is read-only '
195+ throw ArgumentError('Field ${entity .name }.${propertyFieldName (
196+ entity .idProperty )} is read-only '
191197 '(final or getter-only) and it was declared to be self-assigned. '
192- 'However, the currently inserted object (.${propertyFieldName (entity .idProperty )}=\$ {object.${propertyFieldName (entity .idProperty )}}) '
198+ 'However, the currently inserted object (.${propertyFieldName (
199+ entity .idProperty )}=\$ {object.${propertyFieldName (entity .idProperty )}}) '
193200 "doesn't match the inserted ID (ID \$ id). "
194201 'You must assign an ID before calling [box.put()].');
195202 }
@@ -209,7 +216,8 @@ class CodeChunks {
209216 return '[]' ;
210217 default :
211218 throw InvalidGenerationSourceError (
212- 'Cannot figure out default value for field: ${p .fieldType } ${p .name }' );
219+ 'Cannot figure out default value for field: ${p .fieldType } ${p
220+ .name }' );
213221 }
214222 }
215223
@@ -286,13 +294,14 @@ class CodeChunks {
286294 } else if (p.type == OBXPropertyType .DateNano ) {
287295 if (p.fieldIsNullable) {
288296 accessorSuffix =
289- ' == null ? null : object.${propertyFieldName (p )}' ;
297+ ' == null ? null : object.${propertyFieldName (p )}' ;
290298 if (p.entity! .nullSafetyEnabled) accessorSuffix += '!' ;
291299 }
292300 accessorSuffix += '.microsecondsSinceEpoch * 1000' ;
293301 }
294302 }
295- return 'fbb.add${_propertyFlatBuffersType [p .type ]}($fbField , object.${propertyFieldName (p )}$accessorSuffix );' ;
303+ return 'fbb.add${_propertyFlatBuffersType [p
304+ .type ]}($fbField , object.${propertyFieldName (p )}$accessorSuffix );' ;
296305 }
297306 });
298307
@@ -316,14 +325,16 @@ class CodeChunks {
316325 // property to its index in entity.properties.
317326 final fieldIndexes = < String , int > {};
318327 final fieldReaders =
319- entity.properties.mapIndexed ((int index, ModelProperty p) {
328+ entity.properties.mapIndexed ((int index, ModelProperty p) {
320329 fieldIndexes[propertyFieldName (p)] = index;
321330
322331 String ? fbReader;
323332 var readFieldOrNull = () =>
324- 'const $fbReader .vTableGetNullable(buffer, rootOffset, ${propertyFlatBuffersvTableOffset (p )})' ;
333+ 'const $fbReader .vTableGetNullable(buffer, rootOffset, ${propertyFlatBuffersvTableOffset (
334+ p )})' ;
325335 var readFieldNonNull = ([String ? defaultValue]) =>
326- 'const $fbReader .vTableGet(buffer, rootOffset, ${propertyFlatBuffersvTableOffset (p )}, ${defaultValue ?? fieldDefaultValue (p )})' ;
336+ 'const $fbReader .vTableGet(buffer, rootOffset, ${propertyFlatBuffersvTableOffset (
337+ p )}, ${defaultValue ?? fieldDefaultValue (p )})' ;
327338 var readField =
328339 () => p.fieldIsNullable ? readFieldOrNull () : readFieldNonNull ();
329340 final valueVar = '${propertyFieldName (p )}Value' ;
@@ -336,7 +347,8 @@ class CodeChunks {
336347 fbReader = 'fb.ListReader<int>(fb.Int8Reader())' ;
337348 if (p.fieldIsNullable) {
338349 preLines.add ('final $valueVar = ${readFieldOrNull ()};' );
339- return '$valueVar == null ? null : ${p .fieldType }.fromList($valueVar )' ;
350+ return '$valueVar == null ? null : ${p
351+ .fieldType }.fromList($valueVar )' ;
340352 } else {
341353 return '${p .fieldType }.fromList(${readFieldNonNull ('[]' )})' ;
342354 }
@@ -363,43 +375,32 @@ class CodeChunks {
363375 }
364376 } else {
365377 if (p.type == OBXPropertyType .Date ) {
366- return "DateTime.fromMillisecondsSinceEpoch(${readFieldNonNull ('0' )})" ;
378+ return "DateTime.fromMillisecondsSinceEpoch(${readFieldNonNull (
379+ '0' )})" ;
367380 } else if (p.type == OBXPropertyType .DateNano ) {
368- return "DateTime.fromMicrosecondsSinceEpoch((${readFieldNonNull ('0' )} / 1000).round())" ;
381+ return "DateTime.fromMicrosecondsSinceEpoch((${readFieldNonNull (
382+ '0' )} / 1000).round())" ;
369383 }
370384 }
371385 throw InvalidGenerationSourceError (
372- 'Invalid property data type ${p .type } for a DateTime field ${entity .name }.${p .name }' );
386+ 'Invalid property data type ${p .type } for a DateTime field ${entity
387+ .name }.${p .name }' );
373388 }
374389 return readField ();
375390 }).toList (growable: false );
376391
377- // add initializers for relations
378- entity.properties.forEachIndexed ((int index, ModelProperty p) {
379- if (p.isRelation) {
380- postLines.add (
381- 'object.${propertyFieldName (p )}.targetId = ${fieldReaders [index ]};'
382- '\n object.${propertyFieldName (p )}.attach(store);' );
383- }
384- });
385-
386- postLines.addAll (entity.relations.map ((ModelRelation rel) =>
387- 'InternalToManyAccess.setRelInfo(object.${rel .name }, store, ${relInfo (entity , rel )}, store.box<${entity .name }>());' ));
388-
389- postLines.addAll (entity.backlinks.map ((ModelBacklink bl) {
390- return 'InternalToManyAccess.setRelInfo(object.${bl .name }, store, ${backlinkRelInfo (entity , bl )}, store.box<${entity .name }>());' ;
391- }));
392-
393392 // try to initialize as much as possible using the constructor
394393 entity.constructorParams.forEachWhile ((String declaration) {
395394 // See [EntityResolver.constructorParams()] for the format.
396- final paramName = declaration.split (' ' )[0 ];
397- final paramType = declaration.split (' ' )[1 ];
395+ final declarationParts = declaration.split (' ' );
396+ final paramName = declarationParts[0 ];
397+ final paramType = declarationParts[1 ];
398+ final paramDartType = declarationParts[2 ];
398399
399400 final index = fieldIndexes[paramName];
400401 if (index == null ) {
401402 // If we can't find a positional param, we can't use the constructor at all.
402- if (paramType == 'positional' ) {
403+ if (paramType == 'positional' || paramType == 'required-named' ) {
403404 log.warning ("Cannot use the default constructor of '${entity .name }': "
404405 "don't know how to initialize param $paramName - no such property." );
405406 constructorLines.clear ();
@@ -411,13 +412,26 @@ class CodeChunks {
411412 return true ; // continue to the next param
412413 }
413414
415+ var paramValueCode = fieldReaders[index];
416+ if (entity.properties[index].isRelation) {
417+ if (paramDartType.startsWith ('ToOne<' )) {
418+ paramValueCode = 'ToOne(targetId: ${paramValueCode })' ;
419+ } else if (paramType == 'optional-named' ) {
420+ log.info ("Skipping constructor parameter $paramName on "
421+ "'${entity .name }': the matching field is a relation but the type "
422+ "isn't - don't know how to initialize this parameter." );
423+ return true ;
424+ }
425+ }
426+
414427 switch (paramType) {
415428 case 'positional' :
416429 case 'optional' :
417- constructorLines.add (fieldReaders[index] );
430+ constructorLines.add (paramValueCode );
418431 break ;
419- case 'named' :
420- constructorLines.add ('$paramName : ${fieldReaders [index ]}' );
432+ case 'required-named' :
433+ case 'optional-named' :
434+ constructorLines.add ('$paramName : ${paramValueCode }' );
421435 break ;
422436 default :
423437 throw InvalidGenerationSourceError (
@@ -438,33 +452,56 @@ class CodeChunks {
438452 }
439453 });
440454
455+ // add initializers for relations
456+ entity.properties.forEachIndexed ((int index, ModelProperty p) {
457+ if (! p.isRelation) return ;
458+ if (fieldReaders[index].isNotEmpty) {
459+ postLines.add (
460+ 'object.${propertyFieldName (
461+ p )}.targetId = ${fieldReaders [index ]};' );
462+ }
463+ postLines.add ('object.${propertyFieldName (p )}.attach(store);' );
464+ });
465+
466+ postLines.addAll (entity.relations.map ((ModelRelation rel) =>
467+ 'InternalToManyAccess.setRelInfo(object.${rel .name }, store, ${relInfo (
468+ entity , rel )}, store.box<${entity .name }>());' ));
469+
470+ postLines.addAll (entity.backlinks.map ((ModelBacklink bl) {
471+ return 'InternalToManyAccess.setRelInfo(object.${bl
472+ .name }, store, ${backlinkRelInfo (entity , bl )}, store.box<${entity
473+ .name }>());' ;
474+ }));
475+
441476 return '''(Store store, ByteData fbData) {
442477 final buffer = fb.BufferContext(fbData);
443478 final rootOffset = buffer.derefObject(0);
444479 ${preLines .join ('\n ' )}
445- final object = ${entity .name }(${constructorLines .join (', \n ' )})${cascadeLines .join ('\n ' )};
480+ final object = ${entity .name }(${constructorLines .join (
481+ ', \n ' )})${cascadeLines .join ('\n ' )};
446482 ${postLines .join ('\n ' )}
447483 return object;
448484 }''' ;
449485 }
450486
451487 static String toOneRelations (ModelEntity entity) =>
452488 '[' +
453- entity.properties
454- .where ((ModelProperty prop) => prop.isRelation)
455- .map ((ModelProperty prop) => 'object.${propertyFieldName (prop )}' )
456- .join (',' ) +
457- ']' ;
489+ entity.properties
490+ .where ((ModelProperty prop) => prop.isRelation)
491+ .map ((ModelProperty prop) => 'object.${propertyFieldName (prop )}' )
492+ .join (',' ) +
493+ ']' ;
458494
459495 static String relInfo (ModelEntity entity, ModelRelation rel) =>
460- 'RelInfo<${entity .name }>.toMany(${rel .id .id }, object.${propertyFieldAccess (entity .idProperty , '!' )})' ;
496+ 'RelInfo<${entity .name }>.toMany(${rel .id
497+ .id }, object.${propertyFieldAccess (entity .idProperty , '!' )})' ;
461498
462499 static String backlinkRelInfo (ModelEntity entity, ModelBacklink bl) {
463500 final srcEntity = entity.model.findEntityByName (bl.srcEntity);
464501 if (srcEntity == null ) {
465502 throw InvalidGenerationSourceError (
466503 'Invalid relation backlink ${entity .name }.${bl .name } '
467- '- source entity ${bl .srcEntity } not found.' );
504+ '- source entity ${bl .srcEntity } not found.' );
468505 }
469506
470507 // either of these will be set, based on the source field that matches
@@ -475,13 +512,13 @@ class CodeChunks {
475512 final matchingProps = srcEntity.properties
476513 .where ((p) => p.isRelation && p.relationTarget == entity.name);
477514 final matchingRels =
478- srcEntity.relations.where ((r) => r.targetId == entity.id);
515+ srcEntity.relations.where ((r) => r.targetId == entity.id);
479516 final candidatesCount = matchingProps.length + matchingRels.length;
480517 if (candidatesCount > 1 ) {
481518 throw InvalidGenerationSourceError (
482519 'Ambiguous relation backlink source for ${entity .name }.${bl .name }.'
483- ' Matching property: $matchingProps .'
484- ' Matching standalone relations: $matchingRels .' );
520+ ' Matching property: $matchingProps .'
521+ ' Matching standalone relations: $matchingRels .' );
485522 } else if (matchingProps.isNotEmpty) {
486523 srcProp = matchingProps.first;
487524 } else if (matchingRels.isNotEmpty) {
@@ -497,11 +534,14 @@ class CodeChunks {
497534
498535 if (srcRel != null ) {
499536 return 'RelInfo<${srcEntity .name }>.toManyBacklink('
500- '${srcRel .id .id }, object.${propertyFieldAccess (entity .idProperty , '!' )})' ;
537+ '${srcRel .id .id }, object.${propertyFieldAccess (
538+ entity .idProperty , '!' )})' ;
501539 } else if (srcProp != null ) {
502540 return 'RelInfo<${srcEntity .name }>.toOneBacklink('
503- '${srcProp .id .id }, object.${propertyFieldAccess (entity .idProperty , '!' )}, '
504- '(${srcEntity .name } srcObject) => srcObject.${propertyFieldName (srcProp )})' ;
541+ '${srcProp .id .id }, object.${propertyFieldAccess (
542+ entity .idProperty , '!' )}, '
543+ '(${srcEntity .name } srcObject) => srcObject.${propertyFieldName (
544+ srcProp )})' ;
505545 } else {
506546 throw InvalidGenerationSourceError (
507547 'Unknown relation backlink source for ${entity .name }.${bl .name }' );
@@ -511,9 +551,10 @@ class CodeChunks {
511551 static String toManyRelations (ModelEntity entity) {
512552 final definitions = < String > [];
513553 definitions.addAll (entity.relations.map (
514- (ModelRelation rel) => '${relInfo (entity , rel )}: object.${rel .name }' ));
554+ (ModelRelation rel) => '${relInfo (entity , rel )}: object.${rel
555+ .name }' ));
515556 definitions.addAll (entity.backlinks.map ((ModelBacklink bl) =>
516- '${backlinkRelInfo (entity , bl )}: object.${bl .name }' ));
557+ '${backlinkRelInfo (entity , bl )}: object.${bl .name }' ));
517558 return '{${definitions .join (',' )}}' ;
518559 }
519560
@@ -564,7 +605,7 @@ class CodeChunks {
564605 static final ${propertyFieldName (prop )} = ''' ;
565606 if (prop.isRelation) {
566607 propCode +=
567- 'QueryRelationToOne<${entity .name }, ${prop .relationTarget }>' ;
608+ 'QueryRelationToOne<${entity .name }, ${prop .relationTarget }>' ;
568609 } else {
569610 propCode += 'Query${fieldType }Property<${entity .name }>' ;
570611 }
0 commit comments