44
55import 'package:analyzer/dart/element/element2.dart' ;
66import 'package:build/build.dart' ;
7+ import 'package:collection/collection.dart' ;
78import 'package:source_gen/source_gen.dart' ;
89
910import '../type_helper.dart' ;
@@ -48,13 +49,25 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
4849 );
4950 }
5051
51- final sealedSuperClassesOrEmpty = sealedSuperClasses (element);
52+ final sealedSupersAndConfigs = sealedSuperClasses (element).map (
53+ (superClass) => (
54+ classElement: superClass,
55+ config: jsonSerializableConfig (superClass, _generator),
56+ ),
57+ );
5258
53- final sealedDiscriminators = sealedSuperClassesOrEmpty
54- .map ((sealedClass) => jsonSerializableConfig (sealedClass, _generator))
55- .map ((config) => config? .unionDiscriminator);
59+ if (sealedSupersAndConfigs.isNotEmpty &&
60+ sealedSupersAndConfigs.any ((e) => e.config == null )) {
61+ throw InvalidGenerationSourceError (
62+ 'The class `${element .displayName }` is annotated '
63+ 'with `JsonSerializable` but its superclass is not annotated '
64+ 'with `JsonSerializable`.' ,
65+ todo: 'Add `@JsonSerializable` annotation to the sealed class.' ,
66+ element: element,
67+ );
68+ }
5669
57- if ((sealedSuperClassesOrEmpty .isNotEmpty || element.isSealed) &&
70+ if ((sealedSupersAndConfigs .isNotEmpty || element.isSealed) &&
5871 config.genericArgumentFactories) {
5972 throw InvalidGenerationSourceError (
6073 'The class `${element .displayName }` is annotated '
@@ -68,32 +81,43 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
6881 );
6982 }
7083
84+ if (sealedSupersAndConfigs.firstWhereOrNull (
85+ (e) => e.config? .unionDiscriminator == config.unionDiscriminator,
86+ )
87+ case final conflictingSuper? when element.isSealed) {
88+ throw InvalidGenerationSource (
89+ 'The classes `${conflictingSuper .classElement .displayName }` and '
90+ '${element .displayName } are nested sealed classes, but they have '
91+ 'the same discriminator ${config .unionDiscriminator }.' ,
92+ todo:
93+ 'Rename one of the discriminators with `unionDiscriminator` '
94+ 'field of `@JsonSerializable`.' ,
95+ );
96+ }
97+
98+ if (sealedSupersAndConfigs.firstWhereOrNull (
99+ (e) => e.config? .createToJson != config.createToJson,
100+ )
101+ case final diffSuper? ) {
102+ throw InvalidGenerationSourceError (
103+ 'The class `${diffSuper .classElement .displayName }` is sealed but its '
104+ 'subclass `${element .displayName }` has a different '
105+ '`createToJson` option than the base class.' ,
106+ element: element,
107+ );
108+ }
109+
71110 if (element.isSealed) {
72- if (sealedDiscriminators.contains (config.unionDiscriminator)) {
73- throw InvalidGenerationSource (
74- 'Nested sealed classes cannot have the same discriminator.' ,
75- todo:
76- 'Rename one of the discriminators with `unionDiscriminator` '
77- 'field in `@JsonSerializable`.' ,
78- );
79- }
80- sealedClassImplementations (element).forEach ((impl) {
81- final annotationConfig = jsonSerializableConfig (impl, _generator);
111+ sealedSubClasses (element).forEach ((sub) {
112+ final annotationConfig = jsonSerializableConfig (sub, _generator);
82113
83114 if (annotationConfig == null ) {
84115 throw InvalidGenerationSourceError (
85116 'The class `${element .displayName }` is sealed but its '
86- 'implementation `${impl .displayName }` is not annotated with '
117+ 'subclass `${sub .displayName }` is not annotated with '
87118 '`JsonSerializable`.' ,
88- todo: 'Add `@JsonSerializable` annotation to ${impl .displayName }.' ,
89- );
90- }
91-
92- if (annotationConfig.createToJson != config.createToJson) {
93- throw InvalidGenerationSourceError (
94- 'The class `${element .displayName }` is sealed but its '
95- 'implementation `${impl .displayName }` has a different '
96- '`createToJson` option than the base class.' ,
119+ todo: 'Add `@JsonSerializable` annotation to ${sub .displayName }.' ,
120+ element: sub,
97121 );
98122 }
99123 });
@@ -166,7 +190,9 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
166190 ..fold (< String > {}, (Set <String > set , fe) {
167191 final jsonKey = nameAccess (fe);
168192
169- if (sealedDiscriminators.contains (jsonKey)) {
193+ if (sealedSupersAndConfigs.any (
194+ (e) => e.config? .unionDiscriminator == jsonKey,
195+ )) {
170196 throw InvalidGenerationSourceError (
171197 'The JSON key "$jsonKey " is conflicting with the discriminator '
172198 'of sealed superclass ' ,
0 commit comments