From 2fe2d2a681d70ff87cee25a53e55e26ce8661a22 Mon Sep 17 00:00:00 2001 From: Him188 Date: Fri, 18 Sep 2020 20:35:36 +0800 Subject: [PATCH] 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` --- .../mirai/console/data/AbstractPluginData.kt | 111 ++++++++++++++++- .../mirai/console/data/AutoSavePluginData.kt | 1 + .../mamoe/mirai/console/data/PluginData.kt | 117 +----------------- .../mirai/console/data/PluginDataStorage.kt | 1 + .../net/mamoe/mirai/console/data/ValueName.kt | 3 + .../data/MultiFilePluginDataStorageImpl.kt | 9 +- .../console/internal/data/PluginDataImpl.kt | 2 +- 7 files changed, 121 insertions(+), 123 deletions(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AbstractPluginData.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AbstractPluginData.kt index ce55fae6c..080170e9f 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AbstractPluginData.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AbstractPluginData.kt @@ -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> = mutableListOf() /** * 供手动实现时值跟踪使用 (如 Java 用户). 一般 Kotlin 用户需使用 [provideDelegate] */ - public override fun > T.track(valueName: String, annotations: List): T = - apply { valueNodes.add(ValueNode(valueName, this, annotations, this.serializer)) } + @ConsoleExperimentalApi + public fun > track( + value: T, + /** + * 值名称. + * + * 如果属性带有 [ValueName], 则使用 [ValueName.value], + * 否则使用 [属性名称][KProperty.name] + * + * @see [ValueNode.value] + */ + valueName: String, + annotations: List, + ): 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.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 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( + /** + * 节点名称. + * + * 如果属性带有 [ValueName], 则使用 [ValueName.value], + * 否则使用 [属性名称][KProperty.name] + */ + val valueName: String, + /** + * 属性值代理 + */ + val value: Value, + /** + * 注解列表 + */ + val annotations: List, + /** + * 属性值更新器 + */ + val updaterSerializer: KSerializer, + ) +} + +/** + * 获取这个 [KProperty] 委托的 [Value] + * + * 示例: + * ``` + * object MyData : AutoSavePluginData(PluginMain) { + * val list: List by value() + * } + * + * val value: Value> = MyData.findBackingFieldValue(MyData::list) + * ``` + * + * @see PluginData + */ +@ConsoleExperimentalApi +public fun AbstractPluginData.findBackingFieldValue(property: KProperty): Value? = + findBackingFieldValue(property.valueName) + +/** + * 获取这个 [KProperty] 委托的 [Value] + * + * 示例: + * ``` + * object MyData : AutoSavePluginData(PluginMain) { + * @ValueName("theList") + * val list: List by value() + * val int: Int by value() + * } + * + * val value: Value> = MyData.findBackingFieldValue("theList") // 需使用 @ValueName 标注的名称 + * val intValue: Value = MyData.findBackingFieldValue("int") + * ``` + * + * @see PluginData + */ +@ConsoleExperimentalApi +public fun AbstractPluginData.findBackingFieldValue(propertyValueName: String): Value? { + @Suppress("UNCHECKED_CAST") + return this.valueNodes.find { it.valueName == propertyValueName }?.value as Value +} + +/** + * 获取这个 [KProperty] 委托的 [Value] + * + * 示例: + * ``` + * object MyData : AutoSavePluginData(PluginMain) { + * val list: List by value() + * } + * + * val value: PluginData.ValueNode> = MyData.findBackingFieldValueNode(MyData::list) + * ``` + * + * @see PluginData + */ +@ConsoleExperimentalApi +public fun AbstractPluginData.findBackingFieldValueNode(property: KProperty): AbstractPluginData.ValueNode? { + @Suppress("UNCHECKED_CAST") + return this.valueNodes.find { it == property } as AbstractPluginData.ValueNode? } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AutoSavePluginData.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AutoSavePluginData.kt index 85e45bc10..937a32de4 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AutoSavePluginData.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AutoSavePluginData.kt @@ -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) { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginData.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginData.kt index 28f27c62c..705c90996 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginData.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginData.kt @@ -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> - /** * 这个 [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( - /** - * 节点名称. - * - * 如果属性带有 [ValueName], 则使用 [ValueName.value], - * 否则使用 [属性名称][KProperty.name] - */ - val valueName: String, - /** - * 属性值代理 - */ - val value: Value, - /** - * 注解列表 - */ - val annotations: List, - /** - * 属性值更新器 - */ - val updaterSerializer: KSerializer - ) - - /** - * 供手动实现时值跟踪使用 (如 Java 用户). 一般 Kotlin 用户需使用 [provideDelegate] - */ - public fun > T.track( - /** - * 值名称. - * - * 如果属性带有 [ValueName], 则使用 [ValueName.value], - * 否则使用 [属性名称][KProperty.name] - * - * @see [ValueNode.value] - */ - valueName: String, - annotations: List - ): T - - /** - * 所有 [valueNodes] 更新和保存序列化器. 仅供内部使用 - */ public val updaterSerializer: KSerializer /** * 当所属于这个 [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 by value() - * } - * - * val value: Value> = MyData.findBackingFieldValue(MyData::list) - * ``` - * - * @see PluginData - */ -public fun PluginData.findBackingFieldValue(property: KProperty): Value? = - findBackingFieldValue(property.valueName) - -/** - * 获取这个 [KProperty] 委托的 [Value] - * - * 如, 对于 - * ``` - * object MyData : AutoSavePluginData(PluginMain) { - * @ValueName("theList") - * val list: List by value() - * val int: Int by value() - * } - * - * val value: Value> = MyData.findBackingFieldValue("theList") // 需使用 @ValueName 标注的名称 - * val intValue: Value = MyData.findBackingFieldValue("int") - * ``` - * - * @see PluginData - */ -public fun PluginData.findBackingFieldValue(propertyValueName: String): Value? { - return this.valueNodes.find { it.valueName == propertyValueName }?.value as Value -} - - -/** - * 获取这个 [KProperty] 委托的 [Value] - * - * 如, 对于 - * ``` - * object MyData : AutoSavePluginData(PluginMain) { - * val list: List by value() - * } - * - * val value: PluginData.ValueNode> = MyData.findBackingFieldValueNode(MyData::list) - * ``` - * - * @see PluginData - */ -public fun PluginData.findBackingFieldValueNode(property: KProperty): PluginData.ValueNode? { - return this.valueNodes.find { it == property } as PluginData.ValueNode? -} // don't default = 0, cause ambiguity //// region PluginData_value_primitives CODEGEN //// diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataStorage.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataStorage.kt index 2f09d6f09..8e4e667ac 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataStorage.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataStorage.kt @@ -135,6 +135,7 @@ public interface MultiFilePluginDataStorage : PluginDataStorage { } } +@ConsoleExperimentalApi @get:JvmSynthetic public inline val MultiFilePluginDataStorage.directory: File get() = this.directoryPath.toFile() \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/ValueName.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/ValueName.kt index 9737bf73a..d1017080b 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/ValueName.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/ValueName.kt @@ -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) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/MultiFilePluginDataStorageImpl.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/MultiFilePluginDataStorageImpl.kt index a753a52cd..351ea18ea 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/MultiFilePluginDataStorageImpl.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/MultiFilePluginDataStorageImpl.kt @@ -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()?.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()?.valueNodes?.size} properties)" } } } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/PluginDataImpl.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/PluginDataImpl.kt index 4dc70fa25..d388d87fc 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/PluginDataImpl.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/PluginDataImpl.kt @@ -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