diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo3/compiler/ReservedKeywords.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo3/compiler/ReservedKeywords.kt index 5b6bd748163..c58b44dcd65 100644 --- a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo3/compiler/ReservedKeywords.kt +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo3/compiler/ReservedKeywords.kt @@ -10,6 +10,10 @@ private val JAVA_RESERVED_WORDS = arrayOf( "transient", "try", "true", "void", "volatile", "while" ) +private val TYPE_REGEX = "(?:type)_*".toRegex() +private val COMPANION_REGEX = "(?:Companion)_*".toRegex() +private val KOTLIN_ENUM_RESERVED_WORDS_REGEX = "(?:name|ordinal)_*".toRegex() + fun String.escapeJavaReservedWord() = if (this in JAVA_RESERVED_WORDS) "${this}_" else this // Does nothing. KotlinPoet will add the backticks @@ -19,21 +23,29 @@ internal fun String.escapeTypeReservedWord(): String? { return when { // type is forbidden because we use it as a companion property to hold the CompiledType // See https://github.com/apollographql/apollo-kotlin/issues/4293 - "(?:type)_*".toRegex().matches(this) -> "${this}_" + TYPE_REGEX.matches(this) -> "${this}_" else -> null } } +private fun String.escapeCompanionReservedWord(): String? { + return when { + // Companion is forbidden because a Companion class is generated in enum and sealed classes + // See https://github.com/apollographql/apollo-kotlin/issues/4557 + COMPANION_REGEX.matches(this) -> "${this}_" + else -> null + } +} fun String.escapeKotlinReservedWordInEnum(): String { return when { // name and ordinal are forbidden because already used in Kotlin // See https://kotlinlang.org/docs/enum-classes.html#working-with-enum-constants:~:text=properties%20for%20obtaining%20its%20name%20and%20position - "(?:name|ordinal)_*".toRegex().matches(this) -> "${this}_" - else -> escapeTypeReservedWord() ?: escapeKotlinReservedWord() + KOTLIN_ENUM_RESERVED_WORDS_REGEX.matches(this) -> "${this}_" + else -> escapeTypeReservedWord() ?: escapeCompanionReservedWord() ?: escapeKotlinReservedWord() } } fun String.escapeKotlinReservedWordInSealedClass(): String { - return escapeTypeReservedWord() ?: escapeKotlinReservedWord() + return escapeTypeReservedWord() ?: escapeCompanionReservedWord() ?: escapeKotlinReservedWord() } diff --git a/tests/enums/src/main/graphql/schema.graphqls b/tests/enums/src/main/graphql/schema.graphqls index 27e5b0e66bb..3372f4a30ad 100644 --- a/tests/enums/src/main/graphql/schema.graphqls +++ b/tests/enums/src/main/graphql/schema.graphqls @@ -20,6 +20,7 @@ enum Direction { # Value names should be escaped with _ suffixes when generating enums name, ordinal, + Companion, } enum Gravity { @@ -32,6 +33,9 @@ enum Gravity { LEFT, RIGHT, + # Value names should be escaped with _ suffixes when generating sealed classes + Companion, + # Value names should not be escaped when generating sealed classes name, ordinal, diff --git a/tests/enums/src/test/kotlin/test/EnumsTest.kt b/tests/enums/src/test/kotlin/test/EnumsTest.kt index ec64bccb037..5fba7faa9ca 100644 --- a/tests/enums/src/test/kotlin/test/EnumsTest.kt +++ b/tests/enums/src/test/kotlin/test/EnumsTest.kt @@ -17,6 +17,7 @@ class EnumsTest { assertEquals(Direction.name_, Direction.safeValueOf("name")) assertEquals(Direction.ordinal_, Direction.safeValueOf("ordinal")) assertEquals(Direction.type__, Direction.safeValueOf("type")) + assertEquals(Direction.Companion_, Direction.safeValueOf("Companion")) } @Test @@ -27,6 +28,7 @@ class EnumsTest { assertEquals(Gravity.name, Gravity.safeValueOf("name")) assertEquals(Gravity.ordinal, Gravity.safeValueOf("ordinal")) assertEquals(Gravity.type__, Gravity.safeValueOf("type")) + assertEquals(Gravity.Companion_, Gravity.safeValueOf("Companion")) } @Test @@ -37,6 +39,7 @@ class EnumsTest { assertEquals(enums.java.type.Direction.name, enums.java.type.Direction.safeValueOf("name")) assertEquals(enums.java.type.Direction.ordinal, enums.java.type.Direction.safeValueOf("ordinal")) assertEquals(enums.java.type.Direction.type__, enums.java.type.Direction.safeValueOf("type")) + assertEquals(enums.java.type.Direction.Companion, enums.java.type.Direction.safeValueOf("Companion")) } @Test @@ -47,6 +50,7 @@ class EnumsTest { assertEquals(enums.java.type.Gravity.name, enums.java.type.Gravity.safeValueOf("name")) assertEquals(enums.java.type.Gravity.ordinal, enums.java.type.Gravity.safeValueOf("ordinal")) assertEquals(enums.java.type.Gravity.type__, enums.java.type.Gravity.safeValueOf("type")) + assertEquals(enums.java.type.Gravity.Companion, enums.java.type.Gravity.safeValueOf("Companion")) } @@ -76,6 +80,7 @@ class EnumsTest { Gravity.BOTTOM, Gravity.LEFT, Gravity.RIGHT, + Gravity.Companion_, Gravity.name, Gravity.ordinal, Gravity.type__,