Introducing transient properties in scripting API

This commit is contained in:
Ilya Chernikov
2019-07-24 19:57:47 +02:00
parent 5fe843d754
commit e41bbe9328
8 changed files with 89 additions and 43 deletions
@@ -5,15 +5,20 @@
package kotlin.script.experimental.util
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.io.Serializable
import kotlin.reflect.KClass
import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.script.experimental.api.KotlinType
open class PropertiesCollection(private val properties: Map<Key<*>, Any?> = emptyMap()) : Serializable {
open class PropertiesCollection(private var properties: Map<Key<*>, Any?> = emptyMap()) : Serializable {
class Key<T>(val name: String, @Transient val getDefaultValue: PropertiesCollection.() -> T?) : Serializable {
open class Key<T>(
val name: String,
@Transient val getDefaultValue: PropertiesCollection.() -> T?
) : Serializable {
constructor(name: String, defaultValue: T? = null) : this(name, { defaultValue })
@@ -27,11 +32,17 @@ open class PropertiesCollection(private val properties: Map<Key<*>, Any?> = empt
}
}
class PropertyKeyDelegate<T>(private val getDefaultValue: PropertiesCollection.() -> T?) {
constructor(defaultValue: T?) : this({ defaultValue })
class TransientKey<T>(
name: String,
getDefaultValue: PropertiesCollection.() -> T?
) : Key<T>(name, getDefaultValue)
class PropertyKeyDelegate<T>(private val getDefaultValue: PropertiesCollection.() -> T?, val isTransient: Boolean = false) {
constructor(defaultValue: T?, isTransient: Boolean = false) : this({ defaultValue }, isTransient)
operator fun getValue(thisRef: Any?, property: KProperty<*>): Key<T> =
Key(property.name, getDefaultValue)
if (isTransient) TransientKey(property.name, getDefaultValue)
else Key(property.name, getDefaultValue)
}
class PropertyKeyCopyDelegate<T>(val source: Key<T>) {
@@ -51,14 +62,29 @@ open class PropertiesCollection(private val properties: Map<Key<*>, Any?> = empt
fun entries(): Set<Map.Entry<Key<*>, Any?>> = properties.entries
val notTransientData: Map<Key<*>, Any?> get() = properties.filterKeys { it !is TransientKey<*>}
override fun equals(other: Any?): Boolean =
(other as? PropertiesCollection)?.let { it.properties == properties } == true
override fun hashCode(): Int = properties.hashCode()
private fun writeObject(outputStream: ObjectOutputStream) {
outputStream.writeObject(notTransientData)
}
private fun readObject(inputStream: ObjectInputStream) {
@Suppress("UNCHECKED_CAST")
properties = inputStream.readObject() as Map<Key<*>, Any?>
}
companion object {
fun <T> key(defaultValue: T? = null): PropertyKeyDelegate<T> = PropertyKeyDelegate(defaultValue)
fun <T> key(getDefaultValue: PropertiesCollection.() -> T?): PropertyKeyDelegate<T> = PropertyKeyDelegate(getDefaultValue)
fun <T> key(defaultValue: T? = null, isTransient: Boolean = false): PropertyKeyDelegate<T> =
PropertyKeyDelegate(defaultValue, isTransient)
fun <T> key(getDefaultValue: PropertiesCollection.() -> T?, isTransient: Boolean = false): PropertyKeyDelegate<T> =
PropertyKeyDelegate(getDefaultValue, isTransient)
fun <T> keyCopy(source: Key<T>): PropertyKeyCopyDelegate<T> = PropertyKeyCopyDelegate(source)
@JvmStatic