mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-10 18:40:15 +08:00
API stabilization for PluginData:
Move members valueNodes, ValueNode, track from PluginData to AbstractPluginData; Move findBackingFieldValue, findBackingFieldValueNode from PluginData.kt to AbstractPluginData.kt; Mark unstable APIs with `@ConsoleExperimentalApi`
This commit is contained in:
parent
53890bcb5d
commit
2fe2d2a681
@ -12,10 +12,10 @@
|
||||
package net.mamoe.mirai.console.data
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import net.mamoe.mirai.console.data.PluginData.ValueNode
|
||||
import net.mamoe.mirai.console.internal.data.PluginDataImpl
|
||||
import net.mamoe.mirai.console.internal.data.getAnnotationListForValueSerialization
|
||||
import net.mamoe.mirai.console.internal.data.valueName
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
@ -31,13 +31,26 @@ public abstract class AbstractPluginData : PluginData, PluginDataImpl() {
|
||||
*
|
||||
* @see provideDelegate
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public override val valueNodes: MutableList<ValueNode<*>> = mutableListOf()
|
||||
|
||||
/**
|
||||
* 供手动实现时值跟踪使用 (如 Java 用户). 一般 Kotlin 用户需使用 [provideDelegate]
|
||||
*/
|
||||
public override fun <T : SerializerAwareValue<*>> T.track(valueName: String, annotations: List<Annotation>): T =
|
||||
apply { valueNodes.add(ValueNode(valueName, this, annotations, this.serializer)) }
|
||||
@ConsoleExperimentalApi
|
||||
public fun <T : SerializerAwareValue<*>> track(
|
||||
value: T,
|
||||
/**
|
||||
* 值名称.
|
||||
*
|
||||
* 如果属性带有 [ValueName], 则使用 [ValueName.value],
|
||||
* 否则使用 [属性名称][KProperty.name]
|
||||
*
|
||||
* @see [ValueNode.value]
|
||||
*/
|
||||
valueName: String,
|
||||
annotations: List<Annotation>,
|
||||
): T = value.apply { this@AbstractPluginData.valueNodes.add(ValueNode(valueName, this, annotations, this.serializer)) }
|
||||
|
||||
/**
|
||||
* 使用 `by value()` 时自动调用此方法, 添加对 [Value] 的值修改的跟踪, 并创建 [ValueNode] 加入 [valueNodes]
|
||||
@ -45,17 +58,19 @@ public abstract class AbstractPluginData : PluginData, PluginDataImpl() {
|
||||
public operator fun <T : SerializerAwareValue<*>> T.provideDelegate(
|
||||
thisRef: Any?,
|
||||
property: KProperty<*>,
|
||||
): T = track(property.valueName, property.getAnnotationListForValueSerialization())
|
||||
): T = track(this, property.valueName, property.getAnnotationListForValueSerialization())
|
||||
|
||||
/**
|
||||
* 所有 [valueNodes] 更新和保存序列化器. 仅供内部使用
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public final override val updaterSerializer: KSerializer<Unit>
|
||||
get() = super.updaterSerializer
|
||||
|
||||
/**
|
||||
* 当所属于这个 [PluginData] 的 [Value] 的 [值][Value.value] 被修改时被调用.
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public override fun onValueChanged(value: Value<*>) {
|
||||
// no-op by default
|
||||
}
|
||||
@ -63,7 +78,95 @@ public abstract class AbstractPluginData : PluginData, PluginDataImpl() {
|
||||
/**
|
||||
* 当这个 [PluginData] 被放入一个 [PluginDataStorage] 时调用
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public override fun onInit(owner: PluginDataHolder, storage: PluginDataStorage) {
|
||||
// no-op by default
|
||||
}
|
||||
|
||||
/**
|
||||
* 由 [track] 创建, 来自一个通过 `by value` 初始化的属性节点.
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public data class ValueNode<T>(
|
||||
/**
|
||||
* 节点名称.
|
||||
*
|
||||
* 如果属性带有 [ValueName], 则使用 [ValueName.value],
|
||||
* 否则使用 [属性名称][KProperty.name]
|
||||
*/
|
||||
val valueName: String,
|
||||
/**
|
||||
* 属性值代理
|
||||
*/
|
||||
val value: Value<out T>,
|
||||
/**
|
||||
* 注解列表
|
||||
*/
|
||||
val annotations: List<Annotation>,
|
||||
/**
|
||||
* 属性值更新器
|
||||
*/
|
||||
val updaterSerializer: KSerializer<Unit>,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取这个 [KProperty] 委托的 [Value]
|
||||
*
|
||||
* 示例:
|
||||
* ```
|
||||
* object MyData : AutoSavePluginData(PluginMain) {
|
||||
* val list: List<String> by value()
|
||||
* }
|
||||
*
|
||||
* val value: Value<List<String>> = MyData.findBackingFieldValue(MyData::list)
|
||||
* ```
|
||||
*
|
||||
* @see PluginData
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public fun <T> AbstractPluginData.findBackingFieldValue(property: KProperty<T>): Value<out T>? =
|
||||
findBackingFieldValue(property.valueName)
|
||||
|
||||
/**
|
||||
* 获取这个 [KProperty] 委托的 [Value]
|
||||
*
|
||||
* 示例:
|
||||
* ```
|
||||
* object MyData : AutoSavePluginData(PluginMain) {
|
||||
* @ValueName("theList")
|
||||
* val list: List<String> by value()
|
||||
* val int: Int by value()
|
||||
* }
|
||||
*
|
||||
* val value: Value<List<String>> = MyData.findBackingFieldValue("theList") // 需使用 @ValueName 标注的名称
|
||||
* val intValue: Value<Int> = MyData.findBackingFieldValue("int")
|
||||
* ```
|
||||
*
|
||||
* @see PluginData
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public fun <T> AbstractPluginData.findBackingFieldValue(propertyValueName: String): Value<out T>? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return this.valueNodes.find { it.valueName == propertyValueName }?.value as Value<out T>
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取这个 [KProperty] 委托的 [Value]
|
||||
*
|
||||
* 示例:
|
||||
* ```
|
||||
* object MyData : AutoSavePluginData(PluginMain) {
|
||||
* val list: List<String> by value()
|
||||
* }
|
||||
*
|
||||
* val value: PluginData.ValueNode<List<String>> = MyData.findBackingFieldValueNode(MyData::list)
|
||||
* ```
|
||||
*
|
||||
* @see PluginData
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public fun <T> AbstractPluginData.findBackingFieldValueNode(property: KProperty<T>): AbstractPluginData.ValueNode<out T>? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return this.valueNodes.find { it == property } as AbstractPluginData.ValueNode<out T>?
|
||||
}
|
@ -121,6 +121,7 @@ public open class AutoSavePluginData private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
@ConsoleExperimentalApi
|
||||
public final override fun onValueChanged(value: Value<*>) {
|
||||
debuggingLogger1.error { "onValueChanged: $value" }
|
||||
if (::owner_.isInitialized) {
|
||||
|
@ -21,14 +21,16 @@ import kotlinx.serialization.KSerializer
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.RESTRICTED_NO_ARG_CONSTRUCTOR
|
||||
import net.mamoe.mirai.console.data.java.JAutoSavePluginData
|
||||
import net.mamoe.mirai.console.internal.data.*
|
||||
import net.mamoe.mirai.console.internal.data.createInstanceSmart
|
||||
import net.mamoe.mirai.console.internal.data.typeOf0
|
||||
import net.mamoe.mirai.console.internal.data.valueFromKTypeImpl
|
||||
import net.mamoe.mirai.console.internal.data.valueImpl
|
||||
import net.mamoe.mirai.console.plugin.jvm.AbstractJvmPlugin
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
|
||||
import net.mamoe.mirai.console.plugin.jvm.reloadPluginData
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import kotlin.internal.LowPriorityInOverloadResolution
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
|
||||
@ -107,16 +109,6 @@ import kotlin.reflect.full.findAnnotation
|
||||
* @see PluginDataExtensions 相关 [SerializerAwareValue] 映射函数
|
||||
*/
|
||||
public interface PluginData {
|
||||
/**
|
||||
* 添加了追踪的 [ValueNode] 列表 (即使用 `by value()` 委托的属性), 即通过 `by value` 初始化的属性列表.
|
||||
*
|
||||
* 他们的修改会被跟踪, 并触发 [onValueChanged].
|
||||
*
|
||||
* @see provideDelegate
|
||||
* @see track
|
||||
*/
|
||||
public val valueNodes: MutableList<ValueNode<*>>
|
||||
|
||||
/**
|
||||
* 这个 [PluginData] 保存时使用的名称. 默认通过 [ValueName] 获取, 否则使用 [类全名][KClass.qualifiedName] (即 [Class.getCanonicalName])
|
||||
*/
|
||||
@ -129,56 +121,13 @@ public interface PluginData {
|
||||
?: throw IllegalArgumentException("Cannot find a serial name for ${this::class}")
|
||||
}
|
||||
|
||||
/**
|
||||
* 由 [provideDelegate] 创建, 来自一个通过 `by value` 初始化的属性节点.
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public data class ValueNode<T>(
|
||||
/**
|
||||
* 节点名称.
|
||||
*
|
||||
* 如果属性带有 [ValueName], 则使用 [ValueName.value],
|
||||
* 否则使用 [属性名称][KProperty.name]
|
||||
*/
|
||||
val valueName: String,
|
||||
/**
|
||||
* 属性值代理
|
||||
*/
|
||||
val value: Value<out T>,
|
||||
/**
|
||||
* 注解列表
|
||||
*/
|
||||
val annotations: List<Annotation>,
|
||||
/**
|
||||
* 属性值更新器
|
||||
*/
|
||||
val updaterSerializer: KSerializer<Unit>
|
||||
)
|
||||
|
||||
/**
|
||||
* 供手动实现时值跟踪使用 (如 Java 用户). 一般 Kotlin 用户需使用 [provideDelegate]
|
||||
*/
|
||||
public fun <T : SerializerAwareValue<*>> T.track(
|
||||
/**
|
||||
* 值名称.
|
||||
*
|
||||
* 如果属性带有 [ValueName], 则使用 [ValueName.value],
|
||||
* 否则使用 [属性名称][KProperty.name]
|
||||
*
|
||||
* @see [ValueNode.value]
|
||||
*/
|
||||
valueName: String,
|
||||
annotations: List<Annotation>
|
||||
): T
|
||||
|
||||
/**
|
||||
* 所有 [valueNodes] 更新和保存序列化器. 仅供内部使用
|
||||
*/
|
||||
public val updaterSerializer: KSerializer<Unit>
|
||||
|
||||
/**
|
||||
* 当所属于这个 [PluginData] 的 [Value] 的 [值][Value.value] 被修改时被调用.
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public fun onValueChanged(value: Value<*>)
|
||||
|
||||
/**
|
||||
@ -188,62 +137,6 @@ public interface PluginData {
|
||||
public fun onInit(owner: PluginDataHolder, storage: PluginDataStorage)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取这个 [KProperty] 委托的 [Value]
|
||||
*
|
||||
* 如, 对于
|
||||
* ```
|
||||
* object MyData : AutoSavePluginData(PluginMain) {
|
||||
* val list: List<String> by value()
|
||||
* }
|
||||
*
|
||||
* val value: Value<List<String>> = MyData.findBackingFieldValue(MyData::list)
|
||||
* ```
|
||||
*
|
||||
* @see PluginData
|
||||
*/
|
||||
public fun <T> PluginData.findBackingFieldValue(property: KProperty<T>): Value<out T>? =
|
||||
findBackingFieldValue(property.valueName)
|
||||
|
||||
/**
|
||||
* 获取这个 [KProperty] 委托的 [Value]
|
||||
*
|
||||
* 如, 对于
|
||||
* ```
|
||||
* object MyData : AutoSavePluginData(PluginMain) {
|
||||
* @ValueName("theList")
|
||||
* val list: List<String> by value()
|
||||
* val int: Int by value()
|
||||
* }
|
||||
*
|
||||
* val value: Value<List<String>> = MyData.findBackingFieldValue("theList") // 需使用 @ValueName 标注的名称
|
||||
* val intValue: Value<Int> = MyData.findBackingFieldValue("int")
|
||||
* ```
|
||||
*
|
||||
* @see PluginData
|
||||
*/
|
||||
public fun <T> PluginData.findBackingFieldValue(propertyValueName: String): Value<out T>? {
|
||||
return this.valueNodes.find { it.valueName == propertyValueName }?.value as Value<T>
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取这个 [KProperty] 委托的 [Value]
|
||||
*
|
||||
* 如, 对于
|
||||
* ```
|
||||
* object MyData : AutoSavePluginData(PluginMain) {
|
||||
* val list: List<String> by value()
|
||||
* }
|
||||
*
|
||||
* val value: PluginData.ValueNode<List<String>> = MyData.findBackingFieldValueNode(MyData::list)
|
||||
* ```
|
||||
*
|
||||
* @see PluginData
|
||||
*/
|
||||
public fun <T> PluginData.findBackingFieldValueNode(property: KProperty<T>): PluginData.ValueNode<out T>? {
|
||||
return this.valueNodes.find { it == property } as PluginData.ValueNode<out T>?
|
||||
}
|
||||
|
||||
// don't default = 0, cause ambiguity
|
||||
//// region PluginData_value_primitives CODEGEN ////
|
||||
|
@ -135,6 +135,7 @@ public interface MultiFilePluginDataStorage : PluginDataStorage {
|
||||
}
|
||||
}
|
||||
|
||||
@ConsoleExperimentalApi
|
||||
@get:JvmSynthetic
|
||||
public inline val MultiFilePluginDataStorage.directory: File
|
||||
get() = this.directoryPath.toFile()
|
@ -9,6 +9,8 @@
|
||||
|
||||
package net.mamoe.mirai.console.data
|
||||
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
|
||||
/**
|
||||
* 序列化之后的名称.
|
||||
*
|
||||
@ -27,6 +29,7 @@ package net.mamoe.mirai.console.data
|
||||
* a: b
|
||||
* ```
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
public annotation class ValueName(val value: String)
|
||||
|
@ -9,10 +9,7 @@
|
||||
|
||||
package net.mamoe.mirai.console.internal.data
|
||||
|
||||
import net.mamoe.mirai.console.data.MultiFilePluginDataStorage
|
||||
import net.mamoe.mirai.console.data.PluginData
|
||||
import net.mamoe.mirai.console.data.PluginDataHolder
|
||||
import net.mamoe.mirai.console.data.PluginDataStorage
|
||||
import net.mamoe.mirai.console.data.*
|
||||
import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
@ -42,7 +39,7 @@ internal open class MultiFilePluginDataStorageImpl(
|
||||
} else {
|
||||
this.store(holder, instance) // save an initial copy
|
||||
}
|
||||
logger.debug { "Successfully loaded PluginData: ${instance.saveName} (containing ${instance.valueNodes.size} properties)" }
|
||||
logger.debug { "Successfully loaded PluginData: ${instance.saveName} (containing ${instance.castOrNull<AbstractPluginData>()?.valueNodes?.size} properties)" }
|
||||
}
|
||||
|
||||
protected open fun getPluginDataFile(holder: PluginDataHolder, instance: PluginData): File {
|
||||
@ -83,7 +80,7 @@ internal open class MultiFilePluginDataStorageImpl(
|
||||
throw IllegalStateException("Exception while saving $instance, saveName=${instance.saveName}", it)
|
||||
}
|
||||
)
|
||||
logger.debug { "Successfully saved PluginData: ${instance.saveName} (containing ${instance.valueNodes.size} properties)" }
|
||||
logger.debug { "Successfully saved PluginData: ${instance.saveName} (containing ${instance.castOrNull<AbstractPluginData>()?.valueNodes?.size} properties)" }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,8 @@ 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.ValueNode
|
||||
import net.mamoe.mirai.console.data.PluginData
|
||||
import net.mamoe.mirai.console.data.PluginData.ValueNode
|
||||
import net.mamoe.mirai.console.data.Value
|
||||
import net.mamoe.mirai.console.data.ValueDescription
|
||||
import net.mamoe.mirai.console.data.ValueName
|
||||
|
Loading…
Reference in New Issue
Block a user