Skip to content

Commit 9e12073

Browse files
Generator: more helpful error, test if ambiguous backlink source #130
1 parent bde3409 commit 9e12073

File tree

3 files changed

+64
-14
lines changed

3 files changed

+64
-14
lines changed

generator/lib/src/code_builder.dart

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -399,12 +399,19 @@ class CodeBuilder extends Builder {
399399
ModelRelation? srcRel;
400400
ModelProperty? srcProp;
401401

402-
throwAmbiguousError(String prop, String rel) =>
403-
throw InvalidGenerationSourceError(
404-
"Ambiguous relation backlink source for '${entity.name}.${bl.name}':"
405-
" Found matching property '$prop' and to-many relation '$rel'."
406-
" Maybe specify source name in @Backlink() annotation.",
407-
);
402+
throwAmbiguousError(
403+
Iterable<ModelProperty> toOneProps,
404+
Iterable<ModelRelation> toManyRels,
405+
) {
406+
final toOneList = toOneProps.map((p) => p.relationField);
407+
final toManyList = toManyRels.map((r) => r.name);
408+
final fieldList = [...toOneList, ...toManyList].join(', ');
409+
throw InvalidGenerationSourceError(
410+
"Can't determine backlink source for \"${entity.name}.${bl.name}\" "
411+
"as there is more than one matching ToOne or ToMany relation in \"${srcEntity.name}\": $fieldList."
412+
" Add the name of the source relation to the annotation, like @Backlink('<source>'), or modify your entity classes.",
413+
);
414+
}
408415

409416
if (bl.srcField.isEmpty) {
410417
final matchingProps = srcEntity.properties.where(
@@ -415,7 +422,7 @@ class CodeBuilder extends Builder {
415422
);
416423
final candidatesCount = matchingProps.length + matchingRels.length;
417424
if (candidatesCount > 1) {
418-
throwAmbiguousError(matchingProps.toString(), matchingRels.toString());
425+
throwAmbiguousError(matchingProps, matchingRels);
419426
} else if (matchingProps.isNotEmpty) {
420427
srcProp = matchingProps.first;
421428
} else if (matchingRels.isNotEmpty) {
@@ -428,7 +435,7 @@ class CodeBuilder extends Builder {
428435
);
429436

430437
if (srcProp != null && srcRel != null) {
431-
throwAmbiguousError(srcProp.toString(), srcRel.toString());
438+
throwAmbiguousError([srcProp], [srcRel]);
432439
}
433440
}
434441

generator/test/code_builder_test.dart

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ void main() {
203203
}
204204
''';
205205

206-
final result = await testEnv.run(source, expectNoOutput: true);
206+
final result = await testEnv.run(source, ignoreOutput: true);
207207

208208
expect(result.builderResult.succeeded, false);
209209
expect(
@@ -324,6 +324,49 @@ void main() {
324324
);
325325
});
326326

327+
test('Errors if backlink source is not unique', () async {
328+
final source = r'''
329+
library example;
330+
import 'package:objectbox/objectbox.dart';
331+
332+
@Entity()
333+
class Example {
334+
@Id()
335+
int id = 0;
336+
337+
final relA1 = ToOne<A>();
338+
final relA2 = ToOne<A>();
339+
final relA3 = ToMany<A>();
340+
}
341+
342+
@Entity()
343+
class A {
344+
@Id()
345+
int id = 0;
346+
347+
@Backlink()
348+
final backRel = ToMany<Example>();
349+
}
350+
''';
351+
352+
final testEnv = GeneratorTestEnv();
353+
final result = await testEnv.run(source, ignoreOutput: true);
354+
355+
expect(result.builderResult.succeeded, false);
356+
expect(
357+
result.logs,
358+
contains(
359+
isA<LogRecord>()
360+
.having((r) => r.level, 'level', Level.SEVERE)
361+
.having(
362+
(r) => r.message,
363+
'message',
364+
contains('Can\'t determine backlink source for "A.backRel"'),
365+
),
366+
),
367+
);
368+
});
369+
327370
test('@TargetIdProperty ToOne annotation', () async {
328371
final source = r'''
329372
library example;
@@ -368,7 +411,7 @@ void main() {
368411
''';
369412

370413
final testEnv = GeneratorTestEnv();
371-
final result = await testEnv.run(source, expectNoOutput: true);
414+
final result = await testEnv.run(source, ignoreOutput: true);
372415

373416
expect(result.builderResult.succeeded, false);
374417
expect(
@@ -403,7 +446,7 @@ void main() {
403446
''';
404447

405448
final testEnv = GeneratorTestEnv();
406-
final result = await testEnv.run(source, expectNoOutput: true);
449+
final result = await testEnv.run(source, ignoreOutput: true);
407450

408451
expect(result.builderResult.succeeded, false);
409452
expect(

generator/test/generator_test_env.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class GeneratorTestEnv {
3737

3838
Future<GeneratorTestResult> run(
3939
String source, {
40-
bool expectNoOutput = false,
40+
bool ignoreOutput = false,
4141
}) async {
4242
final library = "example";
4343
// Enable resolving imports (imported packages must be a dependency of this package)
@@ -66,7 +66,7 @@ class GeneratorTestEnv {
6666
[resolver, codeBuilder],
6767
sourceAssets,
6868
readerWriter: readerWriter,
69-
outputs: expectNoOutput ? {} : expectedOutputs,
69+
outputs: ignoreOutput ? null : expectedOutputs,
7070
onLog: (record) {
7171
// Setting onLog overwrites the useful default logger set by
7272
// testBuilders, so reimplement it
@@ -76,7 +76,7 @@ class GeneratorTestEnv {
7676
},
7777
);
7878

79-
if (!expectNoOutput) {
79+
if (!ignoreOutput) {
8080
// Assert generator model
8181
final modelFile = File(path.join("lib", config.jsonFile));
8282
final jsonModel = await _readModelFile(modelFile);

0 commit comments

Comments
 (0)