From ef2c033124ce2073088d530e7948e4866630c476 Mon Sep 17 00:00:00 2001 From: Georgii Alexandrov <39917064+alxxndrv@users.noreply.github.com> Date: Mon, 25 Aug 2025 14:11:26 +0300 Subject: [PATCH 1/2] Emit switch without fallback for single-case Output enums (default-only responses) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #810 OpenAPI operations that declare only a default response produced an accessor like: switch self { case .default: return …; default: throw … } Since the enum has a single case, the fallback was statically unreachable and triggered a compiler warning: “Default will never be executed.” This change omits the fallback branch when the Output enum is provably single-case (default-only), eliminating the warning and keeping the accessor exhaustive. Accessor signatures remain throwing for source compatibility. Details - Generator: Gate the fallback default branch in [`TypesFileTranslator.translateResponseOutcomeInTypes()`](Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift:31) behind a single-case check (contains default and exactly one response outcome). Multi-case outputs remain unchanged and still throw on mismatches. - Tests: Update default-only expected snippet to match the new, exhaustive switch without a fallback in [`SnippetBasedReferenceTests.swift`](Tests/OpenAPIGeneratorReferenceTests/SnippetBasedReferenceTests.swift:3412). No new tests added. --- .../Responses/translateResponseOutcome.swift | 59 +++++++++++-------- .../SnippetBasedReferenceTests.swift | 5 -- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift index b0b1fcd4..db17b311 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift @@ -87,6 +87,39 @@ extension TypesFileTranslator { staticMemberDecl = nil } + let isSingleCaseOutput = operation.containsDefaultResponse && operation.responseOutcomes.count == 1 + + var throwingGetterCases: [SwitchCaseDescription] = [ + SwitchCaseDescription( + kind: .case( + .dot(responseKind.identifier), + responseKind.wantsStatusCode ? ["_", "response"] : ["response"] + ), + body: [.expression(.return(.identifierPattern("response")))] + ) + ] + if !isSingleCaseOutput { + throwingGetterCases.append( + SwitchCaseDescription( + kind: .default, + body: [ + .expression( + .try( + .identifierPattern("throwUnexpectedResponseStatus") + .call([ + .init( + label: "expectedStatus", + expression: .literal(.string(responseKind.prettyName)) + ), + .init(label: "response", expression: .identifierPattern("self")), + ]) + ) + ) + ] + ) + ) + } + let throwingGetterDesc = VariableDescription( accessModifier: config.access, kind: .var, @@ -96,31 +129,7 @@ extension TypesFileTranslator { .expression( .switch( switchedExpression: .identifierPattern("self"), - cases: [ - SwitchCaseDescription( - kind: .case( - .dot(responseKind.identifier), - responseKind.wantsStatusCode ? ["_", "response"] : ["response"] - ), - body: [.expression(.return(.identifierPattern("response")))] - ), - SwitchCaseDescription( - kind: .default, - body: [ - .expression( - .try( - .identifierPattern("throwUnexpectedResponseStatus") - .call([ - .init( - label: "expectedStatus", - expression: .literal(.string(responseKind.prettyName)) - ), .init(label: "response", expression: .identifierPattern("self")), - ]) - ) - ) - ] - ), - ] + cases: throwingGetterCases ) ) ], diff --git a/Tests/OpenAPIGeneratorReferenceTests/SnippetBasedReferenceTests.swift b/Tests/OpenAPIGeneratorReferenceTests/SnippetBasedReferenceTests.swift index f3a59d0d..b697174e 100644 --- a/Tests/OpenAPIGeneratorReferenceTests/SnippetBasedReferenceTests.swift +++ b/Tests/OpenAPIGeneratorReferenceTests/SnippetBasedReferenceTests.swift @@ -3416,11 +3416,6 @@ final class SnippetBasedReferenceTests: XCTestCase { switch self { case let .`default`(_, response): return response - default: - try throwUnexpectedResponseStatus( - expectedStatus: "default", - response: self - ) } } } From c43c85c197df9832eab961947bd8f1377e048248 Mon Sep 17 00:00:00 2001 From: Georgii Alexandrov <39917064+alxxndrv@users.noreply.github.com> Date: Mon, 25 Aug 2025 20:06:02 +0300 Subject: [PATCH 2/2] Made throwing-getter default-case check inline; remove `let isSingleCaseOutput` --- .../Translator/Responses/translateResponseOutcome.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift index db17b311..9f12dc46 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift @@ -87,8 +87,6 @@ extension TypesFileTranslator { staticMemberDecl = nil } - let isSingleCaseOutput = operation.containsDefaultResponse && operation.responseOutcomes.count == 1 - var throwingGetterCases: [SwitchCaseDescription] = [ SwitchCaseDescription( kind: .case( @@ -98,7 +96,7 @@ extension TypesFileTranslator { body: [.expression(.return(.identifierPattern("response")))] ) ] - if !isSingleCaseOutput { + if !operation.containsDefaultResponse || operation.responseOutcomes.count > 1 { throwingGetterCases.append( SwitchCaseDescription( kind: .default,