mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-11 02:50:15 +08:00
Cleanup, remove old settings
This commit is contained in:
parent
11cb8d5c68
commit
687729df4e
@ -16,8 +16,6 @@ import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.plugin.PluginLoader
|
||||
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
|
||||
import net.mamoe.mirai.console.setting.SettingStorage
|
||||
import net.mamoe.mirai.console.setting.internal.ConsoleBuiltInSetting
|
||||
import net.mamoe.mirai.utils.DefaultLogger
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
@ -72,14 +70,6 @@ object MiraiConsole : CoroutineScope, IMiraiConsole {
|
||||
|
||||
override val builtInPluginLoaders: List<PluginLoader<*, *>> get() = instance.builtInPluginLoaders
|
||||
|
||||
@Suppress("CANNOT_WEAKEN_ACCESS_PRIVILEGE")
|
||||
internal override val jvmSettingStorage: SettingStorage
|
||||
get() = instance.jvmSettingStorage
|
||||
|
||||
@Suppress("CANNOT_WEAKEN_ACCESS_PRIVILEGE")
|
||||
override val consoleBuiltIntSettingStorage: SettingStorage
|
||||
get() = instance.consoleBuiltIntSettingStorage
|
||||
|
||||
init {
|
||||
DefaultLogger = { identity -> this.newLogger(identity) }
|
||||
this.coroutineContext[Job]!!.invokeOnCompletion {
|
||||
@ -116,16 +106,6 @@ internal interface IMiraiConsole : CoroutineScope {
|
||||
* 内建加载器列表, 一般需要包含 [JarPluginLoader]
|
||||
*/
|
||||
val builtInPluginLoaders: List<PluginLoader<*, *>>
|
||||
|
||||
/**
|
||||
* 内建的供 [JvmPlugin] 使用的 [SettingStorage]
|
||||
*/
|
||||
val jvmSettingStorage: SettingStorage
|
||||
|
||||
/**
|
||||
* 内建的供 [ConsoleBuiltInSetting] 使用的 [SettingStorage]
|
||||
*/
|
||||
val consoleBuiltIntSettingStorage: SettingStorage
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,7 +15,6 @@ import net.mamoe.mirai.console.plugin.AbstractFilePluginLoader
|
||||
import net.mamoe.mirai.console.plugin.PluginLoadException
|
||||
import net.mamoe.mirai.console.plugin.internal.JvmPluginImpl
|
||||
import net.mamoe.mirai.console.plugin.internal.PluginsLoader
|
||||
import net.mamoe.mirai.console.setting.SettingStorage
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import java.io.File
|
||||
@ -49,8 +48,6 @@ object JarPluginLoader : AbstractFilePluginLoader<JvmPlugin, JvmPluginDescriptio
|
||||
}
|
||||
}
|
||||
|
||||
val settingStorage: SettingStorage = MiraiConsole.jvmSettingStorage
|
||||
|
||||
override fun getPluginDescription(plugin: JvmPlugin): JvmPluginDescription = plugin.description
|
||||
|
||||
override fun Sequence<File>.mapToDescription(): List<JvmPluginDescription> {
|
||||
|
@ -12,9 +12,6 @@
|
||||
package net.mamoe.mirai.console.plugin.jvm
|
||||
|
||||
import net.mamoe.mirai.console.plugin.internal.JvmPluginImpl
|
||||
import net.mamoe.mirai.console.plugin.internal.job
|
||||
import net.mamoe.mirai.console.setting.Setting
|
||||
import net.mamoe.mirai.console.setting.Value
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
@ -23,20 +20,4 @@ import kotlin.coroutines.EmptyCoroutineContext
|
||||
*/
|
||||
abstract class KotlinPlugin @JvmOverloads constructor(
|
||||
parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
) : JvmPlugin, JvmPluginImpl(parentCoroutineContext) {
|
||||
abstract inner class PluginSetting : Setting() {
|
||||
private val track =
|
||||
@Suppress("LeakingThis")
|
||||
JarPluginLoader.settingStorage.trackOn(this)
|
||||
|
||||
init {
|
||||
this@KotlinPlugin.job.invokeOnCompletion {
|
||||
track.close()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onElementChanged(value: Value<*>) {
|
||||
TODO()
|
||||
}
|
||||
}
|
||||
}
|
||||
) : JvmPlugin, JvmPluginImpl(parentCoroutineContext)
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE", "unused")
|
||||
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import net.mamoe.mirai.console.setting.internal.SettingImpl
|
||||
import net.mamoe.mirai.console.setting.internal.serialNameOrPropertyName
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.KProperty0
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
|
||||
/**
|
||||
* 在配置文件和图像界面中保存的名称.
|
||||
*/
|
||||
typealias SerialName = kotlinx.serialization.SerialName
|
||||
|
||||
/**
|
||||
* 在配置文件和图像界面中显示的说明.
|
||||
*/
|
||||
typealias Comment = net.mamoe.yamlkt.Comment
|
||||
|
||||
/**
|
||||
* 配置的基类. 所有配置必须拥有一个无参构造器, 以用于在 [MutableList] 与 [MutableMap] 中动态识别类型
|
||||
*/
|
||||
@Suppress("EXPOSED_SUPER_CLASS")
|
||||
abstract class Setting : SettingImpl() {
|
||||
|
||||
/**
|
||||
* 表示这个配置的嵌套对象, 自动绑定数据更新.
|
||||
*/
|
||||
abstract inner class Inner : Setting() {
|
||||
internal lateinit var attachedValue: Value<*>
|
||||
override fun onElementChanged(value: Value<*>) {
|
||||
this@Setting.onElementChanged(attachedValue)
|
||||
}
|
||||
}
|
||||
|
||||
data class PropertyInfo(
|
||||
val serialName: String,
|
||||
val annotations: List<Annotation>,
|
||||
val propertyOriginalName: String?
|
||||
)
|
||||
|
||||
/**
|
||||
* 这个配置的名称, 仅对于顶层配置有效.
|
||||
*/
|
||||
@MiraiExperimentalAPI
|
||||
open val serialName: String
|
||||
get() = this::class.findAnnotation<SerialName>()?.value
|
||||
?: this::class.qualifiedName
|
||||
?: error("Names should be assigned to anonymous classes manually by overriding serialName")
|
||||
|
||||
|
||||
// for Java only
|
||||
fun <T : Any> addProperty(
|
||||
propertyInfo: PropertyInfo,
|
||||
value: Value<*>
|
||||
): Value<*> {
|
||||
if (built) error("The Setting is already serialized so it's structure is immutable.")
|
||||
valueList.add(value to propertyInfo)
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取这个属性的真实 [Value] 委托
|
||||
*/
|
||||
@get:JvmSynthetic
|
||||
val <R : Any> KProperty0<R>.correspondingValue: Value<R>
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
get() = findCorrespondingValue(this)
|
||||
?: throw NoSuchElementException("No corresponding Value found for property $this")
|
||||
|
||||
/**
|
||||
* 获取这个属性的真实 [Value] 委托
|
||||
*/
|
||||
fun <R : Any> findCorrespondingValue(property: KProperty0<R>): Value<R>? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return this@Setting.valueList.firstOrNull { it.second.propertyOriginalName == property.name }?.first as Value<R>?
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供属性委托, 并添加这个对象的自动保存跟踪.
|
||||
*/
|
||||
@JvmSynthetic
|
||||
operator fun <T : Any> Value<T>.provideDelegate(
|
||||
thisRef: Setting,
|
||||
property: KProperty<*>
|
||||
): ReadWriteProperty<Setting, T> {
|
||||
if (built) error("The Setting is already serialized so it's structure is immutable.")
|
||||
valueList.add(this to PropertyInfo(property.serialNameOrPropertyName, property.annotations, property.name))
|
||||
return this
|
||||
}
|
||||
|
||||
abstract override fun onElementChanged(value: Value<*>)
|
||||
|
||||
override fun toString(): String = yamlForToString.stringify(this.serializer, this)
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于更新或保存这个 [Value] 的序列化器.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val <T : Setting> T.serializer: KSerializer<T>
|
||||
get() = kotlinSerializer as KSerializer<T>
|
@ -1,65 +0,0 @@
|
||||
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.internal.getChecked
|
||||
import net.mamoe.mirai.console.setting.internal.SettingSerializerMark
|
||||
import java.io.Closeable
|
||||
import java.io.File
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
|
||||
/**
|
||||
* [Setting] 存储方式
|
||||
*/
|
||||
interface SettingStorage {
|
||||
interface TrackedSetting : Closeable {
|
||||
fun save()
|
||||
fun update()
|
||||
|
||||
override fun close()
|
||||
}
|
||||
|
||||
fun trackOn(setting: Setting): TrackedSetting
|
||||
|
||||
fun saveAll()
|
||||
fun updateAll()
|
||||
}
|
||||
|
||||
class SingleFileSettingStorage(
|
||||
val file: File
|
||||
) : SettingStorage {
|
||||
private val descriptor: MutableList<Setting> = ArrayList()
|
||||
private val updaterSerializer: KSerializer<SettingSerializerMark> = object : KSerializer<SettingSerializerMark> {
|
||||
override val descriptor: SerialDescriptor = SerialDescriptor("SingleFileSettingStorage") {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun deserialize(decoder: Decoder): SettingSerializerMark {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: SettingSerializerMark) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
init {
|
||||
require(file.isFile) { "file $file is not a file" }
|
||||
require(file.canRead()) { "file $file is not readable" }
|
||||
}
|
||||
|
||||
override fun trackOn(setting: Setting): SettingStorage.TrackedSetting {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun saveAll() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun updateAll() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "unused")
|
||||
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import net.mamoe.mirai.console.setting.internal.valueImpl
|
||||
import kotlin.internal.LowPriorityInOverloadResolution
|
||||
|
||||
|
||||
/**
|
||||
* !!! This file is auto-generated by backend/codegen/src/kotlin/net.mamoe.mirai.console.codegen.SettingValueUseSiteCodegen.kt
|
||||
* !!! DO NOT MODIFY THIS FILE MANUALLY
|
||||
*/
|
||||
|
||||
|
||||
fun Setting.value(default: Int): IntValue = valueImpl(default)
|
||||
fun Setting.value(default: Short): ShortValue = valueImpl(default)
|
||||
fun Setting.value(default: Byte): ByteValue = valueImpl(default)
|
||||
fun Setting.value(default: Long): LongValue = valueImpl(default)
|
||||
fun Setting.value(default: Float): FloatValue = valueImpl(default)
|
||||
fun Setting.value(default: Double): DoubleValue = valueImpl(default)
|
||||
fun Setting.value(default: Boolean): BooleanValue = valueImpl(default)
|
||||
fun Setting.value(default: Char): CharValue = valueImpl(default)
|
||||
fun Setting.value(default: String): StringValue = valueImpl(default)
|
||||
fun Setting.value(default: IntArray): IntArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: ShortArray): ShortArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: ByteArray): ByteArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: LongArray): LongArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: FloatArray): FloatArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: DoubleArray): DoubleArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: BooleanArray): BooleanArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: CharArray): CharArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Int>): TypedIntArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Short>): TypedShortArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Byte>): TypedByteArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Long>): TypedLongArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Float>): TypedFloatArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Double>): TypedDoubleArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Boolean>): TypedBooleanArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Char>): TypedCharArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<String>): TypedStringArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Int>): IntListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Short>): ShortListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Byte>): ByteListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Long>): LongListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Float>): FloatListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Double>): DoubleListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Boolean>): BooleanListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Char>): CharListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<String>): StringListValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Int>): IntSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Short>): ShortSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Byte>): ByteSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Long>): LongSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Float>): FloatSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Double>): DoubleSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Boolean>): BooleanSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Char>): CharSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<String>): StringSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Int>): MutableIntListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Short>): MutableShortListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Byte>): MutableByteListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Long>): MutableLongListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Float>): MutableFloatListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Double>): MutableDoubleListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Boolean>): MutableBooleanListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Char>): MutableCharListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<String>): MutableStringListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Int>): MutableIntSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Short>): MutableShortSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Byte>): MutableByteSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Long>): MutableLongSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Float>): MutableFloatSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Double>): MutableDoubleSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Boolean>): MutableBooleanSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Char>): MutableCharSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<String>): MutableStringSetValue = valueImpl(default)
|
||||
|
||||
fun <T : Setting> Setting.value(default: T): Value<T> {
|
||||
require(this::class != default::class) {
|
||||
"Recursive nesting is prohibited"
|
||||
}
|
||||
return valueImpl(default).also {
|
||||
if (default is Setting.Inner) {
|
||||
default.attachedValue = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <T : Setting> Setting.value(default: T, crossinline initializer: T.() -> Unit): Value<T> =
|
||||
value(default).also { it.value.apply(initializer) }
|
||||
|
||||
inline fun <reified T : Setting> Setting.value(default: List<T>): SettingListValue<T> = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
inline fun <reified T : Setting> Setting.value(default: MutableList<T>): MutableSettingListValue<T> = valueImpl(default)
|
||||
|
||||
|
||||
inline fun <reified T : Setting> Setting.value(default: Set<T>): SettingSetValue<T> = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
inline fun <reified T : Setting> Setting.value(default: MutableSet<T>): MutableSettingSetValue<T> = valueImpl(default)
|
||||
|
||||
/**
|
||||
* 创建一个只引用对象而不跟踪其属性的值.
|
||||
*
|
||||
* @param T 类型. 必须拥有 [kotlinx.serialization.Serializable] 注解 (因此编译器会自动生成序列化器)
|
||||
*/
|
||||
@DangerousReferenceOnlyValue
|
||||
@JvmName("valueDynamic")
|
||||
@LowPriorityInOverloadResolution
|
||||
inline fun <reified T : Any> Setting.value(default: T): Value<T> = valueImpl(default)
|
||||
|
||||
@RequiresOptIn(
|
||||
"""
|
||||
这种只保存引用的 Value 可能会导致意料之外的结果, 在使用时须保持谨慎.
|
||||
对值的改变不会触发自动保存, 也不会同步到 UI 中. 在 UI 中只能编辑序列化之后的值.
|
||||
""", level = RequiresOptIn.Level.WARNING
|
||||
)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(AnnotationTarget.FUNCTION)
|
||||
annotation class DangerousReferenceOnlyValue
|
||||
|
@ -1,170 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
* !!! This file is auto-generated by backend/codegen/src/main/kotlin/net.mamoe.mirai.console.codegen.ValuesCodegen.kt
|
||||
* !!! for better performance
|
||||
* !!! DO NOT MODIFY THIS FILE MANUALLY
|
||||
*/
|
||||
|
||||
sealed class Value<T : Any> : ReadWriteProperty<Setting, T> {
|
||||
abstract var value: T
|
||||
|
||||
/**
|
||||
* 用于更新 [value] 的序列化器
|
||||
*/
|
||||
abstract val serializer: KSerializer<T>
|
||||
override fun getValue(thisRef: Setting, property: KProperty<*>): T = value
|
||||
override fun setValue(thisRef: Setting, property: KProperty<*>, value: T) {
|
||||
this.value = value
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (other::class != this::class) return false
|
||||
other as Value<*>
|
||||
return other.value == this.value
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = value.hashCode()
|
||||
}
|
||||
|
||||
sealed class PrimitiveValue<T : Any> : Value<T>()
|
||||
|
||||
sealed class NumberValue<T : Number> : Value<T>()
|
||||
abstract class IntValue internal constructor() : NumberValue<Int>()
|
||||
abstract class ShortValue internal constructor() : NumberValue<Short>()
|
||||
abstract class ByteValue internal constructor() : NumberValue<Byte>()
|
||||
abstract class LongValue internal constructor() : NumberValue<Long>()
|
||||
abstract class FloatValue internal constructor() : NumberValue<Float>()
|
||||
abstract class DoubleValue internal constructor() : NumberValue<Double>()
|
||||
|
||||
abstract class BooleanValue internal constructor() : PrimitiveValue<Boolean>()
|
||||
abstract class CharValue internal constructor() : PrimitiveValue<Char>()
|
||||
abstract class StringValue internal constructor() : PrimitiveValue<String>()
|
||||
|
||||
// T can be primitive array or typed Array
|
||||
sealed class ArrayValue<T : Any> : Value<T>()
|
||||
sealed class PrimitiveArrayValue<T : Any> : ArrayValue<T>()
|
||||
|
||||
abstract class IntArrayValue internal constructor() : PrimitiveArrayValue<IntArray>(), Iterable<Int> {
|
||||
override fun iterator(): Iterator<Int> = this.value.iterator()
|
||||
}
|
||||
|
||||
abstract class ShortArrayValue internal constructor() : PrimitiveArrayValue<ShortArray>(), Iterable<Short> {
|
||||
override fun iterator(): Iterator<Short> = this.value.iterator()
|
||||
}
|
||||
|
||||
abstract class ByteArrayValue internal constructor() : PrimitiveArrayValue<ByteArray>(), Iterable<Byte> {
|
||||
override fun iterator(): Iterator<Byte> = this.value.iterator()
|
||||
}
|
||||
|
||||
abstract class LongArrayValue internal constructor() : PrimitiveArrayValue<LongArray>(), Iterable<Long> {
|
||||
override fun iterator(): Iterator<Long> = this.value.iterator()
|
||||
}
|
||||
|
||||
abstract class FloatArrayValue internal constructor() : PrimitiveArrayValue<FloatArray>(), Iterable<Float> {
|
||||
override fun iterator(): Iterator<Float> = this.value.iterator()
|
||||
}
|
||||
|
||||
abstract class DoubleArrayValue internal constructor() : PrimitiveArrayValue<DoubleArray>(), Iterable<Double> {
|
||||
override fun iterator(): Iterator<Double> = this.value.iterator()
|
||||
}
|
||||
|
||||
abstract class BooleanArrayValue internal constructor() : PrimitiveArrayValue<BooleanArray>(), Iterable<Boolean> {
|
||||
override fun iterator(): Iterator<Boolean> = this.value.iterator()
|
||||
}
|
||||
|
||||
abstract class CharArrayValue internal constructor() : PrimitiveArrayValue<CharArray>(), Iterable<Char> {
|
||||
override fun iterator(): Iterator<Char> = this.value.iterator()
|
||||
}
|
||||
|
||||
|
||||
sealed class TypedPrimitiveArrayValue<E> : ArrayValue<Array<E>>(), Iterable<E> {
|
||||
override fun iterator() = this.value.iterator()
|
||||
}
|
||||
|
||||
abstract class TypedIntArrayValue internal constructor() : TypedPrimitiveArrayValue<Int>()
|
||||
abstract class TypedShortArrayValue internal constructor() : TypedPrimitiveArrayValue<Short>()
|
||||
abstract class TypedByteArrayValue internal constructor() : TypedPrimitiveArrayValue<Byte>()
|
||||
abstract class TypedLongArrayValue internal constructor() : TypedPrimitiveArrayValue<Long>()
|
||||
abstract class TypedFloatArrayValue internal constructor() : TypedPrimitiveArrayValue<Float>()
|
||||
abstract class TypedDoubleArrayValue internal constructor() : TypedPrimitiveArrayValue<Double>()
|
||||
abstract class TypedBooleanArrayValue internal constructor() : TypedPrimitiveArrayValue<Boolean>()
|
||||
abstract class TypedCharArrayValue internal constructor() : TypedPrimitiveArrayValue<Char>()
|
||||
abstract class TypedStringArrayValue internal constructor() : TypedPrimitiveArrayValue<String>()
|
||||
|
||||
sealed class ListValue<E> : Value<List<E>>(), List<E>
|
||||
abstract class IntListValue internal constructor() : ListValue<Int>()
|
||||
abstract class ShortListValue internal constructor() : ListValue<Short>()
|
||||
abstract class ByteListValue internal constructor() : ListValue<Byte>()
|
||||
abstract class LongListValue internal constructor() : ListValue<Long>()
|
||||
abstract class FloatListValue internal constructor() : ListValue<Float>()
|
||||
abstract class DoubleListValue internal constructor() : ListValue<Double>()
|
||||
abstract class BooleanListValue internal constructor() : ListValue<Boolean>()
|
||||
abstract class CharListValue internal constructor() : ListValue<Char>()
|
||||
abstract class StringListValue internal constructor() : ListValue<String>()
|
||||
|
||||
abstract class SettingListValue<T : Setting> internal constructor() : Value<List<T>>(), List<T>
|
||||
|
||||
sealed class SetValue<E> : Value<Set<E>>(), Set<E>
|
||||
abstract class IntSetValue internal constructor() : SetValue<Int>()
|
||||
abstract class ShortSetValue internal constructor() : SetValue<Short>()
|
||||
abstract class ByteSetValue internal constructor() : SetValue<Byte>()
|
||||
abstract class LongSetValue internal constructor() : SetValue<Long>()
|
||||
abstract class FloatSetValue internal constructor() : SetValue<Float>()
|
||||
abstract class DoubleSetValue internal constructor() : SetValue<Double>()
|
||||
abstract class BooleanSetValue internal constructor() : SetValue<Boolean>()
|
||||
abstract class CharSetValue internal constructor() : SetValue<Char>()
|
||||
abstract class StringSetValue internal constructor() : SetValue<String>()
|
||||
|
||||
abstract class SettingSetValue<T : Setting> internal constructor() : Value<Set<T>>(), Set<T>
|
||||
|
||||
abstract class SettingValue<T : Setting> internal constructor() : Value<T>()
|
||||
|
||||
abstract class MutableListValue<T : Any> internal constructor() : Value<MutableList<Value<T>>>(), MutableList<T>
|
||||
|
||||
abstract class MutableIntListValue internal constructor() : Value<MutableList<Int>>(), MutableList<Int>
|
||||
abstract class MutableShortListValue internal constructor() : Value<MutableList<Short>>(), MutableList<Short>
|
||||
abstract class MutableByteListValue internal constructor() : Value<MutableList<Byte>>(), MutableList<Byte>
|
||||
abstract class MutableLongListValue internal constructor() : Value<MutableList<Long>>(), MutableList<Long>
|
||||
abstract class MutableFloatListValue internal constructor() : Value<MutableList<Float>>(), MutableList<Float>
|
||||
abstract class MutableDoubleListValue internal constructor() : Value<MutableList<Double>>(), MutableList<Double>
|
||||
abstract class MutableBooleanListValue internal constructor() : Value<MutableList<Boolean>>(), MutableList<Boolean>
|
||||
abstract class MutableCharListValue internal constructor() : Value<MutableList<Char>>(), MutableList<Char>
|
||||
abstract class MutableStringListValue internal constructor() : Value<MutableList<String>>(), MutableList<String>
|
||||
|
||||
abstract class MutableSettingListValue<T : Setting> internal constructor() : Value<MutableList<T>>(), MutableList<T>
|
||||
|
||||
abstract class MutableSetValue<T : Any> internal constructor() : Value<MutableSet<Value<T>>>(), MutableSet<T>
|
||||
|
||||
abstract class MutableIntSetValue internal constructor() : Value<MutableSet<Int>>(), MutableSet<Int>
|
||||
abstract class MutableShortSetValue internal constructor() : Value<MutableSet<Short>>(), MutableSet<Short>
|
||||
abstract class MutableByteSetValue internal constructor() : Value<MutableSet<Byte>>(), MutableSet<Byte>
|
||||
abstract class MutableLongSetValue internal constructor() : Value<MutableSet<Long>>(), MutableSet<Long>
|
||||
abstract class MutableFloatSetValue internal constructor() : Value<MutableSet<Float>>(), MutableSet<Float>
|
||||
abstract class MutableDoubleSetValue internal constructor() : Value<MutableSet<Double>>(), MutableSet<Double>
|
||||
abstract class MutableBooleanSetValue internal constructor() : Value<MutableSet<Boolean>>(), MutableSet<Boolean>
|
||||
abstract class MutableCharSetValue internal constructor() : Value<MutableSet<Char>>(), MutableSet<Char>
|
||||
abstract class MutableStringSetValue internal constructor() : Value<MutableSet<String>>(), MutableSet<String>
|
||||
|
||||
abstract class MutableSettingSetValue<T : Setting> internal constructor() : Value<MutableSet<T>>(), MutableSet<T>
|
||||
|
||||
|
||||
/**
|
||||
* 只引用这个对象, 而不跟踪其成员.
|
||||
* 仅适用于基础类型, 用于 mutable list/map 等情况; 或标注了 [Serializable] 的类.
|
||||
*/
|
||||
abstract class DynamicReferenceValue<T : Any> internal constructor() : Value<T>()
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
|
||||
import kotlinx.coroutines.Job
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.setting.Setting
|
||||
import net.mamoe.mirai.console.setting.Value
|
||||
|
||||
|
||||
internal abstract class ConsoleBuiltInSetting : Setting() {
|
||||
private val track =
|
||||
@Suppress("LeakingThis")
|
||||
MiraiConsole.jvmSettingStorage.trackOn(this)
|
||||
|
||||
init {
|
||||
MiraiConsole.coroutineContext[Job]!!.invokeOnCompletion {
|
||||
track.close()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onElementChanged(value: Value<*>) {
|
||||
TODO()
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -12,140 +12,12 @@ package net.mamoe.mirai.console.setting.internal
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.builtins.ListSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import net.mamoe.mirai.console.setting.SerialName
|
||||
import net.mamoe.mirai.console.setting.Setting
|
||||
import net.mamoe.mirai.console.setting.Value
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import net.mamoe.yamlkt.YamlConfiguration
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
|
||||
internal abstract class SettingImpl {
|
||||
|
||||
@JvmField
|
||||
internal var valueList: MutableList<Pair<Value<*>, Setting.PropertyInfo>> = mutableListOf()
|
||||
|
||||
@JvmField
|
||||
internal var built: Boolean = false
|
||||
|
||||
internal val updaterSerializer: KSerializer<SettingSerializerMark> by lazy {
|
||||
built = true
|
||||
SettingUpdaterSerializer(this as Setting)
|
||||
}
|
||||
|
||||
internal val kotlinSerializer: KSerializer<Setting> by lazy {
|
||||
object : KSerializer<Setting> {
|
||||
override val descriptor: SerialDescriptor
|
||||
get() = this@SettingImpl.updaterSerializer.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): Setting {
|
||||
this@SettingImpl.updaterSerializer.deserialize(decoder)
|
||||
return this@SettingImpl as Setting
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: Setting) {
|
||||
this@SettingImpl.updaterSerializer.serialize(
|
||||
encoder,
|
||||
SettingSerializerMark
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun onElementChanged(value: Value<*>)
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
internal val yamlForToString =
|
||||
Yaml(
|
||||
configuration = YamlConfiguration(
|
||||
nonStrictNullability = true,
|
||||
nonStrictNumber = true,
|
||||
stringSerialization = YamlConfiguration.StringSerialization.NONE,
|
||||
classSerialization = YamlConfiguration.MapSerialization.FLOW_MAP,
|
||||
listSerialization = YamlConfiguration.ListSerialization.FLOW_SEQUENCE
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal class SettingUpdaterSerializer(
|
||||
private val instance: Setting
|
||||
) : KSerializer<SettingSerializerMark> {
|
||||
override val descriptor: SerialDescriptor by lazy {
|
||||
@OptIn(MiraiExperimentalAPI::class)
|
||||
SerialDescriptor(instance.serialName) {
|
||||
for ((value, prop) in instance.valueList) {
|
||||
val (serialName, annotations) = prop
|
||||
element(serialName, value.serializer.descriptor, annotations, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST") // erased, no problem.
|
||||
override fun deserialize(decoder: Decoder): SettingSerializerMark = decoder.decodeStructure(descriptor) {
|
||||
if (this.decodeSequentially()) {
|
||||
instance.valueList.forEachIndexed { index, (value, _) ->
|
||||
val v = value as Value<Any>
|
||||
v.value = this.decodeSerializableElement(
|
||||
value.serializer.descriptor,
|
||||
index,
|
||||
v.serializer
|
||||
)
|
||||
}
|
||||
} else {
|
||||
while (true) {
|
||||
val index = this.decodeElementIndex(descriptor)
|
||||
if (index == CompositeDecoder.READ_DONE) return@decodeStructure SettingSerializerMark
|
||||
val value = instance.valueList[index].first as Value<Any>
|
||||
value.value = this.decodeSerializableElement(
|
||||
descriptor,
|
||||
index,
|
||||
value.serializer
|
||||
)
|
||||
}
|
||||
}
|
||||
SettingSerializerMark
|
||||
}
|
||||
|
||||
private val emptyList = emptyList<String>()
|
||||
private val emptyListSerializer = ListSerializer(String.serializer())
|
||||
|
||||
override fun serialize(encoder: Encoder, value: SettingSerializerMark) {
|
||||
if (instance.valueList.isEmpty()) {
|
||||
emptyListSerializer.serialize(encoder, emptyList)
|
||||
} else encoder.encodeStructure(descriptor) {
|
||||
instance.valueList.forEachIndexed { index, (value, _) ->
|
||||
@Suppress("UNCHECKED_CAST") // erased, no problem.
|
||||
this.encodeElementSmart(descriptor, index, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// until https://github.com/Him188/yamlkt/issues/2 fixed
|
||||
internal fun <T : Any> CompositeEncoder.encodeElementSmart(
|
||||
descriptor: SerialDescriptor,
|
||||
index: Int,
|
||||
value: Value<T>
|
||||
) {
|
||||
when (value.value::class) {
|
||||
String::class -> this.encodeStringElement(descriptor, index, value.value as String)
|
||||
Int::class -> this.encodeIntElement(descriptor, index, value.value as Int)
|
||||
Byte::class -> this.encodeByteElement(descriptor, index, value.value as Byte)
|
||||
Char::class -> this.encodeCharElement(descriptor, index, value.value as Char)
|
||||
Long::class -> this.encodeLongElement(descriptor, index, value.value as Long)
|
||||
Float::class -> this.encodeFloatElement(descriptor, index, value.value as Float)
|
||||
Double::class -> this.encodeDoubleElement(descriptor, index, value.value as Double)
|
||||
Boolean::class -> this.encodeBooleanElement(descriptor, index, value.value as Boolean)
|
||||
else ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
this.encodeSerializableElement(descriptor, index, value.serializer as KSerializer<Any>, value.value)
|
||||
}
|
||||
}
|
||||
|
||||
internal object SettingSerializerMark
|
||||
|
||||
internal val KProperty<*>.serialNameOrPropertyName: String get() = this.findAnnotation<SerialName>()?.value ?: this.name
|
||||
|
@ -1,324 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.builtins.ListSerializer
|
||||
import kotlinx.serialization.builtins.SetSerializer
|
||||
import net.mamoe.mirai.console.setting.*
|
||||
import net.mamoe.yamlkt.YamlDynamicSerializer
|
||||
import kotlin.internal.LowPriorityInOverloadResolution
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.full.createInstance
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/// region MUTABLE LIST
|
||||
|
||||
@PublishedApi
|
||||
@JvmName("valueImplSetting")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal inline fun <reified T : Setting> Setting.valueImpl(
|
||||
default: List<T>
|
||||
): SettingListValue<T> = valueImpl(default, T::class.createInstance().serializer)
|
||||
|
||||
@PublishedApi
|
||||
@JvmName("valueImplSettingMutable")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal inline fun <reified T : Setting> Setting.valueImpl(
|
||||
default: MutableList<T>
|
||||
): MutableSettingListValue<T> = valueImpl(default, T::class.createInstance().serializer)
|
||||
|
||||
|
||||
/*
|
||||
@PublishedApi
|
||||
@JvmName("valueImpl1")
|
||||
internal fun <T : Any> Setting.valueImpl(
|
||||
default: MutableList<T>,
|
||||
valueMapper: (T) -> Value<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): MutableListValue<T> = valueImpl(default.mapTo(mutableListOf(), valueMapper), valueMapper, elementSerializer)
|
||||
*/
|
||||
internal fun <T : Any> Setting.valueImpl(
|
||||
default: MutableList<Value<T>>,
|
||||
valueMapper: (T) -> Value<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): MutableListValue<T> {
|
||||
var internalValue: MutableList<Value<T>> = default
|
||||
|
||||
fun updateShadow(): MutableList<T> =
|
||||
internalValue.shadowMap(transform = { it.value }, transformBack = { valueMapper(it) })
|
||||
|
||||
var shadowed: MutableList<T> = updateShadow()
|
||||
|
||||
|
||||
val delegt = dynamicMutableList { shadowed }
|
||||
return object : MutableListValue<T>(), MutableList<T> by delegt {
|
||||
override var value: MutableList<Value<T>>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
shadowed = updateShadow()
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer: KSerializer<MutableList<Value<T>>> = object : KSerializer<MutableList<Value<T>>> {
|
||||
private val delegate = ListSerializer(elementSerializer)
|
||||
override val descriptor: SerialDescriptor = delegate.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): MutableList<Value<T>> {
|
||||
return delegate.deserialize(decoder).mapTo(mutableListOf(), valueMapper)
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: MutableList<Value<T>>) {
|
||||
delegate.serialize(encoder, value.map { it.value })
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T : Setting> Setting.valueImpl(
|
||||
default: MutableList<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): MutableSettingListValue<T> {
|
||||
var internalValue: MutableList<T> = default
|
||||
|
||||
val delegt = dynamicMutableList { internalValue }
|
||||
return object : MutableSettingListValue<T>(), MutableList<T> by delegt {
|
||||
override var value: MutableList<T>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer: KSerializer<MutableList<T>> = object : KSerializer<MutableList<T>> {
|
||||
private val delegate = ListSerializer(elementSerializer)
|
||||
override val descriptor: SerialDescriptor = delegate.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): MutableList<T> {
|
||||
return delegate.deserialize(decoder).toMutableList() // TODO: 2020/5/17 ATTACH OBSERVER
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: MutableList<T>) {
|
||||
delegate.serialize(encoder, value)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T : Setting> Setting.valueImpl(
|
||||
default: List<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): SettingListValue<T> {
|
||||
var internalValue: List<T> = default
|
||||
|
||||
val delegt = dynamicList { internalValue }
|
||||
return object : SettingListValue<T>(), List<T> by delegt {
|
||||
override var value: List<T>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer: KSerializer<List<T>> = object : KSerializer<List<T>> {
|
||||
private val delegate = ListSerializer(elementSerializer)
|
||||
override val descriptor: SerialDescriptor = delegate.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): List<T> {
|
||||
return delegate.deserialize(decoder) // TODO: 2020/5/17 ATTACH OBSERVER
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: List<T>) {
|
||||
delegate.serialize(encoder, value)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T : Setting> Setting.valueImpl(
|
||||
default: Set<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): SettingSetValue<T> {
|
||||
var internalValue: Set<T> = default
|
||||
|
||||
val delegt = dynamicSet { internalValue }
|
||||
return object : SettingSetValue<T>(), Set<T> by delegt {
|
||||
override var value: Set<T>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer: KSerializer<Set<T>> = object : KSerializer<Set<T>> {
|
||||
private val delegate = SetSerializer(elementSerializer)
|
||||
override val descriptor: SerialDescriptor = delegate.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): Set<T> {
|
||||
return delegate.deserialize(decoder) // TODO: 2020/5/17 ATTACH OBSERVER
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: Set<T>) {
|
||||
delegate.serialize(encoder, value)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T : Setting> Setting.valueImpl(
|
||||
default: MutableSet<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): MutableSettingSetValue<T> {
|
||||
var internalValue: MutableSet<T> = default
|
||||
|
||||
val delegt = dynamicMutableSet { internalValue }
|
||||
return object : MutableSettingSetValue<T>(), MutableSet<T> by delegt {
|
||||
override var value: MutableSet<T>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer: KSerializer<MutableSet<T>> = object : KSerializer<MutableSet<T>> {
|
||||
private val delegate = SetSerializer(elementSerializer)
|
||||
override val descriptor: SerialDescriptor = delegate.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): MutableSet<T> {
|
||||
return delegate.deserialize(decoder).toMutableSet() // TODO: 2020/5/17 ATTACH OBSERVER
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: MutableSet<T>) {
|
||||
delegate.serialize(encoder, value)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
// region MUTABLE SET
|
||||
|
||||
@PublishedApi
|
||||
@JvmName("valueImplSetting")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal inline fun <reified T : Setting> Setting.valueImpl(
|
||||
default: Set<T>
|
||||
): SettingSetValue<T> = valueImpl(default, T::class.createInstance().serializer)
|
||||
|
||||
@PublishedApi
|
||||
@JvmName("valueImplSettingMutable")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal inline fun <reified T : Setting> Setting.valueImpl(
|
||||
default: MutableSet<T>
|
||||
): MutableSettingSetValue<T> = valueImpl(default, T::class.createInstance().serializer)
|
||||
|
||||
/*
|
||||
@JvmName("valueImpl1")
|
||||
@PublishedApi
|
||||
internal fun <T : Any> Setting.valueImpl(
|
||||
default: MutableSet<T>,
|
||||
valueMapper: (T) -> Value<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): MutableSetValue<T> = valueImpl(default.mapTo(mutableSetOf(), valueMapper), valueMapper, elementSerializer)
|
||||
*/
|
||||
@JvmName("valueImplMutable")
|
||||
internal fun <T : Any> Setting.valueImpl(
|
||||
default: MutableSet<Value<T>>,
|
||||
valueMapper: (T) -> Value<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): MutableSetValue<T> {
|
||||
var internalValue: MutableSet<Value<T>> = default
|
||||
|
||||
fun updateShadow(): MutableSet<T> =
|
||||
internalValue.shadowMap(transform = { it.value }, transformBack = { valueMapper(it) })
|
||||
|
||||
var shadowed: MutableSet<T> = updateShadow()
|
||||
|
||||
val delegt = dynamicMutableSet { shadowed }
|
||||
return object : MutableSetValue<T>(), MutableSet<T> by delegt {
|
||||
override var value: MutableSet<Value<T>>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
shadowed = updateShadow()
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer: KSerializer<MutableSet<Value<T>>> = object : KSerializer<MutableSet<Value<T>>> {
|
||||
private val delegate = SetSerializer(elementSerializer)
|
||||
override val descriptor: SerialDescriptor = delegate.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): MutableSet<Value<T>> {
|
||||
return delegate.deserialize(decoder).mapTo(mutableSetOf(), valueMapper)
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: MutableSet<Value<T>>) {
|
||||
delegate.serialize(encoder, value.mapTo(mutableSetOf()) { it.value })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region DYNAMIC PRIMITIVES AND SERIALIZABLE
|
||||
|
||||
/**
|
||||
* For primitives and serializable only
|
||||
*/
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
@PublishedApi
|
||||
@LowPriorityInOverloadResolution
|
||||
internal inline fun <reified T : Any> Setting.valueImpl(default: T): Value<T> =
|
||||
valueImpl(default, T::class)
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T : Any> Setting.valueImpl(default: T, clazz: KClass<out T>): Value<T> {
|
||||
if (default is Setting) @Suppress("UNCHECKED_CAST") return valueImpl(default as Setting) as Value<T>
|
||||
|
||||
@OptIn(ImplicitReflectionSerializer::class)
|
||||
requireNotNull(clazz.serializerOrNull()) {
|
||||
"${clazz.qualifiedName} is not serializable"
|
||||
}
|
||||
return object : DynamicReferenceValue<T>() {
|
||||
override var value: T = default
|
||||
override val serializer: KSerializer<T> = object : KSerializer<T> {
|
||||
override val descriptor: SerialDescriptor
|
||||
get() = YamlDynamicSerializer.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): T =
|
||||
YamlDynamicSerializer.deserialize(decoder).smartCastPrimitive(clazz)
|
||||
|
||||
override fun serialize(encoder: Encoder, value: T) = YamlDynamicSerializer.serialize(encoder, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
@ -10,17 +10,8 @@
|
||||
|
||||
package net.mamoe.mirai.console.utils
|
||||
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.setting.Value
|
||||
import net.mamoe.mirai.console.setting.internal.ConsoleBuiltInSetting
|
||||
import net.mamoe.mirai.console.setting.value
|
||||
import net.mamoe.mirai.contact.User
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.locks.Condition
|
||||
import java.util.concurrent.locks.Lock
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
|
||||
|
||||
/**
|
||||
|
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin
|
||||
import net.mamoe.mirai.console.setting.value
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
||||
val plugin = MyPlugin()
|
||||
|
||||
class MyPlugin : KotlinPlugin() {
|
||||
|
||||
inner class MySetting : PluginSetting() {
|
||||
val int by value(1)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
internal object TestCommand : PluginCommand(
|
||||
plugin,
|
||||
CommandDescriptor("test") {
|
||||
param<String>()
|
||||
}
|
||||
) {
|
||||
override suspend fun CommandSender.onCommand(args: CommandArgs): Boolean {
|
||||
val s = args.getReified<String>()
|
||||
sendMessage(s)
|
||||
return true
|
||||
}
|
||||
}*/
|
||||
|
||||
internal class TestCommands {
|
||||
@Test
|
||||
fun testFlatten() {
|
||||
assertEquals(listOf("test", "v1"), "test v1".flattenCommandComponents().toList())
|
||||
assertEquals(listOf("test", "v1"), PlainText("test v1").flattenCommandComponents().toList())
|
||||
assertEquals(listOf("test", "v1"), arrayOf("test ", "v1", " ").flattenCommandComponents().toList())
|
||||
assertEquals(
|
||||
listOf("test", "v1"),
|
||||
messageChainOf("test v1".toMessage(), " ".toMessage()).flattenCommandComponents().toList()
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
@Test
|
||||
fun testRegister() {
|
||||
assertTrue(TestCommand.register())
|
||||
assertEquals(listOf("test"), TestCommand.allNames.single().toList())
|
||||
|
||||
assertFalse(TestCommand.register())
|
||||
assertFalse(
|
||||
object : PluginCommand(
|
||||
plugin,
|
||||
CommandDescriptor("test") {
|
||||
param<String>()
|
||||
}
|
||||
) {
|
||||
override suspend fun CommandSender.onCommand(args: CommandArgs): Boolean {
|
||||
val s = args.getReified<String>()
|
||||
sendMessage(s)
|
||||
return true
|
||||
}
|
||||
}.register()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testExecute() = runBlocking {
|
||||
TestCommand.register()
|
||||
assertEquals(
|
||||
"ok",
|
||||
withSender {
|
||||
execute("test", "arg")
|
||||
}.contentToString()
|
||||
)
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
internal inline fun withSender(block: CommandSender.() -> Unit): MessageChain {
|
||||
val result = MessageChainBuilder()
|
||||
val sender: CommandSender = object : CommandSender {
|
||||
override val bot: Bot?
|
||||
get() = null
|
||||
|
||||
override suspend fun sendMessage(message: Message) {
|
||||
result.add(message)
|
||||
}
|
||||
|
||||
}
|
||||
sender.let(block)
|
||||
return result.asMessageChain()
|
||||
}
|
@ -9,15 +9,19 @@
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
object TestCompositeCommand : CompositeCommand(
|
||||
TestCommandOwner,
|
||||
"name1", "name2",
|
||||
description = """
|
||||
desc
|
||||
""".trimIndent()
|
||||
)
|
||||
"groupManagement", "grpMgn"
|
||||
) {
|
||||
@SubCommand
|
||||
suspend fun CommandSender.mute(image: Image, target: Member, seconds: Int) {
|
||||
target.mute(seconds)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class TestComposite {
|
||||
|
Loading…
Reference in New Issue
Block a user