diff --git a/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateSchema.swift b/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateSchema.swift index d34036c7..58b6b049 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateSchema.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateSchema.swift @@ -115,6 +115,7 @@ extension FileTranslator { let enumDecl = try translateStringEnum( typeName: typeName, userDescription: overrides.userDescription ?? coreContext.description, + isNullable: coreContext.nullable, allowedValues: allowedValues ) return [enumDecl] diff --git a/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateStringEnum.swift b/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateStringEnum.swift index 5c87f9df..cd0ac7eb 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateStringEnum.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateStringEnum.swift @@ -20,15 +20,23 @@ extension FileTranslator { /// - typeName: The name of the type to give to the declared enum. /// - openAPIDescription: A user-specified description from the OpenAPI /// document. + /// - isNullable: Whether the enum schema is nullable. /// - allowedValues: The enumerated allowed values. func translateStringEnum( typeName: TypeName, userDescription: String?, + isNullable: Bool, allowedValues: [AnyCodable] ) throws -> Declaration { let rawValues = try allowedValues.map(\.value) .map { anyValue in + // In nullable enum schemas, empty strings are parsed as Void. + // This is unlikely to be fixed, so handling that case here. + // https://github.com/apple/swift-openapi-generator/issues/118 + if isNullable && anyValue is Void { + return "" + } guard let string = anyValue as? String else { throw GenericError(message: "Disallowed value for a string enum '\(typeName)': \(anyValue)") } diff --git a/Tests/OpenAPIGeneratorCoreTests/Translator/CommonTranslations/Test_translateStringEnum.swift b/Tests/OpenAPIGeneratorCoreTests/Translator/CommonTranslations/Test_translateStringEnum.swift new file mode 100644 index 00000000..59a41509 --- /dev/null +++ b/Tests/OpenAPIGeneratorCoreTests/Translator/CommonTranslations/Test_translateStringEnum.swift @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftOpenAPIGenerator open source project +// +// Copyright (c) 2023 Apple Inc. and the SwiftOpenAPIGenerator project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftOpenAPIGenerator project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +import XCTest +import OpenAPIKit30 +@testable import _OpenAPIGeneratorCore + +final class Test_translateStringEnum: Test_Core { + + func testCaseValues() throws { + let names = try _caseValues( + .string( + allowedValues: "a", + "" + ) + ) + XCTAssertEqual(names, ["a", "_empty", "undocumented"]) + } + + func testCaseValuesForNullableSchema() throws { + let names = try _caseValues( + .string( + nullable: true, + allowedValues: "a", + nil + ) + ) + XCTAssertEqual(names, ["a", "_empty", "undocumented"]) + } + + func _caseValues(_ schema: JSONSchema) throws -> [String] { + self.continueAfterFailure = false + let translator = makeTypesTranslator() + let decls = try translator.translateSchema( + typeName: .init(swiftKeyPath: ["FooEnum"]), + schema: schema, + overrides: .none + ) + XCTAssertEqual(decls.count, 1) + let decl = decls[0] + guard case .enum(let enumDesc) = decl.strippingTopComment else { + throw UnexpectedDeclError(actual: decl.info.kind, expected: .enum) + } + XCTAssertEqual(enumDesc.name, "FooEnum") + let names: [String] = enumDesc.members.compactMap { memberDecl in + guard case .enumCase(let caseDesc) = memberDecl.strippingTopComment else { + return nil + } + return caseDesc.name + } + return names + } +}