[Gradle] Lifecycle: Remove LifecycleAwareProperty
Replaced by just keeping the 'awaitFinalValue()' function ^KT-58255 Verification Pending
This commit is contained in:
committed by
Space Team
parent
09dbae5eca
commit
0ab0788763
+1
-1
@@ -53,7 +53,7 @@ abstract class KotlinMultiplatformExtension(project: Project) :
|
||||
}
|
||||
|
||||
internal val internalKotlinTargetHierarchy by lazy {
|
||||
KotlinTargetHierarchyDslImpl(project.kotlinPluginLifecycle, targets, sourceSets)
|
||||
KotlinTargetHierarchyDslImpl(project.objects, targets, sourceSets)
|
||||
}
|
||||
|
||||
@ExperimentalKotlinGradlePluginApi
|
||||
|
||||
+2
-109
@@ -12,13 +12,10 @@ import org.jetbrains.kotlin.gradle.utils.CompletableFuture
|
||||
import org.jetbrains.kotlin.gradle.utils.Future
|
||||
import org.jetbrains.kotlin.gradle.utils.failures
|
||||
import org.jetbrains.kotlin.gradle.utils.getOrPut
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import kotlin.collections.ArrayDeque
|
||||
import kotlin.collections.set
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/*
|
||||
Util functions
|
||||
@@ -191,68 +188,15 @@ internal suspend fun Stage.await() {
|
||||
}
|
||||
|
||||
/**
|
||||
* See [newProperty]
|
||||
*/
|
||||
internal inline fun <reified T : Any> Project.newKotlinPluginLifecycleAwareProperty(
|
||||
finaliseIn: Stage = Stage.FinaliseDsl, initialValue: T? = null,
|
||||
): LifecycleAwareProperty<T> {
|
||||
return kotlinPluginLifecycle.newProperty(T::class.java, finaliseIn, initialValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* See [LifecycleAwareProperty]
|
||||
* Will create a new [LifecycleAwareProperty] which is going to finalise its value in stage [finaliseIn]
|
||||
* and the initialValue [initialValue]
|
||||
*
|
||||
* ## Sample
|
||||
* ```kotlin
|
||||
* val myProperty by project.newKotlinPluginLifecycleAwareProperty<String>()
|
||||
* myProperty.set("hello")
|
||||
* //...
|
||||
* project.launch {
|
||||
* val myFinalValue = myProperty.awaitFinalValue() // <- suspends until final value is known!
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
internal inline fun <reified T : Any> KotlinPluginLifecycle.newProperty(
|
||||
finaliseIn: Stage = Stage.FinaliseDsl, initialValue: T? = null,
|
||||
): LifecycleAwareProperty<T> {
|
||||
return newProperty(T::class.java, finaliseIn, initialValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Will return the [LifecycleAwareProperty] instance if the given receiver was created by [newKotlinPluginLifecycleAwareProperty]
|
||||
*/
|
||||
internal suspend fun <T : Any> Property<T>.findKotlinPluginLifecycleAwareProperty(): LifecycleAwareProperty<T>? {
|
||||
return (currentKotlinPluginLifecycle() as KotlinPluginLifecycleImpl).findLifecycleAwareProperty(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Will suspend until the property finalises its value and therefore a final value can returned.
|
||||
* Note: This only works on properties that are [isKotlinPluginLifecycleAware]
|
||||
* (e.g. by being created using [newKotlinPluginLifecycleAwareProperty]).
|
||||
*
|
||||
* If a property was not created using 'newKotlinPluginLifecycleAwareProperty' then the execution
|
||||
* will suspend until 'FinaliseDsl' and calls [Property.finalizeValue] before returnign the actual value
|
||||
* Will suspend until [Stage.FinaliseDsl], finalise the value using [Property.finalizeValue] and return the
|
||||
* final value.
|
||||
*/
|
||||
internal suspend fun <T : Any> Property<T>.awaitFinalValue(): T? {
|
||||
val lifecycleAwareProperty = findKotlinPluginLifecycleAwareProperty()
|
||||
if (lifecycleAwareProperty != null) {
|
||||
return lifecycleAwareProperty.awaitFinalValue()
|
||||
}
|
||||
|
||||
Stage.FinaliseDsl.await()
|
||||
finalizeValue()
|
||||
return orNull
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this property has an associated [LifecycleAwareProperty]
|
||||
*/
|
||||
internal suspend fun Property<*>.isKotlinPluginLifecycleAware(): Boolean {
|
||||
return findKotlinPluginLifecycleAwareProperty() != null
|
||||
}
|
||||
|
||||
/**
|
||||
* See also [withRestrictedStages]
|
||||
*
|
||||
@@ -395,31 +339,7 @@ internal interface KotlinPluginLifecycle {
|
||||
|
||||
suspend fun await(stage: Stage)
|
||||
|
||||
fun <T : Any> newProperty(
|
||||
type: Class<T>, finaliseIn: Stage, initialValue: T?,
|
||||
): LifecycleAwareProperty<T>
|
||||
|
||||
class IllegalLifecycleException(message: String) : IllegalStateException(message)
|
||||
|
||||
/**
|
||||
* Wrapper around Gradle's [Property] that is aware of the [KotlinPluginLifecycle] and ensures that
|
||||
* the given [property] is finalised in [stage] (also calling [Property.finalizeValue]).
|
||||
*
|
||||
* A property finalised in a given [stage] will allow to safely get the final value using the
|
||||
* [awaitFinalValue] function, suspending the execution until the value is indeed finalised.
|
||||
*
|
||||
* See [Project.newKotlinPluginLifecycleAwareProperty] to create a new instance
|
||||
*/
|
||||
interface LifecycleAwareProperty<T : Any> {
|
||||
val finaliseIn: Stage
|
||||
val property: Property<T>
|
||||
|
||||
/**
|
||||
* See [LifecycleAwareProperty]
|
||||
*/
|
||||
suspend fun awaitFinalValue(): T?
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>): Property<T> = this.property
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -437,7 +357,6 @@ private class KotlinPluginLifecycleImpl(override val project: Project) : KotlinP
|
||||
private val isFinishedWithFailures = AtomicBoolean(false)
|
||||
|
||||
override var stage: Stage = Stage.values.first()
|
||||
private val properties = WeakHashMap<Property<*>, WeakReference<LifecycleAwareProperty<*>>>()
|
||||
|
||||
fun start() {
|
||||
check(!isStarted.getAndSet(true)) {
|
||||
@@ -576,32 +495,6 @@ private class KotlinPluginLifecycleImpl(override val project: Project) : KotlinP
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T : Any> newProperty(type: Class<T>, finaliseIn: Stage, initialValue: T?): LifecycleAwareProperty<T> {
|
||||
val property = project.objects.property(type)
|
||||
if (initialValue != null) property.set(initialValue)
|
||||
if (finaliseIn <= stage) property.finalizeValue()
|
||||
else enqueue(finaliseIn) { property.finalizeValue() }
|
||||
val lifecycleAwareProperty = LifecycleAwarePropertyImpl(finaliseIn, property)
|
||||
properties[property] = WeakReference(lifecycleAwareProperty)
|
||||
return lifecycleAwareProperty
|
||||
}
|
||||
|
||||
fun <T : Any> findLifecycleAwareProperty(property: Property<T>): LifecycleAwareProperty<T>? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return properties[property]?.get() as? LifecycleAwareProperty<T>
|
||||
}
|
||||
|
||||
private class LifecycleAwarePropertyImpl<T : Any>(
|
||||
override val finaliseIn: Stage,
|
||||
override val property: Property<T>,
|
||||
) : LifecycleAwareProperty<T> {
|
||||
|
||||
override suspend fun awaitFinalValue(): T? {
|
||||
finaliseIn.await()
|
||||
return property.orNull
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class KotlinPluginLifecycleCoroutineContextElement(
|
||||
|
||||
+10
-10
@@ -16,19 +16,19 @@ import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.utils.property
|
||||
|
||||
internal class KotlinTargetHierarchyDslImpl(
|
||||
private val lifecycle: KotlinPluginLifecycle,
|
||||
objects: ObjectFactory,
|
||||
private val targets: DomainObjectCollection<KotlinTarget>,
|
||||
private val sourceSets: NamedDomainObjectContainer<KotlinSourceSet>
|
||||
private val sourceSets: NamedDomainObjectContainer<KotlinSourceSet>,
|
||||
) : KotlinTargetHierarchyDsl {
|
||||
|
||||
private val _appliedDescriptors = mutableListOf<KotlinTargetHierarchyDescriptor>()
|
||||
val appliedDescriptors: List<KotlinTargetHierarchyDescriptor> get() = _appliedDescriptors
|
||||
|
||||
override val android: KotlinAndroidTargetHierarchyDsl = KotlinAndroidTargetHierarchyDslImpl(lifecycle)
|
||||
override val android: KotlinAndroidTargetHierarchyDsl = KotlinAndroidTargetHierarchyDslImpl(objects)
|
||||
|
||||
override fun apply(
|
||||
hierarchyDescriptor: KotlinTargetHierarchyDescriptor,
|
||||
describeExtension: (KotlinTargetHierarchyBuilder.Root.() -> Unit)?
|
||||
describeExtension: (KotlinTargetHierarchyBuilder.Root.() -> Unit)?,
|
||||
) {
|
||||
val descriptor = hierarchyDescriptor.extendIfNotNull(describeExtension)
|
||||
_appliedDescriptors.add(descriptor)
|
||||
@@ -51,12 +51,12 @@ internal class KotlinTargetHierarchyDslImpl(
|
||||
private fun KotlinTargetHierarchyDescriptor.extendIfNotNull(describe: (KotlinTargetHierarchyBuilder.Root.() -> Unit)?) =
|
||||
if (describe == null) this else extend(describe)
|
||||
|
||||
internal class KotlinAndroidTargetHierarchyDslImpl(lifecycle: KotlinPluginLifecycle) : KotlinAndroidTargetHierarchyDsl {
|
||||
override val main: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(lifecycle)
|
||||
override val unitTest: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(lifecycle)
|
||||
override val instrumentedTest: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(lifecycle)
|
||||
internal class KotlinAndroidTargetHierarchyDslImpl(objects: ObjectFactory) : KotlinAndroidTargetHierarchyDsl {
|
||||
override val main: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(objects)
|
||||
override val unitTest: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(objects)
|
||||
override val instrumentedTest: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(objects)
|
||||
}
|
||||
|
||||
internal class KotlinAndroidVariantHierarchyDslImpl(lifecycle: KotlinPluginLifecycle) : KotlinAndroidVariantHierarchyDsl {
|
||||
override val sourceSetTree: Property<KotlinTargetHierarchy.SourceSetTree> by lifecycle.newProperty()
|
||||
internal class KotlinAndroidVariantHierarchyDslImpl(objects: ObjectFactory) : KotlinAndroidVariantHierarchyDsl {
|
||||
override val sourceSetTree: Property<KotlinTargetHierarchy.SourceSetTree> = objects.property()
|
||||
}
|
||||
+2
-14
@@ -25,7 +25,7 @@ class KotlinAndroidTargetHierarchyDsl {
|
||||
|
||||
@Test
|
||||
fun `test - module - not set`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||
val dsl = KotlinAndroidVariantHierarchyDslImpl(project.kotlinPluginLifecycle)
|
||||
val dsl = KotlinAndroidVariantHierarchyDslImpl(project.objects)
|
||||
project.kotlinPluginLifecycle.launch {
|
||||
assertNull(dsl.sourceSetTree.orNull)
|
||||
assertNull(dsl.sourceSetTree.awaitFinalValue())
|
||||
@@ -34,25 +34,13 @@ class KotlinAndroidTargetHierarchyDsl {
|
||||
|
||||
@Test
|
||||
fun `test - module - can be set in users afterEvaluate`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||
val dsl = KotlinAndroidVariantHierarchyDslImpl(project.kotlinPluginLifecycle)
|
||||
val dsl = KotlinAndroidVariantHierarchyDslImpl(project.objects)
|
||||
afterEvaluate { dsl.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("x")) }
|
||||
dsl.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("-set-before-after-evaluate-"))
|
||||
assertEquals("x", dsl.sourceSetTree.awaitFinalValue()?.name)
|
||||
assertEquals(KotlinPluginLifecycle.Stage.FinaliseDsl, currentKotlinPluginLifecycle().stage)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - module - cannot be set after FinaliseDsl`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||
val dsl = KotlinAndroidVariantHierarchyDslImpl(project.kotlinPluginLifecycle)
|
||||
launchInStage(KotlinPluginLifecycle.Stage.FinaliseDsl.previousOrThrow) {
|
||||
dsl.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("x"))
|
||||
}
|
||||
|
||||
launchInStage(KotlinPluginLifecycle.Stage.FinaliseDsl) {
|
||||
assertFails { dsl.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("y")) }
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - module - is respected in default refines edges`() {
|
||||
val project = buildProject {
|
||||
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("FunctionName")
|
||||
|
||||
package org.jetbrains.kotlin.gradle.unitTests
|
||||
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.EvaluateBuildscript
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.FinaliseDsl
|
||||
import org.jetbrains.kotlin.gradle.plugin.awaitFinalValue
|
||||
import org.jetbrains.kotlin.gradle.plugin.currentKotlinPluginLifecycle
|
||||
import org.jetbrains.kotlin.gradle.plugin.launchInStage
|
||||
import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP
|
||||
import org.jetbrains.kotlin.gradle.util.runLifecycleAwareTest
|
||||
import org.jetbrains.kotlin.gradle.utils.newProperty
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFails
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertNull
|
||||
|
||||
class LifecycleAwaitFinalPropertyValueTest {
|
||||
private val project = buildProjectWithMPP()
|
||||
|
||||
@Test
|
||||
fun `test - awaitFinalValue`() = project.runLifecycleAwareTest {
|
||||
val property = project.newProperty<Int>()
|
||||
|
||||
launchInStage(FinaliseDsl.previousOrThrow.previousOrThrow) {
|
||||
property.set(1)
|
||||
}
|
||||
|
||||
launchInStage(FinaliseDsl.previousOrThrow.previousOrThrow) {
|
||||
assertEquals(1, property.get())
|
||||
property.set(2)
|
||||
}
|
||||
|
||||
assertEquals(EvaluateBuildscript, currentKotlinPluginLifecycle().stage)
|
||||
assertEquals(2, property.awaitFinalValue())
|
||||
assertEquals(FinaliseDsl, currentKotlinPluginLifecycle().stage)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - changing value after finalized`() = project.runLifecycleAwareTest {
|
||||
val property = project.newProperty<Int>()
|
||||
property.set(1)
|
||||
|
||||
launchInStage(FinaliseDsl.previousOrThrow) {
|
||||
property.awaitFinalValue()
|
||||
}
|
||||
|
||||
launchInStage(FinaliseDsl.nextOrThrow) {
|
||||
assertFailsWith<IllegalStateException> { property.set(2) }
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - creating a property - after finaliseDsl stage already passed`() = project.runLifecycleAwareTest {
|
||||
launchInStage(KotlinPluginLifecycle.Stage.last) {
|
||||
val property = project.newProperty<String>()
|
||||
assertNull(property.awaitFinalValue())
|
||||
assertFails { property.set("") }
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - creating a property - in finaliseIn stage`() = project.runLifecycleAwareTest {
|
||||
launchInStage(KotlinPluginLifecycle.Stage.FinaliseDsl) {
|
||||
val property = project.newProperty<String>()
|
||||
assertNull(property.awaitFinalValue())
|
||||
assertFails { property.set("") }
|
||||
}
|
||||
}
|
||||
}
|
||||
-86
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("FunctionName")
|
||||
|
||||
package org.jetbrains.kotlin.gradle.unitTests
|
||||
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.awaitFinalValue
|
||||
import org.jetbrains.kotlin.gradle.plugin.currentKotlinPluginLifecycle
|
||||
import org.jetbrains.kotlin.gradle.plugin.launchInStage
|
||||
import org.jetbrains.kotlin.gradle.plugin.newKotlinPluginLifecycleAwareProperty
|
||||
import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP
|
||||
import org.jetbrains.kotlin.gradle.util.runLifecycleAwareTest
|
||||
import org.jetbrains.kotlin.gradle.utils.newProperty
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Test
|
||||
import kotlin.test.*
|
||||
|
||||
class LifecycleAwarePropertyTest {
|
||||
private val project = buildProjectWithMPP()
|
||||
|
||||
@Test
|
||||
fun `test - awaitFinalValue`() = project.runLifecycleAwareTest {
|
||||
val property by project.newKotlinPluginLifecycleAwareProperty<Int>(AfterFinaliseRefinesEdges)
|
||||
assertTrue(property.isKotlinPluginLifecycleAware())
|
||||
|
||||
launchInStage(FinaliseRefinesEdges.previousOrThrow) {
|
||||
property.set(1)
|
||||
}
|
||||
|
||||
launchInStage(FinaliseRefinesEdges) {
|
||||
assertEquals(1, property.get())
|
||||
property.set(2)
|
||||
}
|
||||
|
||||
assertEquals(EvaluateBuildscript, currentKotlinPluginLifecycle().stage)
|
||||
assertEquals(2, property.awaitFinalValue())
|
||||
assertEquals(AfterFinaliseRefinesEdges, currentKotlinPluginLifecycle().stage)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - awaitFinalValue - on non lifecycle aware property`() = project.runLifecycleAwareTest {
|
||||
val property = project.newProperty<String>()
|
||||
assertFalse(property.isKotlinPluginLifecycleAware())
|
||||
assertEquals(KotlinPluginLifecycle.Stage.EvaluateBuildscript, currentKotlinPluginLifecycle().stage)
|
||||
assertNull(property.awaitFinalValue())
|
||||
assertEquals(KotlinPluginLifecycle.Stage.FinaliseDsl, currentKotlinPluginLifecycle().stage)
|
||||
assertFails { property.set("x") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - changing value after finalized`() = project.runLifecycleAwareTest {
|
||||
val property by project.newKotlinPluginLifecycleAwareProperty<Int>(AfterEvaluateBuildscript)
|
||||
property.set(1)
|
||||
|
||||
launchInStage(AfterEvaluateBuildscript) {
|
||||
assertFailsWith<IllegalStateException> { property.set(2) }
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - creating a property - after finaliseIn stage already passed`() = project.runLifecycleAwareTest {
|
||||
launchInStage(KotlinPluginLifecycle.Stage.last) {
|
||||
val property by project.newKotlinPluginLifecycleAwareProperty<String>(Companion.first)
|
||||
|
||||
/* Property was finalised immediately */
|
||||
assertFailsWith<IllegalStateException> { property.set("Expected to fail") }
|
||||
assertNull(property.orNull)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - creating a property - in finaliseIn stage`() = project.runLifecycleAwareTest {
|
||||
launchInStage(KotlinPluginLifecycle.Stage.FinaliseDsl) {
|
||||
val property by project.newKotlinPluginLifecycleAwareProperty<String>(FinaliseDsl)
|
||||
|
||||
/* Property was finalised immediately */
|
||||
assertFailsWith<IllegalStateException> { property.set("Expected to fail") }
|
||||
assertNull(property.orNull)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user