[Gradle] KotlinPluginLifecycle: Do not suspend when 'isFinished'

^KT-34662 Verification Pending
This commit is contained in:
Sebastian Sellmair
2023-03-13 15:27:55 +01:00
committed by Space Team
parent b064493c7b
commit 7192b4c5af
2 changed files with 35 additions and 1 deletions
@@ -62,6 +62,8 @@ Util functions
* It can be executed right away, effectively executing the [block] before this launch function returns
* However, when called inside an already existing coroutine (or once Gradle has started executing afterEvaluate listeners),
* then this block executed after this launch function returns and put at the end of the execution queue
*
* If the lifecycle already finished and Gradle moved to its execution phase, then the block will be invoked right away.
*/
internal fun Project.launch(block: suspend KotlinPluginLifecycle.() -> Unit) {
kotlinPluginLifecycle.launch(block)
@@ -431,9 +433,19 @@ private class KotlinPluginLifecycleImpl(override val project: Project) : KotlinP
throw IllegalLifecycleException("Cannot enqueue Action for stage '${this.stage}' in current stage '${this.stage}'")
}
/*
Lifecycle finished: action shall not be enqueued, but just executed right away.
This is desirable, so that .enqueue (and .launch) functions that are scheduled in execution phase
will be executed right away (no suspend necessary or wanted)
*/
if (isFinished.get()) {
action()
return
}
enqueuedActions.getValue(stage).addLast(action)
if (stage == Stage.Configure || isFinished.get()) {
if (stage == Stage.Configure) {
loopIfNecessary()
}
}
@@ -376,6 +376,28 @@ class KotlinPluginLifecycleTest {
await(Stage.values.last())
}
/**
* This requirement is important to safely support project.future { }.getOrThrow() patterns (when the lifecycle is finished),
*/
@Test
fun `test - launching after Lifecycle finished - will execute code right away`() {
project.evaluate()
val actionAInvocations = AtomicInteger(0)
val actionBInvocations = AtomicInteger(0)
project.launch actionB@{
project.launch actionA@{
assertEquals(0, actionBInvocations.get())
assertEquals(1, actionAInvocations.incrementAndGet())
}
assertEquals(1, actionAInvocations.get())
assertEquals(1, actionBInvocations.incrementAndGet())
}
assertEquals(1, actionAInvocations.get())
assertEquals(1, actionBInvocations.get())
}
@Test
fun `test - Stage - previous next utils`() {
assertNull(Stage.values.first().previousOrNull)