Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Codegen] Add CompiledArgumentDefinition #5797

Merged
merged 18 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Have field definitions and their arguments generated inside type classes
  • Loading branch information
BoD committed Apr 10, 2024
commit cf477f6a02e73328f936935a99b268835145effa
15 changes: 0 additions & 15 deletions libraries/apollo-compiler/api/apollo-compiler.api
Original file line number Diff line number Diff line change
Expand Up @@ -640,21 +640,6 @@ public final class com/apollographql/apollo3/compiler/ir/IrArgument$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public final class com/apollographql/apollo3/compiler/ir/IrArgumentDefinition$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lcom/apollographql/apollo3/compiler/ir/IrArgumentDefinition$$serializer;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/apollographql/apollo3/compiler/ir/IrArgumentDefinition;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/apollographql/apollo3/compiler/ir/IrArgumentDefinition;)V
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}

public final class com/apollographql/apollo3/compiler/ir/IrArgumentDefinition$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public final class com/apollographql/apollo3/compiler/ir/IrBooleanValue$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lcom/apollographql/apollo3/compiler/ir/IrBooleanValue$$serializer;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ internal object ClassNames {
val True = ResolverClassName(apolloApiPackageName, "BooleanExpression", "True")
val False = ResolverClassName(apolloApiPackageName, "BooleanExpression", "False")
val CompiledArgument = ResolverClassName(apolloApiPackageName, "CompiledArgument", "Builder")
val CompiledArgumentDefinition = ResolverClassName(apolloApiPackageName, "CompiledArgumentDefinition", "Builder")
val CompiledArgumentDefinition = ResolverClassName(apolloApiPackageName, "CompiledArgumentDefinition")
val CompiledArgumentDefinitionBuilder = ResolverClassName(apolloApiPackageName, "CompiledArgumentDefinition", "Builder")
val CompiledVariable = ResolverClassName(apolloApiPackageName, "CompiledVariable")
val JsonNumber = ResolverClassName(apolloApiJsonPackageName, "JsonNumber")
val CompiledCondition = ResolverClassName(apolloApiPackageName, "CompiledCondition")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ internal object JavaClassNames {
val True = ClassNames.True.toJavaPoetClassName()
val False = ClassNames.False.toJavaPoetClassName()
val CompiledArgumentDefinition = ClassNames.CompiledArgumentDefinition.toJavaPoetClassName()
val CompiledArgumentDefinitionBuilder = ClassNames.CompiledArgumentDefinitionBuilder.toJavaPoetClassName()
val CompiledArgument = ClassNames.CompiledArgument.toJavaPoetClassName()
val CompiledVariable = ClassNames.CompiledVariable.toJavaPoetClassName()
val JsonNumber = ClassNames.JsonNumber.toJavaPoetClassName()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import com.apollographql.apollo3.compiler.codegen.java.S
import com.apollographql.apollo3.compiler.codegen.java.T
import com.apollographql.apollo3.compiler.codegen.java.helpers.codeBlock
import com.apollographql.apollo3.compiler.codegen.java.helpers.toListInitializerCodeblock
import com.apollographql.apollo3.compiler.internal.escapeJavaReservedWord
import com.apollographql.apollo3.compiler.ir.BVariable
import com.apollographql.apollo3.compiler.ir.BooleanExpression
import com.apollographql.apollo3.compiler.ir.IrArgument
import com.apollographql.apollo3.compiler.ir.IrArgumentDefinition
import com.apollographql.apollo3.compiler.ir.IrField
import com.apollographql.apollo3.compiler.ir.IrFragment
import com.apollographql.apollo3.compiler.ir.IrSelection
Expand Down Expand Up @@ -60,7 +60,7 @@ internal class CompiledSelectionsBuilder(
builder.add(".condition($L)", condition.toCompiledConditionInitializer())
}
if (arguments.isNotEmpty()) {
builder.add(".arguments($L)", arguments.sortedBy { it.definition.name }.map { it.codeBlock() }.toListInitializerCodeblock())
builder.add(".arguments($L)", arguments.sortedBy { it.name }.map { it.codeBlock() }.toListInitializerCodeblock())
}
if (selectionSetName != null) {
builder.add(".selections($L)", "__$selectionSetName")
Expand Down Expand Up @@ -118,29 +118,14 @@ internal class CompiledSelectionsBuilder(
return CodeBlock.of("new $T($S, $L)", JavaClassNames.CompiledCondition, expression.value.name, inverted.toString())
}

private fun IrArgumentDefinition.codeBlock(): CodeBlock {
val builder = CodeBlock.builder()
builder.add(
"new $T($S)",
JavaClassNames.CompiledArgumentDefinition,
name,
)
if (isKey) {
builder.add(".isKey(true)")
}
if (isPagination) {
builder.add(".isPagination(true)")
}
builder.add(".build()")
return builder.build()
}

private fun IrArgument.codeBlock(): CodeBlock {
val argumentBuilder = CodeBlock.builder()
argumentBuilder.add(
"new $T($L)",
"new $T($T.$L.${'$'}N)",
JavaClassNames.CompiledArgument,
definition.codeBlock(),
context.resolver.resolveSchemaType(parentType),
context.layout.className(parentField),
name.escapeJavaReservedWord(),
)
if (this.value != null) {
argumentBuilder.add(".value($L)", value.codeBlock())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ internal class InterfaceBuilder(
.addModifiers(Modifier.PUBLIC)
.maybeAddDescription(description)
.maybeAddDeprecation(deprecationReason)
.addTypes(fieldDefinitions.typeSpecs(layout))
.addField(typeFieldSpec(context.resolver))
.build()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
package com.apollographql.apollo3.compiler.codegen.java.schema

import com.apollographql.apollo3.compiler.codegen.SchemaLayout
import com.apollographql.apollo3.compiler.codegen.java.CodegenJavaFile
import com.apollographql.apollo3.compiler.codegen.java.JavaClassBuilder
import com.apollographql.apollo3.compiler.codegen.java.JavaClassNames
import com.apollographql.apollo3.compiler.codegen.java.JavaSchemaContext
import com.apollographql.apollo3.compiler.codegen.java.S
import com.apollographql.apollo3.compiler.codegen.java.T
import com.apollographql.apollo3.compiler.codegen.java.helpers.maybeAddDeprecation
import com.apollographql.apollo3.compiler.codegen.java.helpers.maybeAddDescription
import com.apollographql.apollo3.compiler.codegen.typePackageName
import com.apollographql.apollo3.compiler.internal.escapeJavaReservedWord
import com.apollographql.apollo3.compiler.ir.IrArgumentDefinition
import com.apollographql.apollo3.compiler.ir.IrFieldDefinition
import com.apollographql.apollo3.compiler.ir.IrObject
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.CodeBlock
import com.squareup.javapoet.FieldSpec
import com.squareup.javapoet.TypeSpec
import javax.lang.model.element.Modifier

Expand Down Expand Up @@ -36,7 +45,53 @@ internal class ObjectBuilder(
.addModifiers(Modifier.PUBLIC)
.maybeAddDescription(description)
.maybeAddDeprecation(deprecationReason)
.addTypes(fieldDefinitions.typeSpecs(layout))
.addField(typeFieldSpec(context.resolver))
.build()
}
}

internal fun List<IrFieldDefinition>.typeSpecs(layout: SchemaLayout) = mapNotNull { fieldDefinition ->
if (fieldDefinition.argumentDefinitions.isEmpty()) {
null
} else {
fieldDefinition.typeSpec(layout)
}
}

private fun IrFieldDefinition.typeSpec(layout: SchemaLayout): TypeSpec {
return TypeSpec
.interfaceBuilder(layout.className(name))
.addModifiers(Modifier.PUBLIC)
.addFields(
argumentDefinitions.map { argumentDefinition ->
FieldSpec.builder(
JavaClassNames.CompiledArgumentDefinition,
argumentDefinition.name.escapeJavaReservedWord(),
Modifier.PUBLIC,
Modifier.STATIC,
Modifier.FINAL,
)
.initializer(argumentDefinition.codeBlock())
.build()
}
)
.build()
}

private fun IrArgumentDefinition.codeBlock(): CodeBlock {
val builder = CodeBlock.builder()
builder.add(
"new $T($S)",
JavaClassNames.CompiledArgumentDefinitionBuilder,
name,
)
if (isKey) {
builder.add(".isKey(true)")
}
if (isPagination) {
builder.add(".isPagination(true)")
}
builder.add(".build()")
return builder.build()
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ internal object KotlinSymbols {
val False = ClassNames.False.toKotlinPoetClassName()
val CompiledArgument = ClassNames.CompiledArgument.toKotlinPoetClassName()
val CompiledArgumentDefinition = ClassNames.CompiledArgumentDefinition.toKotlinPoetClassName()
val CompiledArgumentDefinitionBuilder = ClassNames.CompiledArgumentDefinitionBuilder.toKotlinPoetClassName()
val CompiledVariable = ClassNames.CompiledVariable.toKotlinPoetClassName()
val JsonNumber = ClassNames.JsonNumber.toKotlinPoetClassName()
val CompiledCondition = ClassNames.CompiledCondition.toKotlinPoetClassName()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import com.apollographql.apollo3.compiler.internal.applyIf
import com.apollographql.apollo3.compiler.ir.BVariable
import com.apollographql.apollo3.compiler.ir.BooleanExpression
import com.apollographql.apollo3.compiler.ir.IrArgument
import com.apollographql.apollo3.compiler.ir.IrArgumentDefinition
import com.apollographql.apollo3.compiler.ir.IrField
import com.apollographql.apollo3.compiler.ir.IrFragment
import com.apollographql.apollo3.compiler.ir.IrSelection
Expand Down Expand Up @@ -64,7 +63,7 @@ internal class CompiledSelectionsBuilder(
builder.add(".condition(%L)\n", condition.toCompiledConditionInitializer())
}
if (arguments.isNotEmpty()) {
builder.add(".arguments(%L)\n", arguments.sortedBy { it.definition.name }.map { it.codeBlock() }.toListInitializerCodeblock(true))
builder.add(".arguments(%L)\n", arguments.sortedBy { it.name }.map { it.codeBlock() }.toListInitializerCodeblock(true))
}
if (selectionSetName != null) {
builder.add(".selections(%N)\n", "__$selectionSetName")
Expand Down Expand Up @@ -123,30 +122,14 @@ internal class CompiledSelectionsBuilder(
return CodeBlock.of("%T(%S,·%L)", KotlinSymbols.CompiledCondition, expression.value.name, inverted.toString())
}

private fun IrArgumentDefinition.codeBlock(): CodeBlock {
val argumentBuilder = CodeBlock.builder()
argumentBuilder.add(
"%T(%S)",
KotlinSymbols.CompiledArgumentDefinition,
name,
)

if (isKey) {
argumentBuilder.add(".isKey(true)")
}
if (isPagination) {
argumentBuilder.add(".isPagination(true)")
}
argumentBuilder.add(".build()")
return argumentBuilder.build()
}

private fun IrArgument.codeBlock(): CodeBlock {
val argumentBuilder = CodeBlock.builder()
argumentBuilder.add(
"%T(%L)",
"%T(%T.%N.%N)",
KotlinSymbols.CompiledArgument,
definition.codeBlock(),
context.resolver.resolveSchemaType(parentType),
context.layout.className(parentField),
name,
)

if (this.value != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ internal class InterfaceBuilder(
.classBuilder(simpleName)
.maybeAddDescription(description)
.maybeAddDeprecation(deprecationReason)
.addTypes(fieldDefinitions.typeSpecs(layout))
.addType(companionTypeSpec())
.build()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.apollographql.apollo3.compiler.codegen.kotlin.schema

import com.apollographql.apollo3.compiler.capitalizeFirstLetter
import com.apollographql.apollo3.compiler.codegen.SchemaLayout
import com.apollographql.apollo3.compiler.codegen.kotlin.CgFile
import com.apollographql.apollo3.compiler.codegen.kotlin.CgFileBuilder
import com.apollographql.apollo3.compiler.codegen.kotlin.KotlinSchemaContext
import com.apollographql.apollo3.compiler.codegen.kotlin.KotlinSymbols
import com.apollographql.apollo3.compiler.codegen.kotlin.KotlinSymbols.CompiledArgumentDefinitionBuilder
import com.apollographql.apollo3.compiler.codegen.kotlin.helpers.concreteBuilderTypeSpec
import com.apollographql.apollo3.compiler.codegen.kotlin.helpers.concreteMapTypeSpec
import com.apollographql.apollo3.compiler.codegen.kotlin.helpers.maybeAddDeprecation
Expand All @@ -12,10 +15,14 @@ import com.apollographql.apollo3.compiler.codegen.kotlin.helpers.maybeImplementB
import com.apollographql.apollo3.compiler.codegen.kotlin.helpers.topLevelBuildFunSpec
import com.apollographql.apollo3.compiler.codegen.kotlin.schema.util.typePropertySpec
import com.apollographql.apollo3.compiler.codegen.typePackageName
import com.apollographql.apollo3.compiler.ir.IrArgumentDefinition
import com.apollographql.apollo3.compiler.ir.IrFieldDefinition
import com.apollographql.apollo3.compiler.ir.IrObject
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.CodeBlock
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.MemberName
import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.TypeSpec

internal class ObjectBuilder(
Expand Down Expand Up @@ -75,6 +82,7 @@ internal class ObjectBuilder(
.classBuilder(simpleName)
.maybeAddDescription(description)
.maybeAddDeprecation(deprecationReason)
.addTypes(fieldDefinitions.typeSpecs(layout))
.addType(companionTypeSpec())
.build()
}
Expand All @@ -86,3 +94,54 @@ internal class ObjectBuilder(
.build()
}
}

internal fun List<IrFieldDefinition>.typeSpecs(layout: SchemaLayout): List<TypeSpec> {
return mapNotNull { fieldDefinition ->
if (fieldDefinition.argumentDefinitions.isEmpty()) {
null
} else {
fieldDefinition.typeSpec(layout)
}
}
}

private fun IrFieldDefinition.typeSpec(layout: SchemaLayout): TypeSpec {
return TypeSpec
.interfaceBuilder(layout.className(name))
.addType(argumentDefinitions.companionTypeSpec())
.build()
}

private fun List<IrArgumentDefinition>.companionTypeSpec(): TypeSpec {
return TypeSpec.companionObjectBuilder()
.addProperties(
map { argumentDefinition ->
PropertySpec.builder(
name = argumentDefinition.name,
type = KotlinSymbols.CompiledArgumentDefinition,
)
.initializer(argumentDefinition.codeBlock())
.addAnnotation(JvmField::class)
.build()
}
)
.build()
}

private fun IrArgumentDefinition.codeBlock(): CodeBlock {
val argumentBuilder = CodeBlock.builder()
argumentBuilder.add(
"%T(%S)",
CompiledArgumentDefinitionBuilder,
name,
)

if (isKey) {
argumentBuilder.add(".isKey(true)")
}
if (isPagination) {
argumentBuilder.add(".isPagination(true)")
}
argumentBuilder.add(".build()")
return argumentBuilder.build()
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,12 @@ data class IrField(
val selectionSetName: String?,
) : IrSelection

@Serializable
@ApolloExperimental
data class IrArgumentDefinition(
val name: String,
val isKey: Boolean,
val isPagination: Boolean,
)

@Serializable
@ApolloExperimental
data class IrArgument(
val definition: IrArgumentDefinition,
val parentType: String,
val parentField: String,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you merge parentType and parentField (and name) in an id field like in IrModel.id that you can later use to resolve the argument definition classname for that id?

I'm trying to avoid GraphQL things in the IR. It's OK to have opaque ids but IR doesn't need to know about GraphQL names.

val name: String,
/**
* The value for this argument. May be null if the argument is absent
*/
Expand Down
Loading