Skip to content

Commit

Permalink
lazily configure Kapt stub-gen tasks
Browse files Browse the repository at this point in the history
fixes #1053
  • Loading branch information
RBusarow committed Nov 19, 2024
1 parent 501df27 commit f011a4f
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 39 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
### Removed

### Fixed
- The Anvil plugin will no longer cause `KaptGenerateStubsTask` tasks to be configured eagerly ([#1043](https://github.com/square/anvil/pull/1043))

### Security

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,68 @@ class LifecycleTest : BaseGradleTest() {
}
}

@TestFactory
fun `Kotlin tasks are not configured eagerly`() = params.asContainers { versions ->

// tests for https://github.com/square/anvil/issues/1053

listOf(true, false).asTests(
testEnvironmentFactory = AnvilGradleTestEnvironment.Factory().wrap(versions),
testName = { "with kapt: $it" },
) { useKapt ->

val logPrefix = "configuring task"

rootProject {

buildFile {

pluginsBlock(useKsp = false, addKapt = useKapt)

anvilBlock(useKsp = false)

dependencies {
api(libs.dagger2.annotations)
compileOnly(libs.inject)
if (useKapt) {
kapt(libs.dagger2.compiler)
}
}

raw(
"""
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile::class.java).configureEach {
println("$logPrefix: ${'$'}name")
}
""".trimIndent(),
)
}

dir("src/main/java") {
injectClass()
}
}

shouldSucceed("help") {
output.lines()
.filter { logPrefix in it } shouldBe emptyList()
}

// Ensure that the task would fail by forcing configuration
shouldSucceed("compileKotlin", "--dry-run") {

val expected = buildList {
add("configuring task: compileKotlin")
if (useKapt) {
add("configuring task: kaptGenerateStubsKotlin")
}
}

output.lines().filter { logPrefix in it } shouldBe expected
}
}
}

@TestFactory
fun `compileKotlin is up to date when no changes are made`() = params.withKspToggle { _, useKsp ->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import org.gradle.api.Action
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.UnknownTaskException
import org.gradle.api.artifacts.Configuration
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.TaskContainer
Expand Down Expand Up @@ -324,21 +323,21 @@ internal open class AnvilPlugin : KotlinCompilerPluginSupportPlugin {
}

variant.project.pluginManager.withPlugin(KAPT_PLUGIN_ID) {
variant.project
.namedLazy<KaptGenerateStubsTask>(variant.stubsTaskName) { stubsTaskProvider ->
stubsTaskProvider.configure { stubsTask ->
if (!mergingIsDisabled()) {
// Disable incremental compilation for the stub generating task. Trigger the compiler
// plugin if any dependencies in the compile classpath have changed. This will make sure
// that we pick up any change from a dependency when merging all the classes. Without
// this workaround we could make changes in any library, but these changes wouldn't be
// contributed to the Dagger graph, because incremental compilation tricked us.
stubsTask.doFirstCompat {
stubsTask.incremental = false
stubsTask.log(
"Anvil: Incremental compilation enabled: ${stubsTask.incremental} (stub)",
)
}
variant.project.tasks
.withType(KaptGenerateStubsTask::class.java)
.named { it == variant.stubsTaskName }
.configureEach { stubsTask ->
if (!mergingIsDisabled()) {
// Disable incremental compilation for the stub generating task. Trigger the compiler
// plugin if any dependencies in the compile classpath have changed. This will make sure
// that we pick up any change from a dependency when merging all the classes. Without
// this workaround we could make changes in any library, but these changes wouldn't be
// contributed to the Dagger graph, because incremental compilation tricked us.
stubsTask.doFirstCompat {
stubsTask.incremental = false
stubsTask.log(
"Anvil: Incremental compilation enabled: ${stubsTask.incremental} (stub)",
)
}
}
}
Expand Down Expand Up @@ -400,30 +399,11 @@ private fun <T : Task> T.doFirstCompat(block: (T) -> Unit) {
* yet. If the task is never registered, then this method will throw an error after the
* configuration phase.
*/
private inline fun <reified T : Task> Project.namedLazy(
name: String,
crossinline action: (TaskProvider<T>) -> Unit,
) {
try {
action(tasks.named(name, T::class.java))
return
} catch (ignored: UnknownTaskException) {
}

var didRun = false

tasks.withType(T::class.java) { task ->
if (task.name == name) {
action(tasks.named(name, T::class.java))
didRun = true
}
}
private inline fun <reified T : Task> Project.namedLazy(name: String, action: Action<T>) {

afterEvaluate {
if (!didRun) {
throw GradleException("Didn't find task $name with type ${T::class}.")
}
}
tasks.withType(T::class.java)
.named { it == name }
.configureEach(action)
}

/**
Expand Down

0 comments on commit f011a4f

Please sign in to comment.