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