[kotlin-tooling-core] Implement ExtrasProperty
KT-55189
This commit is contained in:
committed by
Space Team
parent
02ec4cb1b5
commit
a23e4a1048
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.tooling.core
|
||||
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
interface ExtrasProperty<T : Any> {
|
||||
val key: Extras.Key<T>
|
||||
}
|
||||
|
||||
val <T : Any> Extras.Key<T>.readProperty get() = extrasReadProperty(this)
|
||||
|
||||
val <T : Any> Extras.Key<T>.readWriteProperty get() = extrasReadWriteProperty(this)
|
||||
|
||||
fun <T : Any> Extras.Key<T>.factoryProperty(factory: () -> T) = extrasFactoryProperty(this, factory)
|
||||
|
||||
fun <T : Any> extrasReadProperty(key: Extras.Key<T>): ExtrasReadOnlyProperty<T> = object : ExtrasReadOnlyProperty<T> {
|
||||
override val key: Extras.Key<T> = key
|
||||
}
|
||||
|
||||
fun <T : Any> extrasReadWriteProperty(key: Extras.Key<T>): ExtrasReadWriteProperty<T> = object : ExtrasReadWriteProperty<T> {
|
||||
override val key: Extras.Key<T> = key
|
||||
}
|
||||
|
||||
fun <T : Any> extrasFactoryProperty(key: Extras.Key<T>, factory: () -> T) = object : ExtrasFactoryProperty<T> {
|
||||
override val key: Extras.Key<T> = key
|
||||
override val factory: () -> T = factory
|
||||
}
|
||||
|
||||
interface ExtrasReadOnlyProperty<T : Any> : ExtrasProperty<T>, ReadOnlyProperty<HasExtras, T?> {
|
||||
override fun getValue(thisRef: HasExtras, property: KProperty<*>): T? {
|
||||
return thisRef.extras[key]
|
||||
}
|
||||
|
||||
fun notNull(defaultValue: T): NotNullExtrasReadOnlyProperty<T> = object : NotNullExtrasReadOnlyProperty<T> {
|
||||
override val defaultValue: T = defaultValue
|
||||
override val key: Extras.Key<T> = this@ExtrasReadOnlyProperty.key
|
||||
}
|
||||
}
|
||||
|
||||
interface NotNullExtrasReadOnlyProperty<T : Any> : ExtrasProperty<T>, ReadOnlyProperty<HasExtras, T> {
|
||||
val defaultValue: T
|
||||
|
||||
override fun getValue(thisRef: HasExtras, property: KProperty<*>): T {
|
||||
return thisRef.extras[key] ?: defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
interface ExtrasReadWriteProperty<T : Any> : ExtrasProperty<T>, ReadWriteProperty<HasMutableExtras, T?> {
|
||||
override fun getValue(thisRef: HasMutableExtras, property: KProperty<*>): T? {
|
||||
return thisRef.extras[key]
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: HasMutableExtras, property: KProperty<*>, value: T?) {
|
||||
if (value != null) thisRef.extras[key] = value
|
||||
else thisRef.extras.remove(key)
|
||||
}
|
||||
|
||||
fun notNull(defaultValue: T): NotNullExtrasReadWriteProperty<T> = object : NotNullExtrasReadWriteProperty<T> {
|
||||
override val defaultValue: T = defaultValue
|
||||
override val key: Extras.Key<T> = this@ExtrasReadWriteProperty.key
|
||||
}
|
||||
}
|
||||
|
||||
interface NotNullExtrasReadWriteProperty<T : Any> : ExtrasProperty<T>, ReadWriteProperty<HasMutableExtras, T> {
|
||||
val defaultValue: T
|
||||
|
||||
override fun getValue(thisRef: HasMutableExtras, property: KProperty<*>): T {
|
||||
return thisRef.extras[key] ?: defaultValue
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: HasMutableExtras, property: KProperty<*>, value: T) {
|
||||
thisRef.extras[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
interface ExtrasFactoryProperty<T : Any> : ExtrasProperty<T>, ReadWriteProperty<HasMutableExtras, T> {
|
||||
val factory: () -> T
|
||||
|
||||
override fun getValue(thisRef: HasMutableExtras, property: KProperty<*>): T {
|
||||
return thisRef.extras.getOrPut(key, factory)
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: HasMutableExtras, property: KProperty<*>, value: T) {
|
||||
thisRef.extras[key] = value
|
||||
}
|
||||
}
|
||||
+2
@@ -27,3 +27,5 @@ operator fun <T : Any> Extras.Key<T>.setValue(receiver: HasMutableExtras, proper
|
||||
receiver.extras[this] = value
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.tooling.core
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
class ExtrasPropertyTest {
|
||||
|
||||
|
||||
class Subject : HasMutableExtras {
|
||||
override val extras: MutableExtras = mutableExtrasOf()
|
||||
}
|
||||
|
||||
class Dummy
|
||||
|
||||
private val keyA = extrasKeyOf<Int>("a")
|
||||
private val keyB = extrasKeyOf<Int>("b")
|
||||
|
||||
private val Subject.readA: Int? by keyA.readProperty
|
||||
private val Subject.readB: Int? by keyB.readProperty
|
||||
|
||||
private var Subject.readWriteA: Int? by keyA.readWriteProperty
|
||||
private var Subject.readWriteB: Int? by keyB.readWriteProperty
|
||||
|
||||
private val Subject.notNullReadA: Int by keyA.readProperty.notNull(1)
|
||||
private val Subject.notNullReadB: Int by keyB.readProperty.notNull(2)
|
||||
|
||||
private var Subject.notNullReadWriteA: Int by keyA.readWriteProperty.notNull(3)
|
||||
private var Subject.notNullReadWriteB: Int by keyB.readWriteProperty.notNull(4)
|
||||
|
||||
private val keyList = extrasKeyOf<MutableList<Dummy>>()
|
||||
private val Subject.factoryList: MutableList<Dummy> by keyList.factoryProperty { mutableListOf() }
|
||||
|
||||
@Test
|
||||
fun `test - readOnlyProperty`() {
|
||||
val subject = Subject()
|
||||
assertNull(subject.readA)
|
||||
assertNull(subject.readB)
|
||||
|
||||
subject.readWriteA = 1
|
||||
assertEquals(1, subject.readA)
|
||||
assertNull(subject.readB)
|
||||
|
||||
subject.readWriteB = 2
|
||||
assertEquals(1, subject.readA)
|
||||
assertEquals(2, subject.readB)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - readWriteProperty`() {
|
||||
val subject = Subject()
|
||||
assertNull(subject.readWriteA)
|
||||
assertNull(subject.readWriteB)
|
||||
|
||||
subject.readWriteA = 1
|
||||
assertEquals(1, subject.readWriteA)
|
||||
assertNull(subject.readB)
|
||||
|
||||
subject.readWriteB = 2
|
||||
assertEquals(1, subject.readWriteA)
|
||||
assertEquals(2, subject.readWriteB)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - readOnlyProperty - notNull`() {
|
||||
val subject = Subject()
|
||||
assertEquals(1, subject.notNullReadA)
|
||||
assertEquals(2, subject.notNullReadB)
|
||||
|
||||
subject.readWriteA = -1
|
||||
assertEquals(-1, subject.notNullReadA)
|
||||
assertEquals(2, subject.notNullReadB)
|
||||
|
||||
subject.readWriteB = -2
|
||||
assertEquals(-1, subject.notNullReadA)
|
||||
assertEquals(-2, subject.notNullReadB)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - readWriteProperty - notNull`() {
|
||||
val subject = Subject()
|
||||
assertEquals(3, subject.notNullReadWriteA)
|
||||
assertEquals(4, subject.notNullReadWriteB)
|
||||
|
||||
subject.notNullReadWriteA = -1
|
||||
assertEquals(-1, subject.notNullReadWriteA)
|
||||
assertEquals(4, subject.notNullReadWriteB)
|
||||
|
||||
subject.notNullReadWriteB = -2
|
||||
assertEquals(-1, subject.notNullReadWriteA)
|
||||
assertEquals(-2, subject.notNullReadWriteB)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - factoryProperty`() {
|
||||
run {
|
||||
val subject = Subject()
|
||||
assertNotNull(subject.factoryList)
|
||||
assertSame(subject.factoryList, subject.factoryList)
|
||||
assertSame(subject.extras[keyList], subject.factoryList)
|
||||
}
|
||||
|
||||
run {
|
||||
val subject = Subject()
|
||||
val list = mutableListOf(Dummy())
|
||||
subject.extras[keyList] = list
|
||||
assertSame(list, subject.factoryList)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user