1
1
package com.apollographql.apollo.compiler.codegen.kotlin.schema
2
2
3
3
import 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
8
4
import com.apollographql.apollo.compiler.codegen.kotlin.CgFile
9
5
import com.apollographql.apollo.compiler.codegen.kotlin.CgFileBuilder
10
6
import com.apollographql.apollo.compiler.codegen.kotlin.KotlinSchemaContext
@@ -18,20 +14,18 @@ import com.apollographql.apollo.compiler.codegen.kotlin.schema.util.typeProperty
18
14
import com.apollographql.apollo.compiler.codegen.typePackageName
19
15
import com.apollographql.apollo.compiler.internal.escapeKotlinReservedWordInSealedClass
20
16
import com.apollographql.apollo.compiler.ir.IrEnum
21
- import com.squareup.kotlinpoet.AnnotationSpec
22
17
import com.squareup.kotlinpoet.ClassName
23
18
import com.squareup.kotlinpoet.CodeBlock
24
19
import com.squareup.kotlinpoet.FunSpec
25
20
import com.squareup.kotlinpoet.KModifier
26
21
import com.squareup.kotlinpoet.ParameterSpec
27
22
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
28
23
import com.squareup.kotlinpoet.PropertySpec
24
+ import com.squareup.kotlinpoet.TypeName
29
25
import com.squareup.kotlinpoet.TypeSpec
30
- import com.squareup.kotlinpoet.buildCodeBlock
31
26
import com.squareup.kotlinpoet.joinToCode
32
- import com.squareup.kotlinpoet.withIndent
33
27
34
- internal class EnumAsSealedInterfaceBuilder (
28
+ internal class EnumAsSealedBuilder (
35
29
private val context : KotlinSchemaContext ,
36
30
private val enum : IrEnum ,
37
31
) : CgFileBuilder {
@@ -56,23 +50,20 @@ internal class EnumAsSealedInterfaceBuilder(
56
50
return CgFile (
57
51
packageName = packageName,
58
52
fileName = simpleName,
59
- typeSpecs = listOf (enum.toSealedInterfaceTypeSpec ())
53
+ typeSpecs = listOf (enum.toSealedClassTypeSpec(), enum.unknownClassTypeSpec ())
60
54
)
61
55
}
62
56
63
- private fun IrEnum.toSealedInterfaceTypeSpec (): TypeSpec {
57
+ private fun IrEnum.toSealedClassTypeSpec (): TypeSpec {
64
58
return TypeSpec .interfaceBuilder(simpleName)
65
59
.maybeAddDescription(description)
60
+ // XXX: can an enum be made deprecated (and not only its values) ?
66
61
.addModifiers(KModifier .SEALED )
67
- .addProperty(
68
- PropertySpec .builder(rawValue, KotlinSymbols .String )
69
- .build()
70
- )
62
+ .addProperty(rawValuePropertySpec)
71
63
.addType(companionTypeSpec())
72
64
.addTypes(values.map { value ->
73
- value.toObjectTypeSpec()
65
+ value.toObjectTypeSpec(selfClassName )
74
66
})
75
- .addType(knownValueTypeSpec())
76
67
.addType(unknownValueTypeSpec())
77
68
.build()
78
69
}
@@ -85,12 +76,12 @@ internal class EnumAsSealedInterfaceBuilder(
85
76
.build()
86
77
}
87
78
88
- private fun IrEnum.Value.toObjectTypeSpec (): TypeSpec {
79
+ private fun IrEnum.Value.toObjectTypeSpec (superClass : TypeName ): TypeSpec {
89
80
return TypeSpec .objectBuilder(targetName.escapeKotlinReservedWordInSealedClass())
90
81
.maybeAddDeprecation(deprecationReason)
91
82
.maybeAddDescription(description)
92
83
.maybeAddRequiresOptIn(context.resolver, optInFeature)
93
- .addSuperinterface(selfClassName.nestedClass( KNOWN__ ) )
84
+ .addSuperinterface(superClass )
94
85
.addProperty(
95
86
PropertySpec .builder(" rawValue" , KotlinSymbols .String )
96
87
.addModifiers(KModifier .OVERRIDE )
@@ -100,99 +91,71 @@ internal class EnumAsSealedInterfaceBuilder(
100
91
.build()
101
92
}
102
93
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." )
106
97
.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)
114
99
.build()
115
100
}
116
101
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 )
134
108
.addFunction(
135
109
FunSpec .builder(" equals" )
136
110
.addModifiers(KModifier .OVERRIDE )
137
111
.addParameter(ParameterSpec (" other" , KotlinSymbols .Any .copy(nullable = true )))
138
112
.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" )
141
115
.build()
142
116
)
143
117
.addFunction(
144
118
FunSpec .builder(" hashCode" )
145
119
.addModifiers(KModifier .OVERRIDE )
146
120
.returns(KotlinSymbols .Int )
147
- .addCode(" return this.$ rawValue .hashCode()" )
121
+ .addCode(" return this.rawValue.hashCode()" )
148
122
.build()
149
123
)
150
124
.addFunction(
151
125
FunSpec .builder(" toString" )
152
126
.addModifiers(KModifier .OVERRIDE )
153
127
.returns(KotlinSymbols .String )
154
- .addCode(" return \" $ UNKNOWN__ (${' $' }$ rawValue )\" " )
128
+ .addCode(" return \" UNKNOWN__(${' $' } rawValue)\" " )
155
129
.build()
156
130
)
157
131
.build()
158
132
}
159
133
160
134
private fun IrEnum.safeValueOfFunSpec (): FunSpec {
161
- return FunSpec .builder(safeValueOf)
135
+ return FunSpec .builder(Identifier . safeValueOf)
162
136
.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 " ,
169
139
selfClassName
170
140
)
171
141
.addSuppressions(enum.values.any { it.deprecationReason != null })
172
142
.maybeAddOptIn(context.resolver, enum.values)
173
- .addParameter(rawValue, KotlinSymbols .String )
143
+ .addParameter(" rawValue" , KotlinSymbols .String )
174
144
.returns(selfClassName)
175
- .beginControlFlow(" return when($ rawValue )" )
145
+ .beginControlFlow(" return when(rawValue)" )
176
146
.addCode(
177
147
values
178
148
.map { CodeBlock .of(" %S -> %T" , it.name, it.valueClassName()) }
179
149
.joinToCode(separator = " \n " , suffix = " \n " )
180
150
)
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())
189
152
.endControlFlow()
190
153
.build()
191
154
}
192
155
193
156
private fun IrEnum.knownValuesFunSpec (): FunSpec {
194
157
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)
196
159
.addSuppressions(enum.values.any { it.deprecationReason != null })
197
160
.maybeAddOptIn(context.resolver, enum.values)
198
161
.returns(KotlinSymbols .Array .parameterizedBy(selfClassName))
@@ -216,4 +179,31 @@ internal class EnumAsSealedInterfaceBuilder(
216
179
return ClassName (selfClassName.packageName, selfClassName.simpleName, targetName.escapeKotlinReservedWordInSealedClass())
217
180
}
218
181
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()
219
209
}
0 commit comments