11package com.apollographql.apollo.compiler.codegen.kotlin.schema
22
33import com.apollographql.apollo.compiler.codegen.Identifier
4- import com.apollographql.apollo.compiler.codegen.Identifier.KNOWN__
5- import com.apollographql.apollo.compiler.codegen.Identifier.UNKNOWN__
6- import com.apollographql.apollo.compiler.codegen.Identifier.rawValue
7- import com.apollographql.apollo.compiler.codegen.Identifier.safeValueOf
84import com.apollographql.apollo.compiler.codegen.kotlin.CgFile
95import com.apollographql.apollo.compiler.codegen.kotlin.CgFileBuilder
106import com.apollographql.apollo.compiler.codegen.kotlin.KotlinSchemaContext
@@ -18,20 +14,18 @@ import com.apollographql.apollo.compiler.codegen.kotlin.schema.util.typeProperty
1814import com.apollographql.apollo.compiler.codegen.typePackageName
1915import com.apollographql.apollo.compiler.internal.escapeKotlinReservedWordInSealedClass
2016import com.apollographql.apollo.compiler.ir.IrEnum
21- import com.squareup.kotlinpoet.AnnotationSpec
2217import com.squareup.kotlinpoet.ClassName
2318import com.squareup.kotlinpoet.CodeBlock
2419import com.squareup.kotlinpoet.FunSpec
2520import com.squareup.kotlinpoet.KModifier
2621import com.squareup.kotlinpoet.ParameterSpec
2722import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
2823import com.squareup.kotlinpoet.PropertySpec
24+ import com.squareup.kotlinpoet.TypeName
2925import com.squareup.kotlinpoet.TypeSpec
30- import com.squareup.kotlinpoet.buildCodeBlock
3126import com.squareup.kotlinpoet.joinToCode
32- import com.squareup.kotlinpoet.withIndent
3327
34- internal class EnumAsSealedInterfaceBuilder (
28+ internal class EnumAsSealedBuilder (
3529 private val context : KotlinSchemaContext ,
3630 private val enum : IrEnum ,
3731) : CgFileBuilder {
@@ -56,23 +50,20 @@ internal class EnumAsSealedInterfaceBuilder(
5650 return CgFile (
5751 packageName = packageName,
5852 fileName = simpleName,
59- typeSpecs = listOf (enum.toSealedInterfaceTypeSpec ())
53+ typeSpecs = listOf (enum.toSealedClassTypeSpec(), enum.unknownClassTypeSpec ())
6054 )
6155 }
6256
63- private fun IrEnum.toSealedInterfaceTypeSpec (): TypeSpec {
57+ private fun IrEnum.toSealedClassTypeSpec (): TypeSpec {
6458 return TypeSpec .interfaceBuilder(simpleName)
6559 .maybeAddDescription(description)
60+ // XXX: can an enum be made deprecated (and not only its values) ?
6661 .addModifiers(KModifier .SEALED )
67- .addProperty(
68- PropertySpec .builder(rawValue, KotlinSymbols .String )
69- .build()
70- )
62+ .addProperty(rawValuePropertySpec)
7163 .addType(companionTypeSpec())
7264 .addTypes(values.map { value ->
73- value.toObjectTypeSpec()
65+ value.toObjectTypeSpec(selfClassName )
7466 })
75- .addType(knownValueTypeSpec())
7667 .addType(unknownValueTypeSpec())
7768 .build()
7869 }
@@ -85,12 +76,12 @@ internal class EnumAsSealedInterfaceBuilder(
8576 .build()
8677 }
8778
88- private fun IrEnum.Value.toObjectTypeSpec (): TypeSpec {
79+ private fun IrEnum.Value.toObjectTypeSpec (superClass : TypeName ): TypeSpec {
8980 return TypeSpec .objectBuilder(targetName.escapeKotlinReservedWordInSealedClass())
9081 .maybeAddDeprecation(deprecationReason)
9182 .maybeAddDescription(description)
9283 .maybeAddRequiresOptIn(context.resolver, optInFeature)
93- .addSuperinterface(selfClassName.nestedClass( KNOWN__ ) )
84+ .addSuperinterface(superClass )
9485 .addProperty(
9586 PropertySpec .builder(" rawValue" , KotlinSymbols .String )
9687 .addModifiers(KModifier .OVERRIDE )
@@ -100,99 +91,71 @@ internal class EnumAsSealedInterfaceBuilder(
10091 .build()
10192 }
10293
103- private fun IrEnum.knownValueTypeSpec (): TypeSpec {
104- return TypeSpec .interfaceBuilder(KNOWN__ )
105- .addKdoc(" An enum value that is known at build time." )
94+ private fun IrEnum.unknownValueTypeSpec (): TypeSpec {
95+ return TypeSpec .interfaceBuilder(" UNKNOWN__ " )
96+ .addKdoc(" An enum value that wasn't known at compile time." )
10697 .addSuperinterface(selfClassName)
107- .addProperty(
108- PropertySpec .builder(rawValue, KotlinSymbols .String )
109- .addModifiers(KModifier .OVERRIDE )
110- .build()
111- )
112- .addModifiers(KModifier .SEALED )
113- .addAnnotation(AnnotationSpec .builder(KotlinSymbols .Suppress ).addMember(" %S" , " ClassName" ).build())
98+ .addProperty(unknownValueRawValuePropertySpec)
11499 .build()
115100 }
116101
117- private fun IrEnum.unknownValueTypeSpec (): TypeSpec {
118- return TypeSpec .classBuilder(UNKNOWN__ )
119- .addKdoc(" An enum value that isn't known at build time." )
120- .addSuperinterface(selfClassName)
121- .primaryConstructor(
122- FunSpec .constructorBuilder()
123- .addAnnotation(AnnotationSpec .builder(KotlinSymbols .ApolloPrivateEnumConstructor ).build())
124- .addParameter(rawValue, KotlinSymbols .String )
125- .build()
126- )
127- .addProperty(
128- PropertySpec .builder(rawValue, KotlinSymbols .String )
129- .addModifiers(KModifier .OVERRIDE )
130- .initializer(rawValue)
131- .build()
132- )
133- .addAnnotation(AnnotationSpec .builder(KotlinSymbols .Suppress ).addMember(" %S" , " ClassName" ).build())
102+ private fun IrEnum.unknownClassTypeSpec (): TypeSpec {
103+ return TypeSpec .classBuilder(" UNKNOWN__${simpleName} " )
104+ .addSuperinterface(unknownValueInterfaceName())
105+ .primaryConstructor(unknownValuePrimaryConstructorSpec)
106+ .addProperty(unknownValueRawValuePropertySpecWithInitializer)
107+ .addModifiers(KModifier .PRIVATE )
134108 .addFunction(
135109 FunSpec .builder(" equals" )
136110 .addModifiers(KModifier .OVERRIDE )
137111 .addParameter(ParameterSpec (" other" , KotlinSymbols .Any .copy(nullable = true )))
138112 .returns(KotlinSymbols .Boolean )
139- .addCode(" if (other !is $UNKNOWN__ ) return false\n " ,)
140- .addCode(" return this.$ rawValue == other.rawValue" )
113+ .addCode(" if (other !is %T ) return false\n " , unknownValueClassName() )
114+ .addCode(" return this.rawValue == other.rawValue" )
141115 .build()
142116 )
143117 .addFunction(
144118 FunSpec .builder(" hashCode" )
145119 .addModifiers(KModifier .OVERRIDE )
146120 .returns(KotlinSymbols .Int )
147- .addCode(" return this.$ rawValue .hashCode()" )
121+ .addCode(" return this.rawValue.hashCode()" )
148122 .build()
149123 )
150124 .addFunction(
151125 FunSpec .builder(" toString" )
152126 .addModifiers(KModifier .OVERRIDE )
153127 .returns(KotlinSymbols .String )
154- .addCode(" return \" $ UNKNOWN__ (${' $' }$ rawValue )\" " )
128+ .addCode(" return \" UNKNOWN__(${' $' } rawValue)\" " )
155129 .build()
156130 )
157131 .build()
158132 }
159133
160134 private fun IrEnum.safeValueOfFunSpec (): FunSpec {
161- return FunSpec .builder(safeValueOf)
135+ return FunSpec .builder(Identifier . safeValueOf)
162136 .addKdoc(
163- """
164- Returns an instance of [%T] representing [$rawValue ].
165-
166- The returned value may be an instance of [$UNKNOWN__ ] if the enum value is not known at build time.
167- You may want to update your schema instead of calling this function directly.
168- """ .trimIndent(),
137+ " Returns the [%T] that represents the specified [rawValue].\n " +
138+ " Note: unknown values of [rawValue] will return [UNKNOWN__]. You may want to update your schema instead of calling this function directly.\n " ,
169139 selfClassName
170140 )
171141 .addSuppressions(enum.values.any { it.deprecationReason != null })
172142 .maybeAddOptIn(context.resolver, enum.values)
173- .addParameter(rawValue, KotlinSymbols .String )
143+ .addParameter(" rawValue" , KotlinSymbols .String )
174144 .returns(selfClassName)
175- .beginControlFlow(" return when($ rawValue )" )
145+ .beginControlFlow(" return when(rawValue)" )
176146 .addCode(
177147 values
178148 .map { CodeBlock .of(" %S -> %T" , it.name, it.valueClassName()) }
179149 .joinToCode(separator = " \n " , suffix = " \n " )
180150 )
181- .addCode(buildCodeBlock {
182- add(" else -> {\n " )
183- withIndent {
184- add(" @%T(%T::class)\n " , KotlinSymbols .OptIn , KotlinSymbols .ApolloPrivateEnumConstructor )
185- add(" $UNKNOWN__ ($rawValue )\n " )
186- }
187- add(" }\n " )
188- })
151+ .addCode(" else -> %T(rawValue)\n " , unknownValueClassName())
189152 .endControlFlow()
190153 .build()
191154 }
192155
193156 private fun IrEnum.knownValuesFunSpec (): FunSpec {
194157 return FunSpec .builder(Identifier .knownValues)
195- .addKdoc(" Returns all [%T] known at build time" , selfClassName)
158+ .addKdoc(" Returns all [%T] known at compile time" , selfClassName)
196159 .addSuppressions(enum.values.any { it.deprecationReason != null })
197160 .maybeAddOptIn(context.resolver, enum.values)
198161 .returns(KotlinSymbols .Array .parameterizedBy(selfClassName))
@@ -216,4 +179,31 @@ internal class EnumAsSealedInterfaceBuilder(
216179 return ClassName (selfClassName.packageName, selfClassName.simpleName, targetName.escapeKotlinReservedWordInSealedClass())
217180 }
218181
182+ private fun unknownValueInterfaceName (): ClassName {
183+ return ClassName (selfClassName.packageName, selfClassName.simpleName, " UNKNOWN__" )
184+ }
185+
186+ private fun unknownValueClassName (): ClassName {
187+ return ClassName (selfClassName.packageName, " UNKNOWN__${selfClassName.simpleName} " )
188+ }
189+
190+ private val unknownValuePrimaryConstructorSpec =
191+ FunSpec .constructorBuilder()
192+ .addParameter(" rawValue" , KotlinSymbols .String )
193+ .build()
194+
195+ private val unknownValueRawValuePropertySpec =
196+ PropertySpec .builder(" rawValue" , KotlinSymbols .String )
197+ .addModifiers(KModifier .OVERRIDE )
198+ .build()
199+
200+ private val unknownValueRawValuePropertySpecWithInitializer =
201+ PropertySpec .builder(" rawValue" , KotlinSymbols .String )
202+ .addModifiers(KModifier .OVERRIDE )
203+ .initializer(" rawValue" )
204+ .build()
205+
206+ private val rawValuePropertySpec =
207+ PropertySpec .builder(" rawValue" , KotlinSymbols .String )
208+ .build()
219209}
0 commit comments