From 720791f082385fdc408ba19a600f0fdc24d26e1b Mon Sep 17 00:00:00 2001 From: Charles-Henri Date: Fri, 10 Jan 2025 19:07:25 +0100 Subject: [PATCH] feat: implement support for discriminated unions in Freezed DTO generation - Added discriminator handling in `UniversalComponentClass` to support oneOf variants. - Updated `dart_freezed_dto_template.dart` to generate sealed classes and union factories based on discriminator values. - Introduced new test cases for discriminated oneOf schemas, including a sample JSON schema and expected output files. - Enhanced OpenApiParser to correctly parse and map discriminator properties from OpenAPI specifications. --- .../templates/dart_freezed_dto_template.dart | 53 +++++++---- .../model/universal_component_class.dart | 13 +++ .../src/parser/parser/open_api_parser.dart | 87 ++++++++++++++++++- swagger_parser/test/e2e/e2e_test.dart | 13 +++ .../discriminated_one_of.3.0.json | 83 ++++++++++++++++++ .../expected_files/export.dart | 13 +++ .../expected_files/models/cat.dart | 22 +++++ .../expected_files/models/cat_type.dart | 23 +++++ .../expected_files/models/dog.dart | 22 +++++ .../expected_files/models/dog_type.dart | 23 +++++ .../expected_files/models/family.dart | 19 ++++ .../models/family_members_union.dart | 42 +++++++++ .../expected_files/models/human.dart | 22 +++++ .../expected_files/models/human_type.dart | 23 +++++ .../enum_class/expected_files/export.dart | 2 +- .../expected_files/models/class_name.dart | 4 +- .../models/class_name_status.dart} | 6 +- .../expected_files/clients/pet_client.dart | 4 +- .../expected_files/export.dart | 2 +- .../expected_files/models/status.dart} | 6 +- 20 files changed, 452 insertions(+), 30 deletions(-) create mode 100644 swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/discriminated_one_of.3.0.json create mode 100644 swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/export.dart create mode 100644 swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/cat.dart create mode 100644 swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/cat_type.dart create mode 100644 swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/dog.dart create mode 100644 swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/dog_type.dart create mode 100644 swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/family.dart create mode 100644 swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/family_members_union.dart create mode 100644 swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/human.dart create mode 100644 swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/human_type.dart rename swagger_parser/test/e2e/tests/{nullable_types.2.0/expected_files/models/status_status.dart => basic/enum_class/expected_files/models/class_name_status.dart} (81%) rename swagger_parser/test/e2e/tests/{basic/enum_class/expected_files/models/status_status.dart => nullable_types.2.0/expected_files/models/status.dart} (82%) diff --git a/swagger_parser/lib/src/generator/templates/dart_freezed_dto_template.dart b/swagger_parser/lib/src/generator/templates/dart_freezed_dto_template.dart index 9c6c0334..c6fb5744 100644 --- a/swagger_parser/lib/src/generator/templates/dart_freezed_dto_template.dart +++ b/swagger_parser/lib/src/generator/templates/dart_freezed_dto_template.dart @@ -21,11 +21,9 @@ ${dartImports(imports: dataClass.imports)} part '${dataClass.name.toSnake}.freezed.dart'; part '${dataClass.name.toSnake}.g.dart'; -${descriptionComment(dataClass.description)}@Freezed() -class $className with _\$$className { - const factory $className(${dataClass.parameters.isNotEmpty ? '{' : ''}${_parametersToString( - dataClass.parameters, - )}${dataClass.parameters.isNotEmpty ? '\n }' : ''}) = _$className; +${descriptionComment(dataClass.description)}@Freezed(${dataClass.discriminator != null ? "unionKey: '${dataClass.discriminator!.propertyName}'" : ''}) +${dataClass.discriminator != null ? 'sealed ' : ''}class $className with _\$$className { +${_factories(dataClass, className)} \n factory $className.fromJson(Map json) => _\$${className}FromJson(json); ${generateValidator ? dataClass.parameters.map(_validationString).nonNulls.join() : ''}} ${generateValidator ? _validateMethod(className, dataClass.parameters) : ''}'''; @@ -154,6 +152,33 @@ String _validateMethod(String className, List types) { return funcBuffer.toString(); } +String _factories(UniversalComponentClass dataClass, String className) { + if (dataClass.discriminator == null) { + return ''' + const factory $className(${dataClass.parameters.isNotEmpty ? '{' : ''}${_parametersToString( + dataClass.parameters, + )}${dataClass.parameters.isNotEmpty ? '\n }' : ''}) = _$className; +'''; + } + + final factories = []; + for (final discriminatorValue in dataClass.discriminator!.discriminatorValueToRefMapping.keys) { + final factoryName = discriminatorValue.toCamel; + final discriminatorRef = dataClass.discriminator!.discriminatorValueToRefMapping[discriminatorValue]!; + final factoryParameters = dataClass.discriminator!.refProperties[discriminatorRef]!; + final unionItemClassName = discriminatorRef.toPascal; + + factories.add(''' + @FreezedUnionValue('$discriminatorValue') + const factory $className.$factoryName(${factoryParameters.isNotEmpty ? '{' : ''}${_parametersToString( + factoryParameters, + )}${factoryParameters.isNotEmpty ? '\n }' : ''}) = $unionItemClassName; +'''); + } + + return factories.join('\n'); +} + String? _validationString(UniversalType type) { final sb = StringBuffer(); if (type.min != null) { @@ -200,12 +225,10 @@ String? _validationString(UniversalType type) { } String _parametersToString(List parameters) { - final sortedByRequired = - List.from(parameters.sorted((a, b) => a.compareTo(b))); + final sortedByRequired = List.from(parameters.sorted((a, b) => a.compareTo(b))); return sortedByRequired .mapIndexed( - (i, e) => - '\n${i != 0 && (e.description?.isNotEmpty ?? false) ? '\n' : ''}${descriptionComment(e.description, tab: ' ')}' + (i, e) => '\n${i != 0 && (e.description?.isNotEmpty ?? false) ? '\n' : ''}${descriptionComment(e.description, tab: ' ')}' '${_jsonKey(e)} ${_required(e)}' '${e.toSuitableType(ProgrammingLanguage.dart)} ${e.name},', ) @@ -228,12 +251,10 @@ String _jsonKey(UniversalType t) { } /// return required if isRequired -String _required(UniversalType t) => - t.isRequired && t.defaultValue == null ? 'required ' : ''; +String _required(UniversalType t) => t.isRequired && t.defaultValue == null ? 'required ' : ''; /// return defaultValue if have -String _defaultValue(UniversalType t) => - '${t.enumType != null ? '${t.type}.${protectDefaultEnum(t.defaultValue)?.toCamel}' : protectDefaultValue( - t.defaultValue, - type: t.type, - )}'; +String _defaultValue(UniversalType t) => '${t.enumType != null ? '${t.type}.${protectDefaultEnum(t.defaultValue)?.toCamel}' : protectDefaultValue( + t.defaultValue, + type: t.type, + )}'; diff --git a/swagger_parser/lib/src/parser/model/universal_component_class.dart b/swagger_parser/lib/src/parser/model/universal_component_class.dart index a22cba39..f716626d 100644 --- a/swagger_parser/lib/src/parser/model/universal_component_class.dart +++ b/swagger_parser/lib/src/parser/model/universal_component_class.dart @@ -10,6 +10,7 @@ final class UniversalComponentClass extends UniversalDataClass { required this.parameters, this.allOf, this.typeDef = false, + this.discriminator, super.description, }); @@ -22,6 +23,18 @@ final class UniversalComponentClass extends UniversalDataClass { /// Temp field for containing info about `allOf` for future processing final ({List refs, List properties})? allOf; + /// When using a discriminated oneOf, this contains the information about the property name, the mapping of the ref to the property name, and the properties of each of the oneOf variants + final ({ + // The name of the property that is used to discriminate the oneOf variants + String propertyName, + + // The mapping of the property value to the ref + Map discriminatorValueToRefMapping, + + // The list of properties stored for each ref + Map> refProperties, + })? discriminator; + /// Whether or not this schema is a basic type /// "Date": { /// "type": "string", diff --git a/swagger_parser/lib/src/parser/parser/open_api_parser.dart b/swagger_parser/lib/src/parser/parser/open_api_parser.dart index 0170da28..6fe3922e 100644 --- a/swagger_parser/lib/src/parser/parser/open_api_parser.dart +++ b/swagger_parser/lib/src/parser/parser/open_api_parser.dart @@ -54,12 +54,14 @@ class OpenApiParser { static const _definitionsConst = 'definitions'; static const _descriptionConst = 'description'; static const _deprecatedConst = 'deprecated'; + static const _discriminatorConst = 'discriminator'; static const _enumConst = 'enum'; static const _formatConst = 'format'; static const _formUrlEncodedConst = 'application/x-www-form-urlencoded'; static const _inConst = 'in'; static const _infoConst = 'info'; static const _itemsConst = 'items'; + static const _mappingConst = 'mapping'; static const _multipartFormDataConst = 'multipart/form-data'; static const _nameConst = 'name'; static const _nullableConst = 'nullable'; @@ -70,6 +72,7 @@ class OpenApiParser { static const _parametersConst = 'parameters'; static const _pathsConst = 'paths'; static const _propertiesConst = 'properties'; + static const _propertyNameConst = 'propertyName'; static const _refConst = r'$ref'; static const _requestBodyConst = 'requestBody'; static const _requestBodiesConst = 'requestBodies'; @@ -895,6 +898,26 @@ class OpenApiParser { } allOfClass.parameters.addAll(allOfClass.allOf!.properties); } + + // check for discriminated oneOf + final discriminatedOneOfClasses = dataClasses.where( + (dc) => dc is UniversalComponentClass && dc.discriminator != null); + for (final discriminatedOneOfClass in discriminatedOneOfClasses) { + if (discriminatedOneOfClass is! UniversalComponentClass) { + continue; + } + final discriminator = discriminatedOneOfClass.discriminator!; + // for each ref, we lookup the matching dataclass and add its properties to the discriminator mapping, its imports are added to the discriminatedOneOfClass's imports + for (final ref in discriminator.discriminatorValueToRefMapping.values) { + final refedClass = dataClasses.firstWhere((dc) => dc.name == ref); + if (refedClass is! UniversalComponentClass) { + continue; + } + discriminator.refProperties[ref] = refedClass.parameters; + discriminatedOneOfClass.imports.addAll(refedClass.imports); + } + } + return dataClasses; } @@ -931,7 +954,7 @@ class OpenApiParser { final (:type, :import) = _findType( arrayItems, name: name, - additionalName: name, + additionalName: additionalName, root: false, isRequired: isRequired, ); @@ -1122,9 +1145,69 @@ class OpenApiParser { map.containsKey(_anyOfConst) || map.containsKey(_oneOfConst) || map[_typeConst] is List) { + // Handle discriminated oneOf + if (map.containsKey(_oneOfConst) && + map.containsKey(_discriminatorConst) && + (map[_discriminatorConst] as Map) + .containsKey(_propertyNameConst) && + (map[_discriminatorConst] as Map) + .containsKey(_mappingConst)) { + final discriminator = map[_discriminatorConst] as Map; + final propertyName = discriminator[_propertyNameConst] as String; + final refMapping = discriminator[_mappingConst] as Map; + + // Create a base union class for the discriminated types + final baseClassName = + '${additionalName ?? ''} ${name ?? ''} Union'.toPascal; + final (newName, description) = protectName( + baseClassName, + uniqueIfNull: true, + description: map[_descriptionConst]?.toString(), + ); + + // Cleanup the refMapping to contain only the class name + final cleanedRefMapping = {}; + for (final key in refMapping.keys) { + final refMap = {_refConst: refMapping[key]}; + cleanedRefMapping[key] = _formatRef(refMap); + } + + // Create a sealed class to represent the discriminated union + _objectClasses.add( + UniversalComponentClass( + name: newName!.toPascal, + imports: SplayTreeSet(), + parameters: [ + UniversalType( + type: 'String', + name: propertyName, + isRequired: true, + ), + ], + discriminator: ( + propertyName: propertyName, + discriminatorValueToRefMapping: cleanedRefMapping, + // This property is populated by the parser after all the data classes are created + refProperties: >{}, + ), + ), + ); + + return ( + type: UniversalType( + type: newName.toPascal, + name: name?.toCamel, + description: description, + isRequired: isRequired, + nullable: map[_nullableConst].toString().toBool() ?? + (root && !isRequired), + ), + import: newName.toPascal, + ); + } + String? ofImport; UniversalType? ofType; - final ofList = map[_allOfConst] ?? map[_anyOfConst] ?? map[_oneOfConst] ?? diff --git a/swagger_parser/test/e2e/e2e_test.dart b/swagger_parser/test/e2e/e2e_test.dart index 522453dc..842d513c 100644 --- a/swagger_parser/test/e2e/e2e_test.dart +++ b/swagger_parser/test/e2e/e2e_test.dart @@ -185,6 +185,19 @@ void main() { ); }); + test('discriminated_one_of.3.0', () async { + await e2eTest( + 'basic/discriminated_one_of.3.0', + (outputDirectory, schemaPath) => SWPConfig( + outputDirectory: outputDirectory, + schemaPath: schemaPath, + jsonSerializer: JsonSerializer.freezed, + putClientsInFolder: true, + ), + schemaFileName: 'discriminated_one_of.3.0.json', + ); + }); + test('empty_class.2.0', () async { await e2eTest( 'basic/empty_class.2.0', diff --git a/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/discriminated_one_of.3.0.json b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/discriminated_one_of.3.0.json new file mode 100644 index 00000000..d636fcf2 --- /dev/null +++ b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/discriminated_one_of.3.0.json @@ -0,0 +1,83 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Family API", + "version": "1.0.0" + }, + "paths": {}, + "components": { + "schemas": { + "Family": { + "type": "object", + "properties": { + "members": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/Cat" + }, + { + "$ref": "#/components/schemas/Dog" + }, + { + "$ref": "#/components/schemas/Human" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "Cat": "#/components/schemas/Cat", + "Dog": "#/components/schemas/Dog", + "Human": "#/components/schemas/Human" + } + } + } + } + } + }, + "Cat": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["Cat"] + }, + "mewCount": { + "type": "integer", + "description": "Number of times the cat meows." + } + }, + "required": ["type", "mewCount"] + }, + "Dog": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["Dog"] + }, + "barkSound": { + "type": "string", + "description": "The sound of the dog's bark." + } + }, + "required": ["type", "barkSound"] + }, + "Human": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["Human"] + }, + "job": { + "type": "string", + "description": "The job of the human." + } + }, + "required": ["type", "job"] + } + } + } +} \ No newline at end of file diff --git a/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/export.dart b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/export.dart new file mode 100644 index 00000000..9f4f6638 --- /dev/null +++ b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/export.dart @@ -0,0 +1,13 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, unused_import + +// Data classes +export 'models/family.dart'; +export 'models/cat.dart'; +export 'models/dog.dart'; +export 'models/human.dart'; +export 'models/family_members_union.dart'; +export 'models/cat_type.dart'; +export 'models/dog_type.dart'; +export 'models/human_type.dart'; diff --git a/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/cat.dart b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/cat.dart new file mode 100644 index 00000000..d91624bb --- /dev/null +++ b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/cat.dart @@ -0,0 +1,22 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, unused_import + +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'cat_type.dart'; + +part 'cat.freezed.dart'; +part 'cat.g.dart'; + +@Freezed() +class Cat with _$Cat { + const factory Cat({ + required CatType type, + + /// Number of times the cat meows. + required int mewCount, + }) = _Cat; + + factory Cat.fromJson(Map json) => _$CatFromJson(json); +} diff --git a/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/cat_type.dart b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/cat_type.dart new file mode 100644 index 00000000..6df6b138 --- /dev/null +++ b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/cat_type.dart @@ -0,0 +1,23 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, unused_import + +import 'package:freezed_annotation/freezed_annotation.dart'; + +@JsonEnum() +enum CatType { + @JsonValue('Cat') + cat('Cat'), + + /// Default value for all unparsed values, allows backward compatibility when adding new values on the backend. + $unknown(null); + + const CatType(this.json); + + factory CatType.fromJson(String json) => values.firstWhere( + (e) => e.json == json, + orElse: () => $unknown, + ); + + final String? json; +} diff --git a/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/dog.dart b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/dog.dart new file mode 100644 index 00000000..cf88cec3 --- /dev/null +++ b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/dog.dart @@ -0,0 +1,22 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, unused_import + +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'dog_type.dart'; + +part 'dog.freezed.dart'; +part 'dog.g.dart'; + +@Freezed() +class Dog with _$Dog { + const factory Dog({ + required DogType type, + + /// The sound of the dog's bark. + required String barkSound, + }) = _Dog; + + factory Dog.fromJson(Map json) => _$DogFromJson(json); +} diff --git a/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/dog_type.dart b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/dog_type.dart new file mode 100644 index 00000000..ea00a09f --- /dev/null +++ b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/dog_type.dart @@ -0,0 +1,23 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, unused_import + +import 'package:freezed_annotation/freezed_annotation.dart'; + +@JsonEnum() +enum DogType { + @JsonValue('Dog') + dog('Dog'), + + /// Default value for all unparsed values, allows backward compatibility when adding new values on the backend. + $unknown(null); + + const DogType(this.json); + + factory DogType.fromJson(String json) => values.firstWhere( + (e) => e.json == json, + orElse: () => $unknown, + ); + + final String? json; +} diff --git a/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/family.dart b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/family.dart new file mode 100644 index 00000000..a3760761 --- /dev/null +++ b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/family.dart @@ -0,0 +1,19 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, unused_import + +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'family_members_union.dart'; + +part 'family.freezed.dart'; +part 'family.g.dart'; + +@Freezed() +class Family with _$Family { + const factory Family({ + required List members, + }) = _Family; + + factory Family.fromJson(Map json) => _$FamilyFromJson(json); +} diff --git a/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/family_members_union.dart b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/family_members_union.dart new file mode 100644 index 00000000..8977e723 --- /dev/null +++ b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/family_members_union.dart @@ -0,0 +1,42 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, unused_import + +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'cat_type.dart'; +import 'dog_type.dart'; +import 'human_type.dart'; + +part 'family_members_union.freezed.dart'; +part 'family_members_union.g.dart'; + +@Freezed(unionKey: 'type') +sealed class FamilyMembersUnion with _$FamilyMembersUnion { + @FreezedUnionValue('Cat') + const factory FamilyMembersUnion.cat({ + required CatType type, + + /// Number of times the cat meows. + required int mewCount, + }) = Cat; + + @FreezedUnionValue('Dog') + const factory FamilyMembersUnion.dog({ + required DogType type, + + /// The sound of the dog's bark. + required String barkSound, + }) = Dog; + + @FreezedUnionValue('Human') + const factory FamilyMembersUnion.human({ + required HumanType type, + + /// The job of the human. + required String job, + }) = Human; + + factory FamilyMembersUnion.fromJson(Map json) => + _$FamilyMembersUnionFromJson(json); +} diff --git a/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/human.dart b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/human.dart new file mode 100644 index 00000000..7a69f3c7 --- /dev/null +++ b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/human.dart @@ -0,0 +1,22 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, unused_import + +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'human_type.dart'; + +part 'human.freezed.dart'; +part 'human.g.dart'; + +@Freezed() +class Human with _$Human { + const factory Human({ + required HumanType type, + + /// The job of the human. + required String job, + }) = _Human; + + factory Human.fromJson(Map json) => _$HumanFromJson(json); +} diff --git a/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/human_type.dart b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/human_type.dart new file mode 100644 index 00000000..95951098 --- /dev/null +++ b/swagger_parser/test/e2e/tests/basic/discriminated_one_of.3.0/expected_files/models/human_type.dart @@ -0,0 +1,23 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, unused_import + +import 'package:freezed_annotation/freezed_annotation.dart'; + +@JsonEnum() +enum HumanType { + @JsonValue('Human') + human('Human'), + + /// Default value for all unparsed values, allows backward compatibility when adding new values on the backend. + $unknown(null); + + const HumanType(this.json); + + factory HumanType.fromJson(String json) => values.firstWhere( + (e) => e.json == json, + orElse: () => $unknown, + ); + + final String? json; +} diff --git a/swagger_parser/test/e2e/tests/basic/enum_class/expected_files/export.dart b/swagger_parser/test/e2e/tests/basic/enum_class/expected_files/export.dart index d0357bd0..53ad2699 100644 --- a/swagger_parser/test/e2e/tests/basic/enum_class/expected_files/export.dart +++ b/swagger_parser/test/e2e/tests/basic/enum_class/expected_files/export.dart @@ -4,4 +4,4 @@ // Data classes export 'models/class_name.dart'; -export 'models/status_status.dart'; +export 'models/class_name_status.dart'; diff --git a/swagger_parser/test/e2e/tests/basic/enum_class/expected_files/models/class_name.dart b/swagger_parser/test/e2e/tests/basic/enum_class/expected_files/models/class_name.dart index b54be90c..469ba960 100644 --- a/swagger_parser/test/e2e/tests/basic/enum_class/expected_files/models/class_name.dart +++ b/swagger_parser/test/e2e/tests/basic/enum_class/expected_files/models/class_name.dart @@ -4,7 +4,7 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import 'status_status.dart'; +import 'class_name_status.dart'; part 'class_name.freezed.dart'; part 'class_name.g.dart'; @@ -13,7 +13,7 @@ part 'class_name.g.dart'; class ClassName with _$ClassName { const factory ClassName({ /// Status values that need to be considered for filter - required List status, + required List status, }) = _ClassName; factory ClassName.fromJson(Map json) => diff --git a/swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/models/status_status.dart b/swagger_parser/test/e2e/tests/basic/enum_class/expected_files/models/class_name_status.dart similarity index 81% rename from swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/models/status_status.dart rename to swagger_parser/test/e2e/tests/basic/enum_class/expected_files/models/class_name_status.dart index 12c634c6..de8fd7b9 100644 --- a/swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/models/status_status.dart +++ b/swagger_parser/test/e2e/tests/basic/enum_class/expected_files/models/class_name_status.dart @@ -5,7 +5,7 @@ import 'package:freezed_annotation/freezed_annotation.dart'; @JsonEnum() -enum StatusStatus { +enum ClassNameStatus { @JsonValue('available') available('available'), @JsonValue('pending') @@ -16,9 +16,9 @@ enum StatusStatus { /// Default value for all unparsed values, allows backward compatibility when adding new values on the backend. $unknown(null); - const StatusStatus(this.json); + const ClassNameStatus(this.json); - factory StatusStatus.fromJson(String json) => values.firstWhere( + factory ClassNameStatus.fromJson(String json) => values.firstWhere( (e) => e.json == json, orElse: () => $unknown, ); diff --git a/swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/clients/pet_client.dart b/swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/clients/pet_client.dart index 729a376f..08ba3eb5 100644 --- a/swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/clients/pet_client.dart +++ b/swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/clients/pet_client.dart @@ -7,7 +7,7 @@ import 'package:dio/dio.dart'; import 'package:retrofit/retrofit.dart'; import '../models/pet.dart'; -import '../models/status_status.dart'; +import '../models/status.dart'; part 'pet_client.g.dart'; @@ -38,7 +38,7 @@ abstract class PetClient { /// [status] - Status values that need to be considered for filter. @GET('/pet/findByStatus') Future> findPetsByStatus({ - @Query('status') required List status, + @Query('status') required List status, }); /// Finds Pets by tags. diff --git a/swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/export.dart b/swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/export.dart index 2c350551..eb44a3ef 100644 --- a/swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/export.dart +++ b/swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/export.dart @@ -7,7 +7,7 @@ export 'clients/pet_client.dart'; // Data classes export 'models/category.dart'; export 'models/pet.dart'; -export 'models/status_status.dart'; +export 'models/status.dart'; export 'models/pet_status.dart'; // Root client export 'rest_client.dart'; diff --git a/swagger_parser/test/e2e/tests/basic/enum_class/expected_files/models/status_status.dart b/swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/models/status.dart similarity index 82% rename from swagger_parser/test/e2e/tests/basic/enum_class/expected_files/models/status_status.dart rename to swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/models/status.dart index 12c634c6..ec286341 100644 --- a/swagger_parser/test/e2e/tests/basic/enum_class/expected_files/models/status_status.dart +++ b/swagger_parser/test/e2e/tests/nullable_types.2.0/expected_files/models/status.dart @@ -5,7 +5,7 @@ import 'package:freezed_annotation/freezed_annotation.dart'; @JsonEnum() -enum StatusStatus { +enum Status { @JsonValue('available') available('available'), @JsonValue('pending') @@ -16,9 +16,9 @@ enum StatusStatus { /// Default value for all unparsed values, allows backward compatibility when adding new values on the backend. $unknown(null); - const StatusStatus(this.json); + const Status(this.json); - factory StatusStatus.fromJson(String json) => values.firstWhere( + factory Status.fromJson(String json) => values.firstWhere( (e) => e.json == json, orElse: () => $unknown, );