Review PluginData, misc improvements, close #138

This commit is contained in:
Him188 2020-09-02 08:59:19 +08:00
parent a7b85f98c3
commit 42bcde38b8
17 changed files with 48 additions and 76 deletions

View File

@ -54,7 +54,6 @@ kotlin {
useExperimentalAnnotation("kotlin.experimental.ExperimentalTypeInference")
useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi")
useExperimentalAnnotation("net.mamoe.mirai.console.data.ExperimentalPluginConfig")
useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleInternalAPI")
}
}

View File

@ -14,8 +14,6 @@ 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.util.ConsoleExperimentalAPI
import net.mamoe.mirai.console.util.ConsoleInternalAPI
/**
* [PluginData] 的默认实现. 支持使用 `by value()` 等委托方法创建 [Value] 并跟踪其改动.
@ -30,13 +28,11 @@ public abstract class AbstractPluginData : PluginData, PluginDataImpl() {
*
* @see provideDelegate
*/
@ConsoleExperimentalAPI
public override val valueNodes: MutableList<ValueNode<*>> = mutableListOf()
/**
* 供手动实现时值跟踪使用 ( Java 用户). 一般 Kotlin 用户需使用 [provideDelegate]
*/
@ConsoleExperimentalAPI
public override fun <T : SerializerAwareValue<*>> T.track(valueName: String): T =
apply { valueNodes.add(ValueNode(valueName, this, this.serializer)) }
@ -45,13 +41,11 @@ public abstract class AbstractPluginData : PluginData, PluginDataImpl() {
*
* @suppress 注意, 这是实验性 API.
*/
@ConsoleExperimentalAPI
public final override val updaterSerializer: KSerializer<Unit>
get() = super.updaterSerializer
/**
* 当所属于这个 [PluginData] [Value] [][Value.value] 被修改时被调用.
*/
@ConsoleInternalAPI
public abstract override fun onValueChanged(value: Value<*>)
}

View File

@ -23,5 +23,4 @@ import kotlinx.coroutines.Job
* @see PluginConfig
* @see AutoSavePluginData
*/
@ExperimentalPluginConfig
public open class AutoSavePluginConfig : AutoSavePluginData(), PluginConfig

View File

@ -17,7 +17,6 @@ import net.mamoe.mirai.console.MiraiConsole
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.console.util.ConsoleInternalAPI
import net.mamoe.mirai.utils.*
/**
@ -39,7 +38,8 @@ public open class AutoSavePluginData private constructor(
public constructor() : this(null)
override fun onStored(owner: PluginDataHolder, storage: PluginDataStorage) {
@ConsoleExperimentalAPI
override fun onInit(owner: PluginDataHolder, storage: PluginDataStorage) {
check(owner is AutoSavePluginDataHolder) { "owner must be AutoSavePluginDataHolder for AutoSavePluginData" }
if (this::storage_.isInitialized) {
@ -121,8 +121,6 @@ public open class AutoSavePluginData private constructor(
}
}
@Suppress("RedundantVisibilityModifier")
@ConsoleInternalAPI
public final override fun onValueChanged(value: Value<*>) {
debuggingLogger1.error { "onValueChanged: $value" }
if (::owner_.isInitialized) {

View File

@ -10,8 +10,6 @@
package net.mamoe.mirai.console.data
import net.mamoe.mirai.console.data.java.JAutoSavePluginConfig
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
import kotlin.annotation.AnnotationTarget.*
/**
* 一个插件的配置数据, 用于和用户交互.
@ -39,19 +37,4 @@ import kotlin.annotation.AnnotationTarget.*
*
* @see PluginData
*/
@ExperimentalPluginConfig
public interface PluginConfig : PluginData
/**
* 标记实验性的 [PluginConfig] API.
*
* @see ConsoleExperimentalAPI
*/
@ConsoleExperimentalAPI
@Retention(AnnotationRetention.BINARY)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR)
@MustBeDocumented
public annotation class ExperimentalPluginConfig(
val message: String = ""
)
public interface PluginConfig : PluginData

View File

@ -11,7 +11,7 @@
"INVISIBLE_REFERENCE",
"INVISIBLE_MEMBER",
"EXPOSED_SUPER_CLASS",
"NOTHING_TO_INLINE", "unused"
"NOTHING_TO_INLINE", "unused", "UNCHECKED_CAST"
)
@file:JvmName("PluginDataKt")
@ -23,7 +23,6 @@ import net.mamoe.mirai.console.internal.data.*
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
import net.mamoe.mirai.console.plugin.jvm.reloadPluginData
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
import net.mamoe.mirai.console.util.ConsoleInternalAPI
import kotlin.internal.LowPriorityInOverloadResolution
import kotlin.reflect.KClass
import kotlin.reflect.KProperty
@ -111,7 +110,6 @@ public interface PluginData {
* @see provideDelegate
* @see track
*/
@ConsoleExperimentalAPI
public val valueNodes: MutableList<ValueNode<*>>
/**
@ -146,7 +144,6 @@ public interface PluginData {
*
* @suppress 注意, 这是实验性 API.
*/
@ConsoleExperimentalAPI
val updaterSerializer: KSerializer<Unit>
)
@ -161,7 +158,6 @@ public interface PluginData {
/**
* 供手动实现时值跟踪使用 ( Java 用户). 一般 Kotlin 用户需使用 [provideDelegate]
*/
@ConsoleExperimentalAPI
public fun <T : SerializerAwareValue<*>> T.track(
/**
* 值名称.
@ -179,20 +175,18 @@ public interface PluginData {
*
* @suppress 注意, 这是实验性 API.
*/
@ConsoleExperimentalAPI
public val updaterSerializer: KSerializer<Unit>
/**
* 当所属于这个 [PluginData] [Value] [][Value.value] 被修改时被调用.
*/
@ConsoleInternalAPI
public fun onValueChanged(value: Value<*>)
/**
* 当这个 [PluginData] 被放入一个 [PluginDataStorage] 时调用
*/
@ConsoleInternalAPI
public fun onStored(owner: PluginDataHolder, storage: PluginDataStorage)
@ConsoleExperimentalAPI
public fun onInit(owner: PluginDataHolder, storage: PluginDataStorage)
}
/**
@ -209,7 +203,6 @@ public interface PluginData {
*
* @see PluginData
*/
@Suppress("UNCHECKED_CAST")
public fun <T> PluginData.findBackingFieldValue(property: KProperty<T>): Value<out T>? =
findBackingFieldValue(property.valueName)
@ -230,7 +223,6 @@ public fun <T> PluginData.findBackingFieldValue(property: KProperty<T>): Value<o
*
* @see PluginData
*/
@Suppress("UNCHECKED_CAST")
public fun <T> PluginData.findBackingFieldValue(propertyValueName: String): Value<out T>? {
return this.valueNodes.find { it.valueName == propertyValueName }?.value as Value<T>
}
@ -250,25 +242,11 @@ public fun <T> PluginData.findBackingFieldValue(propertyValueName: String): Valu
*
* @see PluginData
*/
@Suppress("UNCHECKED_CAST")
public fun <T> PluginData.findBackingFieldValueNode(property: KProperty<T>): PluginData.ValueNode<out T>? {
return this.valueNodes.find { it == property } as PluginData.ValueNode<out T>?
}
/**
* 用于支持属性委托
*/
@JvmSynthetic
public inline operator fun <T> Value<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value
/**
* 用于支持属性委托
*/
@JvmSynthetic
public inline operator fun <T> Value<T>.setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = value
}
// don't default = 0, cause ambiguity
//// region PluginData_value_primitives CODEGEN ////
/**
@ -330,16 +308,19 @@ public fun PluginData.value(default: String): SerializerAwareValue<String> = val
*/
@Suppress("UNCHECKED_CAST")
@LowPriorityInOverloadResolution
public inline fun <reified T> PluginData.value(default: T): SerializerAwareValue<T> =
valueFromKType(typeOf0<T>(), default)
public inline fun <reified T> PluginData.value(
default: T,
crossinline apply: T.() -> Unit = {}
): SerializerAwareValue<T> =
valueFromKType(typeOf0<T>(), default).also { it.value.apply() }
/**
* 通过具体化类型创建一个 [SerializerAwareValue].
* @see valueFromKType 查看更多实现信息
*/
@LowPriorityInOverloadResolution
public inline fun <reified T> PluginData.value(): SerializerAwareValue<T> =
valueImpl(typeOf0<T>(), T::class)
public inline fun <reified T> PluginData.value(apply: T.() -> Unit = {}): SerializerAwareValue<T> =
valueImpl<T>(typeOf0<T>(), T::class).also { it.value.apply() }
@Suppress("UNCHECKED_CAST")
@PublishedApi

View File

@ -4,12 +4,10 @@ package net.mamoe.mirai.console.data
import net.mamoe.mirai.console.data.PluginDataExtensions.withDefault
import net.mamoe.mirai.console.internal.data.ShadowMap
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
/**
* [PluginData] 相关一些扩展
*/
@ConsoleExperimentalAPI
public object PluginDataExtensions {
/**

View File

@ -30,7 +30,7 @@ public interface PluginDataHolder {
* 保存时使用的分类名
*/
@ConsoleExperimentalAPI
public val name: String
public val dataHolderName: String
}
/**

View File

@ -36,8 +36,9 @@ import java.nio.file.Path
@ConsoleExperimentalAPI
public interface PluginDataStorage {
/**
* 读取一个实例. 并为 [instance] [设置 [PluginDataStorage]][PluginData.onStored]
* 读取一个实例. 并为 [instance] [设置 [PluginDataStorage]][PluginData.onInit]
*/
@ConsoleExperimentalAPI
public fun load(holder: PluginDataHolder, instance: PluginData)
/**
@ -45,6 +46,7 @@ public interface PluginDataStorage {
*
* **实现细节**: 调用 [PluginData.updaterSerializer]
*/
@ConsoleExperimentalAPI
public fun store(holder: PluginDataHolder, instance: PluginData)
/*
@ -110,6 +112,7 @@ public interface MemoryPluginDataStorage : PluginDataStorage {
/**
* 用多个文件存储 [PluginData] 实例的 [PluginDataStorage].
*/
@ConsoleExperimentalAPI
public interface MultiFilePluginDataStorage : PluginDataStorage {
/**
* 存放 [PluginData] 的目录.

View File

@ -17,6 +17,8 @@ import kotlinx.serialization.StringFormat
import net.mamoe.mirai.console.internal.data.map
import net.mamoe.mirai.console.internal.data.setValueBySerializer
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
/**
* 表示一个值代理.
@ -30,10 +32,18 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
* @see PrimitiveValue 基础数据类型实现
* @see CompositeValue 复合数据类型实现
*/
public interface Value<T> {
public interface Value<T> : ReadWriteProperty<Any?, T> {
@get:JvmName("get")
@set:JvmName("set")
public var value: T
@JvmSynthetic // avoid ambiguity with property `value`
public override operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
@JvmSynthetic
public override operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = value
}
}
/**
@ -135,34 +145,42 @@ public interface PrimitiveValue<T> : Value<T>
* 表示一个不可空 [Byte] [Value].
*/
public interface ByteValue : PrimitiveValue<Byte>
/**
* 表示一个不可空 [Short] [Value].
*/
public interface ShortValue : PrimitiveValue<Short>
/**
* 表示一个不可空 [Int] [Value].
*/
public interface IntValue : PrimitiveValue<Int>
/**
* 表示一个不可空 [Long] [Value].
*/
public interface LongValue : PrimitiveValue<Long>
/**
* 表示一个不可空 [Float] [Value].
*/
public interface FloatValue : PrimitiveValue<Float>
/**
* 表示一个不可空 [Double] [Value].
*/
public interface DoubleValue : PrimitiveValue<Double>
/**
* 表示一个不可空 [Char] [Value].
*/
public interface CharValue : PrimitiveValue<Char>
/**
* 表示一个不可空 [Boolean] [Value].
*/
public interface BooleanValue : PrimitiveValue<Boolean>
/**
* 表示一个不可空 [String] [Value].
*/

View File

@ -12,7 +12,6 @@
package net.mamoe.mirai.console.data.java
import net.mamoe.mirai.console.data.AutoSavePluginConfig
import net.mamoe.mirai.console.data.ExperimentalPluginConfig
import net.mamoe.mirai.console.data.PluginConfig
import net.mamoe.mirai.console.data.PluginData
@ -38,5 +37,4 @@ import net.mamoe.mirai.console.data.PluginData
* @see JAutoSavePluginData
* @see PluginConfig
*/
@ExperimentalPluginConfig
public abstract class JAutoSavePluginConfig : AutoSavePluginConfig(), PluginConfig

View File

@ -19,7 +19,7 @@ internal class MemoryPluginDataStorageImpl : PluginDataStorage, MemoryPluginData
@Suppress("UNCHECKED_CAST")
override fun load(holder: PluginDataHolder, instance: PluginData) {
instance.onStored(holder, this)
instance.onInit(holder, this)
}
override fun store(holder: PluginDataHolder, instance: PluginData) {

View File

@ -33,7 +33,7 @@ internal open class MultiFilePluginDataStorageImpl(
}
public override fun load(holder: PluginDataHolder, instance: PluginData) {
instance.onStored(holder, this)
instance.onInit(holder, this)
val text = getPluginDataFile(holder, instance).readText()
if (text.isNotBlank()) {
@ -48,7 +48,7 @@ internal open class MultiFilePluginDataStorageImpl(
protected open fun getPluginDataFile(holder: PluginDataHolder, instance: PluginData): File {
val name = instance.saveName
val dir = directoryPath.resolve(holder.name)
val dir = directoryPath.resolve(holder.dataHolderName)
if (dir.isFile) {
error("Target directory $dir for holder $holder is occupied by a file therefore data ${instance::class.qualifiedNameOrTip} can't be saved.")
}

View File

@ -15,7 +15,6 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.console.data.AutoSavePluginConfig
import net.mamoe.mirai.console.data.PluginDataExtensions.mapKeys
import net.mamoe.mirai.console.data.PluginDataExtensions.withEmptyDefault
import net.mamoe.mirai.console.data.getValue
import net.mamoe.mirai.console.data.value
import net.mamoe.mirai.console.util.BotManager
import net.mamoe.mirai.contact.User

View File

@ -37,13 +37,13 @@ internal object ConsoleDataScope : CoroutineScope by MiraiConsole.childScope("Co
internal object ConsoleBuiltInPluginDataHolder : AutoSavePluginDataHolder,
CoroutineScope by ConsoleDataScope.childScope("ConsoleBuiltInPluginDataHolder") {
override val autoSaveIntervalMillis: LongRange = 1.minutesToMillis..10.minutesToMillis
override val name: String get() = "ConsoleBuiltIns"
override val dataHolderName: String get() = "ConsoleBuiltIns"
}
internal object ConsoleBuiltInPluginConfigHolder : AutoSavePluginDataHolder,
CoroutineScope by ConsoleDataScope.childScope("ConsoleBuiltInPluginConfigHolder") {
override val autoSaveIntervalMillis: LongRange = 1.minutesToMillis..10.minutesToMillis
override val name: String get() = "ConsoleBuiltIns"
override val dataHolderName: String get() = "ConsoleBuiltIns"
}
internal object ConsoleBuiltInPluginDataStorage :

View File

@ -113,7 +113,7 @@ internal abstract class JvmPluginInternal(
// for future use
@Suppress("PropertyName")
internal val _intrinsicCoroutineContext: CoroutineContext by lazy {
CoroutineName("Plugin $name")
CoroutineName("Plugin $dataHolderName")
}
@JvmField
internal val coroutineContextInitializer = {
@ -126,7 +126,7 @@ internal abstract class JvmPluginInternal(
.plus(parentCoroutineContext)
.plus(
NamedSupervisorJob(
"Plugin $name",
"Plugin $dataHolderName",
parentCoroutineContext[Job] ?: JarPluginLoaderImpl.coroutineContext[Job]!!
)
)

View File

@ -27,7 +27,9 @@ import kotlin.coroutines.EmptyCoroutineContext
public abstract class AbstractJvmPlugin @JvmOverloads constructor(
parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
) : JvmPlugin, JvmPluginInternal(parentCoroutineContext) {
public final override val name: String get() = this.description.name
@ConsoleExperimentalAPI
public final override val dataHolderName: String
get() = this.description.name
@ConsoleExperimentalAPI
public override val autoSaveIntervalMillis: LongRange = 30.secondsToMillis..10.minutesToMillis