44
55import 'package:analyzer/dart/element/element.dart' ;
66import 'package:build/build.dart' ;
7+ import 'package:collection/collection.dart' ;
78import 'package:source_gen/source_gen.dart' ;
89
910import '../type_helper.dart' ;
@@ -51,13 +52,25 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
5152 );
5253 }
5354
54- final sealedSuperClassesOrEmpty = sealedSuperClasses (element);
55+ final sealedSupersAndConfigs = sealedSuperClasses (element).map (
56+ (superClass) => (
57+ classElement: superClass,
58+ config: jsonSerializableConfig (superClass, _generator),
59+ ),
60+ );
5561
56- final sealedDiscriminators = sealedSuperClassesOrEmpty
57- .map ((sealedClass) => jsonSerializableConfig (sealedClass, _generator))
58- .map ((config) => config? .unionDiscriminator);
62+ if (sealedSupersAndConfigs.isNotEmpty &&
63+ sealedSupersAndConfigs.any ((e) => e.config == null )) {
64+ throw InvalidGenerationSourceError (
65+ 'The class `${element .displayName }` is annotated '
66+ 'with `JsonSerializable` but its superclass is not annotated '
67+ 'with `JsonSerializable`.' ,
68+ todo: 'Add `@JsonSerializable` annotation to the sealed class.' ,
69+ element: element,
70+ );
71+ }
5972
60- if ((sealedSuperClassesOrEmpty .isNotEmpty || element.isSealed) &&
73+ if ((sealedSupersAndConfigs .isNotEmpty || element.isSealed) &&
6174 config.genericArgumentFactories) {
6275 throw InvalidGenerationSourceError (
6376 'The class `${element .displayName }` is annotated '
@@ -70,31 +83,42 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
7083 );
7184 }
7285
86+ if (sealedSupersAndConfigs.firstWhereOrNull (
87+ (e) => e.config? .unionDiscriminator == config.unionDiscriminator,
88+ )
89+ case final conflictingSuper? when element.isSealed) {
90+ throw InvalidGenerationSource (
91+ 'The classes `${conflictingSuper .classElement .displayName }` and '
92+ '${element .displayName } are nested sealed classes, but they have '
93+ 'the same discriminator ${config .unionDiscriminator }.' ,
94+ todo: 'Rename one of the discriminators with `unionDiscriminator` '
95+ 'field of `@JsonSerializable`.' ,
96+ );
97+ }
98+
99+ if (sealedSupersAndConfigs.firstWhereOrNull (
100+ (e) => e.config? .createToJson != config.createToJson,
101+ )
102+ case final diffSuper? ) {
103+ throw InvalidGenerationSourceError (
104+ 'The class `${diffSuper .classElement .displayName }` is sealed but its '
105+ 'subclass `${element .displayName }` has a different '
106+ '`createToJson` option than the base class.' ,
107+ element: element,
108+ );
109+ }
110+
73111 if (element.isSealed) {
74- if (sealedDiscriminators.contains (config.unionDiscriminator)) {
75- throw InvalidGenerationSource (
76- 'Nested sealed classes cannot have the same discriminator.' ,
77- todo: 'Rename one of the discriminators with `unionDiscriminator` '
78- 'field in `@JsonSerializable`.' ,
79- );
80- }
81- sealedClassImplementations (element).forEach ((impl) {
82- final annotationConfig = jsonSerializableConfig (impl, _generator);
112+ sealedSubClasses (element).forEach ((sub) {
113+ final annotationConfig = jsonSerializableConfig (sub, _generator);
83114
84115 if (annotationConfig == null ) {
85116 throw InvalidGenerationSourceError (
86117 'The class `${element .displayName }` is sealed but its '
87- 'implementation `${impl .displayName }` is not annotated with '
118+ 'subclass `${sub .displayName }` is not annotated with '
88119 '`JsonSerializable`.' ,
89- todo: 'Add `@JsonSerializable` annotation to ${impl .displayName }.' ,
90- );
91- }
92-
93- if (annotationConfig.createToJson != config.createToJson) {
94- throw InvalidGenerationSourceError (
95- 'The class `${element .displayName }` is sealed but its '
96- 'implementation `${impl .displayName }` has a different '
97- '`createToJson` option than the base class.' ,
120+ todo: 'Add `@JsonSerializable` annotation to ${sub .displayName }.' ,
121+ element: sub,
98122 );
99123 }
100124 });
@@ -168,7 +192,8 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
168192 (Set <String > set , fe) {
169193 final jsonKey = nameAccess (fe);
170194
171- if (sealedDiscriminators.contains (jsonKey)) {
195+ if (sealedSupersAndConfigs
196+ .any ((e) => e.config? .unionDiscriminator == jsonKey)) {
172197 throw InvalidGenerationSourceError (
173198 'The JSON key "$jsonKey " is conflicting with the discriminator '
174199 'of sealed superclass ' ,
0 commit comments