Skip to content

Commit 8969539

Browse files
committed
test: add tests for new features
1 parent 428c276 commit 8969539

9 files changed

+1338
-11
lines changed

json_serializable/lib/src/generator_helper.dart

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
5656
),
5757
);
5858

59-
if (sealedSupersAndConfigs.isNotEmpty &&
60-
sealedSupersAndConfigs.any((e) => e.config == null)) {
59+
if (sealedSupersAndConfigs.firstWhereOrNull((e) => e.config == null)
60+
case final notAnnotated? when sealedSupersAndConfigs.isNotEmpty) {
6161
throw InvalidGenerationSourceError(
6262
'The class `${element.displayName}` is annotated '
63-
'with `JsonSerializable` but its superclass is not annotated '
63+
'with `JsonSerializable` but its sealed superclass '
64+
'`${notAnnotated.classElement.displayName}` is not annotated '
6465
'with `JsonSerializable`.',
6566
todo: 'Add `@JsonSerializable` annotation to the sealed class.',
6667
element: element,
@@ -87,11 +88,12 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
8788
case final conflictingSuper? when element.isSealed) {
8889
throw InvalidGenerationSource(
8990
'The classes `${conflictingSuper.classElement.displayName}` and '
90-
'${element.displayName} are nested sealed classes, but they have '
91-
'the same discriminator ${config.unionDiscriminator}.',
91+
'`${element.displayName}` are nested sealed classes, but they have '
92+
'the same discriminator `${config.unionDiscriminator}`.',
9293
todo:
9394
'Rename one of the discriminators with `unionDiscriminator` '
9495
'field of `@JsonSerializable`.',
96+
element: element,
9597
);
9698
}
9799

@@ -190,12 +192,13 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
190192
..fold(<String>{}, (Set<String> set, fe) {
191193
final jsonKey = nameAccess(fe);
192194

193-
if (sealedSupersAndConfigs.any(
194-
(e) => e.config?.unionDiscriminator == jsonKey,
195-
)) {
195+
if (sealedSupersAndConfigs.firstWhereOrNull(
196+
(e) => e.config?.unionDiscriminator == jsonKey,
197+
)
198+
case final conflict?) {
196199
throw InvalidGenerationSourceError(
197-
'The JSON key "$jsonKey" is conflicting with the discriminator '
198-
'of sealed superclass ',
200+
'The JSON key `$jsonKey` is conflicting with the discriminator '
201+
'of sealed superclass `${conflict.classElement.displayName}`',
199202
todo: 'Rename the field or the discriminator.',
200203
element: fe,
201204
);

json_serializable/test/json_serializable_test.dart

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,72 @@ const _expectedAnnotatedTests = {
122122
'Reproduce869NullableGenericTypeWithDefault',
123123
'SameCtorAndJsonKeyDefaultValue',
124124
'SetSupport',
125+
'SubFourMultipleImpl',
126+
'SubNestedOneOne',
127+
'SubNestedOneTwo',
128+
'SubNestedTwoOne',
129+
'SubNestedTwoTwo',
130+
'SubOneMultipleImpl',
131+
'SubOneSimpleSealedClass',
132+
'SubOneSimpleSealedClassWithChangedDiscriminator',
133+
'SubOneSimpleSealedClassWithChangedDiscriminatorAndUnionRename',
134+
'SubOneSimpleSealedClassWithChangedUnionRename',
135+
'SubSimpleSealedClassWithoutToJson',
136+
'SubThreeMultipleImpl',
137+
'SubTwoMultipleImpl',
138+
'SubTwoSimpleSealedClass',
139+
'SubTwoSimpleSealedClassWithChangedDiscriminator',
140+
'SubTwoSimpleSealedClassWithChangedDiscriminatorAndUnionRename',
141+
'SubTwoSimpleSealedClassWithChangedUnionRename',
125142
'SubType',
126143
'SubTypeWithAnnotatedFieldOverrideExtends',
127144
'SubTypeWithAnnotatedFieldOverrideExtendsWithOverrides',
128145
'SubTypeWithAnnotatedFieldOverrideImplements',
146+
'SubUnionRenameKebab',
147+
'SubUnionRenameNone',
148+
'SubUnionRenamePascal',
149+
'SubUnionRenameScreamingSnake',
150+
'SubUnionRenameSnake',
151+
'SubWithConflictingDiscriminatorWithDefaultNameExt',
152+
'SubWithConflictingDiscriminatorWithDefaultNameImpl',
153+
'SubWithConflictingDiscriminatorWithFieldRenameExt',
154+
'SubWithConflictingDiscriminatorWithFieldRenameImpl',
155+
'SubWithConflictingDiscriminatorWithJsonKeyExt',
156+
'SubWithConflictingDiscriminatorWithJsonKeyImpl',
157+
'SubWithSubAndSuperGenericArgumentFactoriesExt',
158+
'SubWithSubAndSuperGenericArgumentFactoriesImpl',
159+
'SubWithSubGenericArgumentFactoriesExt',
160+
'SubWithSubGenericArgumentFactoriesImpl',
161+
'SubWithToJsonAndSuperWithoutToJsonExt',
162+
'SubWithToJsonAndSuperWithoutToJsonImpl',
163+
'SubWithoutSuperJsonSerializableAnnotationExt',
164+
'SubWithoutSuperJsonSerializableAnnotationImpl',
165+
'SubWithoutToJsonAndSuperWithToJsonExt',
166+
'SubWithoutToJsonAndSuperWithToJsonImpl',
129167
'SubclassedJsonKey',
168+
'SuperMultipleImplOne',
169+
'SuperMultipleImplTwo',
170+
'SuperNestedOneOne',
171+
'SuperNestedOneTwo',
172+
'SuperNestedTwoOne',
173+
'SuperNestedTwoTwo',
174+
'SuperSimpleSealedClass',
175+
'SuperSimpleSealedClassWithChangedDiscriminator',
176+
'SuperSimpleSealedClassWithChangedDiscriminatorAndUnionRename',
177+
'SuperSimpleSealedClassWithChangedUnionRename',
178+
'SuperSimpleSealedClassWithoutToJson',
179+
'SuperSuperNestedOne',
180+
'SuperSuperNestedTwo',
181+
'SuperSuperSuperNested',
182+
'SuperUnionRenameKebab',
183+
'SuperUnionRenameNone',
184+
'SuperUnionRenamePascal',
185+
'SuperUnionRenameScreamingSnake',
186+
'SuperUnionRenameSnake',
187+
'SuperWithConflictingNestedDiscriminator',
188+
'SuperWithGenericArgumentFactories',
189+
'SuperWithSubExtWithoutJsonSerializableAnnotation',
190+
'SuperWithSubImplWithoutJsonSerializableAnnotation',
130191
'TearOffFromJsonClass',
131192
'ToJsonNullableFalseIncludeIfNullFalse',
132193
'TypedConvertMethods',
@@ -148,5 +209,5 @@ const _expectedAnnotatedTests = {
148209
'WrongConstructorNameClass',
149210
'_BetterPrivateNames',
150211
'annotatedMethod',
151-
'theAnswer',
212+
'theAnswer'
152213
};

json_serializable/test/src/_json_serializable_test_input.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:json_annotation/json_annotation.dart';
1010
import 'package:source_gen_test/annotations.dart';
1111

1212
part 'checked_test_input.dart';
13+
part 'conflicting_discriminator_input.dart';
1314
part 'constants_copy.dart';
1415
part 'core_subclass_type_input.dart';
1516
part 'default_value_input.dart';
@@ -18,8 +19,12 @@ part 'generic_test_input.dart';
1819
part 'inheritance_test_input.dart';
1920
part 'json_converter_test_input.dart';
2021
part 'map_key_variety_test_input.dart';
22+
part 'mismatching_config_input.dart';
23+
part 'missing_annotation_input.dart';
24+
part 'sealed_test_input.dart';
2125
part 'setter_test_input.dart';
2226
part 'to_from_json_test_input.dart';
27+
part 'union_namer_input.dart';
2328
part 'unknown_enum_value_test_input.dart';
2429

2530
@ShouldThrow('`@JsonSerializable` can only be used on classes.')
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// @dart=3.8
2+
3+
part of '_json_serializable_test_input.dart';
4+
5+
@JsonSerializable(unionDiscriminator: 'this_will_conflict')
6+
sealed class SuperWithConflictingSnakeCaseDiscriminator {}
7+
8+
@ShouldThrow(
9+
'The JSON key `this_will_conflict` is conflicting with the discriminator '
10+
'of sealed superclass `SuperWithConflictingSnakeCaseDiscriminator`',
11+
todo: 'Rename the field or the discriminator.',
12+
element: 'thisWillConflict',
13+
)
14+
@JsonSerializable(fieldRename: FieldRename.snake)
15+
class SubWithConflictingDiscriminatorWithFieldRenameExt
16+
extends SuperWithConflictingSnakeCaseDiscriminator {
17+
final String thisWillConflict;
18+
19+
SubWithConflictingDiscriminatorWithFieldRenameExt({
20+
required this.thisWillConflict,
21+
});
22+
}
23+
24+
@ShouldThrow(
25+
'The JSON key `this_will_conflict` is conflicting with the discriminator '
26+
'of sealed superclass `SuperWithConflictingSnakeCaseDiscriminator`',
27+
todo: 'Rename the field or the discriminator.',
28+
element: 'thisWillConflict',
29+
)
30+
@JsonSerializable(fieldRename: FieldRename.snake)
31+
class SubWithConflictingDiscriminatorWithFieldRenameImpl
32+
implements SuperWithConflictingSnakeCaseDiscriminator {
33+
final String thisWillConflict;
34+
35+
SubWithConflictingDiscriminatorWithFieldRenameImpl({
36+
required this.thisWillConflict,
37+
});
38+
}
39+
40+
@ShouldThrow(
41+
'The JSON key `this_will_conflict` is conflicting with the discriminator '
42+
'of sealed superclass `SuperWithConflictingSnakeCaseDiscriminator`',
43+
todo: 'Rename the field or the discriminator.',
44+
element: 'conflict',
45+
)
46+
@JsonSerializable()
47+
class SubWithConflictingDiscriminatorWithJsonKeyExt
48+
extends SuperWithConflictingSnakeCaseDiscriminator {
49+
@JsonKey(name: 'this_will_conflict')
50+
final String conflict;
51+
52+
SubWithConflictingDiscriminatorWithJsonKeyExt({required this.conflict});
53+
}
54+
55+
@ShouldThrow(
56+
'The JSON key `this_will_conflict` is conflicting with the discriminator '
57+
'of sealed superclass `SuperWithConflictingSnakeCaseDiscriminator`',
58+
todo: 'Rename the field or the discriminator.',
59+
element: 'conflict',
60+
)
61+
@JsonSerializable()
62+
class SubWithConflictingDiscriminatorWithJsonKeyImpl
63+
implements SuperWithConflictingSnakeCaseDiscriminator {
64+
@JsonKey(name: 'this_will_conflict')
65+
final String conflict;
66+
67+
SubWithConflictingDiscriminatorWithJsonKeyImpl({required this.conflict});
68+
}
69+
70+
@JsonSerializable(unionDiscriminator: 'conflict')
71+
sealed class SuperWithConflictingDefaultCaseDiscriminator {}
72+
73+
@ShouldThrow(
74+
'The JSON key `conflict` is conflicting with the discriminator '
75+
'of sealed superclass `SuperWithConflictingDefaultCaseDiscriminator`',
76+
todo: 'Rename the field or the discriminator.',
77+
element: 'conflict',
78+
)
79+
@JsonSerializable()
80+
class SubWithConflictingDiscriminatorWithDefaultNameExt
81+
extends SuperWithConflictingDefaultCaseDiscriminator {
82+
final String conflict;
83+
84+
SubWithConflictingDiscriminatorWithDefaultNameExt({required this.conflict});
85+
}
86+
87+
@ShouldThrow(
88+
'The JSON key `conflict` is conflicting with the discriminator '
89+
'of sealed superclass `SuperWithConflictingDefaultCaseDiscriminator`',
90+
todo: 'Rename the field or the discriminator.',
91+
element: 'conflict',
92+
)
93+
@JsonSerializable()
94+
class SubWithConflictingDiscriminatorWithDefaultNameImpl
95+
extends SuperWithConflictingDefaultCaseDiscriminator {
96+
final String conflict;
97+
98+
SubWithConflictingDiscriminatorWithDefaultNameImpl({required this.conflict});
99+
}
100+
101+
@JsonSerializable(unionDiscriminator: 'this_will_conflict')
102+
sealed class SuperSuperSuperWithConflictingNestedDiscriminator {}
103+
104+
@JsonSerializable(unionDiscriminator: 'this_is_fine')
105+
sealed class SuperSuperWithConflictingNestedDiscriminator
106+
extends SuperSuperSuperWithConflictingNestedDiscriminator {}
107+
108+
@ShouldThrow(
109+
'The classes `SuperSuperSuperWithConflictingNestedDiscriminator` and '
110+
'`SuperWithConflictingNestedDiscriminator` are nested sealed classes, but they have '
111+
'the same discriminator `this_will_conflict`.',
112+
todo:
113+
'Rename one of the discriminators with `unionDiscriminator` '
114+
'field of `@JsonSerializable`.',
115+
element: 'SuperWithConflictingNestedDiscriminator',
116+
)
117+
@JsonSerializable(unionDiscriminator: 'this_will_conflict')
118+
sealed class SuperWithConflictingNestedDiscriminator
119+
extends SuperSuperWithConflictingNestedDiscriminator {}

json_serializable/test/src/generic_test_input.dart

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,82 @@ Map<String, dynamic> _$GenericArgumentFactoriesFlagWithoutGenericTypeToJson(
8585
)
8686
@JsonSerializable(genericArgumentFactories: true)
8787
class GenericArgumentFactoriesFlagWithoutGenericType {}
88+
89+
@ShouldThrow(
90+
'The class `SuperWithGenericArgumentFactories` is annotated '
91+
'with `JsonSerializable` field `genericArgumentFactories: true`. '
92+
'`genericArgumentFactories: true` is not supported for classes '
93+
'that are sealed or have sealed superclasses.',
94+
todo: 'Remove the `genericArgumentFactories` option or '
95+
'remove the `sealed` keyword from the class.',
96+
element: 'SuperWithGenericArgumentFactories',
97+
)
98+
@JsonSerializable(
99+
genericArgumentFactories: true,
100+
)
101+
sealed class SuperWithGenericArgumentFactories<T> {}
102+
103+
@JsonSerializable(
104+
genericArgumentFactories: false,
105+
)
106+
sealed class SuperWithoutGenericArgumentFactories {}
107+
108+
@ShouldThrow(
109+
'The class `SubWithSubGenericArgumentFactoriesExt` is annotated '
110+
'with `JsonSerializable` field `genericArgumentFactories: true`. '
111+
'`genericArgumentFactories: true` is not supported for classes '
112+
'that are sealed or have sealed superclasses.',
113+
todo: 'Remove the `genericArgumentFactories` option or '
114+
'remove the `sealed` keyword from the class.',
115+
element: 'SubWithSubGenericArgumentFactoriesExt',
116+
)
117+
@JsonSerializable(
118+
genericArgumentFactories: true,
119+
)
120+
class SubWithSubGenericArgumentFactoriesExt<T>
121+
extends SuperWithoutGenericArgumentFactories {}
122+
123+
@ShouldThrow(
124+
'The class `SubWithSubGenericArgumentFactoriesImpl` is annotated '
125+
'with `JsonSerializable` field `genericArgumentFactories: true`. '
126+
'`genericArgumentFactories: true` is not supported for classes '
127+
'that are sealed or have sealed superclasses.',
128+
todo: 'Remove the `genericArgumentFactories` option or '
129+
'remove the `sealed` keyword from the class.',
130+
element: 'SubWithSubGenericArgumentFactoriesImpl',
131+
)
132+
@JsonSerializable(
133+
genericArgumentFactories: true,
134+
)
135+
class SubWithSubGenericArgumentFactoriesImpl<T>
136+
implements SuperWithoutGenericArgumentFactories {}
137+
138+
@ShouldThrow(
139+
'The class `SubWithSubAndSuperGenericArgumentFactoriesExt` is annotated '
140+
'with `JsonSerializable` field `genericArgumentFactories: true`. '
141+
'`genericArgumentFactories: true` is not supported for classes '
142+
'that are sealed or have sealed superclasses.',
143+
todo: 'Remove the `genericArgumentFactories` option or '
144+
'remove the `sealed` keyword from the class.',
145+
element: 'SubWithSubAndSuperGenericArgumentFactoriesExt',
146+
)
147+
@JsonSerializable(
148+
genericArgumentFactories: true,
149+
)
150+
class SubWithSubAndSuperGenericArgumentFactoriesExt<T>
151+
extends SuperWithGenericArgumentFactories<T> {}
152+
153+
@ShouldThrow(
154+
'The class `SubWithSubAndSuperGenericArgumentFactoriesImpl` is annotated '
155+
'with `JsonSerializable` field `genericArgumentFactories: true`. '
156+
'`genericArgumentFactories: true` is not supported for classes '
157+
'that are sealed or have sealed superclasses.',
158+
todo: 'Remove the `genericArgumentFactories` option or '
159+
'remove the `sealed` keyword from the class.',
160+
element: 'SubWithSubAndSuperGenericArgumentFactoriesImpl',
161+
)
162+
@JsonSerializable(
163+
genericArgumentFactories: true,
164+
)
165+
class SubWithSubAndSuperGenericArgumentFactoriesImpl<T>
166+
implements SuperWithGenericArgumentFactories<T> {}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// @dart=3.8
2+
3+
part of '_json_serializable_test_input.dart';
4+
5+
@JsonSerializable(createToJson: false)
6+
sealed class SuperWithoutToJson {}
7+
8+
@JsonSerializable(createToJson: true)
9+
sealed class SuperWithToJson {}
10+
11+
@ShouldThrow(
12+
'The class `SuperWithoutToJson` is sealed but its '
13+
'subclass `SubWithToJsonAndSuperWithoutToJsonExt` has a different '
14+
'`createToJson` option than the base class.',
15+
element: 'SubWithToJsonAndSuperWithoutToJsonExt',
16+
)
17+
@JsonSerializable(createToJson: true)
18+
class SubWithToJsonAndSuperWithoutToJsonExt extends SuperWithoutToJson {}
19+
20+
@ShouldThrow(
21+
'The class `SuperWithoutToJson` is sealed but its '
22+
'subclass `SubWithToJsonAndSuperWithoutToJsonImpl` has a different '
23+
'`createToJson` option than the base class.',
24+
element: 'SubWithToJsonAndSuperWithoutToJsonImpl',
25+
)
26+
@JsonSerializable(createToJson: true)
27+
class SubWithToJsonAndSuperWithoutToJsonImpl implements SuperWithoutToJson {}
28+
29+
@ShouldThrow(
30+
'The class `SuperWithToJson` is sealed but its '
31+
'subclass `SubWithoutToJsonAndSuperWithToJsonExt` has a different '
32+
'`createToJson` option than the base class.',
33+
element: 'SubWithoutToJsonAndSuperWithToJsonExt',
34+
)
35+
@JsonSerializable(createToJson: false)
36+
class SubWithoutToJsonAndSuperWithToJsonExt extends SuperWithToJson {}
37+
38+
@ShouldThrow(
39+
'The class `SuperWithToJson` is sealed but its '
40+
'subclass `SubWithoutToJsonAndSuperWithToJsonImpl` has a different '
41+
'`createToJson` option than the base class.',
42+
element: 'SubWithoutToJsonAndSuperWithToJsonImpl',
43+
)
44+
@JsonSerializable(createToJson: false)
45+
class SubWithoutToJsonAndSuperWithToJsonImpl implements SuperWithToJson {}

0 commit comments

Comments
 (0)