From f21e08f6b91c21a09f39d4699b5749674d9484dc Mon Sep 17 00:00:00 2001 From: Sebastian Sellmair Date: Tue, 7 Feb 2023 13:30:51 +0100 Subject: [PATCH] [kotlin-tooling-core] Add extrasNullableLazyProperty API ^KT-56431 Verification Pending --- .../api/kotlin-tooling-core.api | 8 +++++ .../kotlin/tooling/core/ExtrasProperty.kt | 25 ++++++++++++- .../kotlin/tooling/core/ExtrasPropertyTest.kt | 35 +++++++++++++++++++ 3 files changed, 67 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 1ee309f46e3..774292e3407 100644 --- a/libraries/tools/kotlin-tooling-core/api/kotlin-tooling-core.api +++ b/libraries/tools/kotlin-tooling-core/api/kotlin-tooling-core.api @@ -98,12 +98,14 @@ public abstract interface class org/jetbrains/kotlin/tooling/core/ExtrasProperty 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 extrasNullableLazyProperty (Lorg/jetbrains/kotlin/tooling/core/Extras$Key;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlin/tooling/core/NullableExtrasLazyProperty; 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 static final fun nullableLazyProperty (Lorg/jetbrains/kotlin/tooling/core/Extras$Key;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlin/tooling/core/NullableExtrasLazyProperty; } public abstract interface class org/jetbrains/kotlin/tooling/core/ExtrasReadOnlyProperty : kotlin/properties/ReadOnlyProperty, org/jetbrains/kotlin/tooling/core/ExtrasProperty { @@ -223,6 +225,12 @@ public abstract interface class org/jetbrains/kotlin/tooling/core/NotNullExtrasR 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/NullableExtrasLazyProperty : kotlin/properties/ReadOnlyProperty, 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 final class org/jetbrains/kotlin/tooling/core/TypeUtils { public static final fun renderReifiedTypeSignatureString (Lkotlin/reflect/KType;)Ljava/lang/String; } 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 5ae97bc39da..8e277fc785c 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,7 +5,7 @@ package org.jetbrains.kotlin.tooling.core -import javax.sound.midi.Receiver +import java.util.* import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty @@ -22,6 +22,9 @@ fun Extras.Key.factoryProperty(factory: () -> T) = extrasFactoryPro fun Extras.Key.lazyProperty(factory: Receiver.() -> T) = extrasLazyProperty(this, factory) +fun Extras.Key>.nullableLazyProperty(factory: Receiver.() -> T?) = + extrasNullableLazyProperty(this, factory) + fun extrasReadProperty(key: Extras.Key): ExtrasReadOnlyProperty = object : ExtrasReadOnlyProperty { override val key: Extras.Key = key } @@ -43,6 +46,14 @@ fun extrasLazyProperty( override val factory: Receiver.() -> T = factory } +fun extrasNullableLazyProperty( + key: Extras.Key>, factory: Receiver.() -> T? +): NullableExtrasLazyProperty = + object : NullableExtrasLazyProperty { + override val key: Extras.Key> = key + override val factory: Receiver.() -> T? = factory + } + inline fun extrasReadWriteProperty(name: String? = null) = extrasReadWriteProperty(extrasKeyOf(name)) @@ -55,6 +66,10 @@ inline fun extrasFactoryProperty(name: String? = null, noinlin inline fun extrasLazyProperty(name: String? = null, noinline factory: Receiver.() -> T) = extrasLazyProperty(extrasKeyOf(name), factory) +inline fun extrasNullableLazyProperty( + name: String? = null, noinline factory: Receiver.() -> T? +) = extrasNullableLazyProperty(extrasKeyOf(name), factory) + interface ExtrasReadOnlyProperty : ExtrasProperty, ReadOnlyProperty { override fun getValue(thisRef: HasExtras, property: KProperty<*>): T? { return thisRef.extras[key] @@ -125,3 +140,11 @@ interface ExtrasLazyProperty : ExtrasPrope thisRef.extras[key] = value } } + +interface NullableExtrasLazyProperty : ExtrasProperty>, ReadOnlyProperty { + val factory: Receiver.() -> T? + + override fun getValue(thisRef: Receiver, property: KProperty<*>): T? { + return thisRef.extras.getOrPut(key) { Optional.ofNullable(thisRef.factory()) }.let { if (it.isPresent) it.get() else null } + } +} 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 0d5be1cdb12..9eee574741f 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 @@ -37,6 +37,18 @@ class ExtrasPropertyTest { private val keySubjectList = extrasKeyOf>() private val Subject.lazyList: MutableList by keySubjectList.lazyProperty { mutableListOf(this) } + private val lazyNullStringInvocations = mutableListOf() + private val Subject.lazyNullString: String? by extrasNullableLazyProperty("null") { + lazyNullStringInvocations.add(this) + null + } + + private val lazyNullableStringInvocations = mutableListOf() + private val Subject.lazyNullableString: String? by extrasNullableLazyProperty("not-null") { + lazyNullableStringInvocations.add(this) + "OK" + } + @Test fun `test - readOnlyProperty`() { val subject = Subject() @@ -136,4 +148,27 @@ class ExtrasPropertyTest { assertSame(list, subject.lazyList) } } + + @Test + fun `test - lazyNullableProperty`() { + val subject1 = Subject() + val subject2 = Subject() + + assertNull(subject1.lazyNullString) + assertNull(subject1.lazyNullString) + assertEquals(listOf(subject1), lazyNullStringInvocations) + + assertNull(subject2.lazyNullString) + assertNull(subject2.lazyNullString) + assertEquals(listOf(subject1, subject2), lazyNullStringInvocations) + + + assertEquals("OK", subject1.lazyNullableString) + assertEquals("OK", subject1.lazyNullableString) + assertEquals(listOf(subject1), lazyNullableStringInvocations) + + assertEquals("OK", subject2.lazyNullableString) + assertEquals("OK", subject2.lazyNullableString) + assertEquals(listOf(subject1, subject2), lazyNullableStringInvocations) + } }