Skip to content

Commit 0ab0788

Browse files
sellmairSpace Team
authored and
Space Team
committed
[Gradle] Lifecycle: Remove LifecycleAwareProperty
Replaced by just keeping the 'awaitFinalValue()' function ^KT-58255 Verification Pending
1 parent 09dbae5 commit 0ab0788

File tree

6 files changed

+92
-220
lines changed

6 files changed

+92
-220
lines changed

libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ abstract class KotlinMultiplatformExtension(project: Project) :
5353
}
5454

5555
internal val internalKotlinTargetHierarchy by lazy {
56-
KotlinTargetHierarchyDslImpl(project.kotlinPluginLifecycle, targets, sourceSets)
56+
KotlinTargetHierarchyDslImpl(project.objects, targets, sourceSets)
5757
}
5858

5959
@ExperimentalKotlinGradlePluginApi

libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginLifecycle.kt

Lines changed: 2 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,10 @@ import org.jetbrains.kotlin.gradle.utils.CompletableFuture
1212
import org.jetbrains.kotlin.gradle.utils.Future
1313
import org.jetbrains.kotlin.gradle.utils.failures
1414
import org.jetbrains.kotlin.gradle.utils.getOrPut
15-
import java.lang.ref.WeakReference
1615
import java.util.*
1716
import java.util.concurrent.atomic.AtomicBoolean
1817
import kotlin.collections.ArrayDeque
19-
import kotlin.collections.set
2018
import kotlin.coroutines.*
21-
import kotlin.reflect.KProperty
2219

2320
/*
2421
Util functions
@@ -191,68 +188,15 @@ internal suspend fun Stage.await() {
191188
}
192189

193190
/**
194-
* See [newProperty]
195-
*/
196-
internal inline fun <reified T : Any> Project.newKotlinPluginLifecycleAwareProperty(
197-
finaliseIn: Stage = Stage.FinaliseDsl, initialValue: T? = null,
198-
): LifecycleAwareProperty<T> {
199-
return kotlinPluginLifecycle.newProperty(T::class.java, finaliseIn, initialValue)
200-
}
201-
202-
/**
203-
* See [LifecycleAwareProperty]
204-
* Will create a new [LifecycleAwareProperty] which is going to finalise its value in stage [finaliseIn]
205-
* and the initialValue [initialValue]
206-
*
207-
* ## Sample
208-
* ```kotlin
209-
* val myProperty by project.newKotlinPluginLifecycleAwareProperty<String>()
210-
* myProperty.set("hello")
211-
* //...
212-
* project.launch {
213-
* val myFinalValue = myProperty.awaitFinalValue() // <- suspends until final value is known!
214-
* }
215-
* ```
216-
*/
217-
internal inline fun <reified T : Any> KotlinPluginLifecycle.newProperty(
218-
finaliseIn: Stage = Stage.FinaliseDsl, initialValue: T? = null,
219-
): LifecycleAwareProperty<T> {
220-
return newProperty(T::class.java, finaliseIn, initialValue)
221-
}
222-
223-
/**
224-
* Will return the [LifecycleAwareProperty] instance if the given receiver was created by [newKotlinPluginLifecycleAwareProperty]
225-
*/
226-
internal suspend fun <T : Any> Property<T>.findKotlinPluginLifecycleAwareProperty(): LifecycleAwareProperty<T>? {
227-
return (currentKotlinPluginLifecycle() as KotlinPluginLifecycleImpl).findLifecycleAwareProperty(this)
228-
}
229-
230-
/**
231-
* Will suspend until the property finalises its value and therefore a final value can returned.
232-
* Note: This only works on properties that are [isKotlinPluginLifecycleAware]
233-
* (e.g. by being created using [newKotlinPluginLifecycleAwareProperty]).
234-
*
235-
* If a property was not created using 'newKotlinPluginLifecycleAwareProperty' then the execution
236-
* will suspend until 'FinaliseDsl' and calls [Property.finalizeValue] before returnign the actual value
191+
* Will suspend until [Stage.FinaliseDsl], finalise the value using [Property.finalizeValue] and return the
192+
* final value.
237193
*/
238194
internal suspend fun <T : Any> Property<T>.awaitFinalValue(): T? {
239-
val lifecycleAwareProperty = findKotlinPluginLifecycleAwareProperty()
240-
if (lifecycleAwareProperty != null) {
241-
return lifecycleAwareProperty.awaitFinalValue()
242-
}
243-
244195
Stage.FinaliseDsl.await()
245196
finalizeValue()
246197
return orNull
247198
}
248199

249-
/**
250-
* @return true if this property has an associated [LifecycleAwareProperty]
251-
*/
252-
internal suspend fun Property<*>.isKotlinPluginLifecycleAware(): Boolean {
253-
return findKotlinPluginLifecycleAwareProperty() != null
254-
}
255-
256200
/**
257201
* See also [withRestrictedStages]
258202
*
@@ -395,31 +339,7 @@ internal interface KotlinPluginLifecycle {
395339

396340
suspend fun await(stage: Stage)
397341

398-
fun <T : Any> newProperty(
399-
type: Class<T>, finaliseIn: Stage, initialValue: T?,
400-
): LifecycleAwareProperty<T>
401-
402342
class IllegalLifecycleException(message: String) : IllegalStateException(message)
403-
404-
/**
405-
* Wrapper around Gradle's [Property] that is aware of the [KotlinPluginLifecycle] and ensures that
406-
* the given [property] is finalised in [stage] (also calling [Property.finalizeValue]).
407-
*
408-
* A property finalised in a given [stage] will allow to safely get the final value using the
409-
* [awaitFinalValue] function, suspending the execution until the value is indeed finalised.
410-
*
411-
* See [Project.newKotlinPluginLifecycleAwareProperty] to create a new instance
412-
*/
413-
interface LifecycleAwareProperty<T : Any> {
414-
val finaliseIn: Stage
415-
val property: Property<T>
416-
417-
/**
418-
* See [LifecycleAwareProperty]
419-
*/
420-
suspend fun awaitFinalValue(): T?
421-
operator fun getValue(thisRef: Any?, property: KProperty<*>): Property<T> = this.property
422-
}
423343
}
424344

425345

@@ -437,7 +357,6 @@ private class KotlinPluginLifecycleImpl(override val project: Project) : KotlinP
437357
private val isFinishedWithFailures = AtomicBoolean(false)
438358

439359
override var stage: Stage = Stage.values.first()
440-
private val properties = WeakHashMap<Property<*>, WeakReference<LifecycleAwareProperty<*>>>()
441360

442361
fun start() {
443362
check(!isStarted.getAndSet(true)) {
@@ -576,32 +495,6 @@ private class KotlinPluginLifecycleImpl(override val project: Project) : KotlinP
576495
}
577496
}
578497
}
579-
580-
override fun <T : Any> newProperty(type: Class<T>, finaliseIn: Stage, initialValue: T?): LifecycleAwareProperty<T> {
581-
val property = project.objects.property(type)
582-
if (initialValue != null) property.set(initialValue)
583-
if (finaliseIn <= stage) property.finalizeValue()
584-
else enqueue(finaliseIn) { property.finalizeValue() }
585-
val lifecycleAwareProperty = LifecycleAwarePropertyImpl(finaliseIn, property)
586-
properties[property] = WeakReference(lifecycleAwareProperty)
587-
return lifecycleAwareProperty
588-
}
589-
590-
fun <T : Any> findLifecycleAwareProperty(property: Property<T>): LifecycleAwareProperty<T>? {
591-
@Suppress("UNCHECKED_CAST")
592-
return properties[property]?.get() as? LifecycleAwareProperty<T>
593-
}
594-
595-
private class LifecycleAwarePropertyImpl<T : Any>(
596-
override val finaliseIn: Stage,
597-
override val property: Property<T>,
598-
) : LifecycleAwareProperty<T> {
599-
600-
override suspend fun awaitFinalValue(): T? {
601-
finaliseIn.await()
602-
return property.orNull
603-
}
604-
}
605498
}
606499

607500
private class KotlinPluginLifecycleCoroutineContextElement(

libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchyDslImpl.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,19 @@ import org.jetbrains.kotlin.gradle.plugin.*
1616
import org.jetbrains.kotlin.gradle.utils.property
1717

1818
internal class KotlinTargetHierarchyDslImpl(
19-
private val lifecycle: KotlinPluginLifecycle,
19+
objects: ObjectFactory,
2020
private val targets: DomainObjectCollection<KotlinTarget>,
21-
private val sourceSets: NamedDomainObjectContainer<KotlinSourceSet>
21+
private val sourceSets: NamedDomainObjectContainer<KotlinSourceSet>,
2222
) : KotlinTargetHierarchyDsl {
2323

2424
private val _appliedDescriptors = mutableListOf<KotlinTargetHierarchyDescriptor>()
2525
val appliedDescriptors: List<KotlinTargetHierarchyDescriptor> get() = _appliedDescriptors
2626

27-
override val android: KotlinAndroidTargetHierarchyDsl = KotlinAndroidTargetHierarchyDslImpl(lifecycle)
27+
override val android: KotlinAndroidTargetHierarchyDsl = KotlinAndroidTargetHierarchyDslImpl(objects)
2828

2929
override fun apply(
3030
hierarchyDescriptor: KotlinTargetHierarchyDescriptor,
31-
describeExtension: (KotlinTargetHierarchyBuilder.Root.() -> Unit)?
31+
describeExtension: (KotlinTargetHierarchyBuilder.Root.() -> Unit)?,
3232
) {
3333
val descriptor = hierarchyDescriptor.extendIfNotNull(describeExtension)
3434
_appliedDescriptors.add(descriptor)
@@ -51,12 +51,12 @@ internal class KotlinTargetHierarchyDslImpl(
5151
private fun KotlinTargetHierarchyDescriptor.extendIfNotNull(describe: (KotlinTargetHierarchyBuilder.Root.() -> Unit)?) =
5252
if (describe == null) this else extend(describe)
5353

54-
internal class KotlinAndroidTargetHierarchyDslImpl(lifecycle: KotlinPluginLifecycle) : KotlinAndroidTargetHierarchyDsl {
55-
override val main: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(lifecycle)
56-
override val unitTest: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(lifecycle)
57-
override val instrumentedTest: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(lifecycle)
54+
internal class KotlinAndroidTargetHierarchyDslImpl(objects: ObjectFactory) : KotlinAndroidTargetHierarchyDsl {
55+
override val main: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(objects)
56+
override val unitTest: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(objects)
57+
override val instrumentedTest: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(objects)
5858
}
5959

60-
internal class KotlinAndroidVariantHierarchyDslImpl(lifecycle: KotlinPluginLifecycle) : KotlinAndroidVariantHierarchyDsl {
61-
override val sourceSetTree: Property<KotlinTargetHierarchy.SourceSetTree> by lifecycle.newProperty()
60+
internal class KotlinAndroidVariantHierarchyDslImpl(objects: ObjectFactory) : KotlinAndroidVariantHierarchyDsl {
61+
override val sourceSetTree: Property<KotlinTargetHierarchy.SourceSetTree> = objects.property()
6262
}

libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/KotlinAndroidTargetHierarchyDsl.kt

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class KotlinAndroidTargetHierarchyDsl {
2525

2626
@Test
2727
fun `test - module - not set`() = buildProjectWithMPP().runLifecycleAwareTest {
28-
val dsl = KotlinAndroidVariantHierarchyDslImpl(project.kotlinPluginLifecycle)
28+
val dsl = KotlinAndroidVariantHierarchyDslImpl(project.objects)
2929
project.kotlinPluginLifecycle.launch {
3030
assertNull(dsl.sourceSetTree.orNull)
3131
assertNull(dsl.sourceSetTree.awaitFinalValue())
@@ -34,25 +34,13 @@ class KotlinAndroidTargetHierarchyDsl {
3434

3535
@Test
3636
fun `test - module - can be set in users afterEvaluate`() = buildProjectWithMPP().runLifecycleAwareTest {
37-
val dsl = KotlinAndroidVariantHierarchyDslImpl(project.kotlinPluginLifecycle)
37+
val dsl = KotlinAndroidVariantHierarchyDslImpl(project.objects)
3838
afterEvaluate { dsl.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("x")) }
3939
dsl.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("-set-before-after-evaluate-"))
4040
assertEquals("x", dsl.sourceSetTree.awaitFinalValue()?.name)
4141
assertEquals(KotlinPluginLifecycle.Stage.FinaliseDsl, currentKotlinPluginLifecycle().stage)
4242
}
4343

44-
@Test
45-
fun `test - module - cannot be set after FinaliseDsl`() = buildProjectWithMPP().runLifecycleAwareTest {
46-
val dsl = KotlinAndroidVariantHierarchyDslImpl(project.kotlinPluginLifecycle)
47-
launchInStage(KotlinPluginLifecycle.Stage.FinaliseDsl.previousOrThrow) {
48-
dsl.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("x"))
49-
}
50-
51-
launchInStage(KotlinPluginLifecycle.Stage.FinaliseDsl) {
52-
assertFails { dsl.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("y")) }
53-
}
54-
}
55-
5644
@Test
5745
fun `test - module - is respected in default refines edges`() {
5846
val project = buildProject {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
4+
*/
5+
6+
@file:Suppress("FunctionName")
7+
8+
package org.jetbrains.kotlin.gradle.unitTests
9+
10+
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
11+
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.EvaluateBuildscript
12+
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.FinaliseDsl
13+
import org.jetbrains.kotlin.gradle.plugin.awaitFinalValue
14+
import org.jetbrains.kotlin.gradle.plugin.currentKotlinPluginLifecycle
15+
import org.jetbrains.kotlin.gradle.plugin.launchInStage
16+
import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP
17+
import org.jetbrains.kotlin.gradle.util.runLifecycleAwareTest
18+
import org.jetbrains.kotlin.gradle.utils.newProperty
19+
import org.junit.Test
20+
import kotlin.test.assertEquals
21+
import kotlin.test.assertFails
22+
import kotlin.test.assertFailsWith
23+
import kotlin.test.assertNull
24+
25+
class LifecycleAwaitFinalPropertyValueTest {
26+
private val project = buildProjectWithMPP()
27+
28+
@Test
29+
fun `test - awaitFinalValue`() = project.runLifecycleAwareTest {
30+
val property = project.newProperty<Int>()
31+
32+
launchInStage(FinaliseDsl.previousOrThrow.previousOrThrow) {
33+
property.set(1)
34+
}
35+
36+
launchInStage(FinaliseDsl.previousOrThrow.previousOrThrow) {
37+
assertEquals(1, property.get())
38+
property.set(2)
39+
}
40+
41+
assertEquals(EvaluateBuildscript, currentKotlinPluginLifecycle().stage)
42+
assertEquals(2, property.awaitFinalValue())
43+
assertEquals(FinaliseDsl, currentKotlinPluginLifecycle().stage)
44+
}
45+
46+
@Test
47+
fun `test - changing value after finalized`() = project.runLifecycleAwareTest {
48+
val property = project.newProperty<Int>()
49+
property.set(1)
50+
51+
launchInStage(FinaliseDsl.previousOrThrow) {
52+
property.awaitFinalValue()
53+
}
54+
55+
launchInStage(FinaliseDsl.nextOrThrow) {
56+
assertFailsWith<IllegalStateException> { property.set(2) }
57+
}
58+
}
59+
60+
@Test
61+
fun `test - creating a property - after finaliseDsl stage already passed`() = project.runLifecycleAwareTest {
62+
launchInStage(KotlinPluginLifecycle.Stage.last) {
63+
val property = project.newProperty<String>()
64+
assertNull(property.awaitFinalValue())
65+
assertFails { property.set("") }
66+
}
67+
}
68+
69+
@Test
70+
fun `test - creating a property - in finaliseIn stage`() = project.runLifecycleAwareTest {
71+
launchInStage(KotlinPluginLifecycle.Stage.FinaliseDsl) {
72+
val property = project.newProperty<String>()
73+
assertNull(property.awaitFinalValue())
74+
assertFails { property.set("") }
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)