Skip to content

Swift code generator produces malformed enum case names from UPPER_CASE/SNAKE_CASE typealiases #148

@myaumura

Description

@myaumura

When a Pkl typealias defines string values in UPPER_CASE, SNAKE_CASE, or plain numeric strings, the Swift code generator produces awkward or invalid enum case names by only lowercasing the first character, rather than properly converting to valid Swift lowerCamelCase identifiers

Case 1: UPPER_CASE / SNAKE_CASE values

Pkl Input

typealias Project = "ANDROID" | "IOS" | "API" | "WEB" 
typealias Service = "GITLAB" | "ALLURE" | "TEST_RUNNER"

Actual Generated Swift

public enum Project: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable {
    case aNDROID = "ANDROID"
    case iOS = "IOS"
    case aPI = "API"
    case wEB = "WEB"
}

public enum Service: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable {
    case gITLAB = "GITLAB"
    case aLLURE = "ALLURE"
    case tEST_RUNNER = "TEST_RUNNER"
}

Expected Behavior

Enum cases should follow Swift naming conventions (lowerCamelCase):

public enum Project: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable {
    case android = "ANDROID"
    case ios = "IOS"
    case api = "API"
    case web = "WEB"
}

public enum Service: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable {
    case gitlab = "GITLAB"
    case allure = "ALLURE"
    case testRunner = "TEST_RUNNER"
}

Case 2: Numeric string values produce invalid Swift

Pkl Input

typealias HttpCode = "400" | "401" | "403" | "404" | "500"

Actual Generated Swift (does not compile)

public enum HttpCode: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable {
    case 400 = "400"
    case 401 = "401"
    case 403 = "403"
    case 404 = "404"
    case 500 = "500"
}

This is invalid Swift — enum case names cannot begin with a digit.

Expected Behavior

Numeric strings should be prefixed or transformed to produce valid identifiers:

public enum HttpCode: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable {
    case n400 = "400" // or _400/`400`
    case n401 = "401"
    case n403 = "403"
    case n404 = "404"
    case n500 = "500"
}

I’d be happy to help fix this issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions