From 764a57f1267df88a3ddb62694ab11b8014b2a8e3 Mon Sep 17 00:00:00 2001 From: Sebastian Sellmair Date: Wed, 7 Dec 2022 09:50:26 +0100 Subject: [PATCH] [kotlin-tooling-core] Implement ExtrasLazyProperty ^KT-55289 Verification Pending --- .../api/kotlin-tooling-core.api | 10 +++++++ .../kotlin/tooling/core/ExtrasProperty.kt | 28 ++++++++++++++++++- .../kotlin/tooling/core/ExtrasPropertyTest.kt | 26 +++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/libraries/tools/kotlin-tooling-core/api/kotlin-tooling-core.api b/libraries/tools/kotlin-tooling-core/api/kotlin-tooling-core.api index a3458bebde3..e11fe3dfb36 100644 --- a/libraries/tools/kotlin-tooling-core/api/kotlin-tooling-core.api +++ b/libraries/tools/kotlin-tooling-core/api/kotlin-tooling-core.api @@ -83,17 +83,27 @@ public abstract interface class org/jetbrains/kotlin/tooling/core/ExtrasFactoryP public fun setValue (Lorg/jetbrains/kotlin/tooling/core/HasMutableExtras;Lkotlin/reflect/KProperty;Ljava/lang/Object;)V } +public abstract interface class org/jetbrains/kotlin/tooling/core/ExtrasLazyProperty : kotlin/properties/ReadWriteProperty, org/jetbrains/kotlin/tooling/core/ExtrasProperty { + public abstract fun getFactory ()Lkotlin/jvm/functions/Function1; + public synthetic fun getValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;)Ljava/lang/Object; + public fun getValue (Lorg/jetbrains/kotlin/tooling/core/HasMutableExtras;Lkotlin/reflect/KProperty;)Ljava/lang/Object; + public synthetic fun setValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;Ljava/lang/Object;)V + public fun setValue (Lorg/jetbrains/kotlin/tooling/core/HasMutableExtras;Lkotlin/reflect/KProperty;Ljava/lang/Object;)V +} + public abstract interface class org/jetbrains/kotlin/tooling/core/ExtrasProperty { public abstract fun getKey ()Lorg/jetbrains/kotlin/tooling/core/Extras$Key; } public final class org/jetbrains/kotlin/tooling/core/ExtrasPropertyKt { public static final fun extrasFactoryProperty (Lorg/jetbrains/kotlin/tooling/core/Extras$Key;Lkotlin/jvm/functions/Function0;)Lorg/jetbrains/kotlin/tooling/core/ExtrasFactoryProperty; + public static final fun extrasLazyProperty (Lorg/jetbrains/kotlin/tooling/core/Extras$Key;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlin/tooling/core/ExtrasLazyProperty; public static final fun extrasReadProperty (Lorg/jetbrains/kotlin/tooling/core/Extras$Key;)Lorg/jetbrains/kotlin/tooling/core/ExtrasReadOnlyProperty; public static final fun extrasReadWriteProperty (Lorg/jetbrains/kotlin/tooling/core/Extras$Key;)Lorg/jetbrains/kotlin/tooling/core/ExtrasReadWriteProperty; public static final fun factoryProperty (Lorg/jetbrains/kotlin/tooling/core/Extras$Key;Lkotlin/jvm/functions/Function0;)Lorg/jetbrains/kotlin/tooling/core/ExtrasFactoryProperty; public static final fun getReadProperty (Lorg/jetbrains/kotlin/tooling/core/Extras$Key;)Lorg/jetbrains/kotlin/tooling/core/ExtrasReadOnlyProperty; public static final fun getReadWriteProperty (Lorg/jetbrains/kotlin/tooling/core/Extras$Key;)Lorg/jetbrains/kotlin/tooling/core/ExtrasReadWriteProperty; + public static final fun lazyProperty (Lorg/jetbrains/kotlin/tooling/core/Extras$Key;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlin/tooling/core/ExtrasLazyProperty; } public abstract interface class org/jetbrains/kotlin/tooling/core/ExtrasReadOnlyProperty : kotlin/properties/ReadOnlyProperty, org/jetbrains/kotlin/tooling/core/ExtrasProperty { diff --git a/libraries/tools/kotlin-tooling-core/src/main/kotlin/org/jetbrains/kotlin/tooling/core/ExtrasProperty.kt b/libraries/tools/kotlin-tooling-core/src/main/kotlin/org/jetbrains/kotlin/tooling/core/ExtrasProperty.kt index bfe0d8ccadf..5ae97bc39da 100644 --- a/libraries/tools/kotlin-tooling-core/src/main/kotlin/org/jetbrains/kotlin/tooling/core/ExtrasProperty.kt +++ b/libraries/tools/kotlin-tooling-core/src/main/kotlin/org/jetbrains/kotlin/tooling/core/ExtrasProperty.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.tooling.core +import javax.sound.midi.Receiver import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty @@ -19,6 +20,8 @@ val Extras.Key.readWriteProperty get() = extrasReadWriteProperty(th fun Extras.Key.factoryProperty(factory: () -> T) = extrasFactoryProperty(this, factory) +fun Extras.Key.lazyProperty(factory: Receiver.() -> T) = extrasLazyProperty(this, factory) + fun extrasReadProperty(key: Extras.Key): ExtrasReadOnlyProperty = object : ExtrasReadOnlyProperty { override val key: Extras.Key = key } @@ -32,6 +35,14 @@ fun extrasFactoryProperty(key: Extras.Key, factory: () -> T) = obje override val factory: () -> T = factory } +fun extrasLazyProperty( + key: Extras.Key, factory: Receiver.() -> T +): ExtrasLazyProperty = + object : ExtrasLazyProperty { + override val key: Extras.Key = key + override val factory: Receiver.() -> T = factory + } + inline fun extrasReadWriteProperty(name: String? = null) = extrasReadWriteProperty(extrasKeyOf(name)) @@ -39,7 +50,10 @@ inline fun extrasReadProperty(name: String? = null) = extrasReadProperty(extrasKeyOf(name)) inline fun extrasFactoryProperty(name: String? = null, noinline factory: () -> T) = - extrasFactoryProperty(extrasKeyOf(name), factory) + extrasFactoryProperty(extrasKeyOf(name), factory) + +inline fun extrasLazyProperty(name: String? = null, noinline factory: Receiver.() -> T) = + extrasLazyProperty(extrasKeyOf(name), factory) interface ExtrasReadOnlyProperty : ExtrasProperty, ReadOnlyProperty { override fun getValue(thisRef: HasExtras, property: KProperty<*>): T? { @@ -99,3 +113,15 @@ interface ExtrasFactoryProperty : ExtrasProperty, ReadWriteProperty< thisRef.extras[key] = value } } + +interface ExtrasLazyProperty : ExtrasProperty, ReadWriteProperty { + val factory: Receiver.() -> T + + override fun getValue(thisRef: Receiver, property: KProperty<*>): T { + return thisRef.extras.getOrPut(key) { thisRef.factory() } + } + + override fun setValue(thisRef: Receiver, property: KProperty<*>, value: T) { + thisRef.extras[key] = value + } +} diff --git a/libraries/tools/kotlin-tooling-core/src/test/kotlin/org/jetbrains/kotlin/tooling/core/ExtrasPropertyTest.kt b/libraries/tools/kotlin-tooling-core/src/test/kotlin/org/jetbrains/kotlin/tooling/core/ExtrasPropertyTest.kt index 371ee3eb1fb..0d5be1cdb12 100644 --- a/libraries/tools/kotlin-tooling-core/src/test/kotlin/org/jetbrains/kotlin/tooling/core/ExtrasPropertyTest.kt +++ b/libraries/tools/kotlin-tooling-core/src/test/kotlin/org/jetbrains/kotlin/tooling/core/ExtrasPropertyTest.kt @@ -34,6 +34,9 @@ class ExtrasPropertyTest { private val keyList = extrasKeyOf>() private val Subject.factoryList: MutableList by keyList.factoryProperty { mutableListOf() } + private val keySubjectList = extrasKeyOf>() + private val Subject.lazyList: MutableList by keySubjectList.lazyProperty { mutableListOf(this) } + @Test fun `test - readOnlyProperty`() { val subject = Subject() @@ -110,4 +113,27 @@ class ExtrasPropertyTest { assertSame(list, subject.factoryList) } } + + + @Test + fun `test - lazyProperty`() { + run { + val subject = Subject() + assertNotNull(subject.lazyList) + assertSame(subject.lazyList, subject.lazyList) + assertSame(subject.extras[keySubjectList], subject.lazyList) + assertSame(subject, subject.lazyList.firstOrNull()) + + val subject2 = Subject() + assertSame(subject2, subject2.lazyList.firstOrNull()) + assertNotSame(subject.lazyList.firstOrNull(), subject2.lazyList.firstOrNull()) + } + + run { + val subject = Subject() + val list = mutableListOf() + subject.extras[keySubjectList] = list + assertSame(list, subject.lazyList) + } + } }