From 3c847f81d7d24e7a1f77040e23dda291e9a7ada4 Mon Sep 17 00:00:00 2001 From: Christian Budde Christensen Date: Tue, 11 May 2021 09:32:42 +0100 Subject: [PATCH 1/3] feat: Improve support for inline-fragments in fragments --- lib/generator.dart | 2 +- lib/generator/data/class_definition.dart | 2 +- .../data/fragment_class_definition.dart | 4 +- lib/generator/ephemeral_data.dart | 12 +- lib/visitor/canonical_visitor.dart | 6 +- lib/visitor/generator_visitor.dart | 32 +- .../inline_fragments_on_fragments.dart | 297 ++++++++++++++++++ 7 files changed, 326 insertions(+), 29 deletions(-) create mode 100644 test/query_generator/fragments/inline_fragments_on_fragments.dart diff --git a/lib/generator.dart b/lib/generator.dart index a081d230..f8763533 100644 --- a/lib/generator.dart +++ b/lib/generator.dart @@ -329,7 +329,7 @@ Make sure your query is correct and your schema is updated.'''); nextFieldName: nextFieldName, nextClassName: ClassName(name: nextType.name.value), alias: fieldAlias, - ofUnion: Nullable(null), + ofUnion: Nullable(null), ), ); } diff --git a/lib/generator/data/class_definition.dart b/lib/generator/data/class_definition.dart index e8c73a88..89671731 100644 --- a/lib/generator/data/class_definition.dart +++ b/lib/generator/data/class_definition.dart @@ -11,7 +11,7 @@ class ClassDefinition extends Definition with DataPrinter { final Iterable properties; /// The type this class extends from, or [null]. - final Name? extension; + final ClassName? extension; /// The types this class implements. final Iterable implementations; diff --git a/lib/generator/data/fragment_class_definition.dart b/lib/generator/data/fragment_class_definition.dart index 68e72c07..f282f6ba 100644 --- a/lib/generator/data/fragment_class_definition.dart +++ b/lib/generator/data/fragment_class_definition.dart @@ -15,8 +15,8 @@ class FragmentClassDefinition extends Definition with DataPrinter { /// Instantiate a fragment class definition. FragmentClassDefinition({ required this.name, - required this.properties, - }) : assert(hasValue(name) && hasValue(properties)), + this.properties = const [], + }) : assert(hasValue(name.name)), super(name: name); @override diff --git a/lib/generator/ephemeral_data.dart b/lib/generator/ephemeral_data.dart index 6734b60a..b0c307f9 100644 --- a/lib/generator/ephemeral_data.dart +++ b/lib/generator/ephemeral_data.dart @@ -74,7 +74,7 @@ class Context { final Name? currentFieldName; /// If part of an union type, which [TypeDefinitionNode] it represents. - final TypeDefinitionNode? ofUnion; + final Name? ofUnion; /// A string to replace the current class name. final Name? alias; @@ -114,7 +114,7 @@ class Context { required TypeDefinitionNode nextType, required Name? nextFieldName, required Name? nextClassName, - Nullable? ofUnion, + Nullable? ofUnion, Name? alias, List? generatedClasses, List? inputsClasses, @@ -143,7 +143,7 @@ class Context { Name? nextFieldName, Name? nextClassName, Name? alias, - Nullable? ofUnion, + Nullable? ofUnion, List? generatedClasses, List? inputsClasses, List? fragments, @@ -203,7 +203,7 @@ class Context { Name? nextFieldName, Name? nextClassName, Name? alias, - Nullable? ofUnion, + Nullable? ofUnion, List? generatedClasses, List? inputsClasses, List? fragments, @@ -261,7 +261,7 @@ class Context { /// Returns a copy of this context, with the same type, but on the first path. Context sameTypeWithNoPath({ Name? alias, - Nullable? ofUnion, + Nullable? ofUnion, List? generatedClasses, List? inputsClasses, List? fragments, @@ -289,7 +289,7 @@ class Context { required TypeDefinitionNode nextType, required Name nextFieldName, required Name nextClassName, - Nullable? ofUnion, + Nullable? ofUnion, Name? alias, List? generatedClasses, List? inputsClasses, diff --git a/lib/visitor/canonical_visitor.dart b/lib/visitor/canonical_visitor.dart index 73646ebb..12fa9221 100644 --- a/lib/visitor/canonical_visitor.dart +++ b/lib/visitor/canonical_visitor.dart @@ -29,7 +29,7 @@ class CanonicalVisitor extends RecursiveVisitor { final nextContext = context.sameTypeWithNoPath( alias: enumName, - ofUnion: Nullable(null), + ofUnion: Nullable(null), ); logFn(context, nextContext.align, '-> Enum'); @@ -53,7 +53,7 @@ class CanonicalVisitor extends RecursiveVisitor { final name = ClassName(name: node.name.value); final nextContext = context.sameTypeWithNoPath( alias: name, - ofUnion: Nullable(null), + ofUnion: Nullable(null), ); logFn(context, nextContext.align, '-> Input class'); @@ -69,7 +69,7 @@ class CanonicalVisitor extends RecursiveVisitor { nextType: node, nextClassName: ClassName(name: nextType.name.value), nextFieldName: ClassName(name: i.name.value), - ofUnion: Nullable(null), + ofUnion: Nullable(null), ), markAsUsed: false, ); diff --git a/lib/visitor/generator_visitor.dart b/lib/visitor/generator_visitor.dart index 2f82d917..6f1760a4 100644 --- a/lib/visitor/generator_visitor.dart +++ b/lib/visitor/generator_visitor.dart @@ -52,22 +52,20 @@ class GeneratorVisitor extends RecursiveVisitor { possibleTypes.addAll(Map.fromIterables(keys, values)); } - final partOfUnion = nextContext.ofUnion != null; - if (partOfUnion) {} - final name = ClassName.fromPath(path: nextContext.fullPathName()); logFn(context, nextContext.align, '└ ${nextContext.path}[${nextContext.currentType!.name.value}][${nextContext.currentClassName} ${nextContext.currentFieldName}] (${nextContext.alias ?? ''})'); logFn(context, nextContext.align, '<- Generated class ${name.namePrintable}.'); - + final ofUnion = context.ofUnion; + if (ofUnion is FragmentName) { + _mixins.add(ofUnion); + } nextContext.generatedClasses.add(ClassDefinition( name: name, properties: _classProperties, mixins: _mixins, - extension: partOfUnion - ? ClassName.fromPath(path: nextContext.rollbackPath().fullPathName()) - : null, + extension: ofUnion is ClassName ? ofUnion : null, factoryPossibilities: possibleTypes, )); } @@ -94,15 +92,16 @@ class GeneratorVisitor extends RecursiveVisitor { void visitInlineFragmentNode(InlineFragmentNode node) { logFn(context, context.align + 1, '${context.path}: ... on ${node.typeCondition!.on.name.value}'); + final ofUnion = context.ofUnion ?? + ClassName.fromPath(path: context.rollbackPath().fullPathName()); final nextType = gql.getTypeByName(context.schema, node.typeCondition!.on); - if (nextType.name.value == context.currentType!.name.value) { final visitor = GeneratorVisitor( context: context.nextTypeWithSamePath( nextType: nextType, nextClassName: null, nextFieldName: null, - ofUnion: Nullable(context.currentType), + ofUnion: Nullable(ofUnion), inputsClasses: [], fragments: [], ), @@ -114,7 +113,7 @@ class GeneratorVisitor extends RecursiveVisitor { nextType: nextType, nextClassName: ClassName(name: nextType.name.value), nextFieldName: ClassPropertyName(name: nextType.name.value), - ofUnion: Nullable(context.currentType), + ofUnion: Nullable(ofUnion), inputsClasses: [], fragments: [], ), @@ -149,7 +148,7 @@ class GeneratorVisitor extends RecursiveVisitor { nextType: leafType, nextClassName: ClassName(name: leafType.name.value), nextFieldName: ClassName(name: node.variable.name.value), - ofUnion: Nullable(null), + ofUnion: Nullable(null), ) .fullPathName(); @@ -234,7 +233,7 @@ class GeneratorVisitor extends RecursiveVisitor { path: context .sameTypeWithNoPath( alias: FragmentName(name: node.name.value), - ofUnion: Nullable(null), + ofUnion: Nullable(null), ) .fullPathName()); @@ -242,7 +241,7 @@ class GeneratorVisitor extends RecursiveVisitor { context: context.sameTypeWithNextPath( alias: fragmentName, generatedClasses: [], - ofUnion: Nullable(null), + ofUnion: Nullable(null), log: false, ), ); @@ -260,7 +259,7 @@ class GeneratorVisitor extends RecursiveVisitor { final partName = FragmentName(name: node.name.value); final nextContext = context.sameTypeWithNoPath( alias: partName, - ofUnion: Nullable(null), + ofUnion: Nullable(null), ); logFn(context, nextContext.align, '-> Fragment'); @@ -270,6 +269,8 @@ class GeneratorVisitor extends RecursiveVisitor { final nextType = gql.getTypeByName(nextContext.schema, node.typeCondition.on); + final fragmentName = + FragmentName.fromPath(path: nextContext.fullPathName()); final visitorContext = Context( schema: context.schema, @@ -285,6 +286,7 @@ class GeneratorVisitor extends RecursiveVisitor { fragments: [], usedEnums: nextContext.usedEnums, usedInputObjects: nextContext.usedInputObjects, + ofUnion: fragmentName, ); final visitor = GeneratorVisitor(context: visitorContext); @@ -298,8 +300,6 @@ class GeneratorVisitor extends RecursiveVisitor { .expand((a) => a) .mergeDuplicatesBy((a) => a.name, (a, b) => a); - final fragmentName = - FragmentName.fromPath(path: nextContext.fullPathName()); logFn(context, nextContext.align, '└ ${nextContext.path}[${node.name.value}]'); logFn(context, nextContext.align, diff --git a/test/query_generator/fragments/inline_fragments_on_fragments.dart b/test/query_generator/fragments/inline_fragments_on_fragments.dart new file mode 100644 index 00000000..a8a4a273 --- /dev/null +++ b/test/query_generator/fragments/inline_fragments_on_fragments.dart @@ -0,0 +1,297 @@ +import 'package:artemis/generator/data/data.dart'; +import 'package:test/test.dart'; + +import '../../helpers.dart'; + +void main() { + group('On inline fragments on fragments', () { + test( + 'Interface fragments', + () async => testGenerator( + query: r''' + fragment InterfaceFragment on InterfaceA { + s + i + ...on ImplementationA { + b + } + ...on ImplementationB { + i2 + } + } + fragment UnionFragment on UnionA { + ...on ImplementationA { + b + } + ...on ImplementationB { + s + } + + } + query some_query { + interface { + ...InterfaceFragment + } + union { + ...UnionFragment + } + } + ''', + schema: r''' + type Query { + interface: InterfaceA + union: UnionA + } + + interface InterfaceA { + s: String + i: Int + } + + union UnionA = ImplementationA | ImplementationB + + type ImplementationA implements InterfaceA { + s: String + i: Int + b: Boolean + } + type ImplementationB implements InterfaceA { + s: String + i: Int + i2: Int + } + + ''', + libraryDefinition: libraryDefinition, + generatedFile: generatedFile, + ), + ); + }); +} + +final LibraryDefinition libraryDefinition = + LibraryDefinition(basename: r'query.graphql', queries: [ + QueryDefinition( + name: QueryName(name: r'SomeQuery$_Query'), + operationName: r'some_query', + classes: [ + ClassDefinition( + name: ClassName(name: r'InterfaceFragmentMixin$_ImplementationA'), + properties: [ + ClassProperty( + type: TypeName(name: r'bool'), + name: ClassPropertyName(name: r'b'), + isResolveType: false) + ], + mixins: [FragmentName(name: r'InterfaceFragmentMixin')], + factoryPossibilities: {}, + typeNameField: ClassPropertyName(name: r'__typename'), + isInput: false), + ClassDefinition( + name: ClassName(name: r'InterfaceFragmentMixin$_ImplementationB'), + properties: [ + ClassProperty( + type: TypeName(name: r'int'), + name: ClassPropertyName(name: r'i2'), + isResolveType: false) + ], + mixins: [FragmentName(name: r'InterfaceFragmentMixin')], + factoryPossibilities: {}, + typeNameField: ClassPropertyName(name: r'__typename'), + isInput: false), + FragmentClassDefinition( + name: FragmentName(name: r'InterfaceFragmentMixin'), + properties: [ + ClassProperty( + type: TypeName(name: r'String'), + name: ClassPropertyName(name: r's'), + isResolveType: false), + ClassProperty( + type: TypeName(name: r'int'), + name: ClassPropertyName(name: r'i'), + isResolveType: false) + ]), + ClassDefinition( + name: ClassName(name: r'UnionFragmentMixin$_ImplementationA'), + properties: [ + ClassProperty( + type: TypeName(name: r'bool'), + name: ClassPropertyName(name: r'b'), + isResolveType: false) + ], + mixins: [FragmentName(name: r'UnionFragmentMixin')], + factoryPossibilities: {}, + typeNameField: ClassPropertyName(name: r'__typename'), + isInput: false), + ClassDefinition( + name: ClassName(name: r'UnionFragmentMixin$_ImplementationB'), + properties: [ + ClassProperty( + type: TypeName(name: r'String'), + name: ClassPropertyName(name: r's'), + isResolveType: false) + ], + mixins: [FragmentName(name: r'UnionFragmentMixin')], + factoryPossibilities: {}, + typeNameField: ClassPropertyName(name: r'__typename'), + isInput: false), + FragmentClassDefinition( + name: FragmentName(name: r'UnionFragmentMixin')), + ClassDefinition( + name: ClassName(name: r'SomeQuery$_Query$_InterfaceA'), + mixins: [FragmentName(name: r'InterfaceFragmentMixin')], + factoryPossibilities: {}, + typeNameField: ClassPropertyName(name: r'__typename'), + isInput: false), + ClassDefinition( + name: ClassName(name: r'SomeQuery$_Query$_UnionA'), + mixins: [FragmentName(name: r'UnionFragmentMixin')], + factoryPossibilities: {}, + typeNameField: ClassPropertyName(name: r'__typename'), + isInput: false), + ClassDefinition( + name: ClassName(name: r'SomeQuery$_Query'), + properties: [ + ClassProperty( + type: TypeName(name: r'SomeQuery$_Query$_InterfaceA'), + name: ClassPropertyName(name: r'interface'), + annotations: [r'''JsonKey(name: 'interface')'''], + isResolveType: false), + ClassProperty( + type: TypeName(name: r'SomeQuery$_Query$_UnionA'), + name: ClassPropertyName(name: r'union'), + isResolveType: false) + ], + factoryPossibilities: {}, + typeNameField: ClassPropertyName(name: r'__typename'), + isInput: false) + ], + generateHelpers: false, + suffix: r'Query') +]); + +const generatedFile = r'''// GENERATED CODE - DO NOT MODIFY BY HAND +// @dart = 2.12 + +import 'package:json_annotation/json_annotation.dart'; +import 'package:equatable/equatable.dart'; +import 'package:gql/ast.dart'; +part 'query.graphql.g.dart'; + +mixin InterfaceFragmentMixin { + String? s; + int? i; +} +mixin UnionFragmentMixin {} + +@JsonSerializable(explicitToJson: true) +class InterfaceFragmentMixin$ImplementationA extends JsonSerializable + with EquatableMixin, InterfaceFragmentMixin { + InterfaceFragmentMixin$ImplementationA(); + + factory InterfaceFragmentMixin$ImplementationA.fromJson( + Map json) => + _$InterfaceFragmentMixin$ImplementationAFromJson(json); + + bool? b; + + @override + List get props => [s, i, b]; + Map toJson() => + _$InterfaceFragmentMixin$ImplementationAToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class InterfaceFragmentMixin$ImplementationB extends JsonSerializable + with EquatableMixin, InterfaceFragmentMixin { + InterfaceFragmentMixin$ImplementationB(); + + factory InterfaceFragmentMixin$ImplementationB.fromJson( + Map json) => + _$InterfaceFragmentMixin$ImplementationBFromJson(json); + + int? i2; + + @override + List get props => [s, i, i2]; + Map toJson() => + _$InterfaceFragmentMixin$ImplementationBToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class UnionFragmentMixin$ImplementationA extends JsonSerializable + with EquatableMixin, UnionFragmentMixin { + UnionFragmentMixin$ImplementationA(); + + factory UnionFragmentMixin$ImplementationA.fromJson( + Map json) => + _$UnionFragmentMixin$ImplementationAFromJson(json); + + bool? b; + + @override + List get props => [b]; + Map toJson() => + _$UnionFragmentMixin$ImplementationAToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class UnionFragmentMixin$ImplementationB extends JsonSerializable + with EquatableMixin, UnionFragmentMixin { + UnionFragmentMixin$ImplementationB(); + + factory UnionFragmentMixin$ImplementationB.fromJson( + Map json) => + _$UnionFragmentMixin$ImplementationBFromJson(json); + + String? s; + + @override + List get props => [s]; + Map toJson() => + _$UnionFragmentMixin$ImplementationBToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class SomeQuery$Query$InterfaceA extends JsonSerializable + with EquatableMixin, InterfaceFragmentMixin { + SomeQuery$Query$InterfaceA(); + + factory SomeQuery$Query$InterfaceA.fromJson(Map json) => + _$SomeQuery$Query$InterfaceAFromJson(json); + + @override + List get props => [s, i]; + Map toJson() => _$SomeQuery$Query$InterfaceAToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class SomeQuery$Query$UnionA extends JsonSerializable + with EquatableMixin, UnionFragmentMixin { + SomeQuery$Query$UnionA(); + + factory SomeQuery$Query$UnionA.fromJson(Map json) => + _$SomeQuery$Query$UnionAFromJson(json); + + @override + List get props => []; + Map toJson() => _$SomeQuery$Query$UnionAToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class SomeQuery$Query extends JsonSerializable with EquatableMixin { + SomeQuery$Query(); + + factory SomeQuery$Query.fromJson(Map json) => + _$SomeQuery$QueryFromJson(json); + + @JsonKey(name: 'interface') + SomeQuery$Query$InterfaceA? kw$interface; + + SomeQuery$Query$UnionA? union; + + @override + List get props => [kw$interface, union]; + Map toJson() => _$SomeQuery$QueryToJson(this); +} +'''; From e9ca908a1dffa191377d4fbd1c25d9a319802730 Mon Sep 17 00:00:00 2001 From: Christian Budde Christensen Date: Tue, 11 May 2021 23:18:01 +0100 Subject: [PATCH 2/3] conf: Bump version --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6c450c4..277a0ec7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 7.0.0-beta.12 + +- support inline fragments in fragment definitions + ## 7.0.0-beta.11 - document generation fix for https://github.com/comigor/artemis/issues/307 diff --git a/pubspec.yaml b/pubspec.yaml index 59b6a44e..3eb88688 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: artemis -version: 7.0.0-beta.11 +version: 7.0.0-beta.12 description: Build dart types from GraphQL schemas and queries (using Introspection Query). homepage: https://github.com/comigor/artemis From 05fbbd0c900552219a1d0bf69e10a2fbe30a0d45 Mon Sep 17 00:00:00 2001 From: Christian Budde Christensen Date: Wed, 12 May 2021 07:25:06 +0100 Subject: [PATCH 3/3] feat: Expand test --- .../inline_fragments_on_fragments.dart | 151 +++++++++++++++++- 1 file changed, 150 insertions(+), 1 deletion(-) diff --git a/test/query_generator/fragments/inline_fragments_on_fragments.dart b/test/query_generator/fragments/inline_fragments_on_fragments.dart index a8a4a273..9800f54a 100644 --- a/test/query_generator/fragments/inline_fragments_on_fragments.dart +++ b/test/query_generator/fragments/inline_fragments_on_fragments.dart @@ -9,11 +9,26 @@ void main() { 'Interface fragments', () async => testGenerator( query: r''' + fragment InterfaceFragment2 on InterfaceA { + interface { + s + } + + ...on ImplementationA { + b + } + ...on ImplementationB { + i2 + } + } fragment InterfaceFragment on InterfaceA { s i ...on ImplementationA { b + interface { + ...InterfaceFragment2 + } } ...on ImplementationB { i2 @@ -46,6 +61,7 @@ void main() { interface InterfaceA { s: String i: Int + interface: InterfaceA } union UnionA = ImplementationA | ImplementationB @@ -54,11 +70,13 @@ void main() { s: String i: Int b: Boolean + interface: InterfaceA } type ImplementationB implements InterfaceA { s: String i: Int i2: Int + interface: InterfaceA } ''', @@ -75,12 +93,70 @@ final LibraryDefinition libraryDefinition = name: QueryName(name: r'SomeQuery$_Query'), operationName: r'some_query', classes: [ + ClassDefinition( + name: ClassName(name: r'InterfaceFragment2Mixin$_InterfaceA'), + properties: [ + ClassProperty( + type: TypeName(name: r'String'), + name: ClassPropertyName(name: r's'), + isResolveType: false) + ], + factoryPossibilities: {}, + typeNameField: ClassPropertyName(name: r'__typename'), + isInput: false), + ClassDefinition( + name: ClassName(name: r'InterfaceFragment2Mixin$_ImplementationA'), + properties: [ + ClassProperty( + type: TypeName(name: r'bool'), + name: ClassPropertyName(name: r'b'), + isResolveType: false) + ], + mixins: [FragmentName(name: r'InterfaceFragment2Mixin')], + factoryPossibilities: {}, + typeNameField: ClassPropertyName(name: r'__typename'), + isInput: false), + ClassDefinition( + name: ClassName(name: r'InterfaceFragment2Mixin$_ImplementationB'), + properties: [ + ClassProperty( + type: TypeName(name: r'int'), + name: ClassPropertyName(name: r'i2'), + isResolveType: false) + ], + mixins: [FragmentName(name: r'InterfaceFragment2Mixin')], + factoryPossibilities: {}, + typeNameField: ClassPropertyName(name: r'__typename'), + isInput: false), + FragmentClassDefinition( + name: FragmentName(name: r'InterfaceFragment2Mixin'), + properties: [ + ClassProperty( + type: TypeName(name: r'InterfaceFragment2Mixin$_InterfaceA'), + name: ClassPropertyName(name: r'interface'), + annotations: [r'''JsonKey(name: 'interface')'''], + isResolveType: false) + ]), + ClassDefinition( + name: ClassName( + name: r'InterfaceFragmentMixin$_ImplementationA$_InterfaceA'), + mixins: [FragmentName(name: r'InterfaceFragment2Mixin')], + factoryPossibilities: {}, + typeNameField: ClassPropertyName(name: r'__typename'), + isInput: false), ClassDefinition( name: ClassName(name: r'InterfaceFragmentMixin$_ImplementationA'), properties: [ ClassProperty( type: TypeName(name: r'bool'), name: ClassPropertyName(name: r'b'), + isResolveType: false), + ClassProperty( + type: TypeName( + name: + r'InterfaceFragmentMixin$_ImplementationA$_InterfaceA'), + name: ClassPropertyName(name: r'interface'), + annotations: [r'''JsonKey(name: 'interface')'''], isResolveType: false) ], mixins: [FragmentName(name: r'InterfaceFragmentMixin')], @@ -178,12 +254,82 @@ import 'package:equatable/equatable.dart'; import 'package:gql/ast.dart'; part 'query.graphql.g.dart'; +mixin InterfaceFragment2Mixin { + @JsonKey(name: 'interface') + InterfaceFragment2Mixin$InterfaceA? kw$interface; +} mixin InterfaceFragmentMixin { String? s; int? i; } mixin UnionFragmentMixin {} +@JsonSerializable(explicitToJson: true) +class InterfaceFragment2Mixin$InterfaceA extends JsonSerializable + with EquatableMixin { + InterfaceFragment2Mixin$InterfaceA(); + + factory InterfaceFragment2Mixin$InterfaceA.fromJson( + Map json) => + _$InterfaceFragment2Mixin$InterfaceAFromJson(json); + + String? s; + + @override + List get props => [s]; + Map toJson() => + _$InterfaceFragment2Mixin$InterfaceAToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class InterfaceFragment2Mixin$ImplementationA extends JsonSerializable + with EquatableMixin, InterfaceFragment2Mixin { + InterfaceFragment2Mixin$ImplementationA(); + + factory InterfaceFragment2Mixin$ImplementationA.fromJson( + Map json) => + _$InterfaceFragment2Mixin$ImplementationAFromJson(json); + + bool? b; + + @override + List get props => [kw$interface, b]; + Map toJson() => + _$InterfaceFragment2Mixin$ImplementationAToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class InterfaceFragment2Mixin$ImplementationB extends JsonSerializable + with EquatableMixin, InterfaceFragment2Mixin { + InterfaceFragment2Mixin$ImplementationB(); + + factory InterfaceFragment2Mixin$ImplementationB.fromJson( + Map json) => + _$InterfaceFragment2Mixin$ImplementationBFromJson(json); + + int? i2; + + @override + List get props => [kw$interface, i2]; + Map toJson() => + _$InterfaceFragment2Mixin$ImplementationBToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class InterfaceFragmentMixin$ImplementationA$InterfaceA extends JsonSerializable + with EquatableMixin, InterfaceFragment2Mixin { + InterfaceFragmentMixin$ImplementationA$InterfaceA(); + + factory InterfaceFragmentMixin$ImplementationA$InterfaceA.fromJson( + Map json) => + _$InterfaceFragmentMixin$ImplementationA$InterfaceAFromJson(json); + + @override + List get props => [kw$interface]; + Map toJson() => + _$InterfaceFragmentMixin$ImplementationA$InterfaceAToJson(this); +} + @JsonSerializable(explicitToJson: true) class InterfaceFragmentMixin$ImplementationA extends JsonSerializable with EquatableMixin, InterfaceFragmentMixin { @@ -195,8 +341,11 @@ class InterfaceFragmentMixin$ImplementationA extends JsonSerializable bool? b; + @JsonKey(name: 'interface') + InterfaceFragmentMixin$ImplementationA$InterfaceA? kw$interface; + @override - List get props => [s, i, b]; + List get props => [s, i, b, kw$interface]; Map toJson() => _$InterfaceFragmentMixin$ImplementationAToJson(this); }