From d120bfe576ac80b2a672fae2f154876459611796 Mon Sep 17 00:00:00 2001 From: Him188 Date: Wed, 24 Jun 2020 04:08:53 +0800 Subject: [PATCH] Rename valueReified to value; Introduce public valueFromKType; Fix CompositeListValueImpl --- .../mamoe/mirai/console/setting/Setting.kt | 38 ++++++++++++++----- .../internal/Setting.value composite impl.kt | 12 ++++-- .../mirai/console/setting/SettingTest.kt | 4 +- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Setting.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Setting.kt index 4f0d43d5e..9f45c874f 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Setting.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Setting.kt @@ -14,17 +14,16 @@ package net.mamoe.mirai.console.setting import kotlinx.serialization.* import kotlinx.serialization.builtins.MapSerializer import kotlinx.serialization.builtins.serializer -import net.mamoe.mirai.console.setting.internal.cast import net.mamoe.mirai.console.setting.internal.isOdd +import net.mamoe.mirai.console.setting.internal.typeOf0 import net.mamoe.mirai.console.setting.internal.valueFromKTypeImpl import net.mamoe.mirai.console.setting.internal.valueImpl -import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.yamlkt.YamlNullableDynamicSerializer import kotlin.internal.LowPriorityInOverloadResolution import kotlin.reflect.KProperty import kotlin.reflect.KType import kotlin.reflect.full.findAnnotation -import kotlin.reflect.typeOf +import kotlin.reflect.jvm.isAccessible // TODO: 2020/6/21 move to JvmPlugin to inherit SettingStorage and CoroutineScope for saving @@ -162,7 +161,21 @@ fun Setting.value(default: String): SerializerAwareValue = valueImpl(def /** - * Creates a [Value] with reified type. + * Creates a [Value] with reified type, and set default value. + * + * @param T reified param type T. + * Supports only primitives, Kotlin built-in collections, + * and classes that are serializable with Kotlinx.serialization + * (typically annotated with [kotlinx.serialization.Serializable]) + */ +@Suppress("UNCHECKED_CAST") +@LowPriorityInOverloadResolution +inline fun Setting.value(default: T): SerializerAwareValue = + value().apply { value = default } + + +/** + * Creates a [Value] with reified type, and set default value by reflection to its no-arg public constructor. * * @param T reified param type T. * Supports only primitives, Kotlin built-in collections, @@ -170,12 +183,17 @@ fun Setting.value(default: String): SerializerAwareValue = valueImpl(def * (typically annotated with [kotlinx.serialization.Serializable]) */ @LowPriorityInOverloadResolution -@MiraiExperimentalAPI -@OptIn(ExperimentalStdlibApi::class) // stable in 1.4 -inline fun Setting.valueReified(default: T): SerializerAwareValue = - valueFromKTypeImpl(typeOf()).cast() +inline fun Setting.value(): SerializerAwareValue = + value( + T::class.constructors.find { it.parameters.isEmpty() && it.isAccessible }?.call() + ?: throw IllegalArgumentException("Cannot construct a default value for given type ${typeOf0()}") + ) -@MiraiExperimentalAPI -fun Setting.valueFromKType(type: KType): SerializerAwareValue = valueFromKTypeImpl(type).cast() +/** + * Creates a [Value] with specified [KType], and set default value. + */ +@Suppress("UNCHECKED_CAST") +fun Setting.valueFromKType(type: KType, default: T): SerializerAwareValue = + (valueFromKTypeImpl(type) as SerializerAwareValue).apply { this.value = default } as SerializerAwareValue // TODO: 2020/6/24 Introduce class TypeToken for compound types for Java. \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/Setting.value composite impl.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/Setting.value composite impl.kt index 4ada0dc61..b2a679108 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/Setting.value composite impl.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/Setting.value composite impl.kt @@ -26,6 +26,10 @@ private val primitiveCollectionsImplemented by lazy { false } +@PublishedApi +@OptIn(ExperimentalStdlibApi::class) +internal inline fun typeOf0(): KType = kotlin.reflect.typeOf() + @PublishedApi @Suppress("UnsafeCall", "SMARTCAST_IMPOSSIBLE", "UNCHECKED_CAST") internal fun Setting.valueFromKTypeImpl(type: KType): SerializerAwareValue<*> { @@ -54,8 +58,8 @@ internal fun Setting.valueFromKTypeImpl(type: KType): SerializerAwareValue<*> { TODO() } else { return createCompositeMapValueImpl( - kToValue = { k -> valueFromKType(type.arguments[0].type!!).also { it.value = k } }, - vToValue = { v -> valueFromKType(type.arguments[1].type!!).also { it.value = v } } + kToValue = { k -> valueFromKType(type.arguments[0].type!!, k) }, + vToValue = { v -> valueFromKType(type.arguments[1].type!!, v) } ).serializableValueWith(serializerMirai(type) as KSerializer>) // erased } } @@ -72,7 +76,7 @@ internal fun Setting.valueFromKTypeImpl(type: KType): SerializerAwareValue<*> { // ... TODO() } else { - return createCompositeListValueImpl { valueFromKType(type.arguments[0].type!!) } + return createCompositeListValueImpl { v -> valueFromKType(type.arguments[0].type!!, v) } .serializableValueWith(serializerMirai(type) as KSerializer>) } } @@ -87,7 +91,7 @@ internal fun Setting.valueFromKTypeImpl(type: KType): SerializerAwareValue<*> { // ... TODO() } else { - return createCompositeSetValueImpl { valueFromKType(type.arguments[0].type!!) } + return createCompositeSetValueImpl { v -> valueFromKType(type.arguments[0].type!!, v) } .serializableValueWith(serializerMirai(type) as KSerializer>) } } diff --git a/backend/mirai-console/src/test/kotlin/net/mamoe/mirai/console/setting/SettingTest.kt b/backend/mirai-console/src/test/kotlin/net/mamoe/mirai/console/setting/SettingTest.kt index 893bcd131..6fce8dbb5 100644 --- a/backend/mirai-console/src/test/kotlin/net/mamoe/mirai/console/setting/SettingTest.kt +++ b/backend/mirai-console/src/test/kotlin/net/mamoe/mirai/console/setting/SettingTest.kt @@ -20,8 +20,8 @@ internal class SettingTest { class MySetting : Setting() { var int by value(1) - val map by valueReified(mapOf("" to "")) - val map2 by valueReified(mutableMapOf("" to mutableMapOf("" to ""))) + val map by value(mapOf("" to "")) + val map2 by value(mutableMapOf("" to mutableMapOf("" to ""))) } @OptIn(UnstableDefault::class)