Skip to content

Commit

Permalink
Add overload for dependsOn
Browse files Browse the repository at this point in the history
  • Loading branch information
martinbonnin committed Feb 7, 2024
1 parent f6f249e commit d071d45
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -766,11 +766,36 @@ interface Service {
fun operationManifestConnection(action: Action<in OperationManifestConnection>)

/**
* Adds a given dependency for the codegen
* Adds a dependency for the codegen. Use this when some types/fragments are generated
* in upstream modules.
*/
fun dependsOn(dependencyNotation: Any)

/**
* Counterpoint of [dependsOn]. [isADependencyOf] allows a schema module to discover
* used types in downstream modules automatically without having to specify [alwaysGenerateTypesMatching].
*
* This works by setting a dependency on the IR in downstream modules.
* Because the IR task and the codegen task are separate this does not create a cycle.
*
* @see [alwaysGenerateTypesMatching]
*/
fun isADependencyOf(dependencyNotation: Any)

/**
* Same as [dependsOn] but tries to do automatic cross-project configuration.
* This is highly experimental and probably not compatible with most Gradle best practices.
*
* Use at your own risks!
*
* @param bidirectional if true and if [dependencyNotation] is a project dependency,
* this version of [dependsOn] also calls [isADependencyOf] automatically by using
* cross-project configuration. This is experimental and probably not project isolation compatible.
*
*/
@ApolloExperimental
fun dependsOn(dependencyNotation: Any, bidirectional: Boolean)

class OperationOutputConnection(
/**
* The task that produces operationOutput
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ abstract class DefaultApolloExtension(
private var hasExplicitService = false
private val adhocComponentWithVariants: AdhocComponentWithVariants
private val apolloMetadataConfiguration: Configuration
private val pendingDownstreamDependencies: MutableMap<String, List<String>> = mutableMapOf()

internal fun getServiceInfos(project: Project): List<ApolloGradleToolingModel.ServiceInfo> = services.map { service ->
DefaultServiceInfo(
Expand All @@ -66,6 +67,19 @@ abstract class DefaultApolloExtension(
)
}

internal fun registerDownstreamProject(serviceName: String, projectPath: String) {
val existingService = services.firstOrNull {
it.name == serviceName
}
if (existingService != null) {
existingService.isADependencyOf(project.rootProject.project(projectPath))
} else {
pendingDownstreamDependencies.compute(serviceName) { _, oldValue ->
oldValue.orEmpty() + projectPath
}
}
}

internal fun getServiceTelemetryData(): List<ApolloGradleToolingModel.TelemetryData.ServiceTelemetryData> = services.map { service ->
DefaultServiceTelemetryData(
codegenModels = service.codegenModels.orNull,
Expand Down Expand Up @@ -545,6 +559,13 @@ abstract class DefaultApolloExtension(
upstreamIrConsumerConfiguration.dependencies.add(it)
codegenMetadataConsumerConfiguration.dependencies.add(it)
}

val pending = pendingDownstreamDependencies.get(name)
if (pending != null) {
pending.forEach {
service.isADependencyOf(project.project(it))
}
}
service.downstreamDependencies.forEach {
downstreamIrConsumerConfiguration.dependencies.add(it)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.apollographql.apollo3.gradle.internal

import com.apollographql.apollo3.annotations.ApolloDeprecatedSince
import com.apollographql.apollo3.gradle.api.ApolloExtension
import com.apollographql.apollo3.gradle.api.Introspection
import com.apollographql.apollo3.gradle.api.RegisterOperationsConfig
import com.apollographql.apollo3.gradle.api.Registry
import com.apollographql.apollo3.gradle.api.Service
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.file.ConfigurableFileTree
import org.gradle.api.file.FileCollection
import org.gradle.api.file.RegularFileProperty
Expand Down Expand Up @@ -188,7 +190,26 @@ abstract class DefaultService @Inject constructor(val project: Project, override
override fun mapScalarToUpload(graphQLName: String) = mapScalar(graphQLName, "com.apollographql.apollo3.api.Upload", "com.apollographql.apollo3.api.UploadAdapter")

override fun dependsOn(dependencyNotation: Any) {
dependsOn(dependencyNotation, false)
}

override fun dependsOn(dependencyNotation: Any, bidirectional: Boolean) {
upstreamDependencies.add(project.dependencies.create(dependencyNotation))
if (bidirectional) {
val upstreamProject = when (dependencyNotation) {
is ProjectDependency -> project.rootProject.project(dependencyNotation.dependencyProject.path)
is Project -> dependencyNotation
else -> error("dependsOn(dependencyNotation, true) requires a Project or ProjectDependency")
}

upstreamProject.plugins.withId("com.apollographql.apollo3") {
val apolloExtension = (upstreamProject.extensions.findByType(ApolloExtension::class.java) as? DefaultApolloExtension)
check(apolloExtension != null) {
"Cannot find 'apollo' extension in upstream project ${upstreamProject.name} (registered: ${upstreamProject.extensions})"
}
apolloExtension.registerDownstreamProject(name, project.path)
}
}
}

override fun isADependencyOf(dependencyNotation: Any) {
Expand Down
19 changes: 19 additions & 0 deletions tests/multi-module-1/bidirectional/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
plugins {
id("org.jetbrains.kotlin.jvm")
id("com.apollographql.apollo3")
}

apolloTest()

dependencies {
implementation(libs.apollo.runtime)
implementation(project(":multi-module-1-root"))
testImplementation(libs.kotlin.test.junit)
}

apollo {
service("service") {
packageNamesFromFilePaths()
dependsOn(project(":multi-module-1-root"), true)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
query GetA {
a {
foo
}

}
1 change: 1 addition & 0 deletions tests/multi-module-1/root/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ apolloTest()

dependencies {
implementation(libs.apollo.runtime)
testImplementation(libs.kotlin.test)
}

apollo {
Expand Down
10 changes: 10 additions & 0 deletions tests/multi-module-1/root/src/main/graphql/schema.graphqls
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
type Query {
long: Long!
a: A
b: B
}

type A {
foo: Int
}

type B {
foo: Int
}

scalar Long
Expand Down
11 changes: 11 additions & 0 deletions tests/multi-module-1/root/src/test/kotlin/MainTest.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
import kotlin.test.Test

class MainTest {
@Test
fun test() {
println(multimodule1.root.fragment.QueryDetails::class.java)
// A is used in the bidirectional module and registered automatically
println(multimodule1.root.type.A::class.java)
// B is not used at all and must not be generated
try {
val clazz = Class.forName("multimodule1.root.type.B")
error("An exception was expected but got $clazz instead")
} catch (e: ClassNotFoundException) {
}
}
}

0 comments on commit d071d45

Please sign in to comment.