From 119bd5a5a4e497184132a189c2f59b97400ea1b1 Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Fri, 30 May 2025 14:36:01 +0200 Subject: [PATCH] Do not add key fields if the cache compiler plugin is already doing it Keep in sync with v4 --- .../api/apollo-annotations.api | 1 + .../api/apollo-annotations.klib.api | 1 + .../annotations/ApolloDeprecatedSince.kt | 1 + .../apollo-compiler/api/apollo-compiler.api | 31 +- .../apollo/compiler/ApolloCompiler.kt | 42 +- .../apollo/compiler/ApolloCompilerPlugin.kt | 186 ++++---- .../ApolloCompilerPluginEnvironment.kt | 30 ++ .../compiler/ApolloCompilerPluginLogger.kt | 3 - .../compiler/ApolloCompilerPluginProvider.kt | 5 +- .../compiler/LegacyOperationIdsGenerator.kt | 20 - .../apollographql/apollo/compiler/Options.kt | 4 +- .../apollo/compiler/entrypoints.kt | 42 +- .../ApolloExecutableDocumentTransform.kt | 409 +++++++++--------- .../internal/DefaultApolloCompilerRegistry.kt | 72 +-- .../internal/LegacyOperationIdsGenerator.kt | 22 + .../apollo/compiler/CodegenTest.kt | 2 +- .../apollo/compiler/MetadataTest.kt | 4 +- .../apollo/compiler/TypenameTest.kt | 20 +- .../ConditionalFragmentsTest.kt | 8 +- .../src/main/kotlin/hooks/TestPlugin.kt | 2 - .../src/main/kotlin/hooks/TestPlugin.kt | 3 - .../src/main/kotlin/hooks/TestPlugin.kt | 2 - .../src/main/kotlin/hooks/TestPlugin.kt | 2 - .../src/main/kotlin/schema/TestPlugin.kt | 4 +- .../src/main/kotlin/hooks/TestPlugin.kt | 3 +- .../src/main/kotlin/com/example/TestPlugin.kt | 2 - 26 files changed, 490 insertions(+), 431 deletions(-) create mode 100644 libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPluginEnvironment.kt delete mode 100644 libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/LegacyOperationIdsGenerator.kt create mode 100644 libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/internal/LegacyOperationIdsGenerator.kt diff --git a/libraries/apollo-annotations/api/apollo-annotations.api b/libraries/apollo-annotations/api/apollo-annotations.api index e5a7d3309f8..3885423aa6f 100644 --- a/libraries/apollo-annotations/api/apollo-annotations.api +++ b/libraries/apollo-annotations/api/apollo-annotations.api @@ -25,6 +25,7 @@ public final class com/apollographql/apollo/annotations/ApolloDeprecatedSince$Ve public static final field v4_0_1 Lcom/apollographql/apollo/annotations/ApolloDeprecatedSince$Version; public static final field v4_0_2 Lcom/apollographql/apollo/annotations/ApolloDeprecatedSince$Version; public static final field v4_1_2 Lcom/apollographql/apollo/annotations/ApolloDeprecatedSince$Version; + public static final field v4_2_1 Lcom/apollographql/apollo/annotations/ApolloDeprecatedSince$Version; public static final field v5_0_0 Lcom/apollographql/apollo/annotations/ApolloDeprecatedSince$Version; public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Lcom/apollographql/apollo/annotations/ApolloDeprecatedSince$Version; diff --git a/libraries/apollo-annotations/api/apollo-annotations.klib.api b/libraries/apollo-annotations/api/apollo-annotations.klib.api index 84969f43475..df4e0bb814e 100644 --- a/libraries/apollo-annotations/api/apollo-annotations.klib.api +++ b/libraries/apollo-annotations/api/apollo-annotations.klib.api @@ -38,6 +38,7 @@ open annotation class com.apollographql.apollo.annotations/ApolloDeprecatedSince enum entry v4_0_1 // com.apollographql.apollo.annotations/ApolloDeprecatedSince.Version.v4_0_1|null[0] enum entry v4_0_2 // com.apollographql.apollo.annotations/ApolloDeprecatedSince.Version.v4_0_2|null[0] enum entry v4_1_2 // com.apollographql.apollo.annotations/ApolloDeprecatedSince.Version.v4_1_2|null[0] + enum entry v4_2_1 // com.apollographql.apollo.annotations/ApolloDeprecatedSince.Version.v4_2_1|null[0] enum entry v5_0_0 // com.apollographql.apollo.annotations/ApolloDeprecatedSince.Version.v5_0_0|null[0] final val entries // com.apollographql.apollo.annotations/ApolloDeprecatedSince.Version.entries|#static{}entries[0] diff --git a/libraries/apollo-annotations/src/commonMain/kotlin/com/apollographql/apollo/annotations/ApolloDeprecatedSince.kt b/libraries/apollo-annotations/src/commonMain/kotlin/com/apollographql/apollo/annotations/ApolloDeprecatedSince.kt index 376ea053757..eebcf6939ab 100644 --- a/libraries/apollo-annotations/src/commonMain/kotlin/com/apollographql/apollo/annotations/ApolloDeprecatedSince.kt +++ b/libraries/apollo-annotations/src/commonMain/kotlin/com/apollographql/apollo/annotations/ApolloDeprecatedSince.kt @@ -34,6 +34,7 @@ annotation class ApolloDeprecatedSince(val version: Version) { v4_0_1, v4_0_2, v4_1_2, // All symbols above are ERRORs in 5.0.0 except a few ones that are perpetual soft deprecations like SubscriptionWsProtocol (https://youtrack.jetbrains.com/issue/KT-54106) + v4_2_1, v5_0_0 } } diff --git a/libraries/apollo-compiler/api/apollo-compiler.api b/libraries/apollo-compiler/api/apollo-compiler.api index 43f256c83e6..5caf06ba15b 100644 --- a/libraries/apollo-compiler/api/apollo-compiler.api +++ b/libraries/apollo-compiler/api/apollo-compiler.api @@ -13,11 +13,11 @@ public final class com/apollographql/apollo/compiler/After : com/apollographql/a public final class com/apollographql/apollo/compiler/ApolloCompiler { public static final field INSTANCE Lcom/apollographql/apollo/compiler/ApolloCompiler; - public final fun buildCodegenSchema (Ljava/util/List;Lcom/apollographql/apollo/compiler/ApolloCompiler$Logger;Lcom/apollographql/apollo/compiler/CodegenSchemaOptions;Ljava/util/List;Lcom/apollographql/apollo/compiler/SchemaTransform;)Lcom/apollographql/apollo/compiler/CodegenSchema; + public final fun buildCodegenSchema (Ljava/util/List;Lcom/apollographql/apollo/compiler/ApolloCompiler$Logger;Lcom/apollographql/apollo/compiler/CodegenSchemaOptions;Ljava/util/List;Lcom/apollographql/apollo/compiler/SchemaDocumentTransform;)Lcom/apollographql/apollo/compiler/CodegenSchema; public final fun buildDataBuilders (Lcom/apollographql/apollo/compiler/CodegenSchema;Lcom/apollographql/apollo/compiler/UsedCoordinates;Lcom/apollographql/apollo/compiler/CodegenOptions;Lcom/apollographql/apollo/compiler/codegen/SchemaLayout;Ljava/util/List;)Lcom/apollographql/apollo/compiler/codegen/SourceOutput; public final fun buildIrOperations (Lcom/apollographql/apollo/compiler/CodegenSchema;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lcom/apollographql/apollo/compiler/IrOptions;Lcom/apollographql/apollo/compiler/ExecutableDocumentTransform;Lcom/apollographql/apollo/compiler/ApolloCompiler$Logger;)Lcom/apollographql/apollo/compiler/ir/IrOperations; public final fun buildSchemaAndOperationsSources (Lcom/apollographql/apollo/compiler/CodegenSchema;Ljava/util/List;Lcom/apollographql/apollo/compiler/IrOptions;Lcom/apollographql/apollo/compiler/CodegenOptions;Lcom/apollographql/apollo/compiler/LayoutFactory;Lcom/apollographql/apollo/compiler/OperationIdsGenerator;Lcom/apollographql/apollo/compiler/Transform;Lcom/apollographql/apollo/compiler/Transform;Lcom/apollographql/apollo/compiler/Transform;Lcom/apollographql/apollo/compiler/ExecutableDocumentTransform;Lcom/apollographql/apollo/compiler/ApolloCompiler$Logger;Ljava/io/File;)Lcom/apollographql/apollo/compiler/codegen/SourceOutput; - public final fun buildSchemaAndOperationsSources (Ljava/util/List;Ljava/util/List;Lcom/apollographql/apollo/compiler/CodegenSchemaOptions;Lcom/apollographql/apollo/compiler/IrOptions;Lcom/apollographql/apollo/compiler/CodegenOptions;Lcom/apollographql/apollo/compiler/LayoutFactory;Lcom/apollographql/apollo/compiler/OperationIdsGenerator;Lcom/apollographql/apollo/compiler/Transform;Lcom/apollographql/apollo/compiler/Transform;Lcom/apollographql/apollo/compiler/Transform;Lcom/apollographql/apollo/compiler/ExecutableDocumentTransform;Lcom/apollographql/apollo/compiler/SchemaTransform;Lcom/apollographql/apollo/compiler/ApolloCompiler$Logger;Ljava/io/File;)Lcom/apollographql/apollo/compiler/codegen/SourceOutput; + public final fun buildSchemaAndOperationsSources (Ljava/util/List;Ljava/util/List;Lcom/apollographql/apollo/compiler/CodegenSchemaOptions;Lcom/apollographql/apollo/compiler/IrOptions;Lcom/apollographql/apollo/compiler/CodegenOptions;Lcom/apollographql/apollo/compiler/LayoutFactory;Lcom/apollographql/apollo/compiler/OperationIdsGenerator;Lcom/apollographql/apollo/compiler/Transform;Lcom/apollographql/apollo/compiler/Transform;Lcom/apollographql/apollo/compiler/Transform;Lcom/apollographql/apollo/compiler/ExecutableDocumentTransform;Lcom/apollographql/apollo/compiler/SchemaDocumentTransform;Lcom/apollographql/apollo/compiler/ApolloCompiler$Logger;Ljava/io/File;)Lcom/apollographql/apollo/compiler/codegen/SourceOutput; public final fun buildSchemaAndOperationsSourcesFromIr (Lcom/apollographql/apollo/compiler/CodegenSchema;Lcom/apollographql/apollo/compiler/ir/IrOperations;Lcom/apollographql/apollo/compiler/UsedCoordinates;Ljava/util/List;Lcom/apollographql/apollo/compiler/CodegenOptions;Lcom/apollographql/apollo/compiler/codegen/SchemaAndOperationsLayout;Lcom/apollographql/apollo/compiler/OperationIdsGenerator;Lcom/apollographql/apollo/compiler/Transform;Lcom/apollographql/apollo/compiler/Transform;Lcom/apollographql/apollo/compiler/Transform;Ljava/io/File;)Lcom/apollographql/apollo/compiler/codegen/SourceOutput; public final fun buildSchemaSources (Lcom/apollographql/apollo/compiler/CodegenSchema;Lcom/apollographql/apollo/compiler/UsedCoordinates;Lcom/apollographql/apollo/compiler/CodegenOptions;Lcom/apollographql/apollo/compiler/codegen/SchemaLayout;Lcom/apollographql/apollo/compiler/Transform;Lcom/apollographql/apollo/compiler/Transform;)Lcom/apollographql/apollo/compiler/codegen/SourceOutput; } @@ -54,14 +54,14 @@ public abstract interface class com/apollographql/apollo/compiler/ApolloCompiler public abstract interface class com/apollographql/apollo/compiler/ApolloCompilerRegistry { public abstract fun registerExecutableDocumentTransform (Ljava/lang/String;[Lcom/apollographql/apollo/compiler/Order;Lcom/apollographql/apollo/compiler/ExecutableDocumentTransform;)V - public abstract fun registerExtraCodeGenerator (Lcom/apollographql/apollo/compiler/CodeGenerator;)V public abstract fun registerForeignSchemas (Ljava/util/List;)V public abstract fun registerIrTransform (Ljava/lang/String;[Lcom/apollographql/apollo/compiler/Order;Lcom/apollographql/apollo/compiler/Transform;)V public abstract fun registerJavaOutputTransform (Ljava/lang/String;[Lcom/apollographql/apollo/compiler/Order;Lcom/apollographql/apollo/compiler/Transform;)V public abstract fun registerKotlinOutputTransform (Ljava/lang/String;[Lcom/apollographql/apollo/compiler/Order;Lcom/apollographql/apollo/compiler/Transform;)V public abstract fun registerLayout (Lcom/apollographql/apollo/compiler/LayoutFactory;)V public abstract fun registerOperationIdsGenerator (Lcom/apollographql/apollo/compiler/OperationIdsGenerator;)V - public abstract fun registerSchemaTransform (Ljava/lang/String;[Lcom/apollographql/apollo/compiler/Order;Lcom/apollographql/apollo/compiler/SchemaTransform;)V + public abstract fun registerSchemaCodeGenerator (Lcom/apollographql/apollo/compiler/SchemaCodeGenerator;)V + public abstract fun registerSchemaTransform (Ljava/lang/String;[Lcom/apollographql/apollo/compiler/Order;Lcom/apollographql/apollo/compiler/SchemaDocumentTransform;)V } public final class com/apollographql/apollo/compiler/Before : com/apollographql/apollo/compiler/Order { @@ -69,10 +69,6 @@ public final class com/apollographql/apollo/compiler/Before : com/apollographql/ public final fun getId ()Ljava/lang/String; } -public abstract interface class com/apollographql/apollo/compiler/CodeGenerator { - public abstract fun generate (Lcom/apollographql/apollo/ast/GQLDocument;Ljava/io/File;)V -} - public final class com/apollographql/apollo/compiler/CodegenMetadata { public static final field Companion Lcom/apollographql/apollo/compiler/CodegenMetadata$Companion; public fun (Ljava/lang/String;Lcom/apollographql/apollo/compiler/TargetLanguage;Ljava/util/List;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V @@ -201,6 +197,11 @@ public abstract interface class com/apollographql/apollo/compiler/CommonCodegenO public abstract fun getUseSemanticNaming ()Ljava/lang/Boolean; } +public abstract interface class com/apollographql/apollo/compiler/DocumentTransform { + public abstract fun transform (Lcom/apollographql/apollo/ast/Schema;Lcom/apollographql/apollo/ast/GQLFragmentDefinition;)Lcom/apollographql/apollo/ast/GQLFragmentDefinition; + public abstract fun transform (Lcom/apollographql/apollo/ast/Schema;Lcom/apollographql/apollo/ast/GQLOperationDefinition;)Lcom/apollographql/apollo/ast/GQLOperationDefinition; +} + public final class com/apollographql/apollo/compiler/EntryPoints { public fun ()V public final fun buildCodegenSchema (Ljava/util/Map;IZLjava/util/List;Ljava/util/function/Consumer;Ljava/io/File;Ljava/io/File;)V @@ -364,7 +365,7 @@ public abstract interface class com/apollographql/apollo/compiler/LayoutFactory } public abstract interface class com/apollographql/apollo/compiler/OperationIdsGenerator { - public abstract fun generate (Ljava/util/Collection;)Ljava/util/List; + public abstract fun generate (Ljava/util/List;)Ljava/util/List; } public abstract interface class com/apollographql/apollo/compiler/OperationsCodegenOpt { @@ -401,6 +402,10 @@ public final class com/apollographql/apollo/compiler/RuntimeAdapterInitializer : public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public abstract interface class com/apollographql/apollo/compiler/SchemaCodeGenerator { + public abstract fun generate (Lcom/apollographql/apollo/ast/GQLDocument;Ljava/io/File;)V +} + public abstract interface class com/apollographql/apollo/compiler/SchemaCodegenOpt { public abstract fun getGenerateSchema ()Ljava/lang/Boolean; public abstract fun getGeneratedSchemaName ()Ljava/lang/String; @@ -409,12 +414,12 @@ public abstract interface class com/apollographql/apollo/compiler/SchemaCodegenO public abstract interface class com/apollographql/apollo/compiler/SchemaCodegenOptions : com/apollographql/apollo/compiler/JavaSchemaCodegenOptions, com/apollographql/apollo/compiler/KotlinSchemaCodegenOptions { } -public abstract interface class com/apollographql/apollo/compiler/SchemaListener { - public abstract fun onSchema (Lcom/apollographql/apollo/ast/Schema;Ljava/io/File;)V +public abstract interface class com/apollographql/apollo/compiler/SchemaDocumentTransform { + public abstract fun transform (Lcom/apollographql/apollo/ast/GQLDocument;)Lcom/apollographql/apollo/ast/GQLDocument; } -public abstract interface class com/apollographql/apollo/compiler/SchemaTransform { - public abstract fun transform (Lcom/apollographql/apollo/ast/GQLDocument;)Lcom/apollographql/apollo/ast/GQLDocument; +public abstract interface class com/apollographql/apollo/compiler/SchemaListener { + public abstract fun onSchema (Lcom/apollographql/apollo/ast/Schema;Ljava/io/File;)V } public final class com/apollographql/apollo/compiler/StringsKt { diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompiler.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompiler.kt index 5029d311417..82a5e768d8d 100644 --- a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompiler.kt +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompiler.kt @@ -45,7 +45,6 @@ import com.apollographql.apollo.compiler.ir.IrOperationsBuilder import com.apollographql.apollo.compiler.ir.IrSchemaBuilder import com.apollographql.apollo.compiler.ir.buildIrDataBuilders import com.apollographql.apollo.compiler.operationoutput.OperationDescriptor -import com.apollographql.apollo.compiler.operationoutput.OperationId import com.apollographql.apollo.compiler.operationoutput.toOperationOutput import com.apollographql.apollo.compiler.pqm.toPersistedQueryManifest import java.io.File @@ -60,7 +59,7 @@ object ApolloCompiler { logger: Logger?, codegenSchemaOptions: CodegenSchemaOptions, foreignSchemas: List, - schemaTransform: SchemaTransform?, + schemaTransform: SchemaDocumentTransform?, ): CodegenSchema { val schemaDocuments = schemaFiles.map { it.normalizedPath to it.file.toGQLDocument(allowJson = true) @@ -190,7 +189,7 @@ object ApolloCompiler { upstreamCodegenModels: List, upstreamFragmentDefinitions: List, options: IrOptions, - executableDocumentTransform: ExecutableDocumentTransform?, + documentTransform: ExecutableDocumentTransform?, logger: Logger?, ): IrOperations { val schema = codegenSchema.schema @@ -232,14 +231,24 @@ object ApolloCompiler { /** * Step 2, Modify the AST to add typename, key fields and call any user-provided transform. + * If we detect that the cache compiler plugin is present, we skip adding the keyfields because it will do it. + * TODO: deprecate `addTypename` */ - var document = ApolloExecutableDocumentTransform(options.addTypename ?: defaultAddTypename).transform( - schema = schema, - document = GQLDocument(userDefinitions, sourceLocation = null), - upstreamFragmentDefinitions + val hasCacheCompilerPlugin = try { + Class.forName("com.apollographql.cache.apollocompilerplugin.internal.ApolloCacheCompilerPlugin") + true + } catch (_: ClassNotFoundException) { + false + } + + var document = ApolloExecutableDocumentTransform(options.addTypename ?: defaultAddTypename, !hasCacheCompilerPlugin).transform( + schema = schema, + document = GQLDocument(userDefinitions, sourceLocation = null), + upstreamFragmentDefinitions ) - if (executableDocumentTransform != null) { - document = executableDocumentTransform.transform(schema, document, upstreamFragmentDefinitions) + + if (documentTransform != null) { + document = documentTransform.transform(schema, document, upstreamFragmentDefinitions) } /** @@ -475,8 +484,8 @@ object ApolloCompiler { irOperationsTransform: Transform?, javaOutputTransform: Transform?, kotlinOutputTransform: Transform?, - executableDocumentTransform: ExecutableDocumentTransform?, - schemaTransform: SchemaTransform?, + documentTransform: ExecutableDocumentTransform?, + schemaDocumentTransform: SchemaDocumentTransform?, logger: Logger?, operationManifestFile: File?, ): SourceOutput { @@ -485,7 +494,7 @@ object ApolloCompiler { logger = logger, codegenSchemaOptions = codegenSchemaOptions, foreignSchemas = emptyList(), - schemaTransform = schemaTransform + schemaTransform = schemaDocumentTransform ) return buildSchemaAndOperationsSources( @@ -498,7 +507,7 @@ object ApolloCompiler { irOperationsTransform, javaOutputTransform, kotlinOutputTransform, - executableDocumentTransform, + documentTransform, logger, operationManifestFile ) @@ -517,7 +526,7 @@ object ApolloCompiler { irOperationsTransform: Transform?, javaOutputTransform: Transform?, kotlinOutputTransform: Transform?, - executableDocumentTransform: ExecutableDocumentTransform?, + documentTransform: ExecutableDocumentTransform?, logger: Logger?, operationManifestFile: File?, ): SourceOutput { @@ -526,7 +535,7 @@ object ApolloCompiler { executableFiles = executableFiles, upstreamCodegenModels = emptyList(), upstreamFragmentDefinitions = emptyList(), - executableDocumentTransform = executableDocumentTransform, + documentTransform = documentTransform, options = irOptions, logger = logger ) @@ -642,6 +651,3 @@ fun interface LayoutFactory { fun create(codegenSchema: CodegenSchema): SchemaAndOperationsLayout? } -fun interface OperationIdsGenerator { - fun generate(operationDescriptorList: Collection): List -} diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPlugin.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPlugin.kt index ce9c6418060..c39b16b677a 100644 --- a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPlugin.kt +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPlugin.kt @@ -5,6 +5,7 @@ import com.apollographql.apollo.annotations.ApolloExperimental import com.apollographql.apollo.ast.ForeignSchema import com.apollographql.apollo.ast.GQLDocument import com.apollographql.apollo.ast.GQLFragmentDefinition +import com.apollographql.apollo.ast.GQLOperationDefinition import com.apollographql.apollo.ast.Schema import com.apollographql.apollo.compiler.codegen.java.JavaOutput import com.apollographql.apollo.compiler.codegen.kotlin.KotlinOutput @@ -12,14 +13,16 @@ import com.apollographql.apollo.compiler.ir.IrOperations import com.apollographql.apollo.compiler.operationoutput.OperationDescriptor import com.apollographql.apollo.compiler.operationoutput.OperationId import java.io.File +import kotlin.jvm.Throws /** * [ApolloCompilerPlugin] allows to customize the behavior of the Apollo Compiler. * - * [ApolloCompilerPlugin] may be instantiated several times in a codegen run. Each instance is created in a - * separate classloader. - * The classloaders contains `apollo-compiler` classes and the runtime classpath of the [ApolloCompilerPlugin]. - * You may throw from [ApolloCompilerPlugin] methods to fail the build. + * [ApolloCompilerPlugin] instances are created by [java.util.ServiceLoader] and may be instantiated several times in a codegen run. + * Each instance is created in a separate classloader and contains the `apollo-compiler` version loaded by your build tool. + * + * You may check [com.apollographql.apollo.compiler.APOLLO_VERSION] to check for compatibility of your + * plugin with the version of `apollo-compiler` available at runtime. */ interface ApolloCompilerPlugin { /** @@ -32,62 +35,74 @@ interface ApolloCompilerPlugin { * @param registry the registry where to register transformations. */ fun beforeCompilationStep(environment: ApolloCompilerPluginEnvironment, registry: ApolloCompilerRegistry) { - } + /** * Computes operation ids for persisted queries. * * @return a list of [OperationId] matching an operation name to its id or null to use the SHA256 default */ @Deprecated("Call `registry.registerOperationIdsGenerator()` from beforeCompilationStep() instead.") - @ApolloDeprecatedSince(ApolloDeprecatedSince.Version.v5_0_0) + @ApolloDeprecatedSince(ApolloDeprecatedSince.Version.v4_2_1) fun operationIds(descriptors: List): List? { return null } } -/** - * [ApolloCompilerPluginEnvironment] contains the environment where the Apollo compiler is run. - */ -class ApolloCompilerPluginEnvironment( - /** - * @see [ApolloCompilerPluginValue] - */ - val arguments: Map, - /** - * A logger that can be used by the plugin. - */ - val logger: ApolloCompilerPluginLogger, -) - -sealed interface Order +@Deprecated("Use CodeGenerator instead.") +@ApolloDeprecatedSince(ApolloDeprecatedSince.Version.v4_2_1) +interface SchemaListener { + /** + * Called when the schema changed and codegen needs to be updated + * + * @param schema the validated schema. + * @param outputDirectory the compiler output directory. This directory is shared with the compiler, make sure to use a specific + * package name to avoid clobbering other files. + */ + fun onSchema(schema: Schema, outputDirectory: File) +} -class Before(val id: String): Order -class After(val id: String): Order -interface ApolloCompilerRegistry { - fun registerForeignSchemas(schemas: List) - @ApolloExperimental - fun registerSchemaTransform(id: String, vararg orders: Order, transform: SchemaTransform) +/** + * A [DocumentTransform] transforms operations and fragments at build time. [DocumentTransform] can add or remove fields automatically for an example. + */ +@Deprecated("Use ExecutableDocumentTransform instead.") +@ApolloDeprecatedSince(ApolloDeprecatedSince.Version.v4_2_1) +interface DocumentTransform { + /** + * Transforms the given operation. + * + * [transform] is called after any processing done by the Apollo compiler such as adding `__typename`. + */ + fun transform(schema: Schema, operation: GQLOperationDefinition): GQLOperationDefinition - @ApolloExperimental - fun registerExecutableDocumentTransform(id: String, vararg orders: Order, transform: ExecutableDocumentTransform) - @ApolloExperimental - fun registerIrTransform(id: String, vararg orders: Order, transform: Transform) + /** + * Transforms the given fragment. + * + * [transform] is called after any processing done by the Apollo compiler such as adding `__typename`. + */ + fun transform(schema: Schema, fragment: GQLFragmentDefinition): GQLFragmentDefinition +} - @ApolloExperimental - fun registerLayout(factory: LayoutFactory) - fun registerOperationIdsGenerator(generator: OperationIdsGenerator) - @ApolloExperimental - fun registerJavaOutputTransform(id: String, vararg orders: Order, transform: Transform) - @ApolloExperimental - fun registerKotlinOutputTransform(id: String, vararg orders: Order, transform: Transform) - @ApolloExperimental - fun registerExtraCodeGenerator(codeGenerator: CodeGenerator) +/** + * Transforms a type + * + * This is not a kotlin function type because this might be used in environment where those types are + * relocated and might fail to load at runtime. For an example, in a Gradle plugin. + */ +@ApolloExperimental +fun interface Transform { + /** + * Transforms the given input into an output of the same type + */ + fun transform(input: T): T } -fun interface SchemaTransform { +/** + * A [SchemaDocumentTransform] transforms the schema at build time. + */ +fun interface SchemaDocumentTransform { /** * Transforms the given schema document. * @@ -96,10 +111,10 @@ fun interface SchemaTransform { fun transform(schemaDocument: GQLDocument): GQLDocument } - /** * A [ExecutableDocumentTransform] transforms operations and fragments at build time. [ExecutableDocumentTransform] can add or remove fields automatically, for an example. */ +@ApolloExperimental fun interface ExecutableDocumentTransform { /** * Transforms the given document. @@ -115,57 +130,70 @@ fun interface ExecutableDocumentTransform { } /** - * Transforms a type + * An [OperationIdsGenerator] is responsible for computing [OperationId] from [OperationDescriptor]. * - * This is not a kotlin function type because this might be used in environments where those types are - * relocated and might fail to load at runtime. For an example, in a Gradle plugin. + * This is used for [persisted queries](https://www.apollographql.com/docs/kotlin/advanced/persisted-queries). */ -fun interface Transform { +@ApolloExperimental +fun interface OperationIdsGenerator { /** - * Transforms the given input into an output of the same type + * Generate the [OperationId]s from [operationDescriptors]. + * Implementations my throw to fail the build. */ - fun transform(input: T): T + @Throws + fun generate(operationDescriptors: List): List } +@ApolloExperimental +sealed interface Order + +@ApolloExperimental +class Before(val id: String): Order + +@ApolloExperimental +class After(val id: String): Order + /** - * A code generator that may write code in [ApolloCompilerPluginEnvironment.outputDirectory] - * - * This is not a kotlin function type because this might be used in environments where those types are - * relocated and might fail to load at runtime. For an example, in a Gradle plugin. + * A code generator that may write extra schema code in addition to what the Apollo Kotlin compiler is generating. */ -fun interface CodeGenerator { +@ApolloExperimental +fun interface SchemaCodeGenerator { /** - * Transforms the given input into an output of the same type + * @param schema a [GQLDocument] representing the current schema. + * @param outputDirectory the directory where to write source files. */ fun generate(schema: GQLDocument, outputDirectory: File) } - -@Deprecated("Use `CodeGenerator` instead.") -@ApolloDeprecatedSince(ApolloDeprecatedSince.Version.v5_0_0) -interface SchemaListener { +interface ApolloCompilerRegistry { /** - * Called when the schema changed and codegen needs to be updated + * Registers an [OperationIdsGenerator]. * - * @param schema the validated schema. - * @param outputDirectory the compiler output directory. This directory is shared with the compiler, make sure to use a specific - * package name to avoid clobbering other files. + * Use this function implement [persisted queries](https://www.apollographql.com/docs/kotlin/advanced/persisted-queries). */ - fun onSchema(schema: Schema, outputDirectory: File) -} + fun registerOperationIdsGenerator(generator: OperationIdsGenerator) -/** - * An argument value for the plugin. - * - * In a Gradle context, these values are used as task inputs as well as passed around classloader. - * - * Prefer using simple classes from the bootstrap classloader: - * - [String] - * - [Int] - * - [Double] - * - [Boolean] - * - [List] - * - [Map] - */ -@ApolloExperimental -typealias ApolloCompilerPluginValue = Any? \ No newline at end of file + @ApolloExperimental + fun registerForeignSchemas(schemas: List) + + @ApolloExperimental + fun registerSchemaTransform(id: String, vararg orders: Order, transform: SchemaDocumentTransform) + + @ApolloExperimental + fun registerExecutableDocumentTransform(id: String, vararg orders: Order, transform: ExecutableDocumentTransform) + + @ApolloExperimental + fun registerIrTransform(id: String, vararg orders: Order, transform: Transform) + + @ApolloExperimental + fun registerLayout(factory: LayoutFactory) + + @ApolloExperimental + fun registerJavaOutputTransform(id: String, vararg orders: Order, transform: Transform) + + @ApolloExperimental + fun registerKotlinOutputTransform(id: String, vararg orders: Order, transform: Transform) + + @ApolloExperimental + fun registerSchemaCodeGenerator(schemaCodeGenerator: SchemaCodeGenerator) +} \ No newline at end of file diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPluginEnvironment.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPluginEnvironment.kt new file mode 100644 index 00000000000..67e939229f6 --- /dev/null +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPluginEnvironment.kt @@ -0,0 +1,30 @@ +package com.apollographql.apollo.compiler + +/** + * [ApolloCompilerPluginEnvironment] contains the environment where the Apollo compiler is run. + */ +class ApolloCompilerPluginEnvironment( + /** + * @see [ApolloCompilerPluginValue] + */ + val arguments: Map, + /** + * A logger that can be used by the plugin. + */ + val logger: ApolloCompilerPluginLogger, +) + +/** + * An argument value for the plugin. + * + * In a Gradle context, these values are used as task inputs as well as passed around classloader. + * + * Prefer using simple classes from the bootstrap classloader: + * - [String] + * - [Int] + * - [Double] + * - [Boolean] + * - [List] + * - [Map] + */ +typealias ApolloCompilerPluginValue = Any? \ No newline at end of file diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPluginLogger.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPluginLogger.kt index 5a5151e8cdb..c53bbbf06b4 100644 --- a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPluginLogger.kt +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPluginLogger.kt @@ -1,13 +1,10 @@ package com.apollographql.apollo.compiler -import com.apollographql.apollo.annotations.ApolloExperimental - /** * [ApolloCompilerPluginLogger] allows logging from the context of the Apollo compiler. * * Typically, the Apollo compiler is run from an isolated classloader and cannot use the Gradle logging functions but can respect the logging level set by the user. */ -@ApolloExperimental interface ApolloCompilerPluginLogger { fun logging(message: String) fun info(message: String) diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPluginProvider.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPluginProvider.kt index 1150c40a919..4608a5d6eb9 100644 --- a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPluginProvider.kt +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/ApolloCompilerPluginProvider.kt @@ -1,13 +1,14 @@ package com.apollographql.apollo.compiler -import com.apollographql.apollo.annotations.ApolloExperimental +import com.apollographql.apollo.annotations.ApolloDeprecatedSince /** * [ApolloCompilerPluginProvider] is entry point for creating [ApolloCompilerPlugin]. * * [ApolloCompilerPluginProvider] is created by [java.util.ServiceLoader], make sure to include a matching `META-INF/services` resource. */ -@ApolloExperimental +@Deprecated("Use ApolloCompilerPlugin directly.") +@ApolloDeprecatedSince(ApolloDeprecatedSince.Version.v4_2_1) fun interface ApolloCompilerPluginProvider { /** * Creates the [ApolloCompilerPlugin] diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/LegacyOperationIdsGenerator.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/LegacyOperationIdsGenerator.kt deleted file mode 100644 index f9e00ba2e84..00000000000 --- a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/LegacyOperationIdsGenerator.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.apollographql.apollo.compiler - -import com.apollographql.apollo.compiler.operationoutput.OperationDescriptor -import com.apollographql.apollo.compiler.operationoutput.OperationId - -internal class LegacyOperationIdsGenerator(private val plugin: ApolloCompilerPlugin): OperationIdsGenerator { - override fun generate(operationDescriptorList: Collection): List { - @Suppress("DEPRECATION") - val operationIds = plugin.operationIds(operationDescriptorList.toList()) - if (operationIds != null) { - println("Apollo: using ApolloCompilerPlugin.operationIds() is deprecated. Please use registry.registerOperationIdsGenerator() instead.") - return operationIds - } - return NoList - } - - companion object { - internal val NoList: List = emptyList() - } -} diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/Options.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/Options.kt index 6e97a45434b..e31479aeb33 100644 --- a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/Options.kt +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/Options.kt @@ -647,8 +647,8 @@ private val NoOpLogger = object : ApolloCompiler.Logger { internal val defaultAlwaysGenerateTypesMatching = emptySet() -internal val defaultOperationIdsGenerator = OperationIdsGenerator { operationDescriptorList -> - operationDescriptorList.map { +internal val defaultOperationIdsGenerator = OperationIdsGenerator { operationDescriptors -> + operationDescriptors.map { OperationId(it.source.sha256(), it.name) } } diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/entrypoints.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/entrypoints.kt index 9a3385cdaf3..ceee935f9e8 100644 --- a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/entrypoints.kt +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/entrypoints.kt @@ -32,7 +32,7 @@ class EntryPoints { val registry = apolloCompilerRegistry( arguments, logLevel, - warnIfNotFound + warnIfNotFound, ) ApolloCompiler.buildCodegenSchema( @@ -40,7 +40,7 @@ class EntryPoints { logger = warning.toLogger(), codegenSchemaOptions = codegenSchemaOptionsFile.toCodegenSchemaOptions(), foreignSchemas = registry.foreignSchemas(), - schemaTransform = registry.schemaTransform() + schemaTransform = registry.schemaDocumentTransform() ).writeTo(codegenSchemaFile) } @@ -54,15 +54,15 @@ class EntryPoints { warning: Consumer, irOperationsFile: File, ) { - val registry = apolloCompilerRegistry(arguments, logLevel) + val registry = apolloCompilerRegistry(arguments, logLevel, false) val upstream = upstreamIrOperations.toInputFiles().map { it.file.toIrOperations() } - buildIrOperations( + ApolloCompiler.buildIrOperations( executableFiles = graphqlFiles.toInputFiles(), codegenSchema = codegenSchemaFiles.toInputFiles().map { it.file }.findCodegenSchemaFile().toCodegenSchema(), upstreamCodegenModels = upstream.map { it.codegenModels }, upstreamFragmentDefinitions = upstream.flatMap { it.fragmentDefinitions }, - executableDocumentTransform = registry.operationsTransform(), + documentTransform = registry.executableDocumentTransform(), options = irOptionsFile.toIrOptions(), logger = warning.toLogger(), ).writeTo(irOperationsFile) @@ -87,10 +87,11 @@ class EntryPoints { warnIfNotFound ) val codegenSchemaFile = codegenSchemaFiles.toInputFiles().map { it.file }.findCodegenSchemaFile() + val codegenSchema = codegenSchemaFile.toCodegenSchema() val upstreamCodegenMetadata = upstreamMetadata.toInputFiles().map { it.file.toCodegenMetadata() } - buildSchemaAndOperationsSourcesFromIr( + ApolloCompiler.buildSchemaAndOperationsSourcesFromIr( codegenSchema = codegenSchema, irOperations = irOperations.toIrOperations(), downstreamUsedCoordinates = downstreamUsedCoordinates.toUsedCoordinates(), @@ -105,7 +106,7 @@ class EntryPoints { ).writeTo(outputDir, true, metadataOutputFile) if (upstreamCodegenMetadata.isEmpty()) { - registry.extraCodeGenerator().generate(codegenSchema.schema.toGQLDocument(), outputDir) + registry.schemaCodeGenerator().generate(codegenSchema.schema.toGQLDocument(), outputDir) } } @@ -115,8 +116,8 @@ class EntryPoints { warnIfNotFound: Boolean, schemaFiles: List, graphqlFiles: List, - codegenSchemaOptionsFile: File, - codegenOptionsFile: File, + codegenSchemaOptions: File, + codegenOptions: File, irOptions: File, warning: Consumer, operationManifestFile: File?, @@ -129,13 +130,12 @@ class EntryPoints { warnIfNotFound ) - val codegenSchemaOptions = codegenSchemaOptionsFile.toCodegenSchemaOptions() val codegenSchema = ApolloCompiler.buildCodegenSchema( schemaFiles = schemaFiles.toInputFiles(), - codegenSchemaOptions = codegenSchemaOptions, + codegenSchemaOptions = codegenSchemaOptions.toCodegenSchemaOptions(), foreignSchemas = registry.foreignSchemas(), logger = warning.toLogger(), - schemaTransform = registry.schemaTransform() + schemaTransform = registry.schemaDocumentTransform() ) val irOperations = buildIrOperations( @@ -143,12 +143,13 @@ class EntryPoints { executableFiles = graphqlFiles.toInputFiles(), upstreamCodegenModels = emptyList(), upstreamFragmentDefinitions = emptyList(), - executableDocumentTransform = registry.operationsTransform(), + documentTransform = registry.executableDocumentTransform(), options = irOptions.toIrOptions(), logger = warning.toLogger(), ) - val codegenOptions = codegenOptionsFile.toCodegenOptions() + @Suppress("NAME_SHADOWING") + val codegenOptions = codegenOptions.toCodegenOptions() val layout = registry.layout(codegenSchema) val sourceOutput = buildSchemaAndOperationsSourcesFromIr( codegenSchema = codegenSchema, @@ -176,7 +177,7 @@ class EntryPoints { sourceOutput.writeTo(outputDir, true, null) - registry.extraCodeGenerator().generate(codegenSchema.schema.toGQLDocument(), outputDir) + registry.schemaCodeGenerator().generate(codegenSchema.schema.toGQLDocument(), outputDir) } fun buildDataBuilders( @@ -192,7 +193,7 @@ class EntryPoints { val registry = apolloCompilerRegistry( arguments, logLevel, - warnIfNotFound + warnIfNotFound, ) val codegenSchemaFile = codegenSchemaFiles.toInputFiles().map { it.file }.findCodegenSchemaFile() val codegenSchema = codegenSchemaFile.toCodegenSchema() @@ -226,6 +227,8 @@ fun Iterable.findCodegenSchemaFile(): File { } ?: error("Cannot find CodegenSchema in $this") } + + internal fun apolloCompilerRegistry( arguments: Map, logLevel: Int, @@ -244,9 +247,13 @@ internal fun apolloCompilerRegistry( registry.registerPlugin(it) } + @Suppress("DEPRECATION") val pluginProviders = ServiceLoader.load(ApolloCompilerPluginProvider::class.java, ApolloCompilerPluginProvider::class.java.classLoader).toList() pluginProviders.forEach { - println("Apollo: using ApolloCompilerPluginProvider is deprecated. Please use ApolloCompilerPlugin directly.") + // we make an exception for our own cache plugin because we want to display a nice error message to users before 4.3 + if (it.javaClass.name != "com.apollographql.cache.apollocompilerplugin.ApolloCacheCompilerPluginProvider") { + println("Apollo: using ApolloCompilerPluginProvider is deprecated. Please use ApolloCompilerPlugin directly.") + } hasPlugin = true val plugin = it.create(environment) plugin.beforeCompilationStep(environment, registry) @@ -260,7 +267,6 @@ internal fun apolloCompilerRegistry( return registry } - internal fun List.toInputFiles(): List = buildList { val iterator = this@toInputFiles.iterator() while (iterator.hasNext()) { diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/internal/ApolloExecutableDocumentTransform.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/internal/ApolloExecutableDocumentTransform.kt index 54880dddb31..8b835d11a69 100644 --- a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/internal/ApolloExecutableDocumentTransform.kt +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/internal/ApolloExecutableDocumentTransform.kt @@ -23,246 +23,243 @@ import com.apollographql.apollo.compiler.ADD_TYPENAME_IF_FRAGMENTS import com.apollographql.apollo.compiler.ADD_TYPENAME_IF_POLYMORPHIC import com.apollographql.apollo.compiler.ExecutableDocumentTransform -internal fun addRequiredFields( - operation: GQLOperationDefinition, - addTypename: String, - schema: Schema, - fragments: Map, -): GQLOperationDefinition { - val parentType = operation.rootTypeDefinition(schema)!!.name - return operation.copy( - selections = operation.selections.addRequiredFields( - schema = schema, - addTypename = addTypename, - fragments = fragments, - parentType = parentType, - parentFields = emptySet(), - isRoot = false, - ) - ) -} - -internal fun addRequiredFields( - fragmentDefinition: GQLFragmentDefinition, - addTypename: String, - schema: Schema, - fragments: Map, -): GQLFragmentDefinition { - val newSelectionSet = fragmentDefinition.selections.addRequiredFields( - schema = schema, - addTypename = addTypename, - fragments = fragments, - parentType = fragmentDefinition.typeCondition.name, - parentFields = emptySet(), - isRoot = true, - ) - - return fragmentDefinition.copy( - selections = newSelectionSet, - ) -} -private fun List.isPolymorphic(schema: Schema, fragments: Map, rootType: String): Boolean { - return any { - when (it) { - is GQLField -> false - is GQLInlineFragment -> { - val tc = it.typeCondition?.name ?: rootType - !schema.isTypeASuperTypeOf(tc, rootType) || it.selections.isPolymorphic(schema, fragments, rootType) - } +internal class ApolloExecutableDocumentTransform(private val addTypename: String, private val addKeyFields: Boolean) : ExecutableDocumentTransform { + override fun transform( + schema: Schema, + document: GQLDocument, + extraFragmentDefinitions: List, + ): GQLDocument { + val userFragments = mutableListOf() + val userOperations = mutableListOf() - is GQLFragmentSpread -> { - val fragmentDefinition = fragments[it.name] ?: error("cannot find fragment ${it.name}") - /** - * If we were only looking at operationBased codegen, we wouldn't need to look inside fragment definitions but responseBased requires - * the __typename at the root of the field to determine the shape - */ - !schema.isTypeASuperTypeOf(fragmentDefinition.typeCondition.name, rootType) || fragmentDefinition.selections.isPolymorphic(schema, fragments, rootType) + document.definitions.forEach { + when (it) { + is GQLFragmentDefinition -> userFragments.add(it) + is GQLOperationDefinition -> userOperations.add(it) + else -> Unit } } - } -} - -/** - * @param isRoot: whether this selection set is considered a valid root for adding __typename - * This is the case for field selection sets but also fragments since fragments can be executed from the cache - */ -private fun List.addRequiredFields( - schema: Schema, - addTypename: String, - fragments: Map, - parentType: String, - parentFields: Set, - isRoot: Boolean, -): List { - if (isEmpty()) { - return this - } - - val selectionSet = this - - val requiresTypename = when (addTypename) { - ADD_TYPENAME_IF_POLYMORPHIC -> isRoot && isPolymorphic(schema, fragments, parentType) - ADD_TYPENAME_IF_FRAGMENTS -> { - selectionSet.any { it is GQLFragmentSpread || it is GQLInlineFragment } + val fragmentDefinitions = (userFragments + extraFragmentDefinitions).associateBy { it.name } + val fragments = userFragments.map { + addRequiredFields(it, schema, fragmentDefinitions) } - ADD_TYPENAME_IF_ABSTRACT -> isRoot && schema.typeDefinition(parentType).isAbstract() - ADD_TYPENAME_ALWAYS -> isRoot - else -> error("Unknown addTypename option: $addTypename") - } - val requiredFieldNames = schema.keyFields(parentType).toMutableSet() - - if (requiredFieldNames.isNotEmpty() || requiresTypename) { - requiredFieldNames.add("__typename") - } - - val fieldNames = parentFields + selectionSet.filterIsInstance().map { it.responseName() }.toSet() - - // Interfaces and unions: add key fields of all possible types in inline fragments - val inlineFragmentsToAdd = if (isRoot) { - val parentTypeDefinition = schema.typeDefinition(parentType) - val possibleTypes = if (parentTypeDefinition is GQLInterfaceTypeDefinition || parentTypeDefinition is GQLUnionTypeDefinition) { - schema.possibleTypes(parentTypeDefinition) - } else { - emptySet() - } - possibleTypes.associateWith { schema.keyFields(it) }.mapNotNull { (possibleType, keyFields) -> - val fieldNamesToAddInInlineFragment = keyFields - fieldNames - if (fieldNamesToAddInInlineFragment.isNotEmpty()) { - GQLInlineFragment( - typeCondition = GQLNamedType(null, possibleType), - selections = fieldNamesToAddInInlineFragment.map { buildField(it) }, - directives = emptyList(), - sourceLocation = null, + val usesDisableErrorPropagation = schema.directiveDefinitions.containsKey(Schema.DISABLE_ERROR_PROPAGATION) + && schema.schemaDefinition?.directives?.any { schema.originalDirectiveName(it.name) == Schema.CATCH_BY_DEFAULT } == true + val operations = userOperations.map { + var operation = addRequiredFields(it, schema, fragmentDefinitions) + if (usesDisableErrorPropagation) { + operation = operation.copy( + directives = operation.directives + GQLDirective(null, Schema.DISABLE_ERROR_PROPAGATION, emptyList()) ) - } else { - null } + operation } - } else { - emptySet() + + return document.copy( + definitions = operations + fragments + ) } - var newSelections = selectionSet.map { - when (it) { - is GQLInlineFragment -> { - it.copy( - selections = it.selections.addRequiredFields( - schema = schema, - addTypename = addTypename, - fragments = fragments, - parentType = it.typeCondition?.name ?: parentType, - parentFields = fieldNames + requiredFieldNames, - isRoot = false - ) + internal fun addRequiredFields( + operation: GQLOperationDefinition, + schema: Schema, + fragments: Map, + ): GQLOperationDefinition { + val parentType = operation.rootTypeDefinition(schema)!!.name + return operation.copy( + selections = operation.selections.addRequiredFields( + schema = schema, + fragments = fragments, + parentType = parentType, + parentFields = emptySet(), + isRoot = false, ) - } - - is GQLFragmentSpread -> it - is GQLField -> it.addRequiredFields(schema, addTypename, fragments, parentType) - } + ) } - val fieldNamesToAdd = (requiredFieldNames - fieldNames).toMutableList() - if (requiresTypename) { - /** - * For "ifFragments", we add the typename always, even if it's already in parentFields - */ - fieldNamesToAdd.add("__typename") + internal fun addRequiredFields( + fragmentDefinition: GQLFragmentDefinition, + schema: Schema, + fragments: Map, + ): GQLFragmentDefinition { + val newSelectionSet = fragmentDefinition.selections.addRequiredFields( + schema = schema, + fragments = fragments, + parentType = fragmentDefinition.typeCondition.name, + parentFields = emptySet(), + isRoot = true, + ) + + return fragmentDefinition.copy( + selections = newSelectionSet, + ) } - newSelections.filterIsInstance().forEach { - /** - * Verify that the fields we add won't overwrite an existing alias - * This is not 100% correct as this validation should be made more globally - */ - check(!fieldNamesToAdd.contains(it.alias)) { - "Field ${it.alias}: ${it.name} in $parentType conflicts with key fields" + private fun List.isPolymorphic(schema: Schema, fragments: Map, rootType: String): Boolean { + return any { + when (it) { + is GQLField -> false + is GQLInlineFragment -> { + val tc = it.typeCondition?.name ?: rootType + !schema.isTypeASuperTypeOf(tc, rootType) || it.selections.isPolymorphic(schema, fragments, rootType) + } + + is GQLFragmentSpread -> { + val fragmentDefinition = fragments[it.name] ?: error("cannot find fragment ${it.name}") + /** + * If we were only looking at operationBased codegen, we wouldn't need to look inside fragment definitions but responseBased requires + * the __typename at the root of the field to determine the shape + */ + !schema.isTypeASuperTypeOf(fragmentDefinition.typeCondition.name, rootType) || fragmentDefinition.selections.isPolymorphic(schema, fragments, rootType) + } + } } } - newSelections = newSelections + fieldNamesToAdd.map { buildField(it) } + inlineFragmentsToAdd + /** + * @param isRoot: whether this selection set is considered a valid root for adding __typename + * This is the case for field selection sets but also fragments since fragments can be executed from the cache + */ + private fun List.addRequiredFields( + schema: Schema, + fragments: Map, + parentType: String, + parentFields: Set, + isRoot: Boolean, + ): List { + if (isEmpty()) { + return this + } - newSelections = if (requiresTypename) { - // remove the __typename if it exists - // and add it again at the top, so we're guaranteed to have it at the beginning of json parsing - // also remove any @include/@skip directive on __typename - listOf(buildField("__typename")) + newSelections.filter { (it as? GQLField)?.name != "__typename" } - } else { - newSelections - } + val selectionSet = this - return newSelections -} + val requiresTypename = when (addTypename) { + ADD_TYPENAME_IF_POLYMORPHIC -> isRoot && isPolymorphic(schema, fragments, parentType) + ADD_TYPENAME_IF_FRAGMENTS -> { + selectionSet.any { it is GQLFragmentSpread || it is GQLInlineFragment } + } -private fun GQLField.addRequiredFields( - schema: Schema, - addTypename: String, - fragments: Map, - parentType: String, -): GQLField { - val typeDefinition = definitionFromScope(schema, parentType)!! - val newSelectionSet = selections.addRequiredFields( - schema = schema, - addTypename = addTypename, - fragments = fragments, - parentType = typeDefinition.type.rawType().name, - parentFields = emptySet(), - isRoot = true - ) + ADD_TYPENAME_IF_ABSTRACT -> isRoot && schema.typeDefinition(parentType).isAbstract() + ADD_TYPENAME_ALWAYS -> isRoot + else -> error("Unknown addTypename option: $addTypename") + } + val requiredFieldNames = if (addKeyFields) { + schema.keyFields(parentType).toMutableSet() + } else { + mutableSetOf() + } - return copy( - selections = newSelectionSet, - ) -} + if (requiredFieldNames.isNotEmpty() || requiresTypename) { + requiredFieldNames.add("__typename") + } -private fun buildField(name: String): GQLField { - return GQLField( - name = name, - arguments = emptyList(), - selections = emptyList(), - sourceLocation = null, - directives = emptyList(), - alias = null, - ) -} + val fieldNames = parentFields + selectionSet.filterIsInstance().map { it.responseName() }.toSet() -internal class ApolloExecutableDocumentTransform(private val addTypename: String) : ExecutableDocumentTransform { - override fun transform( - schema: Schema, - document: GQLDocument, - extraFragmentDefinitions: List, - ): GQLDocument { - val userFragments = mutableListOf() - val userOperations = mutableListOf() + // Interfaces and unions: add key fields of all possible types in inline fragments + val inlineFragmentsToAdd = if (isRoot) { + val parentTypeDefinition = schema.typeDefinition(parentType) + val possibleTypes = if (parentTypeDefinition is GQLInterfaceTypeDefinition || parentTypeDefinition is GQLUnionTypeDefinition) { + schema.possibleTypes(parentTypeDefinition) + } else { + emptySet() + } + possibleTypes.associateWith { schema.keyFields(it) }.mapNotNull { (possibleType, keyFields) -> + val fieldNamesToAddInInlineFragment = keyFields - fieldNames + if (fieldNamesToAddInInlineFragment.isNotEmpty()) { + GQLInlineFragment( + typeCondition = GQLNamedType(null, possibleType), + selections = fieldNamesToAddInInlineFragment.map { buildField(it) }, + directives = emptyList(), + sourceLocation = null, + ) + } else { + null + } + } + } else { + emptySet() + } - document.definitions.forEach { + var newSelections = selectionSet.map { when (it) { - is GQLFragmentDefinition -> userFragments.add(it) - is GQLOperationDefinition -> userOperations.add(it) - else -> Unit + is GQLInlineFragment -> { + it.copy( + selections = it.selections.addRequiredFields( + schema = schema, + fragments = fragments, + parentType = it.typeCondition?.name ?: parentType, + parentFields = fieldNames + requiredFieldNames, + isRoot = false + ) + ) + } + + is GQLFragmentSpread -> it + is GQLField -> it.addRequiredFields(schema, fragments, parentType) } } - val fragmentDefinitions = (userFragments + extraFragmentDefinitions).associateBy { it.name } - val fragments = userFragments.map { - addRequiredFields(it, addTypename, schema, fragmentDefinitions) + + val fieldNamesToAdd = (requiredFieldNames - fieldNames).toMutableList() + if (requiresTypename) { + /** + * For "ifFragments", we add the typename always, even if it's already in parentFields + */ + fieldNamesToAdd.add("__typename") } - val usesDisableErrorPropagation = schema.directiveDefinitions.containsKey(Schema.DISABLE_ERROR_PROPAGATION) - && schema.schemaDefinition?.directives?.any { schema.originalDirectiveName(it.name) == Schema.CATCH_BY_DEFAULT } == true - val operations = userOperations.map { - var operation = addRequiredFields(it, addTypename, schema, fragmentDefinitions) - if (usesDisableErrorPropagation) { - operation = operation.copy( - directives = operation.directives + GQLDirective(null, Schema.DISABLE_ERROR_PROPAGATION, emptyList()) - ) + newSelections.filterIsInstance().forEach { + /** + * Verify that the fields we add won't overwrite an existing alias + * This is not 100% correct as this validation should be made more globally + */ + check(!fieldNamesToAdd.contains(it.alias)) { + "Field ${it.alias}: ${it.name} in $parentType conflicts with key fields" } - operation } - return document.copy( - definitions = operations + fragments + newSelections = newSelections + fieldNamesToAdd.map { buildField(it) } + inlineFragmentsToAdd + + newSelections = if (requiresTypename) { + // remove the __typename if it exists + // and add it again at the top, so we're guaranteed to have it at the beginning of json parsing + // also remove any @include/@skip directive on __typename + listOf(buildField("__typename")) + newSelections.filter { (it as? GQLField)?.name != "__typename" } + } else { + newSelections + } + + return newSelections + } + + private fun GQLField.addRequiredFields( + schema: Schema, + fragments: Map, + parentType: String, + ): GQLField { + val typeDefinition = definitionFromScope(schema, parentType)!! + val newSelectionSet = selections.addRequiredFields( + schema = schema, + fragments = fragments, + parentType = typeDefinition.type.rawType().name, + parentFields = emptySet(), + isRoot = true + ) + + return copy( + selections = newSelectionSet, + ) + } + + private fun buildField(name: String): GQLField { + return GQLField( + name = name, + arguments = emptyList(), + selections = emptyList(), + sourceLocation = null, + directives = emptyList(), + alias = null, ) } } diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/internal/DefaultApolloCompilerRegistry.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/internal/DefaultApolloCompilerRegistry.kt index 5bab2862516..d0012327e84 100644 --- a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/internal/DefaultApolloCompilerRegistry.kt +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/internal/DefaultApolloCompilerRegistry.kt @@ -1,3 +1,5 @@ +@file:Suppress("DEPRECATION") + package com.apollographql.apollo.compiler.internal import com.apollographql.apollo.ast.ForeignSchema @@ -5,14 +7,13 @@ import com.apollographql.apollo.compiler.After import com.apollographql.apollo.compiler.ApolloCompilerPlugin import com.apollographql.apollo.compiler.ApolloCompilerRegistry import com.apollographql.apollo.compiler.Before -import com.apollographql.apollo.compiler.CodeGenerator import com.apollographql.apollo.compiler.CodegenSchema +import com.apollographql.apollo.compiler.ExecutableDocumentTransform import com.apollographql.apollo.compiler.LayoutFactory -import com.apollographql.apollo.compiler.LegacyOperationIdsGenerator import com.apollographql.apollo.compiler.OperationIdsGenerator -import com.apollographql.apollo.compiler.ExecutableDocumentTransform import com.apollographql.apollo.compiler.Order -import com.apollographql.apollo.compiler.SchemaTransform +import com.apollographql.apollo.compiler.SchemaCodeGenerator +import com.apollographql.apollo.compiler.SchemaDocumentTransform import com.apollographql.apollo.compiler.Transform import com.apollographql.apollo.compiler.codegen.SchemaAndOperationsLayout import com.apollographql.apollo.compiler.codegen.java.JavaOutput @@ -64,14 +65,14 @@ private class Node(val id: String, val transform: T) { internal class DefaultApolloCompilerRegistry : ApolloCompilerRegistry { private val foreignSchemas = mutableListOf() - private val schemaTransforms = mutableListOf>() + private val schemaTransforms = mutableListOf>() private val executableDocumentTransforms = mutableListOf>() private val irTransforms = mutableListOf>>() private val layoutFactories = mutableListOf() private val operationIdsGenerators = mutableListOf() private val javaOutputTransforms = mutableListOf>>() private val kotlinOutputTransforms = mutableListOf>>() - private val extraCodeGenerators = mutableListOf() + private val schemaCodeGenerators = mutableListOf() @Suppress("DEPRECATION") fun registerPlugin(plugin: ApolloCompilerPlugin) { @@ -86,7 +87,7 @@ internal class DefaultApolloCompilerRegistry : ApolloCompilerRegistry { override fun registerSchemaTransform( id: String, vararg orders: Order, - transform: SchemaTransform, + transform: SchemaDocumentTransform, ) { schemaTransforms.add(Registration(id, transform, orders)) } @@ -131,22 +132,22 @@ internal class DefaultApolloCompilerRegistry : ApolloCompilerRegistry { kotlinOutputTransforms.add(Registration(id, transform, orders)) } - override fun registerExtraCodeGenerator(codeGenerator: CodeGenerator) { - extraCodeGenerators.add(codeGenerator) + override fun registerSchemaCodeGenerator(schemaCodeGenerator: SchemaCodeGenerator) { + schemaCodeGenerators.add(schemaCodeGenerator) } fun foreignSchemas() = foreignSchemas - fun schemaTransform(): SchemaTransform { + fun schemaDocumentTransform(): SchemaDocumentTransform { val nodes = schemaTransforms.toNodes().sort() - return SchemaTransform { + return SchemaDocumentTransform { nodes.fold(it) { acc, node -> node.transform.transform(acc) } } } - fun operationsTransform(): ExecutableDocumentTransform { + fun executableDocumentTransform(): ExecutableDocumentTransform { val nodes = executableDocumentTransforms.toNodes().sort() return ExecutableDocumentTransform { schema, document, fragmentDefinitions -> nodes.fold(document) { acc, node -> @@ -156,65 +157,69 @@ internal class DefaultApolloCompilerRegistry : ApolloCompilerRegistry { } fun layout(codegenSchema: CodegenSchema): SchemaAndOperationsLayout? { - if (layoutFactories.isEmpty()) { - return null - } - if (layoutFactories.size > 1) { + val candidates = layoutFactories.mapNotNull { it.create(codegenSchema) } + if (candidates.size > 1) { error("Apollo: multiple layouts registered. Check your compiler plugins.") } - return layoutFactories.single().create(codegenSchema) + return candidates.singleOrNull() } fun irOperationsTransform(): Transform { val nodes = irTransforms.toNodes().sort() - return Transform { - nodes.fold(it) { acc, node -> - node.transform.transform(acc) + return object : Transform { + override fun transform(input: IrOperations): IrOperations { + return nodes.fold(input) { acc, node -> + node.transform.transform(acc) + } } } } fun javaOutputTransform(): Transform { val nodes = javaOutputTransforms.toNodes().sort() - return Transform { - nodes.fold(it) { acc, node -> - node.transform.transform(acc) + return object : Transform { + override fun transform(input: JavaOutput): JavaOutput { + return nodes.fold(input) { acc, node -> + node.transform.transform(acc) + } } } } fun kotlinOutputTransform(): Transform { val nodes = kotlinOutputTransforms.toNodes().sort() - return Transform { - nodes.fold(it) { acc, node -> - node.transform.transform(acc) + return object : Transform { + override fun transform(input: KotlinOutput): KotlinOutput { + return nodes.fold(input) { acc, node -> + node.transform.transform(acc) + } } } } fun toOperationIdsGenerator(): OperationIdsGenerator { return OperationIdsGenerator { descriptors -> - val candidates = operationIdsGenerators.mapNotNull { + val candidateIds = operationIdsGenerators.mapNotNull { when (val operationIds = it.generate(descriptors)) { LegacyOperationIdsGenerator.NoList -> null else -> operationIds } } - return@OperationIdsGenerator if (candidates.isEmpty()) { + return@OperationIdsGenerator if (candidateIds.isEmpty()) { descriptors.map { OperationId(it.source.sha256(), it.name) } - } else if (candidates.size == 1) { - candidates.single() + } else if (candidateIds.size == 1) { + candidateIds.single() } else { error("Apollo: multiple operationIdGenerators are registered, please check your compiler plugins.") } } } - fun extraCodeGenerator(): CodeGenerator { - return CodeGenerator { document, outputDirectory -> - extraCodeGenerators.forEach { + fun schemaCodeGenerator(): SchemaCodeGenerator { + return SchemaCodeGenerator { document, outputDirectory -> + schemaCodeGenerators.forEach { it.generate(document, outputDirectory) } } @@ -251,3 +256,4 @@ private fun Collection>.sort(): List> { } return result } + diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/internal/LegacyOperationIdsGenerator.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/internal/LegacyOperationIdsGenerator.kt new file mode 100644 index 00000000000..cb682dfb62e --- /dev/null +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/internal/LegacyOperationIdsGenerator.kt @@ -0,0 +1,22 @@ +package com.apollographql.apollo.compiler.internal + +import com.apollographql.apollo.compiler.ApolloCompilerPlugin +import com.apollographql.apollo.compiler.OperationIdsGenerator +import com.apollographql.apollo.compiler.operationoutput.OperationDescriptor +import com.apollographql.apollo.compiler.operationoutput.OperationId + +internal class LegacyOperationIdsGenerator(private val plugin: ApolloCompilerPlugin): OperationIdsGenerator { + override fun generate(operationDescriptors: List): List { + @Suppress("DEPRECATION") + val operationIds = plugin.operationIds(operationDescriptors) + if (operationIds != null) { + println("Apollo: using ApolloCompiler.operationIds() is deprecated. Please use registry.registerOperationIdsGenerator() from beforeCompilationStep() instead.") + return operationIds + } + return NoList + } + + companion object { + internal val NoList: List = emptyList() + } +} \ No newline at end of file diff --git a/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/CodegenTest.kt b/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/CodegenTest.kt index c9f54f8cf1f..a351f8beeed 100644 --- a/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/CodegenTest.kt +++ b/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/CodegenTest.kt @@ -463,7 +463,7 @@ private fun ApolloCompiler.buildSchemaAndOperationsSourcesAndReturnIrOperations( executableFiles = executableFiles, upstreamCodegenModels = emptyList(), upstreamFragmentDefinitions = emptyList(), - executableDocumentTransform = null, + documentTransform = null, options = irOptions, logger = logger ) diff --git a/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/MetadataTest.kt b/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/MetadataTest.kt index a1cb8eba677..323f4eca683 100644 --- a/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/MetadataTest.kt +++ b/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/MetadataTest.kt @@ -53,7 +53,7 @@ class MetadataTest { executableFiles = setOf(rootGraphQLFile(directory)).toInputFiles(), upstreamCodegenModels = emptyList(), upstreamFragmentDefinitions = emptyList(), - executableDocumentTransform = null, + documentTransform = null, options = irOptionsFile.toIrOptions(), logger = null ).writeTo(rootIrOperationsFile) @@ -63,7 +63,7 @@ class MetadataTest { executableFiles = setOf(leafGraphQLFile(directory)).toInputFiles(), upstreamCodegenModels = rootIrOperationsFile.toIrOperations().codegenModels.let { listOf(it) }, upstreamFragmentDefinitions = rootIrOperationsFile.toIrOperations().fragmentDefinitions, - executableDocumentTransform = null, + documentTransform = null, options = irOptionsFile.toIrOptions(), logger = null ).writeTo(leafIrOperationsFile) diff --git a/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/TypenameTest.kt b/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/TypenameTest.kt index ddc29ac962d..c1324f428be 100644 --- a/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/TypenameTest.kt +++ b/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/TypenameTest.kt @@ -1,14 +1,10 @@ package com.apollographql.apollo.compiler -import com.apollographql.apollo.ast.GQLDocument -import com.apollographql.apollo.ast.GQLFragmentDefinition -import com.apollographql.apollo.ast.GQLOperationDefinition import com.apollographql.apollo.ast.toExecutableDocument import com.apollographql.apollo.ast.toGQLDocument import com.apollographql.apollo.ast.toSchema import com.apollographql.apollo.ast.toUtf8 -import com.apollographql.apollo.ast.validateAsSchema -import com.apollographql.apollo.compiler.internal.addRequiredFields +import com.apollographql.apollo.compiler.internal.ApolloExecutableDocumentTransform import com.google.common.truth.Truth.assertThat import com.google.testing.junit.testparameterinjector.TestParameter import com.google.testing.junit.testparameterinjector.TestParameterInjector @@ -28,19 +24,9 @@ class TypenameTest( val schemaFile = File("src/test/graphql/schema.graphqls") val schema = schemaFile.toGQLDocument().toSchema() - val definitions = graphQLFile.source().buffer().toExecutableDocument(schema).definitions + val document = graphQLFile.source().buffer().toExecutableDocument(schema) - val fragments = definitions.filterIsInstance().associateBy { it.name } - val documentWithTypename = GQLDocument( - definitions = definitions.map { - when (it) { - is GQLOperationDefinition -> addRequiredFields(it, addTypename, schema, fragments) - is GQLFragmentDefinition -> addRequiredFields(it, addTypename, schema, fragments) - else -> it - } - }, - sourceLocation = null - ).toUtf8() + val documentWithTypename = ApolloExecutableDocumentTransform(addTypename, false).transform(schema, document, emptyList()).toUtf8() val extra = when(addTypename) { "ifFragments" -> "" // for backward compat diff --git a/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/conditionalFragments/ConditionalFragmentsTest.kt b/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/conditionalFragments/ConditionalFragmentsTest.kt index a739db52c1a..3db40228f84 100644 --- a/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/conditionalFragments/ConditionalFragmentsTest.kt +++ b/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/conditionalFragments/ConditionalFragmentsTest.kt @@ -38,8 +38,8 @@ class ConditionalFragmentsTest { irOperationsTransform = null, javaOutputTransform = null, kotlinOutputTransform = null, - executableDocumentTransform = null, - schemaTransform = null + documentTransform = null, + schemaDocumentTransform = null ) } @@ -61,8 +61,8 @@ class ConditionalFragmentsTest { irOperationsTransform = null, javaOutputTransform = null, kotlinOutputTransform = null, - executableDocumentTransform = null, - schemaTransform = null + documentTransform = null, + schemaDocumentTransform = null ) } } diff --git a/tests/compiler-plugins/capitalize-enum-values/src/main/kotlin/hooks/TestPlugin.kt b/tests/compiler-plugins/capitalize-enum-values/src/main/kotlin/hooks/TestPlugin.kt index 9d0b4f2e17c..966425fd737 100644 --- a/tests/compiler-plugins/capitalize-enum-values/src/main/kotlin/hooks/TestPlugin.kt +++ b/tests/compiler-plugins/capitalize-enum-values/src/main/kotlin/hooks/TestPlugin.kt @@ -2,9 +2,7 @@ package hooks import com.apollographql.apollo.compiler.ApolloCompilerPlugin import com.apollographql.apollo.compiler.ApolloCompilerPluginEnvironment -import com.apollographql.apollo.compiler.ApolloCompilerPluginProvider import com.apollographql.apollo.compiler.ApolloCompilerRegistry -import com.apollographql.apollo.compiler.Transform import com.apollographql.apollo.compiler.codegen.kotlin.KotlinOutput import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.TypeSpec diff --git a/tests/compiler-plugins/custom-flatten/src/main/kotlin/hooks/TestPlugin.kt b/tests/compiler-plugins/custom-flatten/src/main/kotlin/hooks/TestPlugin.kt index 040d6a43744..e203f130bd6 100644 --- a/tests/compiler-plugins/custom-flatten/src/main/kotlin/hooks/TestPlugin.kt +++ b/tests/compiler-plugins/custom-flatten/src/main/kotlin/hooks/TestPlugin.kt @@ -2,10 +2,7 @@ package hooks import com.apollographql.apollo.compiler.ApolloCompilerPlugin import com.apollographql.apollo.compiler.ApolloCompilerPluginEnvironment -import com.apollographql.apollo.compiler.ApolloCompilerPluginProvider import com.apollographql.apollo.compiler.ApolloCompilerRegistry -import com.apollographql.apollo.compiler.Transform -import com.apollographql.apollo.compiler.ir.IrOperations class TestPlugin : ApolloCompilerPlugin { diff --git a/tests/compiler-plugins/default-null-values/src/main/kotlin/hooks/TestPlugin.kt b/tests/compiler-plugins/default-null-values/src/main/kotlin/hooks/TestPlugin.kt index e85c343350d..878d937e9be 100644 --- a/tests/compiler-plugins/default-null-values/src/main/kotlin/hooks/TestPlugin.kt +++ b/tests/compiler-plugins/default-null-values/src/main/kotlin/hooks/TestPlugin.kt @@ -2,9 +2,7 @@ package hooks import com.apollographql.apollo.compiler.ApolloCompilerPlugin import com.apollographql.apollo.compiler.ApolloCompilerPluginEnvironment -import com.apollographql.apollo.compiler.ApolloCompilerPluginProvider import com.apollographql.apollo.compiler.ApolloCompilerRegistry -import com.apollographql.apollo.compiler.Transform import com.apollographql.apollo.compiler.codegen.kotlin.KotlinOutput import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier diff --git a/tests/compiler-plugins/getters-and-setters/src/main/kotlin/hooks/TestPlugin.kt b/tests/compiler-plugins/getters-and-setters/src/main/kotlin/hooks/TestPlugin.kt index fcc82ef2768..8df4e3b100f 100644 --- a/tests/compiler-plugins/getters-and-setters/src/main/kotlin/hooks/TestPlugin.kt +++ b/tests/compiler-plugins/getters-and-setters/src/main/kotlin/hooks/TestPlugin.kt @@ -2,9 +2,7 @@ package hooks import com.apollographql.apollo.compiler.ApolloCompilerPlugin import com.apollographql.apollo.compiler.ApolloCompilerPluginEnvironment -import com.apollographql.apollo.compiler.ApolloCompilerPluginProvider import com.apollographql.apollo.compiler.ApolloCompilerRegistry -import com.apollographql.apollo.compiler.Transform import com.apollographql.apollo.compiler.capitalizeFirstLetter import com.apollographql.apollo.compiler.codegen.java.JavaOutput import com.squareup.javapoet.JavaFile diff --git a/tests/compiler-plugins/schema-codegen/src/main/kotlin/schema/TestPlugin.kt b/tests/compiler-plugins/schema-codegen/src/main/kotlin/schema/TestPlugin.kt index 63aa0b62e04..1ff33120567 100644 --- a/tests/compiler-plugins/schema-codegen/src/main/kotlin/schema/TestPlugin.kt +++ b/tests/compiler-plugins/schema-codegen/src/main/kotlin/schema/TestPlugin.kt @@ -1,3 +1,5 @@ +@file:Suppress("DEPRECATION") + package schema import com.apollographql.apollo.ast.ForeignSchema @@ -36,7 +38,7 @@ class TestPlugin( ) )) - registry.registerExtraCodeGenerator { schema, outputDirectory -> + registry.registerSchemaCodeGenerator { schema, outputDirectory -> val maxAge = schema.definitions.filterIsInstance() .first { it.name == "Menu" } .directives diff --git a/tests/compiler-plugins/typename-interface/src/main/kotlin/hooks/TestPlugin.kt b/tests/compiler-plugins/typename-interface/src/main/kotlin/hooks/TestPlugin.kt index 8c20dd63c07..9f190359f90 100644 --- a/tests/compiler-plugins/typename-interface/src/main/kotlin/hooks/TestPlugin.kt +++ b/tests/compiler-plugins/typename-interface/src/main/kotlin/hooks/TestPlugin.kt @@ -1,10 +1,11 @@ +@file:Suppress("DEPRECATION") + package hooks import com.apollographql.apollo.compiler.ApolloCompilerPlugin import com.apollographql.apollo.compiler.ApolloCompilerPluginEnvironment import com.apollographql.apollo.compiler.ApolloCompilerPluginProvider import com.apollographql.apollo.compiler.ApolloCompilerRegistry -import com.apollographql.apollo.compiler.Transform import com.apollographql.apollo.compiler.codegen.kotlin.KotlinOutput import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.KModifier diff --git a/tests/schema-transform/plugin/src/main/kotlin/com/example/TestPlugin.kt b/tests/schema-transform/plugin/src/main/kotlin/com/example/TestPlugin.kt index 32acbbef209..bf856112966 100644 --- a/tests/schema-transform/plugin/src/main/kotlin/com/example/TestPlugin.kt +++ b/tests/schema-transform/plugin/src/main/kotlin/com/example/TestPlugin.kt @@ -9,9 +9,7 @@ import com.apollographql.apollo.ast.SourceAwareException import com.apollographql.apollo.ast.toUtf8 import com.apollographql.apollo.compiler.ApolloCompilerPlugin import com.apollographql.apollo.compiler.ApolloCompilerPluginEnvironment -import com.apollographql.apollo.compiler.ApolloCompilerPluginProvider import com.apollographql.apollo.compiler.ApolloCompilerRegistry -import com.apollographql.apollo.compiler.SchemaTransform private class TraversalState(