From 1a01b5fe2d2bf29f85f8d0608b9720e1dd5db906 Mon Sep 17 00:00:00 2001 From: Liam Nichols Date: Thu, 5 Aug 2021 08:47:18 +0100 Subject: [PATCH] Don't generate inline schemas when `allOf` only contains a single schema (#278) * Update TestSpec to include a scenario where allOf is used to change a referenced schemas nullability or description * Update inlineSchema extension on Schema to ignore allOf groups where there is only a single child schema * Update generated fixtures to match expected results after patch * Update CHANGELOG.md * Update TestSpec to include example demonstrated in #267 --- CHANGELOG.md | 2 +- Sources/SwagGenKit/SwaggerExtensions.swift | 2 +- .../Swift/Sources/Models/UserSubclass.swift | 9 +- .../generated/Swift/Sources/Models/Zoo.swift | 109 +++++++++++------- Specs/TestSpec/spec.yml | 16 +++ 5 files changed, 94 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a9235fb0..71beda2e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Fixed - Fixed sporadic crashes due to malformed URLs #268 @marcelvoss -- Fixed generation of inline types for `allOf` #267 +- Fixed generation of inline types for `allOf` #267 @nicholascross, @liamnichols ## 4.4.0 diff --git a/Sources/SwagGenKit/SwaggerExtensions.swift b/Sources/SwagGenKit/SwaggerExtensions.swift index 14e91f45d..e4aea4d37 100644 --- a/Sources/SwagGenKit/SwaggerExtensions.swift +++ b/Sources/SwagGenKit/SwaggerExtensions.swift @@ -156,7 +156,7 @@ extension Schema { case let .group(group): if group.discriminator != nil { return self - } else if case .all = group.type { + } else if case .all = group.type, group.schemas.count > 1 { return self } default: break diff --git a/Specs/TestSpec/generated/Swift/Sources/Models/UserSubclass.swift b/Specs/TestSpec/generated/Swift/Sources/Models/UserSubclass.swift index d11ebc730..d34e692b5 100644 --- a/Specs/TestSpec/generated/Swift/Sources/Models/UserSubclass.swift +++ b/Specs/TestSpec/generated/Swift/Sources/Models/UserSubclass.swift @@ -9,8 +9,12 @@ public class UserSubclass: User { public var age: Int? - public init(id: Int? = nil, name: String? = nil, age: Int? = nil) { + /** last error reported to user object, or null if they have not seen an error. */ + public var lastError: ErrorType? + + public init(id: Int? = nil, name: String? = nil, age: Int? = nil, lastError: ErrorType? = nil) { self.age = age + self.lastError = lastError super.init(id: id, name: name) } @@ -18,6 +22,7 @@ public class UserSubclass: User { let container = try decoder.container(keyedBy: StringCodingKey.self) age = try container.decodeIfPresent("age") + lastError = try container.decodeIfPresent("last_error") try super.init(from: decoder) } @@ -25,12 +30,14 @@ public class UserSubclass: User { var container = encoder.container(keyedBy: StringCodingKey.self) try container.encodeIfPresent(age, forKey: "age") + try container.encodeIfPresent(lastError, forKey: "last_error") try super.encode(to: encoder) } override public func isEqual(to object: Any?) -> Bool { guard let object = object as? UserSubclass else { return false } guard self.age == object.age else { return false } + guard self.lastError == object.lastError else { return false } return super.isEqual(to: object) } } diff --git a/Specs/TestSpec/generated/Swift/Sources/Models/Zoo.swift b/Specs/TestSpec/generated/Swift/Sources/Models/Zoo.swift index b97e4d6ef..9b211a85e 100644 --- a/Specs/TestSpec/generated/Swift/Sources/Models/Zoo.swift +++ b/Specs/TestSpec/generated/Swift/Sources/Models/Zoo.swift @@ -15,50 +15,12 @@ public class Zoo: APIModel { public var inlineAnimals: [InlineAnimals]? + public var manager: Manager? + public var oneOfDog: Dog? public var schemaAnimals: [SingleAnimal]? - public class AllOfDog: Dog { - - public override init(animal: String? = nil, barks: Bool? = nil) { - super.init(animal: animal, barks: barks) - } - - public required init(from decoder: Decoder) throws { - try super.init(from: decoder) - } - - public override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - } - - override public func isEqual(to object: Any?) -> Bool { - guard object is AllOfDog else { return false } - return super.isEqual(to: object) - } - } - - public class InlineAnimal: Animal { - - public override init(animal: String? = nil) { - super.init(animal: animal) - } - - public required init(from decoder: Decoder) throws { - try super.init(from: decoder) - } - - public override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - } - - override public func isEqual(to object: Any?) -> Bool { - guard object is InlineAnimal else { return false } - return super.isEqual(to: object) - } - } - public enum InlineAnimals: Codable, Equatable { case cat(Cat) case dog(Dog) @@ -87,11 +49,73 @@ public class Zoo: APIModel { } } - public init(allOfDog: Dog? = nil, anyOfDog: Dog? = nil, inlineAnimal: Animal? = nil, inlineAnimals: [InlineAnimals]? = nil, oneOfDog: Dog? = nil, schemaAnimals: [SingleAnimal]? = nil) { + public class Manager: User { + + public var value: Value? + + public class Value: APIModel { + + public var id: String + + public init(id: String) { + self.id = id + } + + public required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: StringCodingKey.self) + + id = try container.decode("id") + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: StringCodingKey.self) + + try container.encode(id, forKey: "id") + } + + public func isEqual(to object: Any?) -> Bool { + guard let object = object as? Value else { return false } + guard self.id == object.id else { return false } + return true + } + + public static func == (lhs: Value, rhs: Value) -> Bool { + return lhs.isEqual(to: rhs) + } + } + + public init(id: Int? = nil, name: String? = nil, value: Value? = nil) { + self.value = value + super.init(id: id, name: name) + } + + public required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: StringCodingKey.self) + + value = try container.decodeIfPresent("value") + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: StringCodingKey.self) + + try container.encodeIfPresent(value, forKey: "value") + try super.encode(to: encoder) + } + + override public func isEqual(to object: Any?) -> Bool { + guard let object = object as? Manager else { return false } + guard self.value == object.value else { return false } + return super.isEqual(to: object) + } + } + + public init(allOfDog: Dog? = nil, anyOfDog: Dog? = nil, inlineAnimal: Animal? = nil, inlineAnimals: [InlineAnimals]? = nil, manager: Manager? = nil, oneOfDog: Dog? = nil, schemaAnimals: [SingleAnimal]? = nil) { self.allOfDog = allOfDog self.anyOfDog = anyOfDog self.inlineAnimal = inlineAnimal self.inlineAnimals = inlineAnimals + self.manager = manager self.oneOfDog = oneOfDog self.schemaAnimals = schemaAnimals } @@ -103,6 +127,7 @@ public class Zoo: APIModel { anyOfDog = try container.decodeIfPresent("anyOfDog") inlineAnimal = try container.decodeIfPresent("inlineAnimal") inlineAnimals = try container.decodeArrayIfPresent("inlineAnimals") + manager = try container.decodeIfPresent("manager") oneOfDog = try container.decodeIfPresent("oneOfDog") schemaAnimals = try container.decodeArrayIfPresent("schemaAnimals") } @@ -114,6 +139,7 @@ public class Zoo: APIModel { try container.encodeIfPresent(anyOfDog, forKey: "anyOfDog") try container.encodeIfPresent(inlineAnimal, forKey: "inlineAnimal") try container.encodeIfPresent(inlineAnimals, forKey: "inlineAnimals") + try container.encodeIfPresent(manager, forKey: "manager") try container.encodeIfPresent(oneOfDog, forKey: "oneOfDog") try container.encodeIfPresent(schemaAnimals, forKey: "schemaAnimals") } @@ -124,6 +150,7 @@ public class Zoo: APIModel { guard self.anyOfDog == object.anyOfDog else { return false } guard self.inlineAnimal == object.inlineAnimal else { return false } guard self.inlineAnimals == object.inlineAnimals else { return false } + guard self.manager == object.manager else { return false } guard self.oneOfDog == object.oneOfDog else { return false } guard self.schemaAnimals == object.schemaAnimals else { return false } return true diff --git a/Specs/TestSpec/spec.yml b/Specs/TestSpec/spec.yml index e6983cdce..e8b39bd85 100644 --- a/Specs/TestSpec/spec.yml +++ b/Specs/TestSpec/spec.yml @@ -240,6 +240,11 @@ components: properties: age: type: integer + last_error: + allOf: + - $ref: "#/components/schemas/Error" + nullable: true + description: last error reported to user object, or null if they have not seen an error. UserReference: $ref: "#/components/schemas/User" ModelWithAdditionalProperties: @@ -332,6 +337,17 @@ components: allOfDog: allOf: - $ref: '#/components/schemas/Dog' + manager: + allOf: + - $ref: "#/components/schemas/User" + - properties: + value: + type: object + required: + - id + properties: + id: + type: string SingleAnimal: oneOf: - $ref: "#/components/schemas/Cat"