Skip to content

Commit 8d5b397

Browse files
takeshi-1000czechboy0simonjbeaumont
authored
Calculate required response header parameters for initialize (#150)
### Motivation Resolve #30 ### Modifications Define a computed property on StructBlueprint that tells you whether the struct has an empty initializer, and it is used when response header struct blueprint is created. ### Result If one or more required response header parameters are present, Generates code that needs to set request header parameters when create response. For example you define the yaml below ```yaml responses: '200': description: A success response with a greeting. headers: X-Extra-Arguments: required: false description: "A description here." content: application/json: schema: $ref: '#/components/schemas/Greeting' ``` `Types.swift` is generated like below, and you can set the "headers" parameter if necessary , <img width="765" alt="スクリーンショット 2023-07-29 14 44 45" src="https://github.com/apple/swift-openapi-generator/assets/16571394/c8e5779a-e851-40d6-9c68-9ced8af4dcc2"> if you set required true ```yaml X-Extra-Arguments: required: true ``` `Types.swift` is generated like below, and you should set reponse headers when initialize ![スクリーンショット 2023-07-29 14 52 55](https://github.com/apple/swift-openapi-generator/assets/16571394/33890627-126e-4d94-af89-040943d2b489) ### Test Plan Add test optional response header in SnipetBasedReferenceTests, and modify ReferenceSource a little. --------- Co-authored-by: Honza Dvorsky <honza@apple.com> Co-authored-by: Si Beaumont <simonjbeaumont@gmail.com>
1 parent 379b047 commit 8d5b397

File tree

4 files changed

+63
-11
lines changed

4 files changed

+63
-11
lines changed

Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/StructBlueprint.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@ struct StructBlueprint {
8080
var properties: [PropertyBlueprint]
8181
}
8282

83+
extension StructBlueprint {
84+
85+
/// A Boolean value indicating whether the struct can be initialized using
86+
/// an empty initializer.
87+
///
88+
/// For example, when all the properties of the struct have a default value,
89+
/// the struct can be initialized using `Foo()`. This is important for
90+
/// other types referencing this type.
91+
var hasEmptyInit: Bool {
92+
// If at least one property requires an explicit value, this struct
93+
// cannot have an empty initializer.
94+
properties.allSatisfy { $0.defaultValue != nil }
95+
}
96+
}
97+
8398
/// A structure that contains the information about an OpenAPI object property
8499
/// that is required to generate a matching Swift property.
85100
struct PropertyBlueprint {

Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,21 @@ extension TypesFileTranslator {
3636
let headerProperties: [PropertyBlueprint] = try headers.map { header in
3737
try parseResponseHeaderAsProperty(for: header)
3838
}
39+
let headersStructBlueprint: StructBlueprint = .init(
40+
comment: nil,
41+
access: config.access,
42+
typeName: headersTypeName,
43+
conformances: Constants.Operation.Output.Payload.Headers.conformances,
44+
properties: headerProperties
45+
)
3946
let headersStructDecl = translateStructBlueprint(
40-
.init(
41-
comment: nil,
42-
access: config.access,
43-
typeName: headersTypeName,
44-
conformances: Constants.Operation.Output.Payload.Headers.conformances,
45-
properties: headerProperties
46-
)
47+
headersStructBlueprint
4748
)
4849
let headersProperty = PropertyBlueprint(
4950
comment: .doc("Received HTTP response headers"),
5051
originalName: Constants.Operation.Output.Payload.Headers.variableName,
5152
typeUsage: headersTypeName.asUsage,
52-
default: headerProperties.isEmpty ? .emptyInit : nil,
53+
default: headersStructBlueprint.hasEmptyInit ? .emptyInit : nil,
5354
associatedDeclarations: [
5455
headersStructDecl
5556
],

Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ public enum Components {
686686
/// - headers: Received HTTP response headers
687687
/// - body: Received HTTP response body
688688
public init(
689-
headers: Components.Responses.ErrorBadRequest.Headers,
689+
headers: Components.Responses.ErrorBadRequest.Headers = .init(),
690690
body: Components.Responses.ErrorBadRequest.Body
691691
) {
692692
self.headers = headers
@@ -1006,7 +1006,7 @@ public enum Operations {
10061006
/// - headers: Received HTTP response headers
10071007
/// - body: Received HTTP response body
10081008
public init(
1009-
headers: Operations.createPet.Output.Created.Headers,
1009+
headers: Operations.createPet.Output.Created.Headers = .init(),
10101010
body: Operations.createPet.Output.Created.Body
10111011
) {
10121012
self.headers = headers

Tests/OpenAPIGeneratorReferenceTests/SnippetBasedReferenceTests.swift

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ final class SnippetBasedReferenceTests: XCTestCase {
519519
)
520520
}
521521

522-
func testComponentsResponsesResponseWithHeader() throws {
522+
func testComponentsResponsesResponseWithOptionalHeader() throws {
523523
try self.assertResponsesTranslation(
524524
"""
525525
responses:
@@ -541,6 +541,42 @@ final class SnippetBasedReferenceTests: XCTestCase {
541541
public var headers: Components.Responses.BadRequest.Headers
542542
@frozen public enum Body: Sendable, Equatable, Hashable {}
543543
public var body: Components.Responses.BadRequest.Body?
544+
public init(
545+
headers: Components.Responses.BadRequest.Headers = .init(),
546+
body: Components.Responses.BadRequest.Body? = nil
547+
) {
548+
self.headers = headers
549+
self.body = body
550+
}
551+
}
552+
}
553+
"""
554+
)
555+
}
556+
557+
func testComponentsResponsesResponseWithRequiredHeader() throws {
558+
try self.assertResponsesTranslation(
559+
"""
560+
responses:
561+
BadRequest:
562+
description: Bad request
563+
headers:
564+
X-Reason:
565+
schema:
566+
type: string
567+
required: true
568+
""",
569+
"""
570+
public enum Responses {
571+
public struct BadRequest: Sendable, Equatable, Hashable {
572+
public struct Headers: Sendable, Equatable, Hashable {
573+
public var X_Reason: Swift.String
574+
public init(X_Reason: Swift.String) {
575+
self.X_Reason = X_Reason }
576+
}
577+
public var headers: Components.Responses.BadRequest.Headers
578+
@frozen public enum Body: Sendable, Equatable, Hashable {}
579+
public var body: Components.Responses.BadRequest.Body?
544580
public init(
545581
headers: Components.Responses.BadRequest.Headers,
546582
body: Components.Responses.BadRequest.Body? = nil

0 commit comments

Comments
 (0)