Skip to content

Commit cf6359f

Browse files
BoDmartinbonnin
andauthored
Make enum as sealed class Unknown constructor opt-in (apollographql#5813)
* Make enum as sealed class Unknown constructor opt-in * Introduce ApolloEnumConstructor * Update libraries/apollo-annotations/src/commonMain/kotlin/com/apollographql/apollo3/annotations/ApolloEnumConstructor.kt Co-authored-by: Martin Bonnin <[email protected]> * Update libraries/apollo-annotations/src/commonMain/kotlin/com/apollographql/apollo3/annotations/ApolloEnumConstructor.kt Co-authored-by: Martin Bonnin <[email protected]> --------- Co-authored-by: Martin Bonnin <[email protected]>
1 parent 626f66f commit cf6359f

File tree

5 files changed

+33
-16
lines changed

5 files changed

+33
-16
lines changed

libraries/apollo-annotations/api/apollo-annotations.api

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ public final class com/apollographql/apollo3/annotations/ApolloDeprecatedSince$V
2727
public static fun values ()[Lcom/apollographql/apollo3/annotations/ApolloDeprecatedSince$Version;
2828
}
2929

30+
public abstract interface annotation class com/apollographql/apollo3/annotations/ApolloEnumConstructor : java/lang/annotation/Annotation {
31+
}
32+
3033
public abstract interface annotation class com/apollographql/apollo3/annotations/ApolloExperimental : java/lang/annotation/Annotation {
3134
}
3235

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.apollographql.apollo3.annotations
2+
3+
@RequiresOptIn(
4+
level = RequiresOptIn.Level.WARNING,
5+
message = "The `UNKNOWN__` class represents GraphQL enums that are not present in the schema and whose `rawValue` cannot be checked at build time. You may want to update your schema instead of calling this constructor directly."
6+
)
7+
@Retention(AnnotationRetention.BINARY)
8+
@Target(AnnotationTarget.CONSTRUCTOR)
9+
annotation class ApolloEnumConstructor

libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo3/compiler/codegen/kotlin/KotlinSymbols.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ internal object KotlinSymbols {
105105

106106
val ApolloAdaptableWith = ClassName(ClassNames.apolloAnnotationsPackageName, "ApolloAdaptableWith")
107107
val ApolloExperimental = ClassName(ClassNames.apolloAnnotationsPackageName, "ApolloExperimental")
108+
val ApolloEnumConstructor = ClassName(ClassNames.apolloAnnotationsPackageName, "ApolloEnumConstructor")
108109

109110
val JsExport = ClassName("kotlin.js", "JsExport")
110111

libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo3/compiler/codegen/kotlin/schema/EnumAsSealedBuilder.kt

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ internal class EnumAsSealedBuilder(
8989

9090
private fun IrEnum.unknownValueTypeSpec(): TypeSpec {
9191
return TypeSpec.classBuilder("UNKNOWN__")
92-
.addKdoc("%L", "An enum value that wasn't known at compile time.\n")
93-
.primaryConstructor(primaryConstructorSpec)
92+
.addKdoc("An enum value that wasn't known at compile time.\nConstructor is annotated with [%T] to prevent instantiation outside of this file.", KotlinSymbols.ApolloEnumConstructor)
93+
.primaryConstructor(unknownValuePrimaryConstructorSpec)
9494
.superclass(selfClassName)
9595
.addSuperclassConstructorParameter("rawValue·=·rawValue")
9696
.addFunction(
@@ -132,7 +132,7 @@ internal class EnumAsSealedBuilder(
132132
.map { CodeBlock.of("%S·->·%T", it.name, it.valueClassName()) }
133133
.joinToCode(separator = "\n", suffix = "\n")
134134
)
135-
.addCode("else -> %T(rawValue)\n", unknownValueClassName())
135+
.addCode("else -> @OptIn(%T::class) %T(rawValue)\n", KotlinSymbols.ApolloEnumConstructor, unknownValueClassName())
136136
.endControlFlow()
137137
.build()
138138
}
@@ -167,19 +167,20 @@ internal class EnumAsSealedBuilder(
167167
return ClassName(selfClassName.packageName, selfClassName.simpleName, "UNKNOWN__")
168168
}
169169

170-
private val primaryConstructorSpec =
171-
FunSpec.constructorBuilder()
172-
.addParameter("rawValue", KotlinSymbols.String)
173-
.build()
170+
private val unknownValuePrimaryConstructorSpec =
171+
FunSpec.constructorBuilder()
172+
.addAnnotation(KotlinSymbols.ApolloEnumConstructor)
173+
.addParameter("rawValue", KotlinSymbols.String)
174+
.build()
174175

175176
private val primaryConstructorWithOverriddenParamSpec =
176-
FunSpec.constructorBuilder()
177-
.addParameter("rawValue", KotlinSymbols.String)
178-
.build()
177+
FunSpec.constructorBuilder()
178+
.addParameter("rawValue", KotlinSymbols.String)
179+
.build()
179180

180181
private val rawValuePropertySpec =
181-
PropertySpec.builder("rawValue", KotlinSymbols.String)
182-
.initializer("rawValue")
183-
.build()
182+
PropertySpec.builder("rawValue", KotlinSymbols.String)
183+
.initializer("rawValue")
184+
.build()
184185

185-
}
186+
}

libraries/apollo-compiler/src/test/graphql/com/example/enums_as_sealed/kotlin/responseBased/enums_as_sealed/type/Enum.kt.expected

Lines changed: 5 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)