Review plugin

This commit is contained in:
Him188 2020-10-24 21:24:52 +08:00
parent 15d0cdaf90
commit 3ed018c4f8
4 changed files with 70 additions and 55 deletions

View File

@ -20,6 +20,7 @@ import net.mamoe.mirai.console.internal.data.mkdir
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.Plugin
import net.mamoe.mirai.console.plugin.PluginManager import net.mamoe.mirai.console.plugin.PluginManager
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.safeLoader
import net.mamoe.mirai.console.plugin.description.PluginDependency import net.mamoe.mirai.console.plugin.description.PluginDependency
import net.mamoe.mirai.console.plugin.description.PluginDescription import net.mamoe.mirai.console.plugin.description.PluginDescription
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
@ -60,18 +61,17 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol
override val pluginLoaders: List<PluginLoader<*, *>> override val pluginLoaders: List<PluginLoader<*, *>>
get() = _pluginLoaders.toList() get() = _pluginLoaders.toList()
override val Plugin.description: PluginDescription override fun getPluginDescription(plugin: Plugin): PluginDescription = if (plugin is JvmPlugin) {
get() = if (this is JvmPlugin) { plugin.safeLoader.getPluginDescription(plugin)
this.safeLoader.getPluginDescription(this) } else resolvedPlugins.firstOrNull { it == plugin }
} else resolvedPlugins.firstOrNull { it == this }
?.loader?.cast<PluginLoader<Plugin, PluginDescription>>() ?.loader?.cast<PluginLoader<Plugin, PluginDescription>>()
?.getPluginDescription(this) ?.getPluginDescription(plugin)
?: error("Plugin is unloaded") ?: error("Plugin is unloaded")
init { init {
MiraiConsole.coroutineContext[Job]!!.invokeOnCompletion { MiraiConsole.coroutineContext[Job]!!.invokeOnCompletion {
plugins.forEach { it.disable() } plugins.forEach { disablePlugin(it) }
} }
} }
@ -98,10 +98,10 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol
this.enable(plugin as P) this.enable(plugin as P)
}.fold( }.fold(
onSuccess = { onSuccess = {
logger.info { "Successfully enabled plugin ${plugin.description.name}" } logger.info { "Successfully enabled plugin ${getPluginDescription(plugin).name}" }
}, },
onFailure = { onFailure = {
logger.info { "Cannot enable plugin ${plugin.description.name}" } logger.info { "Cannot enable plugin ${getPluginDescription(plugin).name}" }
throw it throw it
} }
) )
@ -166,7 +166,7 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol
} }
internal fun enableAllLoadedPlugins() { internal fun enableAllLoadedPlugins() {
resolvedPlugins.forEach { it.enable() } resolvedPlugins.forEach { enablePlugin(it) }
} }
@kotlin.jvm.Throws(PluginLoadException::class) @kotlin.jvm.Throws(PluginLoadException::class)
@ -180,7 +180,7 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol
private fun List<PluginLoader<*, *>>.listAndSortAllPlugins(): List<PluginDescriptionWithLoader> { private fun List<PluginLoader<*, *>>.listAndSortAllPlugins(): List<PluginDescriptionWithLoader> {
return flatMap { loader -> return flatMap { loader ->
loader.listPlugins().map { plugin -> plugin.description.wrapWith(loader, plugin) } loader.listPlugins().map { plugin -> getPluginDescription(plugin).wrapWith(loader, plugin) }
}.sortByDependencies() }.sortByDependencies()
} }

View File

@ -12,23 +12,22 @@
package net.mamoe.mirai.console.plugin package net.mamoe.mirai.console.plugin
import net.mamoe.mirai.console.command.CommandOwner import net.mamoe.mirai.console.command.CommandOwner
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.disable import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.getPluginDescription
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.enable
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.safeLoader
import net.mamoe.mirai.console.plugin.description.PluginDependency import net.mamoe.mirai.console.plugin.description.PluginDependency
import net.mamoe.mirai.console.plugin.description.PluginDescription import net.mamoe.mirai.console.plugin.description.PluginDescription
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
import net.mamoe.mirai.console.plugin.loader.PluginLoader import net.mamoe.mirai.console.plugin.loader.PluginLoader
import net.mamoe.mirai.console.util.SemVersion import net.mamoe.mirai.console.util.SemVersion
import kotlin.DeprecationLevel.ERROR
/** /**
* 表示一个 mirai-console 插件. * 表示一个 mirai-console 插件.
* *
* @see PluginManager.enable 启用一个插件 * @see PluginManager.enablePlugin 启用一个插件
* @see PluginManager.disable 禁用一个插件 * @see PluginManager.disablePlugin 禁用一个插件
* @see PluginManager.description 获取一个插件的 [描述][PluginDescription] * @see PluginManager.description 获取一个插件的 [描述][PluginDescription]
* *
* @see PluginDescription 插件描述 需由 [PluginLoader] 帮助提供[PluginLoader.description] * @see PluginDescription 插件描述 需由 [PluginLoader] 帮助提供[PluginLoader.getPluginDescription]
* @see JvmPlugin Java, Kotlin 或其他 JVM 平台插件 * @see JvmPlugin Java, Kotlin 或其他 JVM 平台插件
* @see PluginFileExtensions 支持文件系统存储的扩展 * @see PluginFileExtensions 支持文件系统存储的扩展
* *
@ -38,8 +37,8 @@ public interface Plugin : CommandOwner {
/** /**
* 判断此插件是否已启用 * 判断此插件是否已启用
* *
* @see PluginManager.enable 启用一个插件 * @see PluginManager.enablePlugin 启用一个插件
* @see PluginManager.disable 禁用一个插件 * @see PluginManager.disablePlugin 禁用一个插件
*/ */
public val isEnabled: Boolean public val isEnabled: Boolean
@ -49,32 +48,42 @@ public interface Plugin : CommandOwner {
public val loader: PluginLoader<*, *> public val loader: PluginLoader<*, *>
} }
/** @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
* 获取 [PluginDescription] @kotlin.internal.LowPriorityInOverloadResolution
*/ @Deprecated(
public inline val Plugin.description: PluginDescription get() = this.safeLoader.getPluginDescription(this) "Moved to companion for a better Java API. ",
ReplaceWith("this.description", "net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.description"),
level = ERROR
)
public inline val Plugin.description: PluginDescription
get() = getPluginDescription(this) // resolved to net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.getDescription
/** /**
* 获取 [PluginDescription.name`] * 获取 [PluginDescription.name]
*/ */
public inline val Plugin.name: String get() = this.description.name public inline val Plugin.name: String get() = getPluginDescription(this).name
/**
* 获取 [PluginDescription.id]
*/
public inline val Plugin.id: String get() = getPluginDescription(this).id
/** /**
* 获取 [PluginDescription.version] * 获取 [PluginDescription.version]
*/ */
public inline val Plugin.version: SemVersion get() = this.description.version public inline val Plugin.version: SemVersion get() = getPluginDescription(this).version
/** /**
* 获取 [PluginDescription.info] * 获取 [PluginDescription.info]
*/ */
public inline val Plugin.info: String get() = this.description.info public inline val Plugin.info: String get() = getPluginDescription(this).info
/** /**
* 获取 [PluginDescription.author] * 获取 [PluginDescription.author]
*/ */
public inline val Plugin.author: String get() = this.description.author public inline val Plugin.author: String get() = getPluginDescription(this).author
/** /**
* 获取 [PluginDescription.dependencies] * 获取 [PluginDescription.dependencies]
*/ */
public inline val Plugin.dependencies: Set<PluginDependency> get() = this.description.dependencies public inline val Plugin.dependencies: Set<PluginDependency> get() = getPluginDescription(this).dependencies

View File

@ -105,45 +105,52 @@ public interface PluginManager {
/** /**
* 获取插件的 [描述][PluginDescription], 通过 [PluginLoader.getPluginDescription] * 获取插件的 [描述][PluginDescription], 通过 [PluginLoader.getPluginDescription]
*/ */
public val Plugin.description: PluginDescription public fun getPluginDescription(plugin: Plugin): PluginDescription
/** /**
* 禁用这个插件 * 禁用这个插件
* *
* @see PluginLoader.disable * @see PluginLoader.disable
*/ */
public fun Plugin.disable(): Unit = safeLoader.disable(this) public fun disablePlugin(plugin: Plugin): Unit = plugin.safeLoader.disable(plugin)
/** /**
* 加载这个插件 * 加载这个插件
* *
* @see PluginLoader.load * @see PluginLoader.load
*/ */
public fun Plugin.load(): Unit = safeLoader.load(this) public fun loadPlugin(plugin: Plugin): Unit = plugin.safeLoader.load(plugin)
/** /**
* 启用这个插件 * 启用这个插件
* *
* @see PluginLoader.enable * @see PluginLoader.enable
*/ */
public fun Plugin.enable(): Unit = safeLoader.enable(this) public fun enablePlugin(plugin: Plugin): Unit = plugin.safeLoader.enable(plugin)
// endregion
public companion object INSTANCE : PluginManager by PluginManagerImpl {
/** /**
* 经过泛型类型转换的 [Plugin.loader] * 经过泛型类型转换的 [Plugin.loader]
*/ */
@get:JvmSynthetic @get:JvmSynthetic
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
public val <P : Plugin> P.safeLoader: PluginLoader<P, PluginDescription> public inline val <P : Plugin> P.safeLoader: PluginLoader<P, PluginDescription>
get() = this.loader as PluginLoader<P, PluginDescription> get() = this.loader as PluginLoader<P, PluginDescription>
// endregion
public companion object INSTANCE : PluginManager by PluginManagerImpl { @get:JvmSynthetic
// due to Kotlin's bug public inline val Plugin.description: PluginDescription
public override val Plugin.description: PluginDescription get() = PluginManagerImpl.run { description } get() = getPluginDescription(this)
public override fun Plugin.disable(): Unit = PluginManagerImpl.run { disable() }
public override fun Plugin.enable(): Unit = PluginManagerImpl.run { enable() } @JvmSynthetic
public override fun Plugin.load(): Unit = PluginManagerImpl.run { load() } public inline fun Plugin.disable(): Unit = disablePlugin(this)
public override val <P : Plugin> P.safeLoader: PluginLoader<P, PluginDescription> get() = PluginManagerImpl.run { safeLoader }
@JvmSynthetic
public inline fun Plugin.enable(): Unit = enablePlugin(this)
@JvmSynthetic
public inline fun Plugin.load(): Unit = loadPlugin(this)
} }
} }

View File

@ -14,8 +14,7 @@ package net.mamoe.mirai.console.plugin.loader
import net.mamoe.mirai.console.extensions.PluginLoaderProvider import net.mamoe.mirai.console.extensions.PluginLoaderProvider
import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.Plugin
import net.mamoe.mirai.console.plugin.PluginManager import net.mamoe.mirai.console.plugin.PluginManager
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.disable import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.enablePlugin
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.enable
import net.mamoe.mirai.console.plugin.description.PluginDescription import net.mamoe.mirai.console.plugin.description.PluginDescription
import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader
@ -66,9 +65,9 @@ public interface PluginLoader<P : Plugin, D : PluginDescription> {
public fun getPluginDescription(plugin: P): D public fun getPluginDescription(plugin: P): D
/** /**
* 主动加载一个插件 (实例), 但不 [启用][enable] . 返回加载成功的主类实例 * 主动加载一个插件 (实例), 但不 [启用][enablePlugin] . 返回加载成功的主类实例
* *
* **实现注意**: Console 不会把一个已经启用了的插件再次调用 [load] [enable], 但不排除意外情况. 实现本函数时应在这种情况时立即抛出异常 [IllegalStateException]. * **实现注意**: Console 不会把一个已经启用了的插件再次调用 [load] [enablePlugin], 但不排除意外情况. 实现本函数时应在这种情况时立即抛出异常 [IllegalStateException].
* *
* **实现细节**: 此函数只允许抛出 [PluginLoadException] 作为正常失败原因, 其他任意异常都属于意外错误. * **实现细节**: 此函数只允许抛出 [PluginLoadException] 作为正常失败原因, 其他任意异常都属于意外错误.
* 当异常发生时, 插件将会直接被放弃加载, 并影响依赖它的其他插件. * 当异常发生时, 插件将会直接被放弃加载, 并影响依赖它的其他插件.
@ -82,7 +81,7 @@ public interface PluginLoader<P : Plugin, D : PluginDescription> {
/** /**
* 主动启用这个插件. * 主动启用这个插件.
* *
* **实现注意**: Console 不会把一个已经启用了的插件再次调用 [load] [enable], 但不排除意外情况. 实现本函数时应在这种情况时立即抛出异常 [IllegalStateException]. * **实现注意**: Console 不会把一个已经启用了的插件再次调用 [load] [enablePlugin], 但不排除意外情况. 实现本函数时应在这种情况时立即抛出异常 [IllegalStateException].
* *
* **实现细节**: 此函数可抛出 [PluginLoadException] 作为正常失败原因, 其他任意异常都属于意外错误. * **实现细节**: 此函数可抛出 [PluginLoadException] 作为正常失败原因, 其他任意异常都属于意外错误.
* 当异常发生时, 插件将会直接被放弃加载, 并影响依赖它的其他插件. * 当异常发生时, 插件将会直接被放弃加载, 并影响依赖它的其他插件.
@ -90,7 +89,7 @@ public interface PluginLoader<P : Plugin, D : PluginDescription> {
* @throws PluginLoadException 在加载插件遇到意料之中的错误时抛出 (如找不到主类等). * @throws PluginLoadException 在加载插件遇到意料之中的错误时抛出 (如找不到主类等).
* @throws IllegalStateException 在插件已经被加载时抛出. 这属于意料之外的情况. * @throws IllegalStateException 在插件已经被加载时抛出. 这属于意料之外的情况.
* *
* @see PluginManager.enable * @see PluginManager.enablePlugin
*/ */
@Throws(IllegalStateException::class, PluginLoadException::class) @Throws(IllegalStateException::class, PluginLoadException::class)
public fun enable(plugin: P) public fun enable(plugin: P)
@ -103,7 +102,7 @@ public interface PluginLoader<P : Plugin, D : PluginDescription> {
* *
* @throws PluginLoadException 在加载插件遇到意料之中的错误时抛出 (如找不到主类等). * @throws PluginLoadException 在加载插件遇到意料之中的错误时抛出 (如找不到主类等).
* *
* @see PluginManager.disable * @see PluginManager.disablePlugin
*/ */
@Throws(IllegalStateException::class, PluginLoadException::class) @Throws(IllegalStateException::class, PluginLoadException::class)
public fun disable(plugin: P) public fun disable(plugin: P)