Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
martinbonnin committed Jan 9, 2024
1 parent 8e645d5 commit 86ced24
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 342 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,7 @@ import com.apollographql.apollo3.annotations.ApolloInternal
import com.apollographql.apollo3.compiler.codegen.ResolverClassName
import com.apollographql.apollo3.compiler.codegen.ResolverInfo
import com.apollographql.apollo3.compiler.codegen.ResolverKeyKind
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.okio.decodeFromBufferedSource
import kotlinx.serialization.json.okio.encodeToBufferedSink
import okio.buffer
import okio.sink
import okio.source
import java.io.File

@Serializable
data class CodegenMetadata internal constructor(
Expand All @@ -30,17 +22,3 @@ fun CodegenMetadata.schemaTypes(): Set<String> {
fun CodegenMetadata.resolveSchemaType(name: String): ResolverClassName? {
return resolverInfo.entries.firstOrNull { it.key.kind == ResolverKeyKind.SchemaType && it.key.id == name }?.className
}

@OptIn(ExperimentalSerializationApi::class)
fun CodegenMetadata.writeTo(file: File) {
file.sink().buffer().use {
Json.encodeToBufferedSink(CodegenMetadata.serializer(), this, it)
}
}

@OptIn(ExperimentalSerializationApi::class)
fun File.toCodegenMetadata(): CodegenMetadata {
return source().buffer().use {
Json.decodeFromBufferedSource(CodegenMetadata.serializer(), it)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@ package com.apollographql.apollo3.compiler

import com.apollographql.apollo3.ast.Schema
import com.apollographql.apollo3.ast.findTargetName
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.okio.decodeFromBufferedSource
import kotlinx.serialization.json.okio.encodeToBufferedSink
import okio.buffer
import okio.sink
import okio.source
import java.io.File

/**
* A [Schema] linked with other options that are bound to this schema and need to be the same in all modules
Expand All @@ -37,30 +29,3 @@ internal fun CodegenSchema.allTypes(): List<CodegenType> {
CodegenType(it.name, it.directives.findTargetName(schema))
}.sortedBy { it.name }
}

@OptIn(ExperimentalSerializationApi::class)
fun CodegenSchema.writeTo(file: File) {
file.sink().buffer().use {
Json.encodeToBufferedSink(CodegenSchema.serializer(), this, it)
}
}

@OptIn(ExperimentalSerializationApi::class)
fun File.toCodegenSchema(): CodegenSchema {
return source().buffer().use {
Json.decodeFromBufferedSource(CodegenSchema.serializer(), it)
}
}

@OptIn(ExperimentalSerializationApi::class)
fun File.toCodegenSchemaOptions(): CodegenSchemaOptions {
return source().buffer().use {
Json.decodeFromBufferedSource(CodegenSchemaOptions.serializer(), it)
}
}
@OptIn(ExperimentalSerializationApi::class)
fun File.toIrOptions(): IrOptions {
return source().buffer().use {
Json.decodeFromBufferedSource(IrOptions.serializer(), it)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ import com.apollographql.apollo3.annotations.ApolloExperimental
import com.apollographql.apollo3.annotations.ApolloInternal
import com.apollographql.apollo3.compiler.hooks.ApolloCompilerJavaHooks
import com.apollographql.apollo3.compiler.hooks.ApolloCompilerKotlinHooks
import com.apollographql.apollo3.compiler.ir.IrOperations
import com.apollographql.apollo3.compiler.ir.IrSchema
import com.apollographql.apollo3.compiler.operationoutput.OperationOutput
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.io.File


const val MODELS_RESPONSE_BASED = "responseBased"
const val MODELS_OPERATION_BASED = "operationBased"
const val MODELS_OPERATION_BASED_WITH_INTERFACES = "experimental_operationBasedWithInterfaces"
Expand Down Expand Up @@ -200,27 +198,10 @@ class IrOptions(
val alwaysGenerateTypesMatching: Set<String>? = null,
)

@ApolloExperimental
@Serializable
data class CommonCodegenOptions(
val codegenSchema: CodegenSchema,
val ir: IrOperations,
val irSchema: IrSchema?,
val operationOutput: OperationOutput,

val incomingCodegenMetadata: List<CodegenMetadata>,

/**
* The directory where to write the generated models
*/
val outputDir: File,

/**
* The package name used for operations
*/
val packageNameGenerator: PackageNameGenerator,

//========== codegen options ============
val useSemanticNaming: Boolean,
val useSemanticNaming: Boolean?= null,

//========== on/off flags to switch some codegen off ============
/**
Expand All @@ -229,25 +210,25 @@ data class CommonCodegenOptions(
*
* Set to true if you need to read/write fragments from the cache or if you need to instantiate fragments
*/
val generateFragmentImplementations: Boolean,
val generateFragmentImplementations: Boolean?= null,

/**
* Which methods to auto generate on models, fragments, operations, and input objects
*/
val generateMethods: List<GeneratedMethod>,
val generateMethods: List<GeneratedMethod>?= null,

/**
* Whether to generate the compiled selections used to read/write from the normalized cache.
* Disable this option if you don't use the normalized cache to save some bytecode
*/
val generateResponseFields: Boolean,
val generateResponseFields: Boolean?= null,

/**
* Whether to embed the query document in the [com.apollographql.apollo3.api.Operation]s. By default this is true as it is needed
* to send the operations to the server.
* If performance is critical and you have a way to whitelist/read the document from another place, disable this.
*/
val generateQueryDocument: Boolean,
val generateQueryDocument: Boolean?= null,

/**
* Whether to generate the Schema class.
Expand All @@ -259,18 +240,19 @@ data class CommonCodegenOptions(
*
* Default: false
*/
val generateSchema: Boolean,
val generateSchema: Boolean?= null,

/**
* Class name to use when generating the Schema class.
*
* Default: "__Schema"
*/
val generatedSchemaName: String,
val generatedSchemaName: String?= null,
)

@Serializable
class KotlinCodegenOptions(
val languageVersion: TargetLanguage,
val commonCodegenOptions: CommonCodegenOptions,

/**
* A list of [Regex] patterns for GraphQL enums that should be generated as Kotlin sealed classes instead of the default Kotlin enums.
Expand All @@ -280,29 +262,23 @@ class KotlinCodegenOptions(
*
* Default: emptyList()
*/
val sealedClassesForEnumsMatching: List<String>,
val sealedClassesForEnumsMatching: List<String>? = null,

val generateAsInternal: Boolean,
val generateAsInternal: Boolean? = null,
/**
* Kotlin native will generate [Any?] for optional types
* Setting generateFilterNotNull will generate extra `filterNotNull` functions that will help keep the type information
*/
val generateFilterNotNull: Boolean,

/**
* Hooks to customize the generated Kotlin code.
*/
@ApolloExperimental
val compilerKotlinHooks: ApolloCompilerKotlinHooks,
val generateFilterNotNull: Boolean? = null,

/**
* Whether to generate kotlin constructors with `@JvmOverloads` for more graceful Java interop experience when default values are present.
* Note: when enabled in a multi-platform setup, the generated code can only be used in the common or JVM sourcesets.
*
* Default: false
*/
val addJvmOverloads: Boolean = false,
val requiresOptInAnnotation: String?,
val addJvmOverloads: Boolean? = null,
val requiresOptInAnnotation: String? = null,

/**
* Whether to add the [JsExport] annotation to generated models. This is useful to be able to cast JSON parsed
Expand All @@ -311,7 +287,7 @@ class KotlinCodegenOptions(
* Default: false
*/
@ApolloExperimental
val jsExport: Boolean = false,
val jsExport: Boolean? = null,

/**
* Whether to generate builders in addition to constructors for operations and input types.
Expand All @@ -321,17 +297,20 @@ class KotlinCodegenOptions(
* Default: false
*/
@ApolloExperimental
val generateInputBuilders: Boolean = false,
val generateInputBuilders: Boolean? = null,
)

@Serializable
class JavaCodegenOptions(
val commonCodegenOptions: CommonCodegenOptions,

/**
* Whether to generate builders for java models
*
* Default value: false
* Only valid for java models as kotlin has data classes
*/
val generateModelBuilders: Boolean,
val generateModelBuilders: Boolean? = null,

/**
* A list of [Regex] patterns for GraphQL enums that should be generated as Java classes.
Expand All @@ -341,15 +320,15 @@ class JavaCodegenOptions(
*
* Default: listOf(".*")
*/
val classesForEnumsMatching: List<String>,
val classesForEnumsMatching: List<String>? = null,

/**
* Whether to generate fields as primitive types (`int`, `double`, `boolean`) instead of their boxed types (`Integer`, `Double`,
* `Boolean`) when possible.
*
* Default: false
*/
val generatePrimitiveTypes: Boolean,
val generatePrimitiveTypes: Boolean? = null,

/**
* The style to use for fields that are nullable in the Java generated code.
Expand All @@ -368,14 +347,7 @@ class JavaCodegenOptions(
*
* Default: `none`
*/
val nullableFieldStyle: JavaNullable,


/**
* Hooks to customize the generated Java code.
*/
@ApolloExperimental
val compilerJavaHooks: ApolloCompilerJavaHooks,
val nullableFieldStyle: JavaNullable? = null,
)

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
package com.apollographql.apollo3.compiler

import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.okio.decodeFromBufferedSource
import kotlinx.serialization.json.okio.encodeToBufferedSink
import okio.buffer
import okio.sink
import okio.source
import okio.use
import java.io.File

typealias UsedCoordinates = Map<String, Set<String>>

fun UsedCoordinates.mergeWith(other: UsedCoordinates): UsedCoordinates {
Expand All @@ -20,32 +9,3 @@ fun UsedCoordinates.mergeWith(other: UsedCoordinates): UsedCoordinates {
}
}
}

/**
* An intermediate structure that we used for serialization to enforce the order of elements in the Set.
* I'm not 100% convinced it's required but it doesn't harm and could avoid nasty build cache issues.
*/
@Serializable
private class SerializableUsedCoordinates(
val usedFields: Map<String, List<String>>,
)

private fun UsedCoordinates.toSerializableUsedCoordinates(): SerializableUsedCoordinates = SerializableUsedCoordinates(
usedFields = mapValues { it.value.toList().sorted() }
)

private fun SerializableUsedCoordinates.toUsedCoordinates(): UsedCoordinates = usedFields.mapValues { it.value.toSet() }

@OptIn(ExperimentalSerializationApi::class)
fun UsedCoordinates.writeTo(file: File) {
file.sink().buffer().use {
Json.encodeToBufferedSink(this@writeTo.toSerializableUsedCoordinates(), it)
}
}

@OptIn(ExperimentalSerializationApi::class)
fun File.toUsedCoordinates(): UsedCoordinates {
return this.source().buffer().use {
Json.decodeFromBufferedSource<SerializableUsedCoordinates>(it).toUsedCoordinates()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,9 @@ import com.apollographql.apollo3.compiler.BooleanExpressionSerializer
import com.apollographql.apollo3.compiler.GQLFragmentDefinitionSerializer
import com.apollographql.apollo3.compiler.GQLTypeSerializer
import kotlinx.serialization.Contextual
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.okio.decodeFromBufferedSource
import kotlinx.serialization.json.okio.encodeToBufferedSink
import okio.buffer
import okio.sink
import okio.source
import java.io.File

/**
* Intermediate representation (IR)
Expand Down Expand Up @@ -343,16 +336,4 @@ internal data class IrVariable(

private val json = Json { classDiscriminator = "#class" }

@OptIn(ExperimentalSerializationApi::class)
fun IrOperations.writeTo(file: File) {
file.sink().buffer().use {
json.encodeToBufferedSink(this as DefaultIrOperations, it)
}
}

@OptIn(ExperimentalSerializationApi::class)
fun File.toIrOperations(): IrOperations {
return source().buffer().use {
json.decodeFromBufferedSource<DefaultIrOperations>(it)
}
}

0 comments on commit 86ced24

Please sign in to comment.