Skip to content

Commit 69cfe9d

Browse files
martinbonninBoD
andcommitted
Add ApolloCompilerPluginProvider (apollographql#5865)
* Add logger and arguments * small tweak to the KDoc * improve migration guide * more KDoc * Update libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo3/compiler/ApolloCompilerPluginEnvironment.kt Co-authored-by: Benoit 'BoD' Lubek <[email protected]> * Update libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo3/compiler/ApolloCompilerPluginEnvironment.kt Co-authored-by: Benoit 'BoD' Lubek <[email protected]> * remove exception, messager and add comment --------- Co-authored-by: Benoit 'BoD' Lubek <[email protected]>
1 parent 8b73e15 commit 69cfe9d

23 files changed

+340
-50
lines changed

docs/source/migration/4.0.mdx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,46 @@ If you are using `packageNamesFromFilePaths` and `schemaFile`, you'll need to us
330330
```
331331

332332
<Note>
333+
333334
Apollo Kotlin 3 was using the operation root directories to compute the schema normalized path which could be wrong in some edge cases. Using fileTree ensures the normalized path is consistent.
334335
</Note>
335336

337+
### Migrating to ApolloCompilerPlugin
338+
339+
4.0 introduces `ApolloCompilerPlugin` as a way to customize code generation. `ApolloCompilerPlugin` are loaded using the [ServiceLoader](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html) API and run in a separate classloader from your Gradle build. As a result, using `Service.operationIdGenerator`/`Service.operationOutputGenerator` together with `ApolloCompilerPlugin` is not possible.
340+
341+
`Service.operationIdGenerator`/`Service.operationOutputGenerator` are deprecated and will be removed in a future release. You can migrate to `ApolloCompilerPlugin` using the instructions [from the dedicated page](https://www.apollographql.com/docs/kotlin/v4/advanced/compiler-plugins) and the `ApolloCompilerPlugin.operationIds()` method:
342+
343+
```kotlin
344+
// Replace (in your build scripts)
345+
val operationOutputGenerator = object: OperationOutputGenerator {
346+
override fun generate(operationDescriptorList: Collection<OperationDescriptor>): OperationOutput {
347+
return operationDescriptorList.associateBy {
348+
it.source.sha1()
349+
}
350+
}
351+
override val version: String = "v1"
352+
}
353+
354+
// Or, if using OperationIdGenerator, replace
355+
val operationIdGenerator = object: OperationIdGenerator {
356+
override fun apply(operationDocument: String, operationName: String): String {
357+
return operationDocument.sha1()
358+
}
359+
360+
override val version: String = "v1"
361+
}
362+
363+
// With (in your build compiler plugin module)
364+
class MyPlugin: ApolloCompilerPlugin {
365+
override fun operationIds(descriptors: List<OperationDescriptor>): List<OperationId>? {
366+
return descriptors.map {
367+
OperationId(it.source.sha1(), it.name)
368+
}
369+
}
370+
}
371+
```
372+
336373
### Misc
337374

338375
* Publishing is no longer configured automatically.
@@ -526,6 +563,7 @@ apolloClient.query().rxSingle()
526563
apolloClient.query().toFlow().asFlowable().firstOrError()
527564
```
528565

566+
529567
## Example of a migration
530568

531569
If you are looking for inspiration, we updated the [3.x integration tests to use 4.0](https://github.com/apollographql/apollo-kotlin/pull/5418/). If you have an open source project that migrated, feel free to share it and we'll include it here.

libraries/apollo-compiler/api/apollo-compiler.api

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,9 @@ public final class com/apollographql/apollo3/compiler/codegen/kotlin/helpers/Add
653653
public static final fun addInternal (Lcom/squareup/kotlinpoet/FileSpec$Builder;Ljava/util/List;)Lcom/squareup/kotlinpoet/FileSpec$Builder;
654654
}
655655

656+
public final class com/apollographql/apollo3/compiler/internal/GradleCompilerPluginLogger$Companion {
657+
}
658+
656659
public final class com/apollographql/apollo3/compiler/ir/IrAccessor$Companion {
657660
public final fun serializer ()Lkotlinx/serialization/KSerializer;
658661
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.apollographql.apollo3.compiler
2+
3+
import com.apollographql.apollo3.annotations.ApolloExperimental
4+
5+
/**
6+
* [ApolloCompilerPluginEnvironment] contains the environment where the Apollo compiler is run.
7+
*/
8+
@ApolloExperimental
9+
class ApolloCompilerPluginEnvironment(
10+
/**
11+
* Arguments as passed from the Gradle plugin
12+
*/
13+
val arguments: Map<String, Any?>,
14+
/**
15+
* A logger that can be used by the plugin.
16+
*/
17+
val logger: ApolloCompilerPluginLogger,
18+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.apollographql.apollo3.compiler
2+
3+
import com.apollographql.apollo3.annotations.ApolloExperimental
4+
5+
/**
6+
* [ApolloCompilerPluginLogger] allows logging from the context of the Apollo compiler.
7+
*
8+
* 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.
9+
*/
10+
@ApolloExperimental
11+
interface ApolloCompilerPluginLogger {
12+
fun logging(message: String)
13+
fun info(message: String)
14+
fun warn(message: String)
15+
fun error(message: String)
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.apollographql.apollo3.compiler
2+
3+
import com.apollographql.apollo3.annotations.ApolloExperimental
4+
5+
/**
6+
* [ApolloCompilerPluginProvider] is entry point for creating [ApolloCompilerPlugin].
7+
*
8+
* [ApolloCompilerPluginProvider] is created by [java.util.ServiceLoader], make sure to include a matching `META-INF/services` resource.
9+
*/
10+
@ApolloExperimental
11+
fun interface ApolloCompilerPluginProvider {
12+
/**
13+
* Creates the [ApolloCompilerPlugin]
14+
*/
15+
fun create(environment: ApolloCompilerPluginEnvironment): ApolloCompilerPlugin
16+
}
17+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.apollographql.apollo3.compiler.internal
2+
3+
import com.apollographql.apollo3.annotations.ApolloInternal
4+
import com.apollographql.apollo3.compiler.ApolloCompilerPluginLogger
5+
6+
@ApolloInternal
7+
class GradleCompilerPluginLogger(val loglevel: Int) : ApolloCompilerPluginLogger {
8+
9+
override fun logging(message: String) {
10+
if (loglevel <= LOGGING_LEVEL_LOGGING)
11+
println("v: [apollo] $message")
12+
}
13+
14+
override fun info(message: String) {
15+
if (loglevel <= LOGGING_LEVEL_INFO)
16+
println("i: [apollo] $message")
17+
}
18+
19+
override fun warn(message: String) {
20+
if (loglevel <= LOGGING_LEVEL_WARN)
21+
println("w: [apollo] $message")
22+
}
23+
24+
override fun error(message: String) {
25+
if (loglevel <= LOGGING_LEVEL_ERROR)
26+
println("e: [apollo] $message")
27+
}
28+
29+
companion object {
30+
/**
31+
* Matches Gradle LogLevel
32+
* See https://github.com/gradle/gradle/blob/71f42531a742bc263c61f1d0dc21bb6570cc817b/platforms/core-runtime/logging-api/src/main/java/org/gradle/api/logging/LogLevel.java#L21
33+
*/
34+
const val LOGGING_LEVEL_LOGGING = 0
35+
const val LOGGING_LEVEL_INFO = 1
36+
const val LOGGING_LEVEL_WARN = 3
37+
const val LOGGING_LEVEL_ERROR = 5
38+
}
39+
}

libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo3/compiler/operationoutput/OperationOutput.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class OperationDescriptor(
1919
*/
2020
val name: String,
2121
/**
22-
* The source of the operation as it is sent over the wire, including fragments
22+
* The source of the operation document as it is sent over the wire, including fragments
2323
*/
2424
val source: String,
2525
/**
@@ -30,6 +30,14 @@ class OperationDescriptor(
3030

3131
/**
3232
* The id of an operation associated with its name so that it can be looked up.
33+
*
34+
* @param id the generated id for the operation
35+
* @param name the name of the operation, such as "FooQuery" below
36+
* ```graphql
37+
* query FooQuery {
38+
* foo
39+
* }
40+
* ```
3341
*/
3442
class OperationId(val id: String, val name: String)
3543

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.apollographql.apollo3.gradle.api
2+
3+
import com.apollographql.apollo3.annotations.ApolloExperimental
4+
5+
@ApolloExperimental
6+
interface CompilerPlugin {
7+
/**
8+
* Adds the given argument to the [com.apollographql.apollo3.compiler.ApolloCompilerPlugin].
9+
* If two arguments are added with the same name, the second one overwrites the first one.
10+
*
11+
* @param name the name of the argument
12+
* @param value the value of the argument. One of:
13+
* - [String]
14+
* - [Int]
15+
* - [Double]
16+
* - [Boolean]
17+
* - [List]
18+
* - [Map]
19+
*/
20+
fun argument(name: String, value: Any)
21+
}

libraries/apollo-gradle-plugin-external/src/main/kotlin/com/apollographql/apollo3/gradle/api/Service.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,4 +907,7 @@ interface Service {
907907
}
908908

909909
fun plugin(dependencyNotation: Any)
910+
911+
@ApolloExperimental
912+
fun plugin(dependencyNotation: Any, block: Action<CompilerPlugin>)
910913
}

libraries/apollo-gradle-plugin-external/src/main/kotlin/com/apollographql/apollo3/gradle/internal/ApolloGenerateIrOperationsTask.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@ import com.apollographql.apollo3.compiler.toIrOperations
66
import com.apollographql.apollo3.compiler.toIrOptions
77
import com.apollographql.apollo3.compiler.writeTo
88
import com.apollographql.apollo3.gradle.internal.ApolloGenerateSourcesFromIrTask.Companion.findCodegenSchemaFile
9-
import org.gradle.api.DefaultTask
109
import org.gradle.api.file.ConfigurableFileCollection
1110
import org.gradle.api.file.RegularFileProperty
12-
import org.gradle.api.tasks.Classpath
1311
import org.gradle.api.tasks.InputFile
1412
import org.gradle.api.tasks.InputFiles
1513
import org.gradle.api.tasks.OutputFile
@@ -22,7 +20,7 @@ import org.gradle.workers.WorkerExecutor
2220
import java.io.File
2321
import javax.inject.Inject
2422

25-
abstract class ApolloGenerateIrOperationsTask: DefaultTask() {
23+
abstract class ApolloGenerateIrOperationsTask: ApolloTaskWithClasspath() {
2624
@get:InputFiles
2725
@get:PathSensitive(PathSensitivity.RELATIVE)
2826
abstract val codegenSchemaFiles: ConfigurableFileCollection
@@ -42,9 +40,6 @@ abstract class ApolloGenerateIrOperationsTask: DefaultTask() {
4240
@get:OutputFile
4341
abstract val irOperationsFile: RegularFileProperty
4442

45-
@get:Classpath
46-
abstract val classpath: ConfigurableFileCollection
47-
4843
@Inject
4944
abstract fun getWorkerExecutor(): WorkerExecutor
5045

@@ -61,6 +56,8 @@ abstract class ApolloGenerateIrOperationsTask: DefaultTask() {
6156
it.upstreamIrFiles = upstreamIrFiles.isolate()
6257
it.irOptionsFile.set(irOptionsFile)
6358
it.irOperationsFile.set(irOperationsFile)
59+
it.arguments = arguments.get()
60+
it.logLevel = logLevel.get().ordinal
6461
}
6562
}
6663
}
@@ -69,7 +66,7 @@ private abstract class GenerateIrOperations : WorkAction<GenerateIrOperationsPar
6966
override fun execute() {
7067
with(parameters) {
7168
val upstreamIrOperations = upstreamIrFiles.toInputFiles().map { it.file.toIrOperations() }
72-
val plugin = apolloCompilerPlugin()
69+
val plugin = apolloCompilerPlugin(arguments, logLevel)
7370

7471
ApolloCompiler.buildIrOperations(
7572
executableFiles = graphqlFiles.toInputFiles(),
@@ -89,4 +86,6 @@ private interface GenerateIrOperationsParameters : WorkParameters {
8986
var upstreamIrFiles: List<Pair<String, File>>
9087
val irOptionsFile: RegularFileProperty
9188
val irOperationsFile: RegularFileProperty
89+
var arguments: Map<String, Any?>
90+
var logLevel: Int
9291
}

0 commit comments

Comments
 (0)