mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-25 15:40:28 +08:00
Review PluginData, misc improvements, close #138
This commit is contained in:
parent
a7b85f98c3
commit
42bcde38b8
@ -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")
|
||||
}
|
||||
}
|
||||
|
@ -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<*>)
|
||||
}
|
@ -23,5 +23,4 @@ import kotlinx.coroutines.Job
|
||||
* @see PluginConfig
|
||||
* @see AutoSavePluginData
|
||||
*/
|
||||
@ExperimentalPluginConfig
|
||||
public open class AutoSavePluginConfig : AutoSavePluginData(), PluginConfig
|
@ -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) {
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
@ -30,7 +30,7 @@ public interface PluginDataHolder {
|
||||
* 保存时使用的分类名
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
public val name: String
|
||||
public val dataHolderName: String
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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] 的目录.
|
||||
|
@ -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].
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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.")
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 :
|
||||
|
@ -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]!!
|
||||
)
|
||||
)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user