Skip to content

Commit

Permalink
Clarify SwiftNameOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
czechboy0 committed Dec 10, 2024
1 parent 94173c7 commit 6d98aa4
Show file tree
Hide file tree
Showing 14 changed files with 41 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -495,7 +495,7 @@ struct TypeAssigner {
{
typeNameForComponents()
.appending(
swiftComponent: context.asSwiftSafeName(componentType.openAPIComponentsKey, .capitalize)
swiftComponent: context.asSwiftSafeName(componentType.openAPIComponentsKey, .capitalized)
.uppercasingFirstLetter,
jsonComponent: componentType.openAPIComponentsKey
)
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)))
)
}

Expand Down Expand Up @@ -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)))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down

0 comments on commit 6d98aa4

Please sign in to comment.