From b00422f288fe14a8a5e8491944f736268d2a6eac Mon Sep 17 00:00:00 2001 From: Arthur Crocquevieille Date: Sun, 20 Oct 2024 09:44:18 +0200 Subject: [PATCH 1/3] Generate a convenience static property to create a responses without any parameters --- .../Responses/translateResponseOutcome.swift | 40 +++++++++++++------ .../TypesTranslator/translateOperations.swift | 3 +- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift index a5187b4d..23633b09 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift @@ -23,17 +23,18 @@ extension TypesFileTranslator { /// - operation: The OpenAPI operation. /// - operationJSONPath: The JSON path to the operation in the OpenAPI /// document. - /// - Returns: A declaration of the enum case and a declaration of the + /// - Returns: A tuple containing a declaration of the enum case, a declaration of the /// structure unique to the response that contains the response headers - /// and a body payload. + /// and a body payload, a declaration of a throwing getter and, an optional convenience static property. /// - Throws: An error if there's an issue generating the declarations, such /// as unsupported response types or invalid definitions. func translateResponseOutcomeInTypes( _ outcome: OpenAPI.Operation.ResponseOutcome, operation: OperationDescription, operationJSONPath: String - ) throws -> (payloadStruct: Declaration?, enumCase: Declaration, throwingGetter: Declaration) { - + ) throws -> ( + payloadStruct: Declaration?, enumCase: Declaration, staticMember: Declaration?, throwingGetter: Declaration + ) { let typedResponse = try typedResponse(from: outcome, operation: operation) let responseStructTypeName = typedResponse.typeUsage.typeName let responseKind = outcome.status.value.asKind @@ -55,14 +56,29 @@ extension TypesFileTranslator { } associatedValues.append(.init(type: .init(responseStructTypeName))) - let enumCaseDesc = EnumCaseDescription(name: enumCaseName, kind: .nameWithAssociatedValues(associatedValues)) - let enumCaseDecl: Declaration = .commentable( - responseKind.docComment( - userDescription: typedResponse.response.description, - jsonPath: operationJSONPath + "/responses/" + responseKind.jsonPathComponent - ), - .enumCase(enumCaseDesc) + let enumCaseDocComment = responseKind.docComment( + userDescription: typedResponse.response.description, + jsonPath: operationJSONPath + "/responses/" + responseKind.jsonPathComponent ) + let enumCaseDesc = EnumCaseDescription(name: enumCaseName, kind: .nameWithAssociatedValues(associatedValues)) + let enumCaseDecl: Declaration = .commentable(enumCaseDocComment, .enumCase(enumCaseDesc)) + + var staticMemberDecl: Declaration? + let responseHasNoHeaders = typedResponse.response.headers?.isEmpty ?? true + let responseHasNoContent = typedResponse.response.content.isEmpty + if responseHasNoContent && responseHasNoHeaders && !responseKind.wantsStatusCode { + let staticMemberDesc = VariableDescription( + accessModifier: .internal, + isStatic: true, + kind: .var, + left: .identifier(.pattern(enumCaseName)), + type: .member(["Self"]), + right: .closureInvocation(body: [ + .expression(.functionCall(calledExpression: .dot(enumCaseName), arguments: [.dot("init")])) + ]) + ) + staticMemberDecl = .commentable(enumCaseDocComment, .variable(staticMemberDesc)) + } let throwingGetterDesc = VariableDescription( accessModifier: config.access, @@ -113,7 +129,7 @@ extension TypesFileTranslator { ) let throwingGetterDecl = Declaration.commentable(throwingGetterComment, .variable(throwingGetterDesc)) - return (responseStructDecl, enumCaseDecl, throwingGetterDecl) + return (responseStructDecl, enumCaseDecl, staticMemberDecl, throwingGetterDecl) } } diff --git a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateOperations.swift b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateOperations.swift index 55d01890..8beaae76 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateOperations.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateOperations.swift @@ -143,7 +143,8 @@ extension TypesFileTranslator { let documentedMembers: [Declaration] = documentedOutcomes.flatMap { inlineResponseDecl, caseDecl, - throwingGetter in [inlineResponseDecl, caseDecl, throwingGetter].compactMap { $0 } + staticDecl, + throwingGetter in [inlineResponseDecl, caseDecl, staticDecl, throwingGetter].compactMap { $0 } } let allMembers: [Declaration] From 88dd69492f9e9ddc3bd909d712816a0cb5419844 Mon Sep 17 00:00:00 2001 From: Arthur Crocquevieille Date: Sun, 20 Oct 2024 17:12:47 +0200 Subject: [PATCH 2/3] Update existing tests --- .../Responses/translateResponseOutcome.swift | 13 ++++-- .../ReferenceSources/Petstore/Types.swift | 40 +++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift index 23633b09..26da5d5b 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift @@ -68,14 +68,19 @@ extension TypesFileTranslator { let responseHasNoContent = typedResponse.response.content.isEmpty if responseHasNoContent && responseHasNoHeaders && !responseKind.wantsStatusCode { let staticMemberDesc = VariableDescription( - accessModifier: .internal, + accessModifier: config.access, isStatic: true, kind: .var, left: .identifier(.pattern(enumCaseName)), type: .member(["Self"]), - right: .closureInvocation(body: [ - .expression(.functionCall(calledExpression: .dot(enumCaseName), arguments: [.dot("init")])) - ]) + getter: [ + .expression( + .functionCall( + calledExpression: .dot(enumCaseName), + arguments: [.functionCall(calledExpression: .dot("init"))] + ) + ) + ] ) staticMemberDecl = .commentable(enumCaseDocComment, .variable(staticMemberDesc)) } diff --git a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift index 2baf58a2..47b0390d 100644 --- a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift +++ b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Types.swift @@ -2279,6 +2279,14 @@ public enum Operations { /// /// HTTP response code: `204 noContent`. case noContent(Operations.createPetWithForm.Output.NoContent) + /// Successfully created pet using a url form + /// + /// - Remark: Generated from `#/paths//pets/create/post(createPetWithForm)/responses/204`. + /// + /// HTTP response code: `204 noContent`. + public static var noContent: Self { + .noContent(.init()) + } /// The associated value of the enum case if `self` is `.noContent`. /// /// - Throws: An error if `self` is not `.noContent`. @@ -2499,6 +2507,14 @@ public enum Operations { /// /// HTTP response code: `202 accepted`. case accepted(Operations.postStats.Output.Accepted) + /// Accepted data. + /// + /// - Remark: Generated from `#/paths//pets/stats/post(postStats)/responses/202`. + /// + /// HTTP response code: `202 accepted`. + public static var accepted: Self { + .accepted(.init()) + } /// The associated value of the enum case if `self` is `.accepted`. /// /// - Throws: An error if `self` is not `.accepted`. @@ -2541,6 +2557,14 @@ public enum Operations { /// /// HTTP response code: `204 noContent`. case noContent(Operations.probe.Output.NoContent) + /// Ack + /// + /// - Remark: Generated from `#/paths//probe//post(probe)/responses/204`. + /// + /// HTTP response code: `204 noContent`. + public static var noContent: Self { + .noContent(.init()) + } /// The associated value of the enum case if `self` is `.noContent`. /// /// - Throws: An error if `self` is not `.noContent`. @@ -2626,6 +2650,14 @@ public enum Operations { /// /// HTTP response code: `204 noContent`. case noContent(Operations.updatePet.Output.NoContent) + /// Successfully updated + /// + /// - Remark: Generated from `#/paths//pets/{petId}/patch(updatePet)/responses/204`. + /// + /// HTTP response code: `204 noContent`. + public static var noContent: Self { + .noContent(.init()) + } /// The associated value of the enum case if `self` is `.noContent`. /// /// - Throws: An error if `self` is not `.noContent`. @@ -3098,6 +3130,14 @@ public enum Operations { /// /// HTTP response code: `202 accepted`. case accepted(Operations.multipartUploadTyped.Output.Accepted) + /// Successfully accepted the data. + /// + /// - Remark: Generated from `#/paths//pets/multipart-typed/post(multipartUploadTyped)/responses/202`. + /// + /// HTTP response code: `202 accepted`. + public static var accepted: Self { + .accepted(.init()) + } /// The associated value of the enum case if `self` is `.accepted`. /// /// - Throws: An error if `self` is not `.accepted`. From 4452d7c3be927bf74f35594c60c67b68bac5a5b1 Mon Sep 17 00:00:00 2001 From: Arthur Crocquevieille Date: Mon, 21 Oct 2024 18:37:00 +0200 Subject: [PATCH 3/3] Fix static member variable --- .../Translator/Responses/translateResponseOutcome.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift index 26da5d5b..5fb29ce3 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift @@ -63,7 +63,7 @@ extension TypesFileTranslator { let enumCaseDesc = EnumCaseDescription(name: enumCaseName, kind: .nameWithAssociatedValues(associatedValues)) let enumCaseDecl: Declaration = .commentable(enumCaseDocComment, .enumCase(enumCaseDesc)) - var staticMemberDecl: Declaration? + let staticMemberDecl: Declaration? let responseHasNoHeaders = typedResponse.response.headers?.isEmpty ?? true let responseHasNoContent = typedResponse.response.content.isEmpty if responseHasNoContent && responseHasNoHeaders && !responseKind.wantsStatusCode { @@ -83,6 +83,8 @@ extension TypesFileTranslator { ] ) staticMemberDecl = .commentable(enumCaseDocComment, .variable(staticMemberDesc)) + } else { + staticMemberDecl = nil } let throwingGetterDesc = VariableDescription(