Skip to content

Commit

Permalink
Quote enum item names when necessary (#241) (#242)
Browse files Browse the repository at this point in the history
Add backticks to the enum item name in case it doesn't
start with a letter or an underscore and hence is not
a valid Kotlin identifier.
  • Loading branch information
detouched authored Oct 2, 2023
1 parent 7d622ca commit 2231b9b
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 3 deletions.
4 changes: 2 additions & 2 deletions src/main/kotlin/com/cjbooms/fabrikt/generators/OasDefault.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.cjbooms.fabrikt.generators

import com.cjbooms.fabrikt.model.KotlinTypeInfo
import com.cjbooms.fabrikt.util.toUpperCase
import com.cjbooms.fabrikt.util.NormalisedString.toEnumName
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.CodeBlock
import com.squareup.kotlinpoet.TypeName
Expand Down Expand Up @@ -39,7 +39,7 @@ sealed class OasDefault {

data class EnumValue(val type: TypeName, val enumValue: String) : OasDefault() {
override fun getDefault(): CodeBlock =
CodeBlock.of("%T.${enumValue.toUpperCase()}", type)
CodeBlock.of("%T.${enumValue.toEnumName()}", type)
}

data class JsonNullableValue(val inner: OasDefault) : OasDefault() {
Expand Down
4 changes: 3 additions & 1 deletion src/main/kotlin/com/cjbooms/fabrikt/util/NormalisedString.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ object NormalisedString {
replaceSpecialCharacters()
.camelToSnake()
.toUpperCase()
.quoteIfNotValidIdentifier()

fun String.toKotlinParameterName(): String = this.camelCase()

Expand All @@ -42,4 +43,5 @@ object NormalisedString {
fun String.toUpperCase() = uppercase(Locale.getDefault())
fun String.toLowerCase() = lowercase(Locale.getDefault())
fun String.capitalized() = replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
fun String.decapitalized() = replaceFirstChar { it.lowercase(Locale.getDefault()) }
fun String.decapitalized() = replaceFirstChar { it.lowercase(Locale.getDefault()) }
fun String.quoteIfNotValidIdentifier() = if (first().isLetter() || first() == '_') this else "`$this`"
10 changes: 10 additions & 0 deletions src/test/kotlin/com/cjbooms/fabrikt/util/NormalisedStringTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,14 @@ class NormalisedStringTest {
assertThat("PascalCase_åØÆÅ_enumWith-special/characters.json".toEnumName())
.isEqualTo("PASCAL_CASE_Å_ØÆÅ_ENUM_WITH_SPECIAL_CHARACTERS_JSON")
}

@Test
fun `toEnumName should backtick enum if it starts with non-letter character`() {
assertThat("42".toEnumName()).isEqualTo("`42`")
}

@Test
fun `toEnumName should not backtick enum if it starts with underscore character`() {
assertThat("_42".toEnumName()).isEqualTo("_42")
}
}
6 changes: 6 additions & 0 deletions src/test/resources/examples/defaultValues/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ components:
- tall
- short
default: tall
enum_quoted_default:
type: string
enum:
- 1x
- 2x
default: 2x
boolean_default:
type: boolean
default: true
Expand Down
21 changes: 21 additions & 0 deletions src/test/resources/examples/defaultValues/models/Models.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public data class PersonWithDefaults(
@get:JsonProperty("enum_default")
@get:NotNull
public val enumDefault: PersonWithDefaultsEnumDefault = PersonWithDefaultsEnumDefault.TALL,
@param:JsonProperty("enum_quoted_default")
@get:JsonProperty("enum_quoted_default")
@get:NotNull
public val enumQuotedDefault: PersonWithDefaultsEnumQuotedDefault =
PersonWithDefaultsEnumQuotedDefault.`2X`,
@param:JsonProperty("boolean_default")
@get:JsonProperty("boolean_default")
@get:NotNull
Expand Down Expand Up @@ -57,3 +62,19 @@ public enum class PersonWithDefaultsEnumDefault(
public fun fromValue(`value`: String): PersonWithDefaultsEnumDefault? = mapping[value]
}
}

public enum class PersonWithDefaultsEnumQuotedDefault(
@JsonValue
public val `value`: String,
) {
`1X`("1x"),
`2X`("2x"),
;

public companion object {
private val mapping: Map<String, PersonWithDefaultsEnumQuotedDefault> =
values().associateBy(PersonWithDefaultsEnumQuotedDefault::value)

public fun fromValue(`value`: String): PersonWithDefaultsEnumQuotedDefault? = mapping[value]
}
}
3 changes: 3 additions & 0 deletions src/test/resources/examples/enumExamples/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ components:
- one
- two
- three
- 4
- -5
- _6

ExtensibleEnumObject:
type: string
Expand Down
3 changes: 3 additions & 0 deletions src/test/resources/examples/enumExamples/models/Models.kt
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ public enum class EnumObject(
ONE("one"),
TWO("two"),
THREE("three"),
`4`("4"),
_5("-5"),
_6("_6"),
;

public companion object {
Expand Down

0 comments on commit 2231b9b

Please sign in to comment.