From b92bb2e73670bd5ad8aa82f1e64f15102eea4018 Mon Sep 17 00:00:00 2001 From: takeshi-1000 Date: Tue, 15 Aug 2023 12:28:39 +0900 Subject: [PATCH 1/8] change temporarily so that comments are added to the generated Type --- .../CommonTypes/CommentExtensions.swift | 10 ++++ .../Translator/Content/ContentType.swift | 4 ++ .../Parameters/translateParameter.swift | 4 ++ .../RequestBody/translateRequestBody.swift | 26 ++++++++-- .../Responses/translateResponse.swift | 49 ++++++++++++++----- .../Responses/translateResponseHeader.swift | 10 +++- .../Responses/translateResponseOutcome.swift | 1 + .../Translator/TypeAssignment/TypeName.swift | 4 ++ .../TypesTranslator/translateOperations.swift | 17 ++++--- 9 files changed, 99 insertions(+), 26 deletions(-) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/CommentExtensions.swift b/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/CommentExtensions.swift index 305c45dd..3b5fe6b2 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/CommentExtensions.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/CommentExtensions.swift @@ -96,6 +96,16 @@ extension TypeName { suffix: generatedFromCommentText ) } + + func docCommentWithUserDescription(_ userDescription: String?, subPath: String) -> Comment? { + guard let fullyQualifiedJSONPath else { + return Comment.doc(prefix: userDescription, suffix: nil) + } + return Comment.doc( + prefix: userDescription, + suffix: "- Remark: Generated from `\(fullyQualifiedJSONPath)/\(subPath)`." + ) + } } extension ResponseKind { diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift b/Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift index c125463d..f606f736 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift @@ -142,6 +142,10 @@ struct ContentType: Hashable { var lowercasedTypeAndSubtype: String { "\(lowercasedType)/\(lowercasedSubtype)" } + + var lowercasedTypeAndSubtypeWithEscape: String { + "\(lowercasedType)\\/\(lowercasedSubtype)" + } /// The header value used when sending a content-type header. var headerValueForSending: String { diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift index 4a125508..7e153488 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift @@ -43,7 +43,11 @@ extension TypesFileTranslator { } else { associatedDeclarations = [] } + + let comment: Comment? = parent.docCommentWithUserDescription(nil, + subPath: "\(parameter.location.rawValue)/\(parameter.name)") return .init( + comment: comment, isDeprecated: parameter.parameter.deprecated, originalName: parameter.name, typeUsage: parameter.typeUsage, diff --git a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift index d77a4125..636ea9d4 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift @@ -41,6 +41,7 @@ extension TypesFileTranslator { /// - Returns: A list of declarations; empty if the request body is /// unsupported. func requestBodyContentCases( + typeName: TypeName, for requestBody: TypedRequestBody ) throws -> [Declaration] { var bodyMembers: [Declaration] = [] @@ -54,13 +55,20 @@ extension TypesFileTranslator { } let identifier = contentSwiftName(content.content.contentType) let associatedType = content.resolvedTypeUsage - let contentCase: Declaration = .enumCase( - .init( + + let subPath: String = { + let contentPath = typeName.isComponent ? "content" : "requestBody/content" + return "\(contentPath)/\(content.content.contentType.lowercasedTypeAndSubtypeWithEscape)" + }() + + let contentCase: Declaration = .commentable( + typeName.docCommentWithUserDescription(nil, subPath: subPath), + .enumCase(.init( name: identifier, kind: .nameWithAssociatedValues([ .init(type: associatedType.fullyQualifiedNonOptionalSwiftName) ]) - ) + )) ) bodyMembers.append(contentCase) } @@ -131,7 +139,8 @@ extension TypesFileTranslator { requestBody: TypedRequestBody ) throws -> Declaration { let type = requestBody.typeUsage.typeName - let members = try requestBodyContentCases(for: requestBody) + let members = try requestBodyContentCases(typeName: type, + for: requestBody) return translateRequestBodyInTypes( typeName: type, members: members @@ -154,7 +163,14 @@ extension TypesFileTranslator { conformances: Constants.Operation.Output.conformances, members: members ) - return bodyEnumDecl + let comment: Comment? = { + if typeName.isComponent { + return typeName.docCommentWithUserDescription(nil) + } else { + return typeName.docCommentWithUserDescription(nil, subPath: "requestBody") + } + }() + return .commentable(comment, bodyEnumDecl) } } diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift index 60c73831..261dae9b 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift @@ -20,6 +20,7 @@ extension TypesFileTranslator { /// - typedResponse: The typed response to declare. /// - Returns: A structure declaration. func translateResponseInTypes( + responseKind: String = "", typeName: TypeName, response: TypedResponse ) throws -> Declaration { @@ -34,10 +35,19 @@ extension TypesFileTranslator { inParent: headersTypeName ) let headerProperties: [PropertyBlueprint] = try headers.map { header in - try parseResponseHeaderAsProperty(for: header) + try parseResponseHeaderAsProperty( + responseKind: responseKind, + typeName: typeName, + for: header) } + let headerStructComment: Comment? = { + let subPath = typeName.isComponent + ? "headers" + : "reponses/\(responseKind)/headers" + return typeName.docCommentWithUserDescription(nil, subPath: subPath) + }() let headersStructBlueprint: StructBlueprint = .init( - comment: nil, + comment: headerStructComment, access: config.access, typeName: headersTypeName, conformances: Constants.Operation.Output.Payload.Headers.conformances, @@ -76,22 +86,35 @@ extension TypesFileTranslator { ) bodyCases.append(contentsOf: inlineTypeDecls) } - let bodyCase: Declaration = .enumCase( - name: identifier, - kind: .nameWithAssociatedValues([ - .init(type: associatedType.fullyQualifiedSwiftName) - ]) + let subPathForContentCase = typeName.isComponent + ? "content/\(typedContent.content.contentType.lowercasedTypeAndSubtypeWithEscape)" + : "reponses/\(responseKind)/content/\(typedContent.content.contentType.lowercasedTypeAndSubtypeWithEscape)" + let bodyCase: Declaration = .commentable( + typeName.docCommentWithUserDescription(nil, subPath: subPathForContentCase), + .enumCase( + name: identifier, + kind: .nameWithAssociatedValues([ + .init(type: associatedType.fullyQualifiedSwiftName) + ]) + ) ) bodyCases.append(bodyCase) } + let subPathForContent = typeName.isComponent + ? "content" + : "reponses/\(responseKind)/content" let hasNoContent: Bool = bodyCases.isEmpty - let contentEnumDecl: Declaration = .enum( - isFrozen: true, - accessModifier: config.access, - name: bodyTypeName.shortSwiftName, - conformances: Constants.Operation.Body.conformances, - members: bodyCases + let contentEnumDecl: Declaration = .commentable( + typeName.docCommentWithUserDescription(nil, subPath: subPathForContent), + .enum( + isFrozen: true, + accessModifier: config.access, + name: bodyTypeName.shortSwiftName, + conformances: Constants.Operation.Body.conformances, + members: bodyCases + ) ) + let contentTypeUsage = bodyTypeName.asUsage.withOptional(hasNoContent) let contentProperty = PropertyBlueprint( comment: .doc("Received HTTP response body"), diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift index 2b4543d9..d5cd31c2 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift @@ -22,10 +22,18 @@ extension TypesFileTranslator { /// - header: A response parameter. /// - Returns: A property blueprint. func parseResponseHeaderAsProperty( + responseKind: String = "", + typeName: TypeName, for header: TypedResponseHeader ) throws -> PropertyBlueprint { + let comment: Comment? = { + let subPath: String = typeName.isComponent + ? "headers/\(header.name)" + : "reponses/\(responseKind)/headers/\(header.name)" + return typeName.docCommentWithUserDescription(nil, subPath: subPath) + }() return .init( - comment: nil, + comment: comment, originalName: header.name, typeUsage: header.typeUsage, default: header.header.required ? nil : .nil, diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift index f446fcc5..fa80a3db 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift @@ -42,6 +42,7 @@ extension TypesFileTranslator { let responseStructDecl: Declaration? if typedResponse.isInlined { responseStructDecl = try translateResponseInTypes( + responseKind: responseKind.jsonPathComponent, typeName: typedResponse.typeUsage.typeName, response: typedResponse ) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift b/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift index c1505b21..09312db2 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift @@ -126,6 +126,10 @@ struct TypeName: Equatable { precondition(components.count >= 1, "Cannot get the parent of a root type") return .init(components: components.dropLast()) } + + var isComponent: Bool { + description.contains("#/components") + } } extension TypeName: CustomStringConvertible { diff --git a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateOperations.swift b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateOperations.swift index 88521b64..bdcf461d 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateOperations.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateOperations.swift @@ -36,13 +36,16 @@ extension TypesFileTranslator { inParent: inputTypeName ) } - let structDecl: Declaration = translateStructBlueprint( - .init( - comment: nil, - access: config.access, - typeName: structTypeName, - conformances: Constants.Operation.Input.conformances, - properties: structProperties + let structDecl: Declaration = .commentable( + inputTypeName.docCommentWithUserDescription(nil, subPath: "\(location.rawValue)"), + translateStructBlueprint( + .init( + comment: nil, + access: config.access, + typeName: structTypeName, + conformances: Constants.Operation.Input.conformances, + properties: structProperties + ) ) ) From a36d9f8b265356a06cf6446dfeac20fb46df2e18 Mon Sep 17 00:00:00 2001 From: takeshi-1000 Date: Tue, 15 Aug 2023 12:29:17 +0900 Subject: [PATCH 2/8] modify `Types.swift` in reference sources. --- .../ReferenceSources/Petstore/Types.swift | 96 ++++++++++++++++++- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift index aaedc0cd..bfc1a00c 100644 --- a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift +++ b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift @@ -636,6 +636,7 @@ public enum Components { } /// Types generated from the `#/components/requestBodies` section of the OpenAPI document. public enum RequestBodies { + /// - Remark: Generated from `#/components/requestBodies/UpdatePetRequest`. @frozen public enum UpdatePetRequest: Sendable, Equatable, Hashable { /// - Remark: Generated from `#/components/requestBodies/UpdatePetRequest/json`. public struct jsonPayload: Codable, Equatable, Hashable, Sendable { @@ -666,13 +667,16 @@ public enum Components { case tag } } + /// - Remark: Generated from `#/components/requestBodies/UpdatePetRequest/content/application\/json`. case json(Components.RequestBodies.UpdatePetRequest.jsonPayload) } } /// Types generated from the `#/components/responses` section of the OpenAPI document. public enum Responses { public struct ErrorBadRequest: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/components/responses/ErrorBadRequest/headers`. public struct Headers: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/components/responses/ErrorBadRequest/headers/X-Reason`. public var X_Reason: Swift.String? /// Creates a new `Headers`. /// @@ -682,6 +686,7 @@ public enum Components { } /// Received HTTP response headers public var headers: Components.Responses.ErrorBadRequest.Headers + /// - Remark: Generated from `#/components/responses/ErrorBadRequest/content`. @frozen public enum Body: Sendable, Equatable, Hashable { /// - Remark: Generated from `#/components/responses/ErrorBadRequest/json`. public struct jsonPayload: Codable, Equatable, Hashable, Sendable { @@ -694,6 +699,7 @@ public enum Components { public init(code: Swift.Int) { self.code = code } public enum CodingKeys: String, CodingKey { case code } } + /// - Remark: Generated from `#/components/responses/ErrorBadRequest/content/application\/json`. case json(Components.Responses.ErrorBadRequest.Body.jsonPayload) } /// Received HTTP response body @@ -730,12 +736,15 @@ public enum Operations { public enum listPets { public static let id: String = "listPets" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/path`. public struct Path: Sendable, Equatable, Hashable { /// Creates a new `Path`. public init() {} } public var path: Operations.listPets.Input.Path + /// - Remark: Generated from `#/paths/pets/GET/query`. public struct Query: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/query/limit`. public var limit: Swift.Int32? /// - Remark: Generated from `#/paths/pets/GET/query/habitat`. @frozen @@ -768,6 +777,7 @@ public enum Operations { } public static var allCases: [habitatPayload] { [.water, .land, .air, ._empty] } } + /// - Remark: Generated from `#/paths/pets/GET/query/habitat`. public var habitat: Operations.listPets.Input.Query.habitatPayload? /// - Remark: Generated from `#/paths/pets/GET/query/feedsPayload`. @frozen @@ -802,7 +812,9 @@ public enum Operations { /// - Remark: Generated from `#/paths/pets/GET/query/feeds`. public typealias feedsPayload = [Operations.listPets.Input.Query .feedsPayloadPayload] + /// - Remark: Generated from `#/paths/pets/GET/query/feeds`. public var feeds: Operations.listPets.Input.Query.feedsPayload? + /// - Remark: Generated from `#/paths/pets/GET/query/since`. public var since: Components.Parameters.query_born_since? /// Creates a new `Query`. /// @@ -824,7 +836,9 @@ public enum Operations { } } public var query: Operations.listPets.Input.Query + /// - Remark: Generated from `#/paths/pets/GET/header`. public struct Headers: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/header/My-Request-UUID`. public var My_Request_UUID: Swift.String? /// Creates a new `Headers`. /// @@ -835,11 +849,13 @@ public enum Operations { } } public var headers: Operations.listPets.Input.Headers + /// - Remark: Generated from `#/paths/pets/GET/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} } public var cookies: Operations.listPets.Input.Cookies + /// - Remark: Generated from `#/paths/pets/GET/requestBody`. @frozen public enum Body: Sendable, Equatable, Hashable {} public var body: Operations.listPets.Input.Body? /// Creates a new `Input`. @@ -866,8 +882,11 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Ok: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/reponses/200/headers`. public struct Headers: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/reponses/200/headers/My-Response-UUID`. public var My_Response_UUID: Swift.String + /// - Remark: Generated from `#/paths/pets/GET/reponses/200/headers/My-Tracing-Header`. public var My_Tracing_Header: Components.Headers.TracingHeader? /// Creates a new `Headers`. /// @@ -884,7 +903,9 @@ public enum Operations { } /// Received HTTP response headers public var headers: Operations.listPets.Output.Ok.Headers + /// - Remark: Generated from `#/paths/pets/GET/reponses/200/content`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/reponses/200/content/application\/json`. case json(Components.Schemas.Pets) } /// Received HTTP response body @@ -909,13 +930,16 @@ public enum Operations { /// HTTP response code: `200 ok`. case ok(Operations.listPets.Output.Ok) public struct Default: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/reponses/default/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.listPets.Output.Default.Headers + /// - Remark: Generated from `#/paths/pets/GET/reponses/default/content`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/reponses/default/content/application\/json`. case json(Components.Schemas._Error) } /// Received HTTP response body @@ -948,17 +972,21 @@ public enum Operations { public enum createPet { public static let id: String = "createPet" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/POST/path`. public struct Path: Sendable, Equatable, Hashable { /// Creates a new `Path`. public init() {} } public var path: Operations.createPet.Input.Path + /// - Remark: Generated from `#/paths/pets/POST/query`. public struct Query: Sendable, Equatable, Hashable { /// Creates a new `Query`. public init() {} } public var query: Operations.createPet.Input.Query + /// - Remark: Generated from `#/paths/pets/POST/header`. public struct Headers: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/POST/header/X-Extra-Arguments`. public var X_Extra_Arguments: Components.Schemas.CodeError? /// Creates a new `Headers`. /// @@ -969,12 +997,15 @@ public enum Operations { } } public var headers: Operations.createPet.Input.Headers + /// - Remark: Generated from `#/paths/pets/POST/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} } public var cookies: Operations.createPet.Input.Cookies + /// - Remark: Generated from `#/paths/pets/POST/requestBody`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/POST/requestBody/content/application\/json`. case json(Components.Schemas.CreatePetRequest) } public var body: Operations.createPet.Input.Body @@ -1002,7 +1033,9 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Created: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/POST/reponses/201/headers`. public struct Headers: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/POST/reponses/201/headers/X-Extra-Arguments`. public var X_Extra_Arguments: Components.Schemas.CodeError? /// Creates a new `Headers`. /// @@ -1014,7 +1047,9 @@ public enum Operations { } /// Received HTTP response headers public var headers: Operations.createPet.Output.Created.Headers + /// - Remark: Generated from `#/paths/pets/POST/reponses/201/content`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/POST/reponses/201/content/application\/json`. case json(Components.Schemas.Pet) } /// Received HTTP response body @@ -1055,26 +1090,31 @@ public enum Operations { public enum getStats { public static let id: String = "getStats" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/stats/GET/path`. public struct Path: Sendable, Equatable, Hashable { /// Creates a new `Path`. public init() {} } public var path: Operations.getStats.Input.Path + /// - Remark: Generated from `#/paths/pets/stats/GET/query`. public struct Query: Sendable, Equatable, Hashable { /// Creates a new `Query`. public init() {} } public var query: Operations.getStats.Input.Query + /// - Remark: Generated from `#/paths/pets/stats/GET/header`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } public var headers: Operations.getStats.Input.Headers + /// - Remark: Generated from `#/paths/pets/stats/GET/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} } public var cookies: Operations.getStats.Input.Cookies + /// - Remark: Generated from `#/paths/pets/stats/GET/requestBody`. @frozen public enum Body: Sendable, Equatable, Hashable {} public var body: Operations.getStats.Input.Body? /// Creates a new `Input`. @@ -1101,13 +1141,16 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Ok: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/stats/GET/reponses/200/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.getStats.Output.Ok.Headers + /// - Remark: Generated from `#/paths/pets/stats/GET/reponses/200/content`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/stats/GET/reponses/200/content/application\/json`. case json(Components.Schemas.PetStats) } /// Received HTTP response body @@ -1142,27 +1185,33 @@ public enum Operations { public enum postStats { public static let id: String = "postStats" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/stats/POST/path`. public struct Path: Sendable, Equatable, Hashable { /// Creates a new `Path`. public init() {} } public var path: Operations.postStats.Input.Path + /// - Remark: Generated from `#/paths/pets/stats/POST/query`. public struct Query: Sendable, Equatable, Hashable { /// Creates a new `Query`. public init() {} } public var query: Operations.postStats.Input.Query + /// - Remark: Generated from `#/paths/pets/stats/POST/header`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } public var headers: Operations.postStats.Input.Headers + /// - Remark: Generated from `#/paths/pets/stats/POST/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} } public var cookies: Operations.postStats.Input.Cookies + /// - Remark: Generated from `#/paths/pets/stats/POST/requestBody`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/stats/POST/requestBody/content/application\/json`. case json(Components.Schemas.PetStats) } public var body: Operations.postStats.Input.Body @@ -1190,12 +1239,14 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Accepted: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/stats/POST/reponses/202/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.postStats.Output.Accepted.Headers + /// - Remark: Generated from `#/paths/pets/stats/POST/reponses/202/content`. @frozen public enum Body: Sendable, Equatable, Hashable {} /// Received HTTP response body public var body: Operations.postStats.Output.Accepted.Body? @@ -1229,26 +1280,31 @@ public enum Operations { public enum probe { public static let id: String = "probe" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/probe/POST/path`. public struct Path: Sendable, Equatable, Hashable { /// Creates a new `Path`. public init() {} } public var path: Operations.probe.Input.Path + /// - Remark: Generated from `#/paths/probe/POST/query`. public struct Query: Sendable, Equatable, Hashable { /// Creates a new `Query`. public init() {} } public var query: Operations.probe.Input.Query + /// - Remark: Generated from `#/paths/probe/POST/header`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } public var headers: Operations.probe.Input.Headers + /// - Remark: Generated from `#/paths/probe/POST/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} } public var cookies: Operations.probe.Input.Cookies + /// - Remark: Generated from `#/paths/probe/POST/requestBody`. @frozen public enum Body: Sendable, Equatable, Hashable {} public var body: Operations.probe.Input.Body? /// Creates a new `Input`. @@ -1275,12 +1331,14 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct NoContent: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/probe/POST/reponses/204/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.probe.Output.NoContent.Headers + /// - Remark: Generated from `#/paths/probe/POST/reponses/204/content`. @frozen public enum Body: Sendable, Equatable, Hashable {} /// Received HTTP response body public var body: Operations.probe.Output.NoContent.Body? @@ -1316,7 +1374,9 @@ public enum Operations { public enum updatePet { public static let id: String = "updatePet" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/path`. public struct Path: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/path/petId`. public var petId: Swift.Int64 /// Creates a new `Path`. /// @@ -1325,16 +1385,19 @@ public enum Operations { public init(petId: Swift.Int64) { self.petId = petId } } public var path: Operations.updatePet.Input.Path + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/query`. public struct Query: Sendable, Equatable, Hashable { /// Creates a new `Query`. public init() {} } public var query: Operations.updatePet.Input.Query + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/header`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } public var headers: Operations.updatePet.Input.Headers + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} @@ -1365,12 +1428,14 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct NoContent: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/reponses/204/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.updatePet.Output.NoContent.Headers + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/reponses/204/content`. @frozen public enum Body: Sendable, Equatable, Hashable {} /// Received HTTP response body public var body: Operations.updatePet.Output.NoContent.Body? @@ -1394,12 +1459,14 @@ public enum Operations { /// HTTP response code: `204 noContent`. case noContent(Operations.updatePet.Output.NoContent) public struct BadRequest: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/reponses/400/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.updatePet.Output.BadRequest.Headers + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/reponses/400/content`. @frozen public enum Body: Sendable, Equatable, Hashable { /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/json`. public struct jsonPayload: Codable, Equatable, Hashable, Sendable { @@ -1412,6 +1479,7 @@ public enum Operations { public init(message: Swift.String) { self.message = message } public enum CodingKeys: String, CodingKey { case message } } + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/reponses/400/content/application\/json`. case json(Operations.updatePet.Output.BadRequest.Body.jsonPayload) } /// Received HTTP response body @@ -1448,7 +1516,9 @@ public enum Operations { public enum uploadAvatarForPet { public static let id: String = "uploadAvatarForPet" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/path`. public struct Path: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/path/petId`. public var petId: Components.Parameters.path_petId /// Creates a new `Path`. /// @@ -1457,22 +1527,29 @@ public enum Operations { public init(petId: Components.Parameters.path_petId) { self.petId = petId } } public var path: Operations.uploadAvatarForPet.Input.Path + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/query`. public struct Query: Sendable, Equatable, Hashable { /// Creates a new `Query`. public init() {} } public var query: Operations.uploadAvatarForPet.Input.Query + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/header`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } public var headers: Operations.uploadAvatarForPet.Input.Headers + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} } public var cookies: Operations.uploadAvatarForPet.Input.Cookies - @frozen public enum Body: Sendable, Equatable, Hashable { case binary(Foundation.Data) } + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/requestBody`. + @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/requestBody/content/application\/octet-stream`. + case binary(Foundation.Data) + } public var body: Operations.uploadAvatarForPet.Input.Body /// Creates a new `Input`. /// @@ -1498,13 +1575,16 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Ok: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/200/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.uploadAvatarForPet.Output.Ok.Headers + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/200/content`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/200/content/application\/octet-stream`. case binary(Foundation.Data) } /// Received HTTP response body @@ -1529,13 +1609,18 @@ public enum Operations { /// HTTP response code: `200 ok`. case ok(Operations.uploadAvatarForPet.Output.Ok) public struct PreconditionFailed: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/412/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.uploadAvatarForPet.Output.PreconditionFailed.Headers - @frozen public enum Body: Sendable, Equatable, Hashable { case json(Swift.String) } + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/412/content`. + @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/412/content/application\/json`. + case json(Swift.String) + } /// Received HTTP response body public var body: Operations.uploadAvatarForPet.Output.PreconditionFailed.Body /// Creates a new `PreconditionFailed`. @@ -1559,13 +1644,18 @@ public enum Operations { /// HTTP response code: `412 preconditionFailed`. case preconditionFailed(Operations.uploadAvatarForPet.Output.PreconditionFailed) public struct InternalServerError: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/500/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.uploadAvatarForPet.Output.InternalServerError.Headers - @frozen public enum Body: Sendable, Equatable, Hashable { case text(Swift.String) } + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/500/content`. + @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/500/content/text\/plain`. + case text(Swift.String) + } /// Received HTTP response body public var body: Operations.uploadAvatarForPet.Output.InternalServerError.Body /// Creates a new `InternalServerError`. From 62428873074206cde7f30d7d5d9bf0b70a967962 Mon Sep 17 00:00:00 2001 From: takeshi-1000 Date: Wed, 16 Aug 2023 09:52:49 +0900 Subject: [PATCH 3/8] Apply suggestions from code review Co-authored-by: Honza Dvorsky --- .../Translator/Parameters/translateParameter.swift | 6 ++++-- .../Translator/RequestBody/translateRequestBody.swift | 6 ++---- .../Translator/Responses/translateResponse.swift | 4 ++-- .../Translator/Responses/translateResponseHeader.swift | 4 ++-- .../Translator/Responses/translateResponseOutcome.swift | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift index 7e153488..7eefa2a4 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift @@ -44,8 +44,10 @@ extension TypesFileTranslator { associatedDeclarations = [] } - let comment: Comment? = parent.docCommentWithUserDescription(nil, - subPath: "\(parameter.location.rawValue)/\(parameter.name)") + let comment: Comment? = parent.docCommentWithUserDescription( + nil, + subPath: "\(parameter.location.rawValue)/\(parameter.name)" + ) return .init( comment: comment, isDeprecated: parameter.parameter.deprecated, diff --git a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift index 636ea9d4..e95a01b5 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift @@ -41,7 +41,6 @@ extension TypesFileTranslator { /// - Returns: A list of declarations; empty if the request body is /// unsupported. func requestBodyContentCases( - typeName: TypeName, for requestBody: TypedRequestBody ) throws -> [Declaration] { var bodyMembers: [Declaration] = [] @@ -63,7 +62,7 @@ extension TypesFileTranslator { let contentCase: Declaration = .commentable( typeName.docCommentWithUserDescription(nil, subPath: subPath), - .enumCase(.init( + .enumCase( name: identifier, kind: .nameWithAssociatedValues([ .init(type: associatedType.fullyQualifiedNonOptionalSwiftName) @@ -139,8 +138,7 @@ extension TypesFileTranslator { requestBody: TypedRequestBody ) throws -> Declaration { let type = requestBody.typeUsage.typeName - let members = try requestBodyContentCases(typeName: type, - for: requestBody) + let members = try requestBodyContentCases(for: requestBody) return translateRequestBodyInTypes( typeName: type, members: members diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift index 261dae9b..2988e142 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift @@ -20,7 +20,7 @@ extension TypesFileTranslator { /// - typedResponse: The typed response to declare. /// - Returns: A structure declaration. func translateResponseInTypes( - responseKind: String = "", + responseKind: ResponseKind, typeName: TypeName, response: TypedResponse ) throws -> Declaration { @@ -43,7 +43,7 @@ extension TypesFileTranslator { let headerStructComment: Comment? = { let subPath = typeName.isComponent ? "headers" - : "reponses/\(responseKind)/headers" + : "responses/\(responseKind)/headers" return typeName.docCommentWithUserDescription(nil, subPath: subPath) }() let headersStructBlueprint: StructBlueprint = .init( diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift index d5cd31c2..7d2bd650 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift @@ -22,14 +22,14 @@ extension TypesFileTranslator { /// - header: A response parameter. /// - Returns: A property blueprint. func parseResponseHeaderAsProperty( - responseKind: String = "", + responseKind: ResponseKind, typeName: TypeName, for header: TypedResponseHeader ) throws -> PropertyBlueprint { let comment: Comment? = { let subPath: String = typeName.isComponent ? "headers/\(header.name)" - : "reponses/\(responseKind)/headers/\(header.name)" + : "responses/\(responseKind)/headers/\(header.name)" return typeName.docCommentWithUserDescription(nil, subPath: subPath) }() return .init( diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift index fa80a3db..ddafe9bd 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift @@ -42,7 +42,7 @@ extension TypesFileTranslator { let responseStructDecl: Declaration? if typedResponse.isInlined { responseStructDecl = try translateResponseInTypes( - responseKind: responseKind.jsonPathComponent, + responseKind: responseKind, typeName: typedResponse.typeUsage.typeName, response: typedResponse ) From 4188460d7e724641a0bda1a85e42990d2a26f613 Mon Sep 17 00:00:00 2001 From: takeshi-1000 Date: Wed, 16 Aug 2023 18:42:01 +0900 Subject: [PATCH 4/8] modify some code - fix around `responseKind` - make `isComponent` more reliable - add comment for some methods and property. - addjust soundness --- .../CommonTypes/CommentExtensions.swift | 9 ++++- .../Translator/Content/ContentType.swift | 6 ++- .../Parameters/translateParameter.swift | 2 +- .../RequestBody/translateRequestBody.swift | 13 ++++--- .../Responses/translateResponse.swift | 39 ++++++++++++------- .../Responses/translateResponseHeader.swift | 12 ++++-- .../Translator/TypeAssignment/TypeName.swift | 8 +++- .../translateComponentResponses.swift | 1 + 8 files changed, 62 insertions(+), 28 deletions(-) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/CommentExtensions.swift b/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/CommentExtensions.swift index 3b5fe6b2..b85d8524 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/CommentExtensions.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/CommentExtensions.swift @@ -96,14 +96,19 @@ extension TypeName { suffix: generatedFromCommentText ) } - + + /// Returns a documentation comment by appending the "generated from" with some path + /// string to the specified user description. + /// - Parameter userDescription: The description specified by the user + /// - Parameter subPath: Sub path following `fullyQualifiedJSONPath` + /// in the OpenAPI document. func docCommentWithUserDescription(_ userDescription: String?, subPath: String) -> Comment? { guard let fullyQualifiedJSONPath else { return Comment.doc(prefix: userDescription, suffix: nil) } return Comment.doc( prefix: userDescription, - suffix: "- Remark: Generated from `\(fullyQualifiedJSONPath)/\(subPath)`." + suffix: "- Remark: Generated from `\(fullyQualifiedJSONPath)/\(subPath)`." ) } } diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift b/Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift index f606f736..12ec2fef 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift @@ -142,7 +142,11 @@ struct ContentType: Hashable { var lowercasedTypeAndSubtype: String { "\(lowercasedType)/\(lowercasedSubtype)" } - + + /// Returns the type and subtype as a "\/" string. + /// + /// Lowercased to ease case-insensitive comparisons, + /// and escaped to show that the slash between type and subtype is not a path. var lowercasedTypeAndSubtypeWithEscape: String { "\(lowercasedType)\\/\(lowercasedSubtype)" } diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift index 7eefa2a4..f3b5f722 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift @@ -43,7 +43,7 @@ extension TypesFileTranslator { } else { associatedDeclarations = [] } - + let comment: Comment? = parent.docCommentWithUserDescription( nil, subPath: "\(parameter.location.rawValue)/\(parameter.name)" diff --git a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift index e95a01b5..2aa72183 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift @@ -54,20 +54,23 @@ extension TypesFileTranslator { } let identifier = contentSwiftName(content.content.contentType) let associatedType = content.resolvedTypeUsage - + let subPath: String = { - let contentPath = typeName.isComponent ? "content" : "requestBody/content" + let contentPath = requestBody.typeUsage.typeName.isComponent ? "content" : "requestBody/content" return "\(contentPath)/\(content.content.contentType.lowercasedTypeAndSubtypeWithEscape)" }() - + let contentCase: Declaration = .commentable( - typeName.docCommentWithUserDescription(nil, subPath: subPath), + requestBody + .typeUsage + .typeName + .docCommentWithUserDescription(nil, subPath: subPath), .enumCase( name: identifier, kind: .nameWithAssociatedValues([ .init(type: associatedType.fullyQualifiedNonOptionalSwiftName) ]) - )) + ) ) bodyMembers.append(contentCase) } diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift index 2988e142..84565b09 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift @@ -20,7 +20,7 @@ extension TypesFileTranslator { /// - typedResponse: The typed response to declare. /// - Returns: A structure declaration. func translateResponseInTypes( - responseKind: ResponseKind, + responseKind: ResponseKind?, typeName: TypeName, response: TypedResponse ) throws -> Declaration { @@ -38,13 +38,15 @@ extension TypesFileTranslator { try parseResponseHeaderAsProperty( responseKind: responseKind, typeName: typeName, - for: header) + for: header + ) } let headerStructComment: Comment? = { - let subPath = typeName.isComponent - ? "headers" - : "responses/\(responseKind)/headers" - return typeName.docCommentWithUserDescription(nil, subPath: subPath) + if let responseKind = responseKind?.jsonPathComponent, !typeName.isComponent { + return typeName.docCommentWithUserDescription(nil, subPath: "responses/\(responseKind)/headers") + } else { + return typeName.docCommentWithUserDescription(nil, subPath: "headers") + } }() let headersStructBlueprint: StructBlueprint = .init( comment: headerStructComment, @@ -86,9 +88,15 @@ extension TypesFileTranslator { ) bodyCases.append(contentsOf: inlineTypeDecls) } - let subPathForContentCase = typeName.isComponent - ? "content/\(typedContent.content.contentType.lowercasedTypeAndSubtypeWithEscape)" - : "reponses/\(responseKind)/content/\(typedContent.content.contentType.lowercasedTypeAndSubtypeWithEscape)" + + let subPathForContentCase: String = { + if let responseKind = responseKind?.jsonPathComponent, !typeName.isComponent { + return + "responses/\(responseKind)/content/\(typedContent.content.contentType.lowercasedTypeAndSubtypeWithEscape)" + } else { + return "content/\(typedContent.content.contentType.lowercasedTypeAndSubtypeWithEscape)" + } + }() let bodyCase: Declaration = .commentable( typeName.docCommentWithUserDescription(nil, subPath: subPathForContentCase), .enumCase( @@ -100,9 +108,13 @@ extension TypesFileTranslator { ) bodyCases.append(bodyCase) } - let subPathForContent = typeName.isComponent - ? "content" - : "reponses/\(responseKind)/content" + let subPathForContent: String = { + if let responseKind = responseKind?.jsonPathComponent, !typeName.isComponent { + return "responses/\(responseKind)/content" + } else { + return "content" + } + }() let hasNoContent: Bool = bodyCases.isEmpty let contentEnumDecl: Declaration = .commentable( typeName.docCommentWithUserDescription(nil, subPath: subPathForContent), @@ -114,7 +126,7 @@ extension TypesFileTranslator { members: bodyCases ) ) - + let contentTypeUsage = bodyTypeName.asUsage.withOptional(hasNoContent) let contentProperty = PropertyBlueprint( comment: .doc("Received HTTP response body"), @@ -159,6 +171,7 @@ extension TypesFileTranslator { of: OpenAPI.Response.self ) return try translateResponseInTypes( + responseKind: nil, typeName: typeName, response: response ) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift index 7d2bd650..24c0fc9f 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift @@ -22,14 +22,18 @@ extension TypesFileTranslator { /// - header: A response parameter. /// - Returns: A property blueprint. func parseResponseHeaderAsProperty( - responseKind: ResponseKind, + responseKind: ResponseKind?, typeName: TypeName, for header: TypedResponseHeader ) throws -> PropertyBlueprint { let comment: Comment? = { - let subPath: String = typeName.isComponent - ? "headers/\(header.name)" - : "responses/\(responseKind)/headers/\(header.name)" + let subPath: String = { + if let responseKind = responseKind?.jsonPathComponent, !typeName.isComponent { + return "responses/\(responseKind)/headers/\(header.name)" + } else { + return "headers/\(header.name)" + } + }() return typeName.docCommentWithUserDescription(nil, subPath: subPath) }() return .init( diff --git a/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift b/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift index 09312db2..b753a299 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift @@ -126,9 +126,13 @@ struct TypeName: Equatable { precondition(components.count >= 1, "Cannot get the parent of a root type") return .init(components: components.dropLast()) } - + + /// Returns a bool value indicating whether the list of JSON path components contains "#" first and "components" second. var isComponent: Bool { - description.contains("#/components") + guard let jsonKeyPathComponents else { + return false + } + return jsonKeyPathComponents[0] == "#" && jsonKeyPathComponents[1] == "components" } } diff --git a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateComponentResponses.swift b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateComponentResponses.swift index f9c64082..74addc7a 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateComponentResponses.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateComponentResponses.swift @@ -41,6 +41,7 @@ extension TypesFileTranslator { try typedResponses .map { value in try translateResponseInTypes( + responseKind: nil, typeName: value.typeUsage.typeName, response: value ) From 709e885b47b598ebc8c2f9ec1a6b5c4ac448cd86 Mon Sep 17 00:00:00 2001 From: takeshi-1000 Date: Wed, 16 Aug 2023 18:42:38 +0900 Subject: [PATCH 5/8] modify Types.swift --- .../ReferenceSources/Petstore/Types.swift | 66 ++++++------- .../Types.swift | 96 ++++++++++++++++++- 2 files changed, 127 insertions(+), 35 deletions(-) diff --git a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift index 6029caa6..e50d6ee3 100644 --- a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift +++ b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift @@ -882,11 +882,11 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Ok: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/GET/reponses/200/headers`. + /// - Remark: Generated from `#/paths/pets/GET/responses/200/headers`. public struct Headers: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/GET/reponses/200/headers/My-Response-UUID`. + /// - Remark: Generated from `#/paths/pets/GET/responses/200/headers/My-Response-UUID`. public var My_Response_UUID: Swift.String - /// - Remark: Generated from `#/paths/pets/GET/reponses/200/headers/My-Tracing-Header`. + /// - Remark: Generated from `#/paths/pets/GET/responses/200/headers/My-Tracing-Header`. public var My_Tracing_Header: Components.Headers.TracingHeader? /// Creates a new `Headers`. /// @@ -903,9 +903,9 @@ public enum Operations { } /// Received HTTP response headers public var headers: Operations.listPets.Output.Ok.Headers - /// - Remark: Generated from `#/paths/pets/GET/reponses/200/content`. + /// - Remark: Generated from `#/paths/pets/GET/responses/200/content`. @frozen public enum Body: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/GET/reponses/200/content/application\/json`. + /// - Remark: Generated from `#/paths/pets/GET/responses/200/content/application\/json`. case json(Components.Schemas.Pets) } /// Received HTTP response body @@ -930,16 +930,16 @@ public enum Operations { /// HTTP response code: `200 ok`. case ok(Operations.listPets.Output.Ok) public struct Default: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/GET/reponses/default/headers`. + /// - Remark: Generated from `#/paths/pets/GET/responses/default/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.listPets.Output.Default.Headers - /// - Remark: Generated from `#/paths/pets/GET/reponses/default/content`. + /// - Remark: Generated from `#/paths/pets/GET/responses/default/content`. @frozen public enum Body: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/GET/reponses/default/content/application\/json`. + /// - Remark: Generated from `#/paths/pets/GET/responses/default/content/application\/json`. case json(Components.Schemas._Error) } /// Received HTTP response body @@ -1033,9 +1033,9 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Created: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/POST/reponses/201/headers`. + /// - Remark: Generated from `#/paths/pets/POST/responses/201/headers`. public struct Headers: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/POST/reponses/201/headers/X-Extra-Arguments`. + /// - Remark: Generated from `#/paths/pets/POST/responses/201/headers/X-Extra-Arguments`. public var X_Extra_Arguments: Components.Schemas.CodeError? /// Creates a new `Headers`. /// @@ -1047,9 +1047,9 @@ public enum Operations { } /// Received HTTP response headers public var headers: Operations.createPet.Output.Created.Headers - /// - Remark: Generated from `#/paths/pets/POST/reponses/201/content`. + /// - Remark: Generated from `#/paths/pets/POST/responses/201/content`. @frozen public enum Body: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/POST/reponses/201/content/application\/json`. + /// - Remark: Generated from `#/paths/pets/POST/responses/201/content/application\/json`. case json(Components.Schemas.Pet) } /// Received HTTP response body @@ -1141,16 +1141,16 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Ok: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/stats/GET/reponses/200/headers`. + /// - Remark: Generated from `#/paths/pets/stats/GET/responses/200/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.getStats.Output.Ok.Headers - /// - Remark: Generated from `#/paths/pets/stats/GET/reponses/200/content`. + /// - Remark: Generated from `#/paths/pets/stats/GET/responses/200/content`. @frozen public enum Body: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/stats/GET/reponses/200/content/application\/json`. + /// - Remark: Generated from `#/paths/pets/stats/GET/responses/200/content/application\/json`. case json(Components.Schemas.PetStats) } /// Received HTTP response body @@ -1239,14 +1239,14 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Accepted: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/stats/POST/reponses/202/headers`. + /// - Remark: Generated from `#/paths/pets/stats/POST/responses/202/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.postStats.Output.Accepted.Headers - /// - Remark: Generated from `#/paths/pets/stats/POST/reponses/202/content`. + /// - Remark: Generated from `#/paths/pets/stats/POST/responses/202/content`. @frozen public enum Body: Sendable, Equatable, Hashable {} /// Received HTTP response body public var body: Operations.postStats.Output.Accepted.Body? @@ -1331,14 +1331,14 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct NoContent: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/probe/POST/reponses/204/headers`. + /// - Remark: Generated from `#/paths/probe/POST/responses/204/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.probe.Output.NoContent.Headers - /// - Remark: Generated from `#/paths/probe/POST/reponses/204/content`. + /// - Remark: Generated from `#/paths/probe/POST/responses/204/content`. @frozen public enum Body: Sendable, Equatable, Hashable {} /// Received HTTP response body public var body: Operations.probe.Output.NoContent.Body? @@ -1428,14 +1428,14 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct NoContent: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/reponses/204/headers`. + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/204/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.updatePet.Output.NoContent.Headers - /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/reponses/204/content`. + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/204/content`. @frozen public enum Body: Sendable, Equatable, Hashable {} /// Received HTTP response body public var body: Operations.updatePet.Output.NoContent.Body? @@ -1459,14 +1459,14 @@ public enum Operations { /// HTTP response code: `204 noContent`. case noContent(Operations.updatePet.Output.NoContent) public struct BadRequest: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/reponses/400/headers`. + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/400/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.updatePet.Output.BadRequest.Headers - /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/reponses/400/content`. + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/400/content`. @frozen public enum Body: Sendable, Equatable, Hashable { /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/json`. public struct jsonPayload: Codable, Equatable, Hashable, Sendable { @@ -1479,7 +1479,7 @@ public enum Operations { public init(message: Swift.String) { self.message = message } public enum CodingKeys: String, CodingKey { case message } } - /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/reponses/400/content/application\/json`. + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/400/content/application\/json`. case json(Operations.updatePet.Output.BadRequest.Body.jsonPayload) } /// Received HTTP response body @@ -1575,16 +1575,16 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Ok: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/200/headers`. + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/200/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.uploadAvatarForPet.Output.Ok.Headers - /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/200/content`. + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/200/content`. @frozen public enum Body: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/200/content/application\/octet-stream`. + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/200/content/application\/octet-stream`. case binary(Foundation.Data) } /// Received HTTP response body @@ -1609,16 +1609,16 @@ public enum Operations { /// HTTP response code: `200 ok`. case ok(Operations.uploadAvatarForPet.Output.Ok) public struct PreconditionFailed: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/412/headers`. + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/412/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.uploadAvatarForPet.Output.PreconditionFailed.Headers - /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/412/content`. + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/412/content`. @frozen public enum Body: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/412/content/application\/json`. + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/412/content/application\/json`. case json(Swift.String) } /// Received HTTP response body @@ -1644,16 +1644,16 @@ public enum Operations { /// HTTP response code: `412 preconditionFailed`. case preconditionFailed(Operations.uploadAvatarForPet.Output.PreconditionFailed) public struct InternalServerError: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/500/headers`. + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/500/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.uploadAvatarForPet.Output.InternalServerError.Headers - /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/500/content`. + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/500/content`. @frozen public enum Body: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/reponses/500/content/text\/plain`. + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/500/content/text\/plain`. case text(Swift.String) } /// Received HTTP response body diff --git a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Types.swift b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Types.swift index 199f1c58..7243d867 100644 --- a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Types.swift +++ b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Types.swift @@ -636,6 +636,7 @@ public enum Components { } /// Types generated from the `#/components/requestBodies` section of the OpenAPI document. public enum RequestBodies { + /// - Remark: Generated from `#/components/requestBodies/UpdatePetRequest`. @frozen public enum UpdatePetRequest: Sendable, Equatable, Hashable { /// - Remark: Generated from `#/components/requestBodies/UpdatePetRequest/json`. public struct jsonPayload: Codable, Equatable, Hashable, Sendable { @@ -666,13 +667,16 @@ public enum Components { case tag } } + /// - Remark: Generated from `#/components/requestBodies/UpdatePetRequest/content/application\/json`. case json(Components.RequestBodies.UpdatePetRequest.jsonPayload) } } /// Types generated from the `#/components/responses` section of the OpenAPI document. public enum Responses { public struct ErrorBadRequest: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/components/responses/ErrorBadRequest/headers`. public struct Headers: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/components/responses/ErrorBadRequest/headers/X-Reason`. public var X_hyphen_Reason: Swift.String? /// Creates a new `Headers`. /// @@ -684,6 +688,7 @@ public enum Components { } /// Received HTTP response headers public var headers: Components.Responses.ErrorBadRequest.Headers + /// - Remark: Generated from `#/components/responses/ErrorBadRequest/content`. @frozen public enum Body: Sendable, Equatable, Hashable { /// - Remark: Generated from `#/components/responses/ErrorBadRequest/json`. public struct jsonPayload: Codable, Equatable, Hashable, Sendable { @@ -696,6 +701,7 @@ public enum Components { public init(code: Swift.Int) { self.code = code } public enum CodingKeys: String, CodingKey { case code } } + /// - Remark: Generated from `#/components/responses/ErrorBadRequest/content/application\/json`. case json(Components.Responses.ErrorBadRequest.Body.jsonPayload) } /// Received HTTP response body @@ -732,12 +738,15 @@ public enum Operations { public enum listPets { public static let id: String = "listPets" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/path`. public struct Path: Sendable, Equatable, Hashable { /// Creates a new `Path`. public init() {} } public var path: Operations.listPets.Input.Path + /// - Remark: Generated from `#/paths/pets/GET/query`. public struct Query: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/query/limit`. public var limit: Swift.Int32? /// - Remark: Generated from `#/paths/pets/GET/query/habitat`. @frozen @@ -770,6 +779,7 @@ public enum Operations { } public static var allCases: [habitatPayload] { [.water, .land, .air, ._empty] } } + /// - Remark: Generated from `#/paths/pets/GET/query/habitat`. public var habitat: Operations.listPets.Input.Query.habitatPayload? /// - Remark: Generated from `#/paths/pets/GET/query/feedsPayload`. @frozen @@ -804,7 +814,9 @@ public enum Operations { /// - Remark: Generated from `#/paths/pets/GET/query/feeds`. public typealias feedsPayload = [Operations.listPets.Input.Query .feedsPayloadPayload] + /// - Remark: Generated from `#/paths/pets/GET/query/feeds`. public var feeds: Operations.listPets.Input.Query.feedsPayload? + /// - Remark: Generated from `#/paths/pets/GET/query/since`. public var since: Components.Parameters.query_period_born_hyphen_since? /// Creates a new `Query`. /// @@ -826,7 +838,9 @@ public enum Operations { } } public var query: Operations.listPets.Input.Query + /// - Remark: Generated from `#/paths/pets/GET/header`. public struct Headers: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/header/My-Request-UUID`. public var My_hyphen_Request_hyphen_UUID: Swift.String? /// Creates a new `Headers`. /// @@ -837,11 +851,13 @@ public enum Operations { } } public var headers: Operations.listPets.Input.Headers + /// - Remark: Generated from `#/paths/pets/GET/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} } public var cookies: Operations.listPets.Input.Cookies + /// - Remark: Generated from `#/paths/pets/GET/requestBody`. @frozen public enum Body: Sendable, Equatable, Hashable {} public var body: Operations.listPets.Input.Body? /// Creates a new `Input`. @@ -868,8 +884,11 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Ok: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/responses/200/headers`. public struct Headers: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/responses/200/headers/My-Response-UUID`. public var My_hyphen_Response_hyphen_UUID: Swift.String + /// - Remark: Generated from `#/paths/pets/GET/responses/200/headers/My-Tracing-Header`. public var My_hyphen_Tracing_hyphen_Header: Components.Headers.TracingHeader? /// Creates a new `Headers`. /// @@ -886,7 +905,9 @@ public enum Operations { } /// Received HTTP response headers public var headers: Operations.listPets.Output.Ok.Headers + /// - Remark: Generated from `#/paths/pets/GET/responses/200/content`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/responses/200/content/application\/json`. case json(Components.Schemas.Pets) } /// Received HTTP response body @@ -911,13 +932,16 @@ public enum Operations { /// HTTP response code: `200 ok`. case ok(Operations.listPets.Output.Ok) public struct Default: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/responses/default/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.listPets.Output.Default.Headers + /// - Remark: Generated from `#/paths/pets/GET/responses/default/content`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/GET/responses/default/content/application\/json`. case json(Components.Schemas._Error) } /// Received HTTP response body @@ -950,17 +974,21 @@ public enum Operations { public enum createPet { public static let id: String = "createPet" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/POST/path`. public struct Path: Sendable, Equatable, Hashable { /// Creates a new `Path`. public init() {} } public var path: Operations.createPet.Input.Path + /// - Remark: Generated from `#/paths/pets/POST/query`. public struct Query: Sendable, Equatable, Hashable { /// Creates a new `Query`. public init() {} } public var query: Operations.createPet.Input.Query + /// - Remark: Generated from `#/paths/pets/POST/header`. public struct Headers: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/POST/header/X-Extra-Arguments`. public var X_hyphen_Extra_hyphen_Arguments: Components.Schemas.CodeError? /// Creates a new `Headers`. /// @@ -971,12 +999,15 @@ public enum Operations { } } public var headers: Operations.createPet.Input.Headers + /// - Remark: Generated from `#/paths/pets/POST/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} } public var cookies: Operations.createPet.Input.Cookies + /// - Remark: Generated from `#/paths/pets/POST/requestBody`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/POST/requestBody/content/application\/json`. case json(Components.Schemas.CreatePetRequest) } public var body: Operations.createPet.Input.Body @@ -1004,7 +1035,9 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Created: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/POST/responses/201/headers`. public struct Headers: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/POST/responses/201/headers/X-Extra-Arguments`. public var X_hyphen_Extra_hyphen_Arguments: Components.Schemas.CodeError? /// Creates a new `Headers`. /// @@ -1016,7 +1049,9 @@ public enum Operations { } /// Received HTTP response headers public var headers: Operations.createPet.Output.Created.Headers + /// - Remark: Generated from `#/paths/pets/POST/responses/201/content`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/POST/responses/201/content/application\/json`. case json(Components.Schemas.Pet) } /// Received HTTP response body @@ -1057,26 +1092,31 @@ public enum Operations { public enum getStats { public static let id: String = "getStats" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/stats/GET/path`. public struct Path: Sendable, Equatable, Hashable { /// Creates a new `Path`. public init() {} } public var path: Operations.getStats.Input.Path + /// - Remark: Generated from `#/paths/pets/stats/GET/query`. public struct Query: Sendable, Equatable, Hashable { /// Creates a new `Query`. public init() {} } public var query: Operations.getStats.Input.Query + /// - Remark: Generated from `#/paths/pets/stats/GET/header`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } public var headers: Operations.getStats.Input.Headers + /// - Remark: Generated from `#/paths/pets/stats/GET/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} } public var cookies: Operations.getStats.Input.Cookies + /// - Remark: Generated from `#/paths/pets/stats/GET/requestBody`. @frozen public enum Body: Sendable, Equatable, Hashable {} public var body: Operations.getStats.Input.Body? /// Creates a new `Input`. @@ -1103,15 +1143,20 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Ok: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/stats/GET/responses/200/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.getStats.Output.Ok.Headers + /// - Remark: Generated from `#/paths/pets/stats/GET/responses/200/content`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/stats/GET/responses/200/content/application\/json`. case json(Components.Schemas.PetStats) + /// - Remark: Generated from `#/paths/pets/stats/GET/responses/200/content/text\/plain`. case plainText(Swift.String) + /// - Remark: Generated from `#/paths/pets/stats/GET/responses/200/content/application\/octet-stream`. case binary(Foundation.Data) } /// Received HTTP response body @@ -1146,29 +1191,37 @@ public enum Operations { public enum postStats { public static let id: String = "postStats" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/stats/POST/path`. public struct Path: Sendable, Equatable, Hashable { /// Creates a new `Path`. public init() {} } public var path: Operations.postStats.Input.Path + /// - Remark: Generated from `#/paths/pets/stats/POST/query`. public struct Query: Sendable, Equatable, Hashable { /// Creates a new `Query`. public init() {} } public var query: Operations.postStats.Input.Query + /// - Remark: Generated from `#/paths/pets/stats/POST/header`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } public var headers: Operations.postStats.Input.Headers + /// - Remark: Generated from `#/paths/pets/stats/POST/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} } public var cookies: Operations.postStats.Input.Cookies + /// - Remark: Generated from `#/paths/pets/stats/POST/requestBody`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/stats/POST/requestBody/content/application\/json`. case json(Components.Schemas.PetStats) + /// - Remark: Generated from `#/paths/pets/stats/POST/requestBody/content/text\/plain`. case plainText(Swift.String) + /// - Remark: Generated from `#/paths/pets/stats/POST/requestBody/content/application\/octet-stream`. case binary(Foundation.Data) } public var body: Operations.postStats.Input.Body @@ -1196,12 +1249,14 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Accepted: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/stats/POST/responses/202/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.postStats.Output.Accepted.Headers + /// - Remark: Generated from `#/paths/pets/stats/POST/responses/202/content`. @frozen public enum Body: Sendable, Equatable, Hashable {} /// Received HTTP response body public var body: Operations.postStats.Output.Accepted.Body? @@ -1235,26 +1290,31 @@ public enum Operations { public enum probe { public static let id: String = "probe" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/probe/POST/path`. public struct Path: Sendable, Equatable, Hashable { /// Creates a new `Path`. public init() {} } public var path: Operations.probe.Input.Path + /// - Remark: Generated from `#/paths/probe/POST/query`. public struct Query: Sendable, Equatable, Hashable { /// Creates a new `Query`. public init() {} } public var query: Operations.probe.Input.Query + /// - Remark: Generated from `#/paths/probe/POST/header`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } public var headers: Operations.probe.Input.Headers + /// - Remark: Generated from `#/paths/probe/POST/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} } public var cookies: Operations.probe.Input.Cookies + /// - Remark: Generated from `#/paths/probe/POST/requestBody`. @frozen public enum Body: Sendable, Equatable, Hashable {} public var body: Operations.probe.Input.Body? /// Creates a new `Input`. @@ -1281,12 +1341,14 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct NoContent: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/probe/POST/responses/204/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.probe.Output.NoContent.Headers + /// - Remark: Generated from `#/paths/probe/POST/responses/204/content`. @frozen public enum Body: Sendable, Equatable, Hashable {} /// Received HTTP response body public var body: Operations.probe.Output.NoContent.Body? @@ -1322,7 +1384,9 @@ public enum Operations { public enum updatePet { public static let id: String = "updatePet" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/path`. public struct Path: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/path/petId`. public var petId: Swift.Int64 /// Creates a new `Path`. /// @@ -1331,16 +1395,19 @@ public enum Operations { public init(petId: Swift.Int64) { self.petId = petId } } public var path: Operations.updatePet.Input.Path + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/query`. public struct Query: Sendable, Equatable, Hashable { /// Creates a new `Query`. public init() {} } public var query: Operations.updatePet.Input.Query + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/header`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } public var headers: Operations.updatePet.Input.Headers + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} @@ -1371,12 +1438,14 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct NoContent: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/204/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.updatePet.Output.NoContent.Headers + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/204/content`. @frozen public enum Body: Sendable, Equatable, Hashable {} /// Received HTTP response body public var body: Operations.updatePet.Output.NoContent.Body? @@ -1400,12 +1469,14 @@ public enum Operations { /// HTTP response code: `204 noContent`. case noContent(Operations.updatePet.Output.NoContent) public struct BadRequest: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/400/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.updatePet.Output.BadRequest.Headers + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/400/content`. @frozen public enum Body: Sendable, Equatable, Hashable { /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/json`. public struct jsonPayload: Codable, Equatable, Hashable, Sendable { @@ -1418,6 +1489,7 @@ public enum Operations { public init(message: Swift.String) { self.message = message } public enum CodingKeys: String, CodingKey { case message } } + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/400/content/application\/json`. case json(Operations.updatePet.Output.BadRequest.Body.jsonPayload) } /// Received HTTP response body @@ -1454,7 +1526,9 @@ public enum Operations { public enum uploadAvatarForPet { public static let id: String = "uploadAvatarForPet" public struct Input: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/path`. public struct Path: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/path/petId`. public var petId: Components.Parameters.path_period_petId /// Creates a new `Path`. /// @@ -1463,22 +1537,29 @@ public enum Operations { public init(petId: Components.Parameters.path_period_petId) { self.petId = petId } } public var path: Operations.uploadAvatarForPet.Input.Path + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/query`. public struct Query: Sendable, Equatable, Hashable { /// Creates a new `Query`. public init() {} } public var query: Operations.uploadAvatarForPet.Input.Query + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/header`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } public var headers: Operations.uploadAvatarForPet.Input.Headers + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/cookie`. public struct Cookies: Sendable, Equatable, Hashable { /// Creates a new `Cookies`. public init() {} } public var cookies: Operations.uploadAvatarForPet.Input.Cookies - @frozen public enum Body: Sendable, Equatable, Hashable { case binary(Foundation.Data) } + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/requestBody`. + @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/requestBody/content/application\/octet-stream`. + case binary(Foundation.Data) + } public var body: Operations.uploadAvatarForPet.Input.Body /// Creates a new `Input`. /// @@ -1504,13 +1585,16 @@ public enum Operations { } @frozen public enum Output: Sendable, Equatable, Hashable { public struct Ok: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/200/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.uploadAvatarForPet.Output.Ok.Headers + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/200/content`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/200/content/application\/octet-stream`. case binary(Foundation.Data) } /// Received HTTP response body @@ -1535,13 +1619,18 @@ public enum Operations { /// HTTP response code: `200 ok`. case ok(Operations.uploadAvatarForPet.Output.Ok) public struct PreconditionFailed: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/412/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.uploadAvatarForPet.Output.PreconditionFailed.Headers - @frozen public enum Body: Sendable, Equatable, Hashable { case json(Swift.String) } + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/412/content`. + @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/412/content/application\/json`. + case json(Swift.String) + } /// Received HTTP response body public var body: Operations.uploadAvatarForPet.Output.PreconditionFailed.Body /// Creates a new `PreconditionFailed`. @@ -1565,13 +1654,16 @@ public enum Operations { /// HTTP response code: `412 preconditionFailed`. case preconditionFailed(Operations.uploadAvatarForPet.Output.PreconditionFailed) public struct InternalServerError: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/500/headers`. public struct Headers: Sendable, Equatable, Hashable { /// Creates a new `Headers`. public init() {} } /// Received HTTP response headers public var headers: Operations.uploadAvatarForPet.Output.InternalServerError.Headers + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/500/content`. @frozen public enum Body: Sendable, Equatable, Hashable { + /// - Remark: Generated from `#/paths/pets/{petId}/avatar/PUT/responses/500/content/text\/plain`. case plainText(Swift.String) } /// Received HTTP response body From 076b40f5593b958c31fb7065fa6b4e9c87bc9d78 Mon Sep 17 00:00:00 2001 From: takeshi-1000 Date: Thu, 17 Aug 2023 09:32:10 +0900 Subject: [PATCH 6/8] Apply suggestions from code review Co-authored-by: Honza Dvorsky --- .../RequestBody/translateRequestBody.swift | 13 ++++++------- .../Translator/TypeAssignment/TypeName.swift | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift index 2aa72183..9fcc654d 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift @@ -52,18 +52,17 @@ extension TypesFileTranslator { ) bodyMembers.append(contentsOf: inlineTypeDecls) } - let identifier = contentSwiftName(content.content.contentType) + let contentType = content.content.contentType + let identifier = contentSwiftName(contentType) let associatedType = content.resolvedTypeUsage + let typeName = requestBody.typeUsage.typeName let subPath: String = { - let contentPath = requestBody.typeUsage.typeName.isComponent ? "content" : "requestBody/content" - return "\(contentPath)/\(content.content.contentType.lowercasedTypeAndSubtypeWithEscape)" + let contentPath = (typeName.isComponent ? "" : "requestBody/") + "content" + return "\(contentPath)/\(contentType.lowercasedTypeAndSubtypeWithEscape)" }() - let contentCase: Declaration = .commentable( - requestBody - .typeUsage - .typeName + typeName .docCommentWithUserDescription(nil, subPath: subPath), .enumCase( name: identifier, diff --git a/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift b/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift index b753a299..ecbebb0d 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift @@ -128,7 +128,7 @@ struct TypeName: Equatable { } /// Returns a bool value indicating whether the list of JSON path components contains "#" first and "components" second. - var isComponent: Bool { + var isInComponents: Bool { guard let jsonKeyPathComponents else { return false } From 5ff67b8a1795b52ceefeae5d2c840008642e96ff Mon Sep 17 00:00:00 2001 From: takeshi-1000 Date: Thu, 17 Aug 2023 09:39:20 +0900 Subject: [PATCH 7/8] apply code review and fix compile error --- .../RequestBody/translateRequestBody.swift | 4 ++-- .../Responses/translateResponse.swift | 18 ++++++------------ .../Responses/translateResponseHeader.swift | 16 ++++++++-------- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift index 9fcc654d..f706f278 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift @@ -58,7 +58,7 @@ extension TypesFileTranslator { let typeName = requestBody.typeUsage.typeName let subPath: String = { - let contentPath = (typeName.isComponent ? "" : "requestBody/") + "content" + let contentPath = (typeName.isInComponents ? "" : "requestBody/") + "content" return "\(contentPath)/\(contentType.lowercasedTypeAndSubtypeWithEscape)" }() let contentCase: Declaration = .commentable( @@ -164,7 +164,7 @@ extension TypesFileTranslator { members: members ) let comment: Comment? = { - if typeName.isComponent { + if typeName.isInComponents { return typeName.docCommentWithUserDescription(nil) } else { return typeName.docCommentWithUserDescription(nil, subPath: "requestBody") diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift index 84565b09..0e4fe543 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift @@ -24,8 +24,8 @@ extension TypesFileTranslator { typeName: TypeName, response: TypedResponse ) throws -> Declaration { - let response = response.response + let subPathPrefixInOperations: String = "responses/\(responseKind?.jsonPathComponent ?? "")" let headersTypeName = typeName.appending( swiftComponent: Constants.Operation.Output.Payload.Headers.typeName @@ -42,8 +42,8 @@ extension TypesFileTranslator { ) } let headerStructComment: Comment? = { - if let responseKind = responseKind?.jsonPathComponent, !typeName.isComponent { - return typeName.docCommentWithUserDescription(nil, subPath: "responses/\(responseKind)/headers") + if !typeName.isInComponents { + return typeName.docCommentWithUserDescription(nil, subPath: "\(subPathPrefixInOperations)/headers") } else { return typeName.docCommentWithUserDescription(nil, subPath: "headers") } @@ -90,9 +90,9 @@ extension TypesFileTranslator { } let subPathForContentCase: String = { - if let responseKind = responseKind?.jsonPathComponent, !typeName.isComponent { + if !typeName.isInComponents { return - "responses/\(responseKind)/content/\(typedContent.content.contentType.lowercasedTypeAndSubtypeWithEscape)" + "\(subPathPrefixInOperations)/content/\(typedContent.content.contentType.lowercasedTypeAndSubtypeWithEscape)" } else { return "content/\(typedContent.content.contentType.lowercasedTypeAndSubtypeWithEscape)" } @@ -108,13 +108,7 @@ extension TypesFileTranslator { ) bodyCases.append(bodyCase) } - let subPathForContent: String = { - if let responseKind = responseKind?.jsonPathComponent, !typeName.isComponent { - return "responses/\(responseKind)/content" - } else { - return "content" - } - }() + let subPathForContent: String = !typeName.isInComponents ? "\(subPathPrefixInOperations)/content" : "content" let hasNoContent: Bool = bodyCases.isEmpty let contentEnumDecl: Declaration = .commentable( typeName.docCommentWithUserDescription(nil, subPath: subPathForContent), diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift index 24c0fc9f..51ea81ae 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift @@ -27,14 +27,14 @@ extension TypesFileTranslator { for header: TypedResponseHeader ) throws -> PropertyBlueprint { let comment: Comment? = { - let subPath: String = { - if let responseKind = responseKind?.jsonPathComponent, !typeName.isComponent { - return "responses/\(responseKind)/headers/\(header.name)" - } else { - return "headers/\(header.name)" - } - }() - return typeName.docCommentWithUserDescription(nil, subPath: subPath) + if let responseKind = responseKind?.jsonPathComponent, !typeName.isInComponents { + return typeName.docCommentWithUserDescription( + nil, + subPath: "responses/\(responseKind)/headers/\(header.name)" + ) + } else { + return typeName.docCommentWithUserDescription(nil, subPath: "headers/\(header.name)") + } }() return .init( comment: comment, From 692c1e8134199dfbdde319f0edc90b4abbe10abf Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Thu, 17 Aug 2023 10:05:57 +0200 Subject: [PATCH 8/8] Refactored for easier extensibility --- .../CommonTypes/CommentExtensions.swift | 34 +++++++++++++-- .../Translator/Content/ContentType.swift | 4 +- .../Operations/OperationDescription.swift | 5 +-- .../Parameters/translateParameter.swift | 7 +--- .../RequestBody/TypedRequestBody.swift | 3 +- .../RequestBody/translateRequestBody.swift | 27 +++++------- .../Translator/Responses/ResponseKind.swift | 5 ++- .../Responses/translateResponse.swift | 41 ++++++------------- .../Responses/translateResponseHeader.swift | 20 ++++----- .../Responses/translateResponseOutcome.swift | 1 - .../Translator/TypeAssignment/TypeName.swift | 12 ++---- .../translateComponentResponses.swift | 1 - .../TypesTranslator/translateOperations.swift | 2 +- .../ReferenceSources/Petstore/Types.swift | 8 ++-- .../Types.swift | 8 ++-- 15 files changed, 82 insertions(+), 96 deletions(-) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/CommentExtensions.swift b/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/CommentExtensions.swift index b85d8524..b35829a2 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/CommentExtensions.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/CommentExtensions.swift @@ -97,11 +97,13 @@ extension TypeName { ) } - /// Returns a documentation comment by appending the "generated from" with some path + /// Returns a documentation comment by appending the "generated from" /// string to the specified user description. - /// - Parameter userDescription: The description specified by the user - /// - Parameter subPath: Sub path following `fullyQualifiedJSONPath` - /// in the OpenAPI document. + /// + /// The "generated from" string also includes a subpath. + /// - Parameter userDescription: The description specified by the user. + /// - Parameter subPath: A subpath appended to the JSON path of this + /// type name. func docCommentWithUserDescription(_ userDescription: String?, subPath: String) -> Comment? { guard let fullyQualifiedJSONPath else { return Comment.doc(prefix: userDescription, suffix: nil) @@ -146,6 +148,30 @@ extension ResponseKind { } } +extension TypedParameter { + /// Returns a documentation comment for the parameter. + /// - Parameters: + /// - parent: The parent type of the parameter. + func docComment(parent: TypeName) -> Comment? { + parent.docCommentWithUserDescription( + nil, + subPath: "\(parameter.location.rawValue)/\(parameter.name)" + ) + } +} + +extension ContentType { + /// Returns a documentation comment for the content type. + /// - Parameters: + /// - typeName: The type name of the content. + func docComment(typeName: TypeName) -> Comment? { + typeName.docCommentWithUserDescription( + nil, + subPath: lowercasedTypeAndSubtypeWithEscape + ) + } +} + extension Comment { /// Returns a reference documentation string to attach to the generated function for an operation. diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift b/Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift index 12ec2fef..5b29ce76 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift @@ -145,8 +145,8 @@ struct ContentType: Hashable { /// Returns the type and subtype as a "\/" string. /// - /// Lowercased to ease case-insensitive comparisons, - /// and escaped to show that the slash between type and subtype is not a path. + /// Lowercased to ease case-insensitive comparisons, and escaped to show + /// that the slash between type and subtype is not a path separator. var lowercasedTypeAndSubtypeWithEscape: String { "\(lowercasedType)\\/\(lowercasedSubtype)" } diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Operations/OperationDescription.swift b/Sources/_OpenAPIGeneratorCore/Translator/Operations/OperationDescription.swift index b21f63fc..19aedf6e 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Operations/OperationDescription.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Operations/OperationDescription.swift @@ -137,10 +137,7 @@ extension OperationDescription { var outputTypeName: TypeName { operationNamespace.appending( swiftComponent: Constants.Operation.Output.typeName, - - // intentionally nil, we'll append the specific params etc - // with their valid JSON key path when nested inside Output - jsonComponent: nil + jsonComponent: "responses" ) } diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift index f3b5f722..571e9936 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift @@ -43,13 +43,8 @@ extension TypesFileTranslator { } else { associatedDeclarations = [] } - - let comment: Comment? = parent.docCommentWithUserDescription( - nil, - subPath: "\(parameter.location.rawValue)/\(parameter.name)" - ) return .init( - comment: comment, + comment: parameter.docComment(parent: parent), isDeprecated: parameter.parameter.deprecated, originalName: parameter.name, typeUsage: parameter.typeUsage, diff --git a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/TypedRequestBody.swift b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/TypedRequestBody.swift index e61abe24..3a2a3266 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/TypedRequestBody.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/TypedRequestBody.swift @@ -64,7 +64,8 @@ extension FileTranslator { type = try typeAssigner.typeName(for: reference) case .b: type = parent.appending( - swiftComponent: Constants.Operation.Body.typeName + swiftComponent: Constants.Operation.Body.typeName, + jsonComponent: "requestBody" ) } return try typedRequestBody( diff --git a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift index f706f278..54df348e 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift @@ -44,6 +44,8 @@ extension TypesFileTranslator { for requestBody: TypedRequestBody ) throws -> [Declaration] { var bodyMembers: [Declaration] = [] + let typeName = requestBody.typeUsage.typeName + let contentTypeName = typeName.appending(jsonComponent: "content") let contents = requestBody.contents for content in contents { if TypeMatcher.isInlinable(content.content.schema) { @@ -55,15 +57,8 @@ extension TypesFileTranslator { let contentType = content.content.contentType let identifier = contentSwiftName(contentType) let associatedType = content.resolvedTypeUsage - - let typeName = requestBody.typeUsage.typeName - let subPath: String = { - let contentPath = (typeName.isInComponents ? "" : "requestBody/") + "content" - return "\(contentPath)/\(contentType.lowercasedTypeAndSubtypeWithEscape)" - }() let contentCase: Declaration = .commentable( - typeName - .docCommentWithUserDescription(nil, subPath: subPath), + contentType.docComment(typeName: contentTypeName), .enumCase( name: identifier, kind: .nameWithAssociatedValues([ @@ -108,7 +103,8 @@ extension TypesFileTranslator { } else { isRequestBodyOptional = true bodyEnumTypeName = parent.appending( - swiftComponent: Constants.Operation.Body.typeName + swiftComponent: Constants.Operation.Body.typeName, + jsonComponent: "requestBody" ) extraDecls = [ translateRequestBodyInTypes( @@ -163,14 +159,11 @@ extension TypesFileTranslator { conformances: Constants.Operation.Output.conformances, members: members ) - let comment: Comment? = { - if typeName.isInComponents { - return typeName.docCommentWithUserDescription(nil) - } else { - return typeName.docCommentWithUserDescription(nil, subPath: "requestBody") - } - }() - return .commentable(comment, bodyEnumDecl) + let comment: Comment? = typeName.docCommentWithUserDescription(nil) + return .commentable( + comment, + bodyEnumDecl + ) } } diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/ResponseKind.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/ResponseKind.swift index c292e549..a87f516f 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/ResponseKind.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/ResponseKind.swift @@ -181,7 +181,10 @@ enum ResponseKind { /// Returns a new type name that appends the response's Swift name to /// the specified parent type name. func typeName(in parent: TypeName) -> TypeName { - parent.appending(swiftComponent: prettyName.uppercasingFirstLetter) + parent.appending( + swiftComponent: prettyName.uppercasingFirstLetter, + jsonComponent: jsonPathComponent + ) } } diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift index 0e4fe543..0003ea46 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift @@ -20,15 +20,13 @@ extension TypesFileTranslator { /// - typedResponse: The typed response to declare. /// - Returns: A structure declaration. func translateResponseInTypes( - responseKind: ResponseKind?, typeName: TypeName, response: TypedResponse ) throws -> Declaration { let response = response.response - let subPathPrefixInOperations: String = "responses/\(responseKind?.jsonPathComponent ?? "")" - let headersTypeName = typeName.appending( - swiftComponent: Constants.Operation.Output.Payload.Headers.typeName + swiftComponent: Constants.Operation.Output.Payload.Headers.typeName, + jsonComponent: "headers" ) let headers = try typedResponseHeaders( from: response, @@ -36,18 +34,13 @@ extension TypesFileTranslator { ) let headerProperties: [PropertyBlueprint] = try headers.map { header in try parseResponseHeaderAsProperty( - responseKind: responseKind, - typeName: typeName, - for: header + for: header, + parent: headersTypeName ) } - let headerStructComment: Comment? = { - if !typeName.isInComponents { - return typeName.docCommentWithUserDescription(nil, subPath: "\(subPathPrefixInOperations)/headers") - } else { - return typeName.docCommentWithUserDescription(nil, subPath: "headers") - } - }() + let headerStructComment: Comment? = + headersTypeName + .docCommentWithUserDescription(nil) let headersStructBlueprint: StructBlueprint = .init( comment: headerStructComment, access: config.access, @@ -70,7 +63,8 @@ extension TypesFileTranslator { ) let bodyTypeName = typeName.appending( - swiftComponent: Constants.Operation.Body.typeName + swiftComponent: Constants.Operation.Body.typeName, + jsonComponent: "content" ) let typedContents = try supportedTypedContents( response.content, @@ -78,7 +72,8 @@ extension TypesFileTranslator { ) var bodyCases: [Declaration] = [] for typedContent in typedContents { - let identifier = contentSwiftName(typedContent.content.contentType) + let contentType = typedContent.content.contentType + let identifier = contentSwiftName(contentType) let associatedType = typedContent.resolvedTypeUsage if TypeMatcher.isInlinable(typedContent.content.schema), let inlineType = typedContent.typeUsage { let inlineTypeDecls = try translateSchema( @@ -89,16 +84,8 @@ extension TypesFileTranslator { bodyCases.append(contentsOf: inlineTypeDecls) } - let subPathForContentCase: String = { - if !typeName.isInComponents { - return - "\(subPathPrefixInOperations)/content/\(typedContent.content.contentType.lowercasedTypeAndSubtypeWithEscape)" - } else { - return "content/\(typedContent.content.contentType.lowercasedTypeAndSubtypeWithEscape)" - } - }() let bodyCase: Declaration = .commentable( - typeName.docCommentWithUserDescription(nil, subPath: subPathForContentCase), + contentType.docComment(typeName: bodyTypeName), .enumCase( name: identifier, kind: .nameWithAssociatedValues([ @@ -108,10 +95,9 @@ extension TypesFileTranslator { ) bodyCases.append(bodyCase) } - let subPathForContent: String = !typeName.isInComponents ? "\(subPathPrefixInOperations)/content" : "content" let hasNoContent: Bool = bodyCases.isEmpty let contentEnumDecl: Declaration = .commentable( - typeName.docCommentWithUserDescription(nil, subPath: subPathForContent), + bodyTypeName.docCommentWithUserDescription(nil), .enum( isFrozen: true, accessModifier: config.access, @@ -165,7 +151,6 @@ extension TypesFileTranslator { of: OpenAPI.Response.self ) return try translateResponseInTypes( - responseKind: nil, typeName: typeName, response: response ) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift index 51ea81ae..f8a79bae 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseHeader.swift @@ -20,22 +20,16 @@ extension TypesFileTranslator { /// /// - Parameters: /// - header: A response parameter. + /// - parent: The type name of the parent struct. /// - Returns: A property blueprint. func parseResponseHeaderAsProperty( - responseKind: ResponseKind?, - typeName: TypeName, - for header: TypedResponseHeader + for header: TypedResponseHeader, + parent: TypeName ) throws -> PropertyBlueprint { - let comment: Comment? = { - if let responseKind = responseKind?.jsonPathComponent, !typeName.isInComponents { - return typeName.docCommentWithUserDescription( - nil, - subPath: "responses/\(responseKind)/headers/\(header.name)" - ) - } else { - return typeName.docCommentWithUserDescription(nil, subPath: "headers/\(header.name)") - } - }() + let comment = parent.docCommentWithUserDescription( + nil, + subPath: header.name + ) return .init( comment: comment, originalName: header.name, diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift index a19074ba..4c89c276 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift @@ -42,7 +42,6 @@ extension TypesFileTranslator { let responseStructDecl: Declaration? if typedResponse.isInlined { responseStructDecl = try translateResponseInTypes( - responseKind: responseKind, typeName: typedResponse.typeUsage.typeName, response: typedResponse ) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift b/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift index ecbebb0d..f3bd6b3e 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeName.swift @@ -112,8 +112,10 @@ struct TypeName: Equatable { /// - Parameters: /// - swiftComponent: The name of the Swift type component. /// - jsonComponent: The name of the JSON path component. + /// - Precondition: At least one of the components must be non-nil. /// - Returns: A new type name. - func appending(swiftComponent: String, jsonComponent: String? = nil) -> Self { + func appending(swiftComponent: String? = nil, jsonComponent: String? = nil) -> Self { + precondition(swiftComponent != nil || jsonComponent != nil, "At least the Swift or JSON name must be non-nil.") let newComponent = Component(swift: swiftComponent, json: jsonComponent) return .init(components: components + [newComponent]) } @@ -126,14 +128,6 @@ struct TypeName: Equatable { precondition(components.count >= 1, "Cannot get the parent of a root type") return .init(components: components.dropLast()) } - - /// Returns a bool value indicating whether the list of JSON path components contains "#" first and "components" second. - var isInComponents: Bool { - guard let jsonKeyPathComponents else { - return false - } - return jsonKeyPathComponents[0] == "#" && jsonKeyPathComponents[1] == "components" - } } extension TypeName: CustomStringConvertible { diff --git a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateComponentResponses.swift b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateComponentResponses.swift index 74addc7a..f9c64082 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateComponentResponses.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateComponentResponses.swift @@ -41,7 +41,6 @@ extension TypesFileTranslator { try typedResponses .map { value in try translateResponseInTypes( - responseKind: nil, typeName: value.typeUsage.typeName, response: value ) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateOperations.swift b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateOperations.swift index bdcf461d..6503fe50 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateOperations.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateOperations.swift @@ -37,7 +37,7 @@ extension TypesFileTranslator { ) } let structDecl: Declaration = .commentable( - inputTypeName.docCommentWithUserDescription(nil, subPath: "\(location.rawValue)"), + structTypeName.docCommentWithUserDescription(nil), translateStructBlueprint( .init( comment: nil, diff --git a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift index e50d6ee3..81ef17f8 100644 --- a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift +++ b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift @@ -688,9 +688,9 @@ public enum Components { public var headers: Components.Responses.ErrorBadRequest.Headers /// - Remark: Generated from `#/components/responses/ErrorBadRequest/content`. @frozen public enum Body: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/components/responses/ErrorBadRequest/json`. + /// - Remark: Generated from `#/components/responses/ErrorBadRequest/content/json`. public struct jsonPayload: Codable, Equatable, Hashable, Sendable { - /// - Remark: Generated from `#/components/responses/ErrorBadRequest/json/code`. + /// - Remark: Generated from `#/components/responses/ErrorBadRequest/content/json/code`. public var code: Swift.Int /// Creates a new `jsonPayload`. /// @@ -1468,9 +1468,9 @@ public enum Operations { public var headers: Operations.updatePet.Output.BadRequest.Headers /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/400/content`. @frozen public enum Body: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/json`. + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/400/content/json`. public struct jsonPayload: Codable, Equatable, Hashable, Sendable { - /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/json/message`. + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/400/content/json/message`. public var message: Swift.String /// Creates a new `jsonPayload`. /// diff --git a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Types.swift b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Types.swift index 7243d867..af17148a 100644 --- a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Types.swift +++ b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Types.swift @@ -690,9 +690,9 @@ public enum Components { public var headers: Components.Responses.ErrorBadRequest.Headers /// - Remark: Generated from `#/components/responses/ErrorBadRequest/content`. @frozen public enum Body: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/components/responses/ErrorBadRequest/json`. + /// - Remark: Generated from `#/components/responses/ErrorBadRequest/content/json`. public struct jsonPayload: Codable, Equatable, Hashable, Sendable { - /// - Remark: Generated from `#/components/responses/ErrorBadRequest/json/code`. + /// - Remark: Generated from `#/components/responses/ErrorBadRequest/content/json/code`. public var code: Swift.Int /// Creates a new `jsonPayload`. /// @@ -1478,9 +1478,9 @@ public enum Operations { public var headers: Operations.updatePet.Output.BadRequest.Headers /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/400/content`. @frozen public enum Body: Sendable, Equatable, Hashable { - /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/json`. + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/400/content/json`. public struct jsonPayload: Codable, Equatable, Hashable, Sendable { - /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/json/message`. + /// - Remark: Generated from `#/paths/pets/{petId}/PATCH/responses/400/content/json/message`. public var message: Swift.String /// Creates a new `jsonPayload`. ///