Rename PluginKind to PluginLoadPriority, revise load phases

This commit is contained in:
Him188 2020-09-10 20:41:09 +08:00
parent d7fe94acbd
commit 829bd6d454
10 changed files with 70 additions and 53 deletions

View File

@ -11,6 +11,7 @@ package net.mamoe.mirai.console.extension
import net.mamoe.mirai.console.extensions.PermissionServiceProvider
import net.mamoe.mirai.console.extensions.PluginLoaderProvider
import net.mamoe.mirai.console.extensions.SingletonExtensionSelector
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
/**
@ -28,6 +29,8 @@ public interface FunctionExtension : Extension
/**
* 为某单例服务注册的 [Extension].
*
* 若同时有多个实例可用, 将会使用 [SingletonExtensionSelector.selectSingleton] 选择
*
* @see PermissionServiceProvider
*/
@ConsoleExperimentalAPI

View File

@ -5,12 +5,14 @@ import net.mamoe.mirai.console.extension.SingletonExtension
import net.mamoe.mirai.console.extension.SingletonExtensionPoint
import net.mamoe.mirai.console.permission.ExperimentalPermission
import net.mamoe.mirai.console.permission.PermissionService
import net.mamoe.mirai.console.plugin.description.PluginKind
import net.mamoe.mirai.console.plugin.description.PluginLoadPriority
/**
* [权限服务][PermissionService] 提供器.
*
* 此扩展可由 [PluginKind.LOADER] [PluginKind.HIGH_PRIORITY_EXTENSIONS] 插件提供
* 当插件注册 [PermissionService] , 默认会使用插件的 [PermissionService].
*
* 此扩展可由 [PluginLoadPriority.BEFORE_EXTENSIONS] [PluginLoadPriority.ON_EXTENSIONS] 插件提供
*/
@ExperimentalPermission
public interface PermissionServiceProvider : SingletonExtension<PermissionService<*>> {

View File

@ -3,12 +3,12 @@ package net.mamoe.mirai.console.extensions
import net.mamoe.mirai.console.extension.AbstractExtensionPoint
import net.mamoe.mirai.console.extension.InstanceExtension
import net.mamoe.mirai.console.plugin.PluginLoader
import net.mamoe.mirai.console.plugin.description.PluginKind
import net.mamoe.mirai.console.plugin.description.PluginLoadPriority
/**
* 提供扩展 [PluginLoader]
*
* 此扩展可由 [PluginKind.LOADER] 插件提供
* 此扩展可由 [PluginLoadPriority.BEFORE_EXTENSIONS] 插件提供
*/
public interface PluginLoaderProvider : InstanceExtension<PluginLoader<*, *>> {
public companion object ExtensionPoint : AbstractExtensionPoint<PluginLoaderProvider>(PluginLoaderProvider::class)

View File

@ -12,7 +12,7 @@ package net.mamoe.mirai.console.extensions
import net.mamoe.mirai.console.MiraiConsole
import net.mamoe.mirai.console.extension.*
import net.mamoe.mirai.console.internal.extensions.BuiltInSingletonExtensionSelector
import net.mamoe.mirai.console.plugin.description.PluginKind
import net.mamoe.mirai.console.plugin.description.PluginLoadPriority
import net.mamoe.mirai.console.plugin.name
import net.mamoe.mirai.utils.info
import kotlin.reflect.KClass
@ -22,7 +22,7 @@ import kotlin.reflect.KClass
*
* 如有多个 [SingletonExtensionSelector] 注册, 将会停止服务器.
*
* 此扩展可由 [PluginKind.LOADER] [PluginKind.HIGH_PRIORITY_EXTENSIONS] 插件提供
* 此扩展可由 [PluginLoadPriority.BEFORE_EXTENSIONS] 插件提供
*/
public interface SingletonExtensionSelector : FunctionExtension {

View File

@ -126,20 +126,12 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
val pluginLoadSession: PluginManagerImpl.PluginLoadSession
phase `load plugin provider plugins and high priority extension plugins`@{
phase `load BEFORE_EXTENSIONS plugins`@{
PluginManager // init
mainLogger.verbose { "Loading PluginLoader provider plugins..." }
PluginManagerImpl.loadEnablePluginProviderPlugins()
mainLogger.verbose { "${PluginManager.plugins.size} such plugin(s) loaded." }
mainLogger.verbose { "Scanning high-priority extension and normal plugins..." }
pluginLoadSession = PluginManagerImpl.scanPluginsUsingPluginLoadersIncludingThoseFromPluginLoaderProvider()
mainLogger.verbose { "${pluginLoadSession.allKindsOfPlugins.size} plugin(s) found." }
mainLogger.verbose { "Loading Extension provider plugins..." }
PluginManagerImpl.loadEnableHighPriorityExtensionPlugins(pluginLoadSession)
mainLogger.verbose { "${PluginManager.plugins.size} such plugin(s) loaded." }
}
phase `load SingletonExtensionSelector`@{
@ -149,6 +141,16 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
}
}
phase `load ON_EXTENSIONS plugins`@{
mainLogger.verbose { "Scanning high-priority extension and normal plugins..." }
pluginLoadSession = PluginManagerImpl.scanPluginsUsingPluginLoadersIncludingThoseFromPluginLoaderProvider()
mainLogger.verbose { "${pluginLoadSession.allKindsOfPlugins.size} plugin(s) found." }
mainLogger.verbose { "Loading Extension provider plugins..." }
PluginManagerImpl.loadEnableHighPriorityExtensionPlugins(pluginLoadSession)
mainLogger.verbose { "${PluginManager.plugins.size} such plugin(s) loaded." }
}
phase `load PermissionService`@{
mainLogger.verbose { "Loading PermissionService..." }
PermissionService.INSTANCE.let { ps ->
@ -169,7 +171,7 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
CommandManagerImpl.commandListener // start
}
phase `load normal plugins`@{
phase `load AFTER_EXTENSION plugins`@{
mainLogger.verbose { "Loading normal plugins..." }
val count = PluginManagerImpl.loadEnableNormalPlugins(pluginLoadSession)
mainLogger.verbose { "$count normal plugin(s) loaded." }

View File

@ -22,7 +22,7 @@ import net.mamoe.mirai.console.internal.data.mkdir
import net.mamoe.mirai.console.plugin.*
import net.mamoe.mirai.console.plugin.description.PluginDependency
import net.mamoe.mirai.console.plugin.description.PluginDescription
import net.mamoe.mirai.console.plugin.description.PluginKind
import net.mamoe.mirai.console.plugin.description.PluginLoadPriority
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScope
import net.mamoe.mirai.utils.info
@ -131,7 +131,7 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol
internal fun loadEnableHighPriorityExtensionPlugins(session: PluginLoadSession): Int {
loadersLock.withLock {
session.allKindsOfPlugins.flatMap { it.second }
.filter { it.kind == PluginKind.HIGH_PRIORITY_EXTENSIONS }
.filter { it.loadPriority == PluginLoadPriority.ON_EXTENSIONS }
.sortByDependencies()
.also { it.loadAndEnableAllInOrder() }
.let { return it.size }
@ -142,7 +142,7 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol
internal fun loadEnableNormalPlugins(session: PluginLoadSession): Int {
loadersLock.withLock {
session.allKindsOfPlugins.flatMap { it.second }
.filter { it.kind == PluginKind.NORMAL }
.filter { it.loadPriority == PluginLoadPriority.AFTER_EXTENSIONS }
.sortByDependencies()
.also { it.loadAndEnableAllInOrder() }
.let { return it.size }
@ -191,7 +191,8 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol
loader as PluginLoader<Plugin, PluginDescription>
descriptions.forEach(PluginManagerImpl::checkPluginDescription)
descriptions.filter { it.kind == PluginKind.LOADER }.sortByDependencies().loadAndEnableAllInOrder()
descriptions.filter { it.loadPriority == PluginLoadPriority.BEFORE_EXTENSIONS }.sortByDependencies()
.loadAndEnableAllInOrder()
}
.flatMap { it.second.asSequence() }

View File

@ -18,7 +18,7 @@ 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.PluginDescription
import net.mamoe.mirai.console.plugin.description.PluginKind
import net.mamoe.mirai.console.plugin.description.PluginLoadPriority
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
/**
@ -65,9 +65,9 @@ public inline val Plugin.name: String get() = this.description.name
public inline val Plugin.version: Semver get() = this.description.version
/**
* 获取 [PluginDescription.kind]
* 获取 [PluginDescription.loadPriority]
*/
public inline val Plugin.kind: PluginKind get() = this.description.kind
public inline val Plugin.loadPriority: PluginLoadPriority get() = this.description.loadPriority
/**
* 获取 [PluginDescription.info]

View File

@ -23,9 +23,9 @@ public interface PluginDescription {
/**
* 插件类型. 将会决定加载顺序
*
* @see PluginKind
* @see PluginLoadPriority
*/
public val kind: PluginKind
public val loadPriority: PluginLoadPriority
/**
* 插件 ID, 必须全英文, 仅允许英文字母, '-', '_', '.'.

View File

@ -14,39 +14,46 @@ import kotlinx.serialization.builtins.serializer
import net.mamoe.mirai.console.extension.Extension
import net.mamoe.mirai.console.extensions.BotConfigurationAlterer
import net.mamoe.mirai.console.extensions.PermissionServiceProvider
import net.mamoe.mirai.console.extensions.PluginLoaderProvider
import net.mamoe.mirai.console.extensions.SingletonExtensionSelector
import net.mamoe.mirai.console.internal.data.map
import net.mamoe.mirai.console.plugin.PluginLoader
import net.mamoe.mirai.console.plugin.description.PluginKind.*
import net.mamoe.mirai.console.plugin.description.PluginLoadPriority.*
/**
* 插件类型.
*
* 插件类型将影响加载顺序: [LOADER] -> [HIGH_PRIORITY_EXTENSIONS] -> [NORMAL].
* 插件类型将影响加载顺序: [BEFORE_EXTENSIONS] -> [ON_EXTENSIONS] -> [AFTER_EXTENSIONS].
*
* 依赖解决过程与插件类型有很大关联. 在一个较早的阶段, 只会解决在此阶段加载的插件. 意味着 [LOADER] 不允许依赖一个 [NORMAL] 类型的插件.
* 依赖解决过程与插件类型有很大关联. 在一个较早的阶段, 只会解决在此阶段加载的插件. 意味着 [BEFORE_EXTENSIONS] 不允许依赖一个 [AFTER_EXTENSIONS] 类型的插件.
*/
public enum class PluginKind {
/** 表示此插件提供一个 [PluginLoader], 也可以同时提供其他 [Extension] 应最早被加载 */
LOADER,
public enum class PluginLoadPriority {
/**
* 表示此插件最早被加载. Console 启动时的第一初始化阶段就会加载这些插件.
*
* 一般只有提供 [PluginLoaderProvider] [SingletonExtensionSelector] 的插件才需要在此阶段加载.
*/
BEFORE_EXTENSIONS,
/**
* 表示此插件提供一些高优先级的 [Extension], 应在加载其他 [NORMAL] 类型插件前加载
* 表示此插件提供一些高优先级的 [Extension], 应在加载其他 [AFTER_EXTENSIONS] 类型插件前加载
*
* 高优先级的 [Extension] 通常是覆盖 Console 内置的部分服务的扩展. [PermissionServiceProvider].
*
* 一些普通的 [Extension], [BotConfigurationAlterer], 也可以使用 [NORMAL] 类型插件注册.
* 一些普通的 [Extension], [BotConfigurationAlterer], 也可以使用 [AFTER_EXTENSIONS] 类型插件注册.
*/
HIGH_PRIORITY_EXTENSIONS,
ON_EXTENSIONS,
/** 表示此插件为一个通常的插件, 按照正常的依赖关系加载. */
NORMAL;
/**
* 表示此插件为一个通常的插件, 在扩展处理完毕后加载.
*/
AFTER_EXTENSIONS;
public object AsStringSerializer : KSerializer<PluginKind> by String.serializer().map(
public object AsStringSerializer : KSerializer<PluginLoadPriority> by String.serializer().map(
serializer = { it.name },
deserializer = { str ->
values().firstOrNull {
it.name.equals(str, ignoreCase = true)
} ?: NORMAL
} ?: AFTER_EXTENSIONS
}
)
}

View File

@ -14,7 +14,7 @@ package net.mamoe.mirai.console.plugin.jvm
import com.vdurmont.semver4j.Semver
import net.mamoe.mirai.console.plugin.description.PluginDependency
import net.mamoe.mirai.console.plugin.description.PluginDescription
import net.mamoe.mirai.console.plugin.description.PluginKind
import net.mamoe.mirai.console.plugin.description.PluginLoadPriority
import kotlin.internal.LowPriorityInOverloadResolution
/**
@ -82,7 +82,7 @@ public class JvmPluginDescriptionBuilder(
private var author: String = ""
private var info: String = ""
private var dependencies: MutableSet<PluginDependency> = mutableSetOf()
private var kind: PluginKind = PluginKind.NORMAL
private var loadPriority: PluginLoadPriority = PluginLoadPriority.AFTER_EXTENSIONS
@ILoveKuriyamaMiraiForever
public fun name(value: String): JvmPluginDescriptionBuilder = apply { this.name = value.trim() }
@ -104,17 +104,19 @@ public class JvmPluginDescriptionBuilder(
public fun info(value: String): JvmPluginDescriptionBuilder = apply { this.info = value.trimIndent() }
@ILoveKuriyamaMiraiForever
public fun kind(value: PluginKind): JvmPluginDescriptionBuilder = apply { this.kind = value }
public fun kind(value: PluginLoadPriority): JvmPluginDescriptionBuilder = apply { this.loadPriority = value }
@ILoveKuriyamaMiraiForever
public fun normalPlugin(): JvmPluginDescriptionBuilder = apply { this.kind = PluginKind.NORMAL }
public fun normalPlugin(): JvmPluginDescriptionBuilder =
apply { this.loadPriority = PluginLoadPriority.AFTER_EXTENSIONS }
@ILoveKuriyamaMiraiForever
public fun loaderProviderPlugin(): JvmPluginDescriptionBuilder = apply { this.kind = PluginKind.LOADER }
public fun loaderProviderPlugin(): JvmPluginDescriptionBuilder =
apply { this.loadPriority = PluginLoadPriority.BEFORE_EXTENSIONS }
@ILoveKuriyamaMiraiForever
public fun highPriorityExtensionsPlugin(): JvmPluginDescriptionBuilder =
apply { this.kind = PluginKind.HIGH_PRIORITY_EXTENSIONS }
apply { this.loadPriority = PluginLoadPriority.ON_EXTENSIONS }
@ILoveKuriyamaMiraiForever
public fun dependsOn(
@ -152,7 +154,7 @@ public class JvmPluginDescriptionBuilder(
@Suppress("DEPRECATION_ERROR")
public fun build(): JvmPluginDescription =
SimpleJvmPluginDescription(name, version, id, author, info, dependencies, kind)
SimpleJvmPluginDescription(name, version, id, author, info, dependencies, loadPriority)
@Retention(AnnotationRetention.SOURCE)
@DslMarker
@ -192,7 +194,7 @@ public data class SimpleJvmPluginDescription
public override val author: String = "",
public override val info: String = "",
public override val dependencies: Set<PluginDependency> = setOf(),
public override val kind: PluginKind = PluginKind.NORMAL,
public override val loadPriority: PluginLoadPriority = PluginLoadPriority.AFTER_EXTENSIONS,
) : JvmPluginDescription {
@Deprecated(
@ -214,8 +216,8 @@ public data class SimpleJvmPluginDescription
author: String = "",
info: String = "",
dependencies: Set<PluginDependency> = setOf(),
kind: PluginKind = PluginKind.NORMAL,
) : this(name, Semver(version, Semver.SemverType.LOOSE), id, author, info, dependencies, kind)
loadPriority: PluginLoadPriority = PluginLoadPriority.AFTER_EXTENSIONS,
) : this(name, Semver(version, Semver.SemverType.LOOSE), id, author, info, dependencies, loadPriority)
init {
require(!name.contains(':')) { "':' is forbidden in plugin name" }
@ -240,8 +242,8 @@ public fun JvmPluginDescription(
author: String = "",
info: String = "",
dependencies: Set<PluginDependency> = setOf(),
kind: PluginKind = PluginKind.NORMAL
): JvmPluginDescription = SimpleJvmPluginDescription(name, version, id, author, info, dependencies, kind)
loadPriority: PluginLoadPriority = PluginLoadPriority.AFTER_EXTENSIONS
): JvmPluginDescription = SimpleJvmPluginDescription(name, version, id, author, info, dependencies, loadPriority)
@Deprecated(
"JvmPluginDescription 没有构造器. 请使用 SimpleJvmPluginDescription.",
@ -260,5 +262,5 @@ public fun JvmPluginDescription(
author: String = "",
info: String = "",
dependencies: Set<PluginDependency> = setOf(),
kind: PluginKind = PluginKind.NORMAL
): JvmPluginDescription = SimpleJvmPluginDescription(name, version, id, author, info, dependencies, kind)
loadPriority: PluginLoadPriority = PluginLoadPriority.AFTER_EXTENSIONS
): JvmPluginDescription = SimpleJvmPluginDescription(name, version, id, author, info, dependencies, loadPriority)