
com.apollographql.execution.processor.codegen.ExecutableSchemaBuilderBuilder.kt Maven / Gradle / Ivy
package com.apollographql.execution.processor.codegen
import com.apollographql.execution.processor.sir.Instantiation
import com.apollographql.execution.processor.sir.SirCoercing
import com.apollographql.execution.processor.sir.SirEnumDefinition
import com.apollographql.execution.processor.sir.SirInputObjectDefinition
import com.apollographql.execution.processor.sir.SirObjectDefinition
import com.apollographql.execution.processor.sir.SirScalarDefinition
import com.apollographql.execution.processor.sir.asKotlinPoet
import com.apollographql.execution.processor.sir.SirTypeDefinition
import com.squareup.kotlinpoet.CodeBlock
import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.MemberName
internal class ExecutableSchemaBuilderBuilder(
private val context: KotlinExecutableSchemaContext,
private val serviceName: String,
private val schemaDocument: MemberName,
private val sirTypeDefinitions: List,
) : CgFileBuilder {
val simpleName = "${serviceName}ExecutableSchemaBuilder".capitalizeFirstLetter()
override fun prepare() {}
override fun build(): FileSpec {
return FileSpec.builder(context.packageName, simpleName)
.addFunction(funSpec())
.build()
}
private fun funSpec(): FunSpec {
return FunSpec.builder(simpleName)
.returns(KotlinSymbols.ExecutableSchemaBuilder)
.addModifiers(KModifier.INTERNAL)
.addCode(
buildCode {
add("@Suppress(\"UNCHECKED_CAST\")")
add("fun Any?.cast(): T = this as T\n\n")
// Use a variable so that we don't get an expression return
add("val schemaBuilder = %L()\n", KotlinSymbols.ExecutableSchemaBuilder)
indent {
add(".schema(%M)\n", schemaDocument)
sirTypeDefinitions.filterIsInstance().forEach { sirObjectDefinition ->
add(".addTypeChecker(%S)·{·it·is·%T·}\n", sirObjectDefinition.name, sirObjectDefinition.targetClassName.asKotlinPoet())
sirObjectDefinition.fields.forEach { irTargetField ->
val coordinates = "${sirObjectDefinition.name}.${irTargetField.name}"
add(".addResolver(%S)·{\n%L\n}\n", coordinates, resolverBody(sirObjectDefinition, irTargetField))
}
}
sirTypeDefinitions.filterIsInstance().forEach { sirScalarDefinition ->
add(".addCoercing(%S, %L)\n", sirScalarDefinition.name, sirScalarDefinition.coercing.codeBlock())
}
sirTypeDefinitions.filterIsInstance().forEach { sirInputObjectDefinition ->
add(".addCoercing(%S, %M)\n", sirInputObjectDefinition.name, context.coercings.get(sirInputObjectDefinition.name))
}
sirTypeDefinitions.filterIsInstance().forEach { sirEnumDefinition ->
add(".addCoercing(%S, %M)\n", sirEnumDefinition.name, context.coercings.get(sirEnumDefinition.name))
}
listOf("query", "mutation", "subscription").forEach { operationType ->
val sirObjectDefinition = sirTypeDefinitions.rootType(operationType)
if (sirObjectDefinition != null && sirObjectDefinition.instantiation != Instantiation.UNKNOWN) {
add(".${operationType}Root { %L }\n", sirObjectDefinition.codeBlock())
}
}
}
add("return schemaBuilder")
}
)
.build()
}
}
private fun SirCoercing.codeBlock(): CodeBlock {
return buildCode {
add("%T", className.asKotlinPoet())
if (instantiation == Instantiation.NO_ARG_CONSTRUCTOR) {
add("()")
}
}
}
internal fun List.rootType(operationType: String): SirObjectDefinition? {
return firstOrNull { it is SirObjectDefinition && it.operationType == operationType } as SirObjectDefinition?
}
private fun SirObjectDefinition.codeBlock(): CodeBlock {
return buildCode {
add("%T", targetClassName.asKotlinPoet())
if (instantiation == Instantiation.NO_ARG_CONSTRUCTOR) {
add("()")
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy