diff --git a/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/SwiftSafeNames.swift b/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/SwiftSafeNames.swift index 98614a45..fcd06c6d 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/SwiftSafeNames.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/SwiftSafeNames.swift @@ -13,11 +13,14 @@ //===----------------------------------------------------------------------===// import Foundation -struct SwiftNameOptions: OptionSet { - let rawValue: Int32 - static let none = SwiftNameOptions([]) - static let capitalize = SwiftNameOptions(rawValue: 1 << 0) - static let all: SwiftNameOptions = [.capitalize] +struct SwiftNameOptions { + enum NameKind { + case capitalized + case noncapitalized + } + var kind: NameKind + static let capitalized = SwiftNameOptions(kind: .capitalized) + static let noncapitalized = SwiftNameOptions(kind: .noncapitalized) } extension String { @@ -80,7 +83,7 @@ extension String { /// If the string contains any illegal characters, falls back to the behavior /// matching `safeForSwiftCode_defensive`. func safeForSwiftCode_idiomatic(options: SwiftNameOptions) -> String { - let capitalize = options.contains(.capitalize) + let capitalize = options.kind == .capitalized if isEmpty { return capitalize ? "_Empty_" : "_empty_" } // Detect cases like HELLO_WORLD, sometimes used for constants. let isAllUppercase = allSatisfy { diff --git a/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateAllAnyOneOf.swift b/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateAllAnyOneOf.swift index 92d6745f..6a6d4b70 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateAllAnyOneOf.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateAllAnyOneOf.swift @@ -209,7 +209,7 @@ extension TypesFileTranslator { let decoder: Declaration if let discriminator { let originalName = discriminator.propertyName - let swiftName = context.asSwiftSafeName(originalName, .none) + let swiftName = context.asSwiftSafeName(originalName, .noncapitalized) codingKeysDecls = [ .enum( accessModifier: config.access, diff --git a/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateRawEnum.swift b/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateRawEnum.swift index cb7507be..2b59ed38 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateRawEnum.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateRawEnum.swift @@ -101,12 +101,12 @@ extension FileTranslator { // 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 { - try addIfUnique(id: .string(""), caseName: context.asSwiftSafeName("", .none)) + try addIfUnique(id: .string(""), caseName: context.asSwiftSafeName("", .noncapitalized)) } else { guard let rawValue = anyValue as? String else { throw GenericError(message: "Disallowed value for a string enum '\(typeName)': \(anyValue)") } - let caseName = context.asSwiftSafeName(rawValue, .none) + let caseName = context.asSwiftSafeName(rawValue, .noncapitalized) try addIfUnique(id: .string(rawValue), caseName: caseName) } case .integer: diff --git a/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/DiscriminatorExtensions.swift b/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/DiscriminatorExtensions.swift index 3d0bb3a3..a5fb1172 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/DiscriminatorExtensions.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/DiscriminatorExtensions.swift @@ -80,7 +80,7 @@ extension FileTranslator { /// - Parameter type: The `OneOfMappedType` for which to determine the case name. /// - Returns: A string representing the safe Swift name for the specified `OneOfMappedType`. func safeSwiftNameForOneOfMappedCase(_ type: OneOfMappedType) -> String { - context.asSwiftSafeName(type.rawNames[0], .none) + context.asSwiftSafeName(type.rawNames[0], .noncapitalized) } } diff --git a/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/StructBlueprint.swift b/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/StructBlueprint.swift index c295a5bd..10b5da2f 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/StructBlueprint.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/StructBlueprint.swift @@ -153,7 +153,7 @@ struct PropertyBlueprint { extension PropertyBlueprint { /// A name that is verified to be a valid Swift identifier. - var swiftSafeName: String { context.asSwiftSafeName(originalName, .none) } + var swiftSafeName: String { context.asSwiftSafeName(originalName, .noncapitalized) } /// The JSON path to the property. /// diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Multipart/MultipartContentInspector.swift b/Sources/_OpenAPIGeneratorCore/Translator/Multipart/MultipartContentInspector.swift index 8be5f9a6..cc039388 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Multipart/MultipartContentInspector.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Multipart/MultipartContentInspector.swift @@ -120,7 +120,7 @@ extension FileTranslator { } var parts: [MultipartSchemaTypedContent] = try topLevelObject.properties.compactMap { (key, value) -> MultipartSchemaTypedContent? in - let swiftSafeName = context.asSwiftSafeName(key, .capitalize) + let swiftSafeName = context.asSwiftSafeName(key, .capitalized) let typeName = typeName.appending( swiftComponent: swiftSafeName + Constants.Global.inlineTypeSuffix, jsonComponent: key diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Multipart/translateMultipart.swift b/Sources/_OpenAPIGeneratorCore/Translator/Multipart/translateMultipart.swift index 21163449..1c2d2ed6 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Multipart/translateMultipart.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Multipart/translateMultipart.swift @@ -137,7 +137,7 @@ extension TypesFileTranslator { switch part { case .documentedTyped(let documentedPart): let caseDecl: Declaration = .enumCase( - name: context.asSwiftSafeName(documentedPart.originalName, .none), + name: context.asSwiftSafeName(documentedPart.originalName, .noncapitalized), kind: .nameWithAssociatedValues([.init(type: .init(part.wrapperTypeUsage))]) ) let decl = try translateMultipartPartContent( @@ -404,7 +404,7 @@ extension FileTranslator { switch part { case .documentedTyped(let part): let originalName = part.originalName - let identifier = context.asSwiftSafeName(originalName, .none) + let identifier = context.asSwiftSafeName(originalName, .noncapitalized) let contentType = part.partInfo.contentType let partTypeName = part.typeName let schema = part.schema @@ -613,7 +613,7 @@ extension FileTranslator { switch part { case .documentedTyped(let part): let originalName = part.originalName - let identifier = context.asSwiftSafeName(originalName, .none) + let identifier = context.asSwiftSafeName(originalName, .noncapitalized) let contentType = part.partInfo.contentType let headersTypeName = part.typeName.appending( swiftComponent: Constants.Operation.Output.Payload.Headers.typeName, diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Operations/OperationDescription.swift b/Sources/_OpenAPIGeneratorCore/Translator/Operations/OperationDescription.swift index bceb302c..3626af27 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Operations/OperationDescription.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Operations/OperationDescription.swift @@ -83,14 +83,14 @@ extension OperationDescription { /// Uses the `operationID` value in the OpenAPI operation, if one was /// specified. Otherwise, computes a unique name from the operation's /// path and HTTP method. - var methodName: String { context.asSwiftSafeName(operationID, .none) } + var methodName: String { context.asSwiftSafeName(operationID, .noncapitalized) } /// Returns a Swift-safe type name for the operation. /// /// Uses the `operationID` value in the OpenAPI operation, if one was /// specified. Otherwise, computes a unique name from the operation's /// path and HTTP method. - var operationTypeName: String { context.asSwiftSafeName(operationID, .capitalize) } + var operationTypeName: String { context.asSwiftSafeName(operationID, .capitalized) } /// Returns the identifier for the operation. /// @@ -299,7 +299,7 @@ extension OperationDescription { } let newPath = OpenAPI.Path(newComponents, trailingSlash: path.trailingSlash) let names: [Expression] = orderedPathParameters.map { param in - .identifierPattern("input").dot("path").dot(context.asSwiftSafeName(param, .none)) + .identifierPattern("input").dot("path").dot(context.asSwiftSafeName(param, .noncapitalized)) } let arrayExpr: Expression = .literal(.array(names)) return (newPath.rawValue, arrayExpr) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/TypedParameter.swift b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/TypedParameter.swift index b5d8b425..bfeb5467 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/TypedParameter.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/TypedParameter.swift @@ -48,7 +48,7 @@ extension TypedParameter { var name: String { parameter.name } /// The name of the parameter sanitized to be a valid Swift identifier. - var variableName: String { context.asSwiftSafeName(name, .none) } + var variableName: String { context.asSwiftSafeName(name, .noncapitalized) } /// A Boolean value that indicates whether the parameter must be specified /// when performing the OpenAPI operation. diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Responses/TypedResponseHeader.swift b/Sources/_OpenAPIGeneratorCore/Translator/Responses/TypedResponseHeader.swift index 7c16ece6..5d0932bd 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Responses/TypedResponseHeader.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Responses/TypedResponseHeader.swift @@ -39,7 +39,7 @@ struct TypedResponseHeader { extension TypedResponseHeader { /// The name of the header sanitized to be a valid Swift identifier. - var variableName: String { context.asSwiftSafeName(name, .none) } + var variableName: String { context.asSwiftSafeName(name, .noncapitalized) } /// A Boolean value that indicates whether the response header can /// be omitted in the HTTP response. diff --git a/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeAssigner.swift b/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeAssigner.swift index fae4eb92..5ecf852c 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeAssigner.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/TypeAssignment/TypeAssigner.swift @@ -59,7 +59,7 @@ struct TypeAssigner { /// - Returns: A Swift type name for the specified component type. func typeName(forComponentOriginallyNamed originalName: String, in location: TypeLocation) -> TypeName { typeName(forLocation: location) - .appending(swiftComponent: context.asSwiftSafeName(originalName, .capitalize), jsonComponent: originalName) + .appending(swiftComponent: context.asSwiftSafeName(originalName, .capitalized), jsonComponent: originalName) } /// Returns the type name for an OpenAPI-named component namespace. @@ -127,7 +127,7 @@ struct TypeAssigner { { multipartBodyElementTypeName = try typeName(for: ref) } else { - let swiftSafeName = context.asSwiftSafeName(hint, .capitalize) + let swiftSafeName = context.asSwiftSafeName(hint, .capitalized) multipartBodyElementTypeName = parent.appending( swiftComponent: swiftSafeName + Constants.Global.inlineTypeSuffix, jsonComponent: hint @@ -343,7 +343,7 @@ struct TypeAssigner { } return baseType.appending( - swiftComponent: context.asSwiftSafeName(originalName, .capitalize) + suffix, + swiftComponent: context.asSwiftSafeName(originalName, .capitalized) + suffix, jsonComponent: jsonReferenceComponentOverride ?? originalName ) .asUsage.withOptional(try typeMatcher.isOptional(schema, components: components)) @@ -406,7 +406,7 @@ struct TypeAssigner { of componentType: Component.Type ) -> TypeName { typeName(for: Component.self) - .appending(swiftComponent: context.asSwiftSafeName(key.rawValue, .capitalize), jsonComponent: key.rawValue) + .appending(swiftComponent: context.asSwiftSafeName(key.rawValue, .capitalized), jsonComponent: key.rawValue) } /// Returns a type name for a JSON reference. @@ -471,7 +471,7 @@ struct TypeAssigner { throw JSONReferenceParsingError.nonComponentPathsUnsupported(reference.name) } return typeName(for: componentType) - .appending(swiftComponent: context.asSwiftSafeName(name, .capitalize), jsonComponent: name) + .appending(swiftComponent: context.asSwiftSafeName(name, .capitalized), jsonComponent: name) } /// Returns a type name for the namespace for the specified component type. @@ -495,7 +495,7 @@ struct TypeAssigner { { typeNameForComponents() .appending( - swiftComponent: context.asSwiftSafeName(componentType.openAPIComponentsKey, .capitalize) + swiftComponent: context.asSwiftSafeName(componentType.openAPIComponentsKey, .capitalized) .uppercasingFirstLetter, jsonComponent: componentType.openAPIComponentsKey ) @@ -529,14 +529,14 @@ struct TypeAssigner { case "application/pdf": return "pdf" case "image/jpeg": return "jpeg" default: - let safedType = context.asSwiftSafeName(contentType.originallyCasedType, .none) - let safedSubtype = context.asSwiftSafeName(contentType.originallyCasedSubtype, .none) + let safedType = context.asSwiftSafeName(contentType.originallyCasedType, .noncapitalized) + let safedSubtype = context.asSwiftSafeName(contentType.originallyCasedSubtype, .noncapitalized) let prefix = "\(safedType)_\(safedSubtype)" let params = contentType.lowercasedParameterPairs guard !params.isEmpty else { return prefix } let safedParams = params.map { pair in - pair.split(separator: "=").map { context.asSwiftSafeName(String($0), .none) }.joined(separator: "_") + pair.split(separator: "=").map { context.asSwiftSafeName(String($0), .noncapitalized) }.joined(separator: "_") } .joined(separator: "_") return prefix + "_" + safedParams diff --git a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateServersVariables.swift b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateServersVariables.swift index 4a67ea3e..4517dd92 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateServersVariables.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateServersVariables.swift @@ -84,7 +84,7 @@ extension TypesFileTranslator { /// Swift safe identifiers. init(key: String, variable: OpenAPI.Server.Variable, context: TranslatorContext) { self.key = key - swiftSafeKey = context.asSwiftSafeName(key, .none) + swiftSafeKey = context.asSwiftSafeName(key, .noncapitalized) self.variable = variable } @@ -164,8 +164,8 @@ extension TypesFileTranslator { context: TranslatorContext ) { self.key = key - swiftSafeKey = context.asSwiftSafeName(key, .none) - enumName = context.asSwiftSafeName(key.localizedCapitalized, .capitalize) + swiftSafeKey = context.asSwiftSafeName(key, .noncapitalized) + enumName = context.asSwiftSafeName(key.localizedCapitalized, .capitalized) self.variable = variable self.enumValues = enumValues self.context = context @@ -199,7 +199,7 @@ extension TypesFileTranslator { .init( label: swiftSafeKey, type: .member([enumName]), - defaultValue: .memberAccess(.dot(context.asSwiftSafeName(variable.default, .none))) + defaultValue: .memberAccess(.dot(context.asSwiftSafeName(variable.default, .noncapitalized))) ) } @@ -230,7 +230,7 @@ extension TypesFileTranslator { /// - Parameter name: The original name. /// - Returns: A declaration of an enum case. private func translateVariableCase(_ name: String) -> Declaration { - let caseName = context.asSwiftSafeName(name, .none) + let caseName = context.asSwiftSafeName(name, .noncapitalized) return .enumCase(name: caseName, kind: caseName == name ? .nameOnly : .nameWithRawValue(.string(name))) } } diff --git a/Tests/OpenAPIGeneratorCoreTests/Extensions/Test_SwiftSafeNames.swift b/Tests/OpenAPIGeneratorCoreTests/Extensions/Test_SwiftSafeNames.swift index 03bc92b9..8142d5ec 100644 --- a/Tests/OpenAPIGeneratorCoreTests/Extensions/Test_SwiftSafeNames.swift +++ b/Tests/OpenAPIGeneratorCoreTests/Extensions/Test_SwiftSafeNames.swift @@ -125,15 +125,15 @@ final class Test_SwiftSafeNames: Test_Core { let translator = makeTranslator(nameOverrides: ["MEGA": "m_e_g_a"]) let asSwiftSafeName: (String, SwiftNameOptions) -> String = translator.context.asSwiftSafeName for (input, sanitizedDefensive, _, _) in cases { - XCTAssertEqual(asSwiftSafeName(input, .none), sanitizedDefensive, "Defensive, input: \(input)") + XCTAssertEqual(asSwiftSafeName(input, .noncapitalized), sanitizedDefensive, "Defensive, input: \(input)") } } do { let translator = makeTranslator(namingStrategy: .idiomatic, nameOverrides: ["MEGA": "m_e_g_a"]) let asSwiftSafeName: (String, SwiftNameOptions) -> String = translator.context.asSwiftSafeName for (input, _, idiomaticUpper, idiomaticLower) in cases { - XCTAssertEqual(asSwiftSafeName(input, .capitalize), idiomaticUpper, "Idiomatic upper, input: \(input)") - XCTAssertEqual(asSwiftSafeName(input, .none), idiomaticLower, "Idiomatic lower, input: \(input)") + XCTAssertEqual(asSwiftSafeName(input, .capitalized), idiomaticUpper, "Idiomatic upper, input: \(input)") + XCTAssertEqual(asSwiftSafeName(input, .noncapitalized), idiomaticLower, "Idiomatic lower, input: \(input)") } } } diff --git a/Tests/OpenAPIGeneratorCoreTests/Translator/TypeAssignment/Test_TypeAssigner.swift b/Tests/OpenAPIGeneratorCoreTests/Translator/TypeAssignment/Test_TypeAssigner.swift index c8e8b008..745a65e0 100644 --- a/Tests/OpenAPIGeneratorCoreTests/Translator/TypeAssignment/Test_TypeAssigner.swift +++ b/Tests/OpenAPIGeneratorCoreTests/Translator/TypeAssignment/Test_TypeAssigner.swift @@ -56,7 +56,7 @@ class Test_TypeAssigner: Test_Core { "enum": "_enum", ] for (componentKey, expectedSwiftTypeName) in expectedSchemaTypeNames { - XCTAssertEqual(asSwiftSafeName(componentKey.rawValue, .none), expectedSwiftTypeName) + XCTAssertEqual(asSwiftSafeName(componentKey.rawValue, .noncapitalized), expectedSwiftTypeName) } }