Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 48c3c02

Browse files
EntityResolver: create useful error if property conflicts with relation #140
1 parent 3a032fe commit 48c3c02

File tree

3 files changed

+71
-4
lines changed

3 files changed

+71
-4
lines changed

‎generator/lib/src/entity_resolver.dart‎

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:analyzer/dart/element/element.dart';
66
import 'package:analyzer/dart/element/nullability_suffix.dart';
77
import 'package:analyzer/dart/element/type.dart';
88
import 'package:build/build.dart';
9+
import 'package:collection/collection.dart';
910
import 'package:objectbox/internal.dart';
1011
import 'package:objectbox/objectbox.dart';
1112
import 'package:source_gen/source_gen.dart';
@@ -391,10 +392,11 @@ class EntityResolver extends Builder {
391392
}
392393
}
393394

395+
_checkNoPropertiesConflictWithRelationProperties(entity, classElement);
394396
// Verify there is at most 1 unique property with REPLACE strategy.
395-
ensureSingleUniqueReplace(entity, classElement);
397+
_ensureSingleUniqueReplace(entity, classElement);
396398
// If sync enabled, verify all unique properties use REPLACE strategy.
397-
ifSyncEnsureAllUniqueAreReplace(entity, classElement);
399+
_ifSyncEnsureAllUniqueAreReplace(entity, classElement);
398400

399401
for (var p in entity.properties) {
400402
log.info(' $p');
@@ -618,7 +620,34 @@ class EntityResolver extends Builder {
618620
}
619621
}
620622

621-
void ensureSingleUniqueReplace(
623+
/// Verifies no regular properties are named like ToOne relation
624+
/// properties (which are implicitly created and not defined as a Dart field,
625+
/// so their existence isn't obvious).
626+
void _checkNoPropertiesConflictWithRelationProperties(
627+
ModelEntity entity,
628+
ClassElement classElement,
629+
) {
630+
final relationProps = entity.properties.where((p) => p.isRelation);
631+
final nonRelationProps = entity.properties.whereNot((p) => p.isRelation);
632+
633+
for (var relProp in relationProps) {
634+
var propWithSameName = nonRelationProps.firstWhereOrNull(
635+
(p) => p.name == relProp.name,
636+
);
637+
if (propWithSameName != null) {
638+
final conflictingField = classElement.fields.firstWhereOrNull(
639+
(f) => f.displayName == propWithSameName.name,
640+
);
641+
throw InvalidGenerationSourceError(
642+
'Property name conflicts with the relation property "${relProp.name}" created for the ToOne relation "${relProp.relationField}".'
643+
' Rename the property or use @TargetIdProperty on the ToOne to rename the relation property.',
644+
element: conflictingField,
645+
);
646+
}
647+
}
648+
}
649+
650+
void _ensureSingleUniqueReplace(
622651
ModelEntity entity,
623652
ClassElement classElement,
624653
) {
@@ -633,7 +662,7 @@ class EntityResolver extends Builder {
633662
}
634663
}
635664

636-
void ifSyncEnsureAllUniqueAreReplace(
665+
void _ifSyncEnsureAllUniqueAreReplace(
637666
ModelEntity entity,
638667
ClassElement classElement,
639668
) {

‎generator/test/code_builder_test.dart‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,42 @@ void main() {
298298
expect(renamedRelationProperty!.type, OBXPropertyType.Relation);
299299
});
300300

301+
test('ToOne relation property name conflict', () async {
302+
// Note: unlike in Java, for Dart it's also not supported to "expose" the
303+
// relation ("target ID") property.
304+
final source = r'''
305+
library example;
306+
import 'package:objectbox/objectbox.dart';
307+
308+
@Entity()
309+
class Example {
310+
@Id()
311+
int id = 0;
312+
int? customerId; // conflicts
313+
final customer = ToOne<Example>();
314+
}
315+
''';
316+
317+
final testEnv = GeneratorTestEnv();
318+
final result = await testEnv.run(source, expectNoOutput: true);
319+
320+
expect(result.builderResult.succeeded, false);
321+
expect(
322+
result.logs,
323+
contains(
324+
isA<LogRecord>()
325+
.having((r) => r.level, 'level', Level.SEVERE)
326+
.having(
327+
(r) => r.message,
328+
'message',
329+
contains(
330+
'Property name conflicts with the relation property "customerId"',
331+
),
332+
),
333+
),
334+
);
335+
});
336+
301337
test('HNSW annotation on unsupported type errors', () async {
302338
final source = r'''
303339
library example;

‎objectbox/CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
This can be useful if the default name needs to be used for another property. Or when syncing with
1515
MongoDB to match the name used in the MongoDB database. [#713](https://github.com/objectbox/objectbox-dart/issues/713)
16+
* Provide a helpful error message if the name of a property conflicts with a relation property
17+
created for a `ToOne` relation. [#713](https://github.com/objectbox/objectbox-dart/issues/713)
1618

1719
## 5.0.0 (2025年10月01日)
1820

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /