Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

throw error on primary key set #253

Merged
merged 11 commits into from
Feb 14, 2022
4 changes: 2 additions & 2 deletions .github/workflows/realm-generator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ on:
- .github/workflows/realm-generator.yml

jobs:
Generator_CI:
CI:
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest, macos-latest] # windows is not tested ue to bug in how error messages are rendered
os: [ubuntu-latest, macos-latest] # windows is not tested due to bug in how error messages are rendered
channel: [stable, beta]

defaults:
Expand Down
9 changes: 0 additions & 9 deletions generator/lib/src/field_element_ex.dart
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,6 @@ extension FieldElementEx on FieldElement {
} else {
// Validate collections
if (type.isRealmCollection) {
if (!isFinal) {
throw RealmInvalidGenerationSourceError(
'Realm collection field must be final',
primarySpan: span,
primaryLabel: 'is not final',
todo: "Add a final keyword to the definition of '$displayName'",
element: this,
);
}
if (type.isNullable) {
throw RealmInvalidGenerationSourceError(
'Realm collections cannot be nullable',
Expand Down
7 changes: 5 additions & 2 deletions generator/lib/src/realm_field_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class RealmFieldInfo {
DartType get type => fieldElement.type;

bool get isFinal => fieldElement.isFinal;
bool get isRealmCollection => fieldElement.type.isRealmCollection;
bool get isLate => fieldElement.isLate;
bool get hasDefaultValue => fieldElement.hasInitializer;
bool get optional => type.isNullable;
Expand All @@ -60,11 +61,13 @@ class RealmFieldInfo {
Iterable<String> toCode() sync* {
yield '@override';
yield "$typeName get $name => RealmObject.get<$basicTypeName>(this, '$realmName') as $typeName;";
if (!isFinal) {
bool generateSetter = !isFinal && !primaryKey && !isRealmCollection;
if (generateSetter) {
yield '@override';
yield "set $name(${typeName != typeModelName ? 'covariant ' : ''}$typeName value) => RealmObject.set(this, '$realmName', value);";
} else {
if (isLate) { // we still need to override setter on late final, but just throw error!
bool generateThrowError = isLate || primaryKey || isRealmCollection;
if (generateThrowError) { // we still need to override setter on late final, but just throw error!
blagoev marked this conversation as resolved.
Show resolved Hide resolved
yield '@override';
yield "set $name(${typeName != typeModelName ? 'covariant ' : ''}$typeName value) => throw RealmUnsupportedSetError();";
}
Expand Down
5 changes: 1 addition & 4 deletions generator/lib/src/realm_model_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,7 @@ class RealmModelInfo {
}

yield* allExceptCollections.map((f) {
if (f.isFinal) {
return "RealmObject.set(this, '${f.name}', ${f.name});"; // since no setter will be created!
}
return 'this.${f.name} = ${f.name};'; // defer to generated setter
return "RealmObject.set(this, '${f.name}', ${f.name});";
desistefanova marked this conversation as resolved.
Show resolved Hide resolved
});

yield* collections.map((c) {
Expand Down
95 changes: 27 additions & 68 deletions generator/test/generator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class _Foo {
@RealmModel()
class _Bar {
@PrimaryKey()
late final String id;
late String id;
late bool aBool, another;
var data = Uint8List(16);
// late RealmAny any; // not supported yet
Expand All @@ -91,9 +91,9 @@ class _Bar {
// late Uuid uuid; // not supported yet
@Ignored()
var theMeaningOfEverything = 42;
final list = [0]; // list of ints with default value
// late final Set<int> set; // not supported yet
// final map = <String, int>{}; // not supported yet
list = [0]; // list of ints with default value
// late Set<int> set; // not supported yet
// map = <String, int>{}; // not supported yet

@Indexed()
String? anOptionalString;
Expand Down Expand Up @@ -241,7 +241,7 @@ part 'test.g.dart';
class _Questionable {
@PrimaryKey()
@Indexed()
late final int primartKeysAreAlwaysIndexed;
late int primartKeysAreAlwaysIndexed;
}'''
},
reader: await PackageAssetReader.currentIsolate(),
Expand All @@ -261,7 +261,7 @@ class _Questionable {
' ╷\n'
'7 │ @PrimaryKey()\n'
'8 │ @Indexed()\n'
'9 │ late final int primartKeysAreAlwaysIndexed;\n'
'9 │ late int primartKeysAreAlwaysIndexed;\n'
' │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n'
' ╵\n'
'Remove either the @Indexed or @PrimaryKey annotation from \'primartKeysAreAlwaysIndexed\'.\n'
Expand Down Expand Up @@ -361,15 +361,15 @@ part 'test.g.dart';
@RealmModel()
class _Bad {
@PrimaryKey()
late final int first;
late int first;

@PrimaryKey()
late final String second;
late String second;

late final String another;
late String another;

@PrimaryKey()
late final String third;
late String third;
}
'''
},
Expand All @@ -386,15 +386,15 @@ class _Bad {
'6 │ class _Bad {\n'
' │ ━━━━ in realm model for \'Bad\'\n'
'7 │ @PrimaryKey()\n'
'8 │ late final int first;\n'
'8 │ late int first;\n'
' │ ━━━━━ \n'
'... │\n'
'10 │ @PrimaryKey()\n'
'11 │ late final String second;\n'
'11 │ late String second;\n'
' │ ^^^^^^ second primary key\n'
'... │\n'
'15 │ @PrimaryKey()\n'
'16 │ late final String third;\n'
'16 │ late String third;\n'
' │ ━━━━━ \n'
' ╵\n'
'Avoid duplicated @PrimaryKey() on fields \'first\', \'second\', \'third\'\n'
Expand Down Expand Up @@ -531,7 +531,7 @@ class _Bad {
@PrimaryKey()
@MapTo('key')
@PrimaryKey()
late final int id;
late int id;
}
'''
},
Expand All @@ -552,7 +552,7 @@ class _Bad {
'... │\n'
'9 │ @PrimaryKey()\n'
' │ ^^^^^^^^^^^^^ duplicated annotation\n'
'10 │ late final int id;\n'
'10 │ late int id;\n'
' ╵\n'
'Remove all duplicated @PrimaryKey() annotations.\n'
'',
Expand All @@ -575,7 +575,7 @@ class Base {}
@RealmModel()
class _Bad extends Base {
@PrimaryKey()
late final int id;
late int id;
}
'''
},
Expand Down Expand Up @@ -609,7 +609,7 @@ part 'test.g.dart';
@RealmModel()
class _Bad {
@PrimaryKey()
late final int id;
late int id;

_Bad(this.id);
}
Expand Down Expand Up @@ -637,47 +637,6 @@ class _Bad {
);
});

test('non-final list', () async {
await expectLater(
() async => await testBuilder(
generateRealmObjects(),
{
'pkg|lib/src/test.dart': r'''
import 'package:realm_common/realm_common.dart';

part 'test.g.dart';

@RealmModel()
class _Bad {
@PrimaryKey()
late final int id;

List<int> wrong;
}
'''
},
reader: await PackageAssetReader.currentIsolate(),
),
throwsA(isA<RealmInvalidGenerationSourceError>().having(
(e) => e.format(),
'format()',
'Realm collection field must be final\n'
'\n'
'in: package:pkg/src/test.dart:10:13\n'
' ╷\n'
'5 │ @RealmModel()\n'
'6 │ class _Bad { \n'
' │ ━━━━ in realm model for \'Bad\'\n'
'... │\n'
'10 │ List<int> wrong;\n'
' │ ^^^^^ is not final\n'
' ╵\n'
'Add a final keyword to the definition of \'wrong\'\n'
'',
)),
);
});

test('nullable list', () async {
await expectLater(
() async => await testBuilder(
Expand All @@ -691,9 +650,9 @@ part 'test.g.dart';
@RealmModel()
class _Bad {
@PrimaryKey()
late final int id;
late int id;

final List<int>? wrong;
List<int>? wrong;
}
'''
},
Expand All @@ -710,7 +669,7 @@ class _Bad {
'6 │ class _Bad { \n'
' │ ━━━━ in realm model for \'Bad\'\n'
'... │\n'
'10 │ final List<int>? wrong;\n'
'10 │ List<int>? wrong;\n'
' │ ^^^^^^^^^^ is nullable\n'
' ╵',
)),
Expand All @@ -733,10 +692,10 @@ class _Other {}
@RealmModel()
class _Bad {
@PrimaryKey()
late final int id;
late int id;

final List<int?> okay;
final List<_Other?> wrong;
late List<int?> okay;
late List<_Other?> wrong;
}
'''
},
Expand All @@ -753,7 +712,7 @@ class _Bad {
'9 │ class _Bad { \n'
' │ ━━━━ in realm model for \'Bad\'\n'
'... │\n'
'14 │ final List<_Other?> wrong;\n'
'14 │ late List<_Other?> wrong;\n'
' │ ^^^^^^^^^^^^^ which has a nullable realm object element type\n'
' ╵\n'
'Ensure element type is non-nullable\n'
Expand All @@ -778,7 +737,7 @@ class _Other {}
@RealmModel()
class _Bad {
@PrimaryKey()
late final int id;
late int id;

late _Other wrong;
}
Expand Down Expand Up @@ -945,7 +904,7 @@ part 'test.g.dart';
@MapTo('Bad')
class _Foo {
@PrimaryKey()
late final bool bad;
late bool bad;
}
'''
},
Expand All @@ -963,7 +922,7 @@ class _Foo {
'7 │ class _Foo {\n'
' │ ━━━━ in realm model for \'Bad\'\n'
'8 │ @PrimaryKey()\n'
'9 │ late final bool bad;\n'
'9 │ late bool bad;\n'
' │ ^^^^ bool is not an indexable type\n'
' ╵\n'
'Change the type of \'bad\', or remove the @PrimaryKey() annotation\n'
Expand Down
4 changes: 2 additions & 2 deletions generator/test/good_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ part 'test.g.dart';
@RealmModel()
class _Person {
@PrimaryKey()
late final String name;
late String name;
}''',
},
outputs: {
Expand Down Expand Up @@ -118,7 +118,7 @@ part 'test.g.dart';

@RealmModel()
class _Person {
late final List<_Person> children;
late List<_Person> children;
}''',
},
outputs: {
Expand Down