mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-10 18:40:15 +08:00
API stabilization for PluginData:
Enforce explicit saveName on init
This commit is contained in:
parent
2fe2d2a681
commit
da68027b7c
@ -24,6 +24,11 @@ import kotlin.reflect.KProperty
|
||||
* @see PluginData
|
||||
*/
|
||||
public abstract class AbstractPluginData : PluginData, PluginDataImpl() {
|
||||
/**
|
||||
* 这个 [PluginData] 保存时使用的名称.
|
||||
*/
|
||||
public abstract override val saveName: String
|
||||
|
||||
/**
|
||||
* 添加了追踪的 [ValueNode] 列表, 即通过 `by value` 初始化的属性列表.
|
||||
*
|
||||
@ -32,7 +37,7 @@ public abstract class AbstractPluginData : PluginData, PluginDataImpl() {
|
||||
* @see provideDelegate
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public override val valueNodes: MutableList<ValueNode<*>> = mutableListOf()
|
||||
public val valueNodes: MutableList<ValueNode<*>> = mutableListOf()
|
||||
|
||||
/**
|
||||
* 供手动实现时值跟踪使用 (如 Java 用户). 一般 Kotlin 用户需使用 [provideDelegate]
|
||||
@ -61,7 +66,7 @@ public abstract class AbstractPluginData : PluginData, PluginDataImpl() {
|
||||
): T = track(this, property.valueName, property.getAnnotationListForValueSerialization())
|
||||
|
||||
/**
|
||||
* 所有 [valueNodes] 更新和保存序列化器. 仅供内部使用
|
||||
* 所有 [valueNodes] 更新和保存序列化器.
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public final override val updaterSerializer: KSerializer<Unit>
|
||||
|
@ -23,4 +23,10 @@ import kotlinx.coroutines.Job
|
||||
* @see PluginConfig
|
||||
* @see AutoSavePluginData
|
||||
*/
|
||||
public open class AutoSavePluginConfig : AutoSavePluginData(), PluginConfig
|
||||
public open class AutoSavePluginConfig : AutoSavePluginData, PluginConfig {
|
||||
@Deprecated("请手动指定保存名称. 此构造器将在 1.0.0 删除", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("AutoSavePluginConfig(\"改成保存的名称\")"))
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
public constructor() : super()
|
||||
|
||||
public constructor(saveName: String) : super(saveName)
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip
|
||||
import net.mamoe.mirai.console.internal.plugin.updateWhen
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import net.mamoe.mirai.utils.*
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
|
||||
/**
|
||||
* 链接自动保存的 [PluginData].
|
||||
@ -35,8 +36,22 @@ public open class AutoSavePluginData private constructor(
|
||||
private val autoSaveIntervalMillis_: LongRange get() = owner_.autoSaveIntervalMillis
|
||||
private lateinit var storage_: PluginDataStorage
|
||||
|
||||
public constructor() : this(null)
|
||||
public final override val saveName: String
|
||||
get() = _saveName
|
||||
|
||||
private lateinit var _saveName: String
|
||||
|
||||
public constructor(saveName: String) : this(null) {
|
||||
_saveName = saveName
|
||||
}
|
||||
|
||||
@Deprecated("请手动指定保存名称. 此构造器将在 1.0.0 删除", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("AutoSavePluginConfig"))
|
||||
public constructor() : this(null) {
|
||||
val clazz = this::class
|
||||
_saveName = clazz.findAnnotation<ValueName>()?.value
|
||||
?: clazz.qualifiedName
|
||||
?: throw IllegalArgumentException("Cannot find a serial name for ${this::class}")
|
||||
}
|
||||
|
||||
@ConsoleExperimentalApi
|
||||
override fun onInit(owner: PluginDataHolder, storage: PluginDataStorage) {
|
||||
|
@ -32,12 +32,11 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import kotlin.internal.LowPriorityInOverloadResolution
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
|
||||
/**
|
||||
* 一个插件内部的, 对用户隐藏的数据对象. 可包含对多个 [Value] 的值变更的跟踪.
|
||||
* 一个插件内部的, 对用户隐藏的数据对象. 可包含对多个 [Value] 的值变更的跟踪. 典型的实现为 [AbstractPluginData].
|
||||
*
|
||||
* [PluginData] 不涉及有关数据的存储, 而是只维护数据结构: [属性节点列表][valueNodes].
|
||||
* [AbstractPluginData] 不涉及有关数据的存储, 而是只维护数据结构: [属性节点列表][AbstractPluginData.valueNodes].
|
||||
*
|
||||
* 有关存储方案, 请查看 [PluginDataStorage].
|
||||
*
|
||||
@ -74,7 +73,7 @@ import kotlin.reflect.full.findAnnotation
|
||||
* val theList: MutableList<String> = AccountPluginData.list
|
||||
* ```
|
||||
*
|
||||
* 但也注意, 不要存储 `AccountPluginData.list`. 它可能受不到值跟踪. 若必要存储, 请使用 [PluginData.findBackingFieldValue]
|
||||
* 但也注意, 不要存储 `AccountPluginData.list`. 它可能受不到值跟踪. 若必要存储, 请使用 [AbstractPluginData.findBackingFieldValue]
|
||||
*
|
||||
* ### 使用 Java
|
||||
*
|
||||
@ -110,22 +109,17 @@ import kotlin.reflect.full.findAnnotation
|
||||
*/
|
||||
public interface PluginData {
|
||||
/**
|
||||
* 这个 [PluginData] 保存时使用的名称. 默认通过 [ValueName] 获取, 否则使用 [类全名][KClass.qualifiedName] (即 [Class.getCanonicalName])
|
||||
* 这个 [PluginData] 保存时使用的名称.
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public val saveName: String
|
||||
get() {
|
||||
val clazz = this::class
|
||||
return clazz.findAnnotation<ValueName>()?.value
|
||||
?: clazz.qualifiedName
|
||||
?: throw IllegalArgumentException("Cannot find a serial name for ${this::class}")
|
||||
}
|
||||
|
||||
@ConsoleExperimentalApi
|
||||
public val updaterSerializer: KSerializer<Unit>
|
||||
|
||||
/**
|
||||
* 当所属于这个 [PluginData] 的 [Value] 的 [值][Value.value] 被修改时被调用.
|
||||
* 调用者为 [Value] 的实现.
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public fun onValueChanged(value: Value<*>)
|
||||
@ -202,7 +196,7 @@ public fun PluginData.value(default: String): SerializerAwareValue<String> = val
|
||||
@LowPriorityInOverloadResolution
|
||||
public inline fun <reified T> PluginData.value(
|
||||
default: T,
|
||||
crossinline apply: T.() -> Unit = {}
|
||||
crossinline apply: T.() -> Unit = {},
|
||||
): SerializerAwareValue<T> =
|
||||
valueFromKType(typeOf0<T>(), default).also { it.value.apply() }
|
||||
|
||||
|
@ -37,4 +37,10 @@ import net.mamoe.mirai.console.data.PluginData
|
||||
* @see JAutoSavePluginData
|
||||
* @see PluginConfig
|
||||
*/
|
||||
public abstract class JAutoSavePluginConfig : AutoSavePluginConfig(), PluginConfig
|
||||
public abstract class JAutoSavePluginConfig : AutoSavePluginConfig, PluginConfig {
|
||||
@Deprecated("请手动指定保存名称. 此构造器将在 1.0.0 删除", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("AutoSavePluginConfig(\"改成保存的名称\")"))
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
public constructor() : super()
|
||||
|
||||
public constructor(saveName: String) : super(saveName)
|
||||
}
|
||||
|
@ -66,7 +66,13 @@ import kotlin.reflect.full.createType
|
||||
*
|
||||
* @see PluginData
|
||||
*/
|
||||
public abstract class JAutoSavePluginData : AutoSavePluginData(), PluginConfig {
|
||||
public abstract class JAutoSavePluginData : AutoSavePluginData, PluginConfig {
|
||||
@Deprecated("请手动指定保存名称. 此构造器将在 1.0.0 删除", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("AutoSavePluginConfig(\"改成保存的名称\")"))
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
public constructor() : super()
|
||||
|
||||
public constructor(saveName: String) : super(saveName)
|
||||
|
||||
//// region JPluginData_value_primitives CODEGEN ////
|
||||
|
||||
/**
|
||||
|
@ -18,9 +18,9 @@ import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.CompositeDecoder
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
import net.mamoe.mirai.console.data.AbstractPluginData
|
||||
import net.mamoe.mirai.console.data.AbstractPluginData.ValueNode
|
||||
import net.mamoe.mirai.console.data.PluginData
|
||||
import net.mamoe.mirai.console.data.Value
|
||||
import net.mamoe.mirai.console.data.ValueDescription
|
||||
import net.mamoe.mirai.console.data.ValueName
|
||||
import net.mamoe.yamlkt.Comment
|
||||
@ -34,12 +34,25 @@ import kotlin.reflect.KAnnotatedElement
|
||||
* - Auto-saving
|
||||
*/
|
||||
internal abstract class PluginDataImpl {
|
||||
internal fun findNodeInstance(name: String): ValueNode<*>? = valueNodes.firstOrNull { it.valueName == name }
|
||||
init {
|
||||
@Suppress("LeakingThis")
|
||||
check(this is AbstractPluginData)
|
||||
}
|
||||
|
||||
internal abstract val valueNodes: MutableList<ValueNode<*>>
|
||||
private fun findNodeInstance(name: String): ValueNode<*>? {
|
||||
check(this is AbstractPluginData)
|
||||
return valueNodes.firstOrNull { it.valueName == name }
|
||||
}
|
||||
|
||||
internal open val updaterSerializer: KSerializer<Unit> = object : KSerializer<Unit> {
|
||||
override val descriptor: SerialDescriptor get() = dataUpdaterSerializerDescriptor
|
||||
override val descriptor: SerialDescriptor by lazy {
|
||||
check(this@PluginDataImpl is AbstractPluginData)
|
||||
kotlinx.serialization.descriptors.buildClassSerialDescriptor((this@PluginDataImpl as PluginData).saveName) {
|
||||
for (valueNode in valueNodes) valueNode.run {
|
||||
element(valueName, updaterSerializer.descriptor, annotations = annotations, isOptional = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun deserialize(decoder: Decoder) {
|
||||
@ -84,6 +97,8 @@ internal abstract class PluginDataImpl {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun serialize(encoder: Encoder, value: Unit) {
|
||||
check(this@PluginDataImpl is AbstractPluginData)
|
||||
|
||||
val descriptor = descriptor
|
||||
with(encoder.beginStructure(descriptor)) {
|
||||
repeat(descriptor.elementsCount) { index ->
|
||||
@ -100,18 +115,6 @@ internal abstract class PluginDataImpl {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* flatten
|
||||
*/
|
||||
abstract fun onValueChanged(value: Value<*>)
|
||||
private val dataUpdaterSerializerDescriptor by lazy {
|
||||
kotlinx.serialization.descriptors.buildClassSerialDescriptor((this as PluginData).saveName) {
|
||||
for (valueNode in valueNodes) valueNode.run {
|
||||
element(valueName, updaterSerializer.descriptor, annotations = annotations, isOptional = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun KAnnotatedElement.getAnnotationListForValueSerialization(): List<Annotation> {
|
||||
|
@ -6,10 +6,7 @@ import net.mamoe.mirai.console.data.value
|
||||
import net.mamoe.mirai.console.internal.util.md5
|
||||
import net.mamoe.mirai.console.internal.util.toUHexString
|
||||
|
||||
internal object AutoLoginConfig : AutoSavePluginConfig() {
|
||||
override val saveName: String
|
||||
get() = "AutoLogin"
|
||||
|
||||
internal object AutoLoginConfig : AutoSavePluginConfig("AutoLogin") {
|
||||
@ValueDescription(
|
||||
"""
|
||||
账号和明文密码列表
|
||||
|
@ -16,9 +16,7 @@ internal object BuiltInSingletonExtensionSelector : SingletonExtensionSelector {
|
||||
|
||||
internal val config: SaveData = SaveData()
|
||||
|
||||
internal class SaveData : AutoSavePluginConfig() {
|
||||
override val saveName: String get() = "ExtensionSelector"
|
||||
|
||||
internal class SaveData : AutoSavePluginConfig("ExtensionSelector") {
|
||||
val value: MutableMap<String, String> by value()
|
||||
}
|
||||
|
||||
|
@ -117,12 +117,12 @@ internal object BuiltInPermissionService : AbstractConcurrentPermissionService<P
|
||||
|
||||
@Suppress("RedundantVisibilityModifier")
|
||||
internal class ConcurrentSaveData private constructor(
|
||||
public override val saveName: String,
|
||||
saveName: String,
|
||||
@Suppress("UNUSED_PARAMETER") primaryConstructorMark: Any?,
|
||||
) : AutoSavePluginConfig() {
|
||||
) : AutoSavePluginConfig(saveName) {
|
||||
public val grantedPermissionMap: PluginDataExtensions.NotNullMutableMap<PermissionId, MutableSet<AbstractPermitteeId>>
|
||||
by value<MutableMap<PermissionId, MutableSet<AbstractPermitteeId>>>(ConcurrentHashMap())
|
||||
.withDefault { CopyOnWriteArraySet() }
|
||||
by value<MutableMap<PermissionId, MutableSet<AbstractPermitteeId>>>(ConcurrentHashMap())
|
||||
.withDefault { CopyOnWriteArraySet() }
|
||||
|
||||
public companion object {
|
||||
@JvmStatic
|
||||
|
@ -17,7 +17,7 @@ import kotlin.test.assertSame
|
||||
|
||||
@OptIn(ConsoleInternalApi::class)
|
||||
internal class PluginDataTest {
|
||||
class MyPluginData : AutoSavePluginData() {
|
||||
class MyPluginData : AutoSavePluginData("test") {
|
||||
var int by value(1)
|
||||
val map: MutableMap<String, String> by value()
|
||||
val map2: MutableMap<String, MutableMap<String, String>> by value()
|
||||
|
Loading…
Reference in New Issue
Block a user