mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-01 10:36:04 +08:00
(ABI change) Rewrite ComponentStorage
: order extensions by property priority
. Remove builtinImplementations
and contribute them at the first initialization phase instead.
Close #1888, fix #1860. Add `ComponentStorageInternal` for frontend to provide components. Deprecate: - SingletonExtension - SingletonExtensionPoint - AbstractSingletonExtensionPoint - SingletonExtensionSelector - CommandCallInterceptorProviderImpl - CommandCallInterceptorProviderImplLazy - CommandCallParserProviderImpl - CommandCallParserProviderImplLazy - CommandCallResolverProviderImpl - CommandCallResolverProviderImplLazy ABI breaking change: - `PermissionServiceProvider`: supertype changed - `CommandCallResolverProvider.ExtensionPoint`: supertype changed - `PermissionServiceProvider.ExtensionPoint`: supertype changed
This commit is contained in:
parent
96e943c33f
commit
835059c44c
@ -162,7 +162,7 @@ public interface MiraiConsole : CoroutineScope {
|
||||
*
|
||||
* 调用 [Bot.login] 可登录.
|
||||
*
|
||||
* @see Bot.botInstances 获取现有 [Bot] 实例列表
|
||||
* @see Bot.instances 获取现有 [Bot] 实例列表
|
||||
* @see BotConfigurationAlterer ExtensionPoint
|
||||
*/
|
||||
// don't static
|
||||
@ -225,11 +225,8 @@ public interface MiraiConsole : CoroutineScope {
|
||||
configuration()
|
||||
}
|
||||
|
||||
config = GlobalComponentStorage.run {
|
||||
BotConfigurationAlterer.foldExtensions(config) { acc, extension ->
|
||||
extension.alterConfiguration(id, acc)
|
||||
|
||||
}
|
||||
config = GlobalComponentStorage.foldExtensions(BotConfigurationAlterer, config) { acc, extension ->
|
||||
extension.alterConfiguration(id, acc)
|
||||
}
|
||||
|
||||
return when (password) {
|
||||
|
@ -25,7 +25,6 @@ import net.mamoe.mirai.console.extension.ComponentStorage
|
||||
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
|
||||
import net.mamoe.mirai.console.internal.command.CommandManagerImpl
|
||||
import net.mamoe.mirai.console.internal.data.builtins.ConsoleDataScopeImpl
|
||||
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
|
||||
import net.mamoe.mirai.console.internal.logging.LoggerControllerImpl
|
||||
import net.mamoe.mirai.console.internal.plugin.BuiltInJvmPluginLoaderImpl
|
||||
import net.mamoe.mirai.console.internal.pluginManagerImpl
|
||||
@ -317,6 +316,9 @@ public interface MiraiConsoleImplementation : CoroutineScope {
|
||||
@ConsoleFrontEndImplementation
|
||||
public interface BackendAccess {
|
||||
// GlobalComponentStorage
|
||||
/**
|
||||
* 在 Mirai Console 第一个 phase 之后会包含内建 storages.
|
||||
*/
|
||||
public val globalComponentStorage: ComponentStorage
|
||||
|
||||
// PluginManagerImpl.resolvedPlugins
|
||||
@ -365,7 +367,7 @@ public interface MiraiConsoleImplementation : CoroutineScope {
|
||||
@ConsoleFrontEndImplementation
|
||||
public companion object {
|
||||
private val backendAccessInstance = object : BackendAccess {
|
||||
override val globalComponentStorage: ComponentStorage get() = GlobalComponentStorage
|
||||
override val globalComponentStorage: ComponentStorage get() = getBridge().globalComponentStorage
|
||||
override val resolvedPlugins: MutableList<Plugin> get() = MiraiConsole.pluginManagerImpl.resolvedPlugins
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig
|
||||
import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig.Account.*
|
||||
import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig.Account.PasswordKind.MD5
|
||||
import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig.Account.PasswordKind.PLAIN
|
||||
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
|
||||
import net.mamoe.mirai.console.internal.permission.BuiltInPermissionService
|
||||
import net.mamoe.mirai.console.internal.pluginManagerImpl
|
||||
import net.mamoe.mirai.console.internal.util.autoHexToBytes
|
||||
@ -484,7 +485,7 @@ public object BuiltInCommands {
|
||||
lightYellow()
|
||||
"Built In Permission Service"
|
||||
} else {
|
||||
val plugin = PermissionServiceProvider.providerPlugin
|
||||
val plugin = GlobalComponentStorage.getPreferredExtension(PermissionServiceProvider).plugin
|
||||
if (plugin == null) {
|
||||
PermissionService.INSTANCE.toString()
|
||||
} else {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -44,10 +44,8 @@ public interface CommandCallParser {
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun MessageChain.parseCommandCall(sender: CommandSender): CommandCall? {
|
||||
GlobalComponentStorage.run {
|
||||
CommandCallParserProvider.useExtensions { provider ->
|
||||
provider.instance.parse(sender, this@parseCommandCall)?.let { return it }
|
||||
}
|
||||
GlobalComponentStorage.useEachExtensions(CommandCallParserProvider) { provider ->
|
||||
provider.instance.parse(sender, this@parseCommandCall)?.let { return it }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -12,7 +12,6 @@ package net.mamoe.mirai.console.command.parse
|
||||
import net.mamoe.mirai.console.command.CommandSender
|
||||
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
|
||||
import net.mamoe.mirai.console.extensions.CommandCallParserProvider
|
||||
import net.mamoe.mirai.console.extensions.CommandCallParserProviderImpl
|
||||
import net.mamoe.mirai.console.internal.command.flattenCommandComponents
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
@ -22,6 +21,13 @@ import net.mamoe.mirai.message.data.content
|
||||
@ConsoleExperimentalApi
|
||||
@ExperimentalCommandDescriptors
|
||||
public object SpaceSeparatedCommandCallParser : CommandCallParser {
|
||||
|
||||
@ConsoleExperimentalApi
|
||||
@ExperimentalCommandDescriptors
|
||||
public object Provider : CommandCallParserProvider {
|
||||
override val instance: CommandCallParser get() = SpaceSeparatedCommandCallParser
|
||||
}
|
||||
|
||||
override fun parse(caller: CommandSender, message: MessageChain): CommandCall? {
|
||||
val flatten = message.flattenCommandComponents().filterIsInstance<MessageContent>()
|
||||
if (flatten.isEmpty()) return null
|
||||
@ -31,6 +37,4 @@ public object SpaceSeparatedCommandCallParser : CommandCallParser {
|
||||
valueArguments = flatten.drop(1).map(::DefaultCommandValueArgument)
|
||||
)
|
||||
}
|
||||
|
||||
public object Provider : CommandCallParserProvider by CommandCallParserProviderImpl(SpaceSeparatedCommandCallParser)
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -15,6 +15,7 @@ import net.mamoe.mirai.console.command.descriptor.ArgumentAcceptance.Companion.i
|
||||
import net.mamoe.mirai.console.command.parse.CommandCall
|
||||
import net.mamoe.mirai.console.command.parse.CommandValueArgument
|
||||
import net.mamoe.mirai.console.command.parse.DefaultCommandValueArgument
|
||||
import net.mamoe.mirai.console.extensions.CommandCallResolverProvider
|
||||
import net.mamoe.mirai.console.internal.data.classifierAsKClass
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import net.mamoe.mirai.console.util.safeCast
|
||||
@ -27,6 +28,11 @@ import net.mamoe.mirai.message.data.toMessageChain
|
||||
@ConsoleExperimentalApi
|
||||
@ExperimentalCommandDescriptors
|
||||
public object BuiltInCommandCallResolver : CommandCallResolver {
|
||||
|
||||
internal object Provider : CommandCallResolverProvider {
|
||||
override val instance: CommandCallResolver = BuiltInCommandCallResolver
|
||||
}
|
||||
|
||||
override fun resolve(call: CommandCall): CommandResolveResult {
|
||||
val callee = CommandManager.matchCommand(call.calleeName)
|
||||
?: return CommandResolveResult(CommandExecuteResult.UnresolvedCommand(call))
|
||||
|
@ -66,15 +66,13 @@ public interface CommandCallInterceptor {
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun Message.intercepted(caller: CommandSender): InterceptResult<Message> {
|
||||
GlobalComponentStorage.run {
|
||||
return CommandCallInterceptorProvider.foldExtensions(this@intercepted) { acc, ext ->
|
||||
val intercepted = ext.instance.interceptBeforeCall(acc, caller)
|
||||
intercepted?.fold(
|
||||
onIntercepted = { return intercepted },
|
||||
otherwise = { it }
|
||||
) ?: acc
|
||||
}.let { InterceptResult(it) }
|
||||
}
|
||||
return GlobalComponentStorage.foldExtensions(CommandCallInterceptorProvider, this@intercepted) { acc, ext ->
|
||||
val intercepted = ext.instance.interceptBeforeCall(acc, caller)
|
||||
intercepted?.fold(
|
||||
onIntercepted = { return intercepted },
|
||||
otherwise = { it }
|
||||
) ?: acc
|
||||
}.let { InterceptResult(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,15 +81,13 @@ public interface CommandCallInterceptor {
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun CommandCall.intercepted(): InterceptResult<CommandCall> {
|
||||
GlobalComponentStorage.run {
|
||||
return CommandCallInterceptorProvider.foldExtensions(this@intercepted) { acc, ext ->
|
||||
val intercepted = ext.instance.interceptCall(acc)
|
||||
intercepted?.fold(
|
||||
onIntercepted = { return intercepted },
|
||||
otherwise = { it }
|
||||
) ?: acc
|
||||
}.let { InterceptResult(it) }
|
||||
}
|
||||
return GlobalComponentStorage.foldExtensions(CommandCallInterceptorProvider, this@intercepted) { acc, ext ->
|
||||
val intercepted = ext.instance.interceptCall(acc)
|
||||
intercepted?.fold(
|
||||
onIntercepted = { return intercepted },
|
||||
otherwise = { it }
|
||||
) ?: acc
|
||||
}.let { InterceptResult(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,15 +96,13 @@ public interface CommandCallInterceptor {
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun ResolvedCommandCall.intercepted(): InterceptResult<ResolvedCommandCall> {
|
||||
GlobalComponentStorage.run {
|
||||
return CommandCallInterceptorProvider.foldExtensions(this@intercepted) { acc, ext ->
|
||||
val intercepted = ext.instance.interceptResolvedCall(acc)
|
||||
intercepted?.fold(
|
||||
onIntercepted = { return intercepted },
|
||||
otherwise = { it }
|
||||
) ?: acc
|
||||
}.let { InterceptResult(it) }
|
||||
}
|
||||
return GlobalComponentStorage.foldExtensions(CommandCallInterceptorProvider, this@intercepted) { acc, ext ->
|
||||
val intercepted = ext.instance.interceptResolvedCall(acc)
|
||||
intercepted?.fold(
|
||||
onIntercepted = { return intercepted },
|
||||
otherwise = { it }
|
||||
) ?: acc
|
||||
}.let { InterceptResult(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -76,11 +76,9 @@ public interface CommandCallResolver {
|
||||
@ConsoleExperimentalApi
|
||||
@ExperimentalCommandDescriptors
|
||||
public fun CommandCall.resolve(): CommandResolveResult {
|
||||
GlobalComponentStorage.run {
|
||||
val instance =
|
||||
CommandCallResolverProvider.findSingletonInstance(CommandCallResolverProvider.builtinImplementation)
|
||||
return instance.resolve(this@resolve)
|
||||
}
|
||||
return GlobalComponentStorage.getExtensions(CommandCallResolverProvider).first()
|
||||
.extension.instance
|
||||
.resolve(this@resolve)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -9,27 +9,99 @@
|
||||
|
||||
package net.mamoe.mirai.console.extension
|
||||
|
||||
import net.mamoe.mirai.console.ConsoleFrontEndImplementation
|
||||
import net.mamoe.mirai.console.MiraiConsoleImplementation
|
||||
import net.mamoe.mirai.console.plugin.Plugin
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin.Companion.onLoad
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalApi
|
||||
import java.util.stream.Stream
|
||||
|
||||
/**
|
||||
* 组件容器, 容纳 [Plugin] 注册的 [Extension].
|
||||
*
|
||||
* 插件可在 [JvmPlugin.onLoad] 时提供扩展. 前端可在 [MiraiConsoleImplementation.BackendAccess.globalComponentStorage] 获取全局组件容器.
|
||||
* 目前未允许获取全局组件容器. 如有需求请 [提交 issues](https://github.com/mamoe/mirai/issues/new/choose).
|
||||
*
|
||||
* 实现细节: 线程安全.
|
||||
*
|
||||
* @see Extension
|
||||
* @see JvmPlugin.onLoad
|
||||
*/
|
||||
public interface ComponentStorage {
|
||||
public fun <T : Extension> contribute(
|
||||
extensionPoint: ExtensionPoint<T>,
|
||||
plugin: Plugin,
|
||||
extensionInstance: T,
|
||||
)
|
||||
|
||||
public fun <T : Extension> contribute(
|
||||
extensionPoint: ExtensionPoint<T>,
|
||||
/**
|
||||
* 注册一个扩展
|
||||
*/
|
||||
public fun <E : Extension> contribute(
|
||||
extensionPoint: ExtensionPoint<E>,
|
||||
plugin: Plugin,
|
||||
lazyInstance: () -> T,
|
||||
)
|
||||
extensionInstance: E,
|
||||
) // 2.11: E changed to T (only naming)
|
||||
|
||||
/**
|
||||
* 注册一个扩展. [lazyInstance] 将会在 [getExtensions] 时才会计算.
|
||||
*/
|
||||
public fun <E : Extension> contribute(
|
||||
extensionPoint: ExtensionPoint<E>,
|
||||
plugin: Plugin,
|
||||
lazyInstance: () -> E,
|
||||
) // 2.11: E changed to T (only naming)
|
||||
|
||||
/**
|
||||
* 获取优先级最高的 [ExtensionPoint] 扩展实例. 在未找到任何注册的实例时抛出 [NoSuchElementException].
|
||||
*
|
||||
* @since 2.11
|
||||
*/
|
||||
@MiraiExperimentalApi
|
||||
public fun <E : Extension> getPreferredExtension(
|
||||
extensionPoint: ExtensionPoint<E>,
|
||||
): ExtensionRegistry<E> {
|
||||
return getExtensions(extensionPoint).firstOrNull()
|
||||
?: throw NoSuchElementException("No extension registered for $extensionPoint")
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取注册的 [ExtensionPoint] 扩展实例列表. 返回的 [Sequence] 以 [Extension.priority] 倒序排序.
|
||||
*
|
||||
* @since 2.11
|
||||
*/
|
||||
public fun <E : Extension> getExtensions(
|
||||
extensionPoint: ExtensionPoint<E>,
|
||||
): Sequence<ExtensionRegistry<E>>
|
||||
|
||||
/**
|
||||
* 获取注册的 [ExtensionPoint] 扩展实例列表. 返回的 [Stream] 以 [Extension.priority] 倒序排序.
|
||||
*
|
||||
* @since 2.11
|
||||
*/
|
||||
public fun <E : Extension> getExtensionsStream(
|
||||
extensionPoint: ExtensionPoint<E>,
|
||||
): Stream<ExtensionRegistry<E>>
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅前端实现可用
|
||||
*/
|
||||
@ConsoleFrontEndImplementation
|
||||
public interface ComponentStorageInternal : ComponentStorage {
|
||||
|
||||
/**
|
||||
* 注册一个由 Mirai Console 实现的扩展 (因此没有相关 [Plugin]). [lazyInstance] 将会在 [getExtensions] 时才会计算.
|
||||
*/
|
||||
public fun <E : Extension> contributeConsole(
|
||||
extensionPoint: ExtensionPoint<E>,
|
||||
lazyInstance: () -> E,
|
||||
)
|
||||
|
||||
/**
|
||||
* 注册一个由 Mirai Console 实现的扩展 (因此没有相关 [Plugin]).
|
||||
*/
|
||||
public fun <E : Extension> contributeConsole(
|
||||
extensionPoint: ExtensionPoint<E>,
|
||||
instance: E,
|
||||
) {
|
||||
@Suppress("USELESS_CAST") // bug
|
||||
contributeConsole(extensionPoint, { instance } as () -> E)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -9,12 +9,15 @@
|
||||
|
||||
package net.mamoe.mirai.console.extension
|
||||
|
||||
import net.mamoe.mirai.console.command.parse.SpaceSeparatedCommandCallParser
|
||||
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.extensions.SingletonExtensionSelector.ExtensionPoint.selectSingleton
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin.Companion.onLoad
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import net.mamoe.mirai.utils.DeprecatedSinceMirai
|
||||
|
||||
/**
|
||||
* 表示一个扩展.
|
||||
@ -37,7 +40,18 @@ import net.mamoe.mirai.console.plugin.jvm.JvmPlugin.Companion.onLoad
|
||||
*
|
||||
* @see ComponentStorage
|
||||
*/
|
||||
public interface Extension
|
||||
public interface Extension {
|
||||
/**
|
||||
* 优先级. 越高越先使用. 内嵌的 [SpaceSeparatedCommandCallParser] 拥有优先级 0.
|
||||
*
|
||||
* 若两个 [InstanceExtension] 有相同的优先级, 将会优先使用内嵌的实现, 再按 [ComponentStorage.contribute] 顺序依次使用.
|
||||
*
|
||||
* @since 2.11
|
||||
*/ // https://github.com/mamoe/mirai/issues/1860
|
||||
@ConsoleExperimentalApi
|
||||
public val priority: Int
|
||||
get() = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加一些函数 (方法)的扩展
|
||||
@ -51,6 +65,8 @@ public interface FunctionExtension : Extension
|
||||
*
|
||||
* @see PermissionServiceProvider
|
||||
*/
|
||||
@Deprecated("Please use InstanceExtension instead.", replaceWith = ReplaceWith("InstanceExtension"))
|
||||
@DeprecatedSinceMirai(warningSince = "2.11")
|
||||
public interface SingletonExtension<T> : Extension {
|
||||
public val instance: T
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -12,13 +12,15 @@
|
||||
package net.mamoe.mirai.console.extension
|
||||
|
||||
import net.mamoe.mirai.console.extensions.SingletonExtensionSelector
|
||||
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import net.mamoe.mirai.utils.DeprecatedSinceMirai
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
||||
/**
|
||||
* 由 [Extension] 的伴生对象实现.
|
||||
* 表示一个扩展接入点(扩展类型). 在 Kotlin 由 [Extension] 的伴生对象实现, 在 Java 可通过静态字段提供.
|
||||
*
|
||||
* 在[注册扩展][ComponentStorage.contribute]时需要提供其 [ExtensionPoint], [ExtensionPoint] 也可以用于获取所有注册的扩展 ([ComponentStorage.getExtensions]).
|
||||
*
|
||||
* @see AbstractExtensionPoint
|
||||
*/
|
||||
@ -37,6 +39,8 @@ public abstract class AbstractExtensionPoint<T : Extension>(
|
||||
/**
|
||||
* 表示一个 [SingletonExtension] 的 [ExtensionPoint]
|
||||
*/
|
||||
@Deprecated("Please use InstanceExtensionPoint instead.", replaceWith = ReplaceWith("InstanceExtensionPoint"))
|
||||
@DeprecatedSinceMirai(warningSince = "2.11")
|
||||
public interface SingletonExtensionPoint<T : SingletonExtension<*>> : ExtensionPoint<T>
|
||||
|
||||
/**
|
||||
@ -55,34 +59,56 @@ public abstract class AbstractInstanceExtensionPoint<E : InstanceExtension<T>, T
|
||||
* @since 2.10
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
constructor(
|
||||
extensionType: KClass<E>,
|
||||
/**
|
||||
* 内建的实现列表.
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public vararg val builtinImplementations: () -> E,
|
||||
public constructor(
|
||||
extensionType: KClass<E>
|
||||
) : AbstractExtensionPoint<E>(extensionType) {
|
||||
|
||||
/**
|
||||
* @since 2.10
|
||||
*/
|
||||
@Deprecated(
|
||||
"Default(builtin) implementations are not allowed any more. " +
|
||||
"For plugin authors, provide them with lower priority when plugin being loaded(through the ComponentScope). " +
|
||||
"For frontend implementers, provide them by `BackendAccess.globalComponentScope.contribute`. ",
|
||||
replaceWith = ReplaceWith("AbstractInstanceExtensionPoint(extensionType)"),
|
||||
level = DeprecationLevel.ERROR,
|
||||
)
|
||||
@DeprecatedSinceMirai(errorSince = "2.11") // for removal
|
||||
@ConsoleExperimentalApi
|
||||
public constructor(extensionType: KClass<E>) : this(
|
||||
extensionType,
|
||||
builtinImplementations = arrayOf<() -> E>() as Array<out () -> E>
|
||||
) // to avoid resolution ambiguity
|
||||
public constructor(
|
||||
extensionType: KClass<E>,
|
||||
/**
|
||||
* 内建的实现列表.
|
||||
*/
|
||||
builtinImplementations: () -> E,
|
||||
) : this(extensionType)
|
||||
|
||||
/**
|
||||
* @since 2.0
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
@Deprecated(
|
||||
"Default(builtin) implementations are not allowed any more. " +
|
||||
"For plugin authors, provide them with lower priority when plugin being loaded(through the ComponentScope). " +
|
||||
"For frontend implementers, provide them by `BackendAccess.globalComponentScope.contribute`. ",
|
||||
replaceWith = ReplaceWith("AbstractInstanceExtensionPoint(extensionType)"),
|
||||
level = DeprecationLevel.ERROR
|
||||
)
|
||||
@DeprecatedSinceMirai(errorSince = "2.11") // for removal
|
||||
@ConsoleExperimentalApi // was experimental since 2.0
|
||||
public constructor(extensionType: KClass<E>, vararg builtinImplementations: E) : this(
|
||||
extensionType,
|
||||
builtinImplementations = builtinImplementations.map { { it } }.toTypedArray()
|
||||
)
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
"Please use AbstractInstanceExtensionPoint instead.",
|
||||
replaceWith = ReplaceWith(
|
||||
"AbstractInstanceExtension",
|
||||
"net.mamoe.mirai.console.extension.AbstractInstanceExtensionPoint"
|
||||
)
|
||||
)
|
||||
@DeprecatedSinceMirai(warningSince = "2.11")
|
||||
@Suppress("DEPRECATION")
|
||||
public abstract class AbstractSingletonExtensionPoint<E : SingletonExtension<T>, T>
|
||||
/**
|
||||
* @since 2.10
|
||||
@ -111,12 +137,6 @@ constructor(
|
||||
* 由 [SingletonExtensionSelector] 选择后的实例.
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public open val selectedInstance: T by lazy {
|
||||
GlobalComponentStorage.run {
|
||||
this@AbstractSingletonExtensionPoint.findSingletonInstance(
|
||||
extensionType,
|
||||
builtinImplementation
|
||||
)
|
||||
}
|
||||
}
|
||||
public open val selectedInstance: T
|
||||
get() = throw UnsupportedOperationException("SingletonExtension has been deprecated.")
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.extension
|
||||
|
||||
import net.mamoe.mirai.console.plugin.Plugin
|
||||
import net.mamoe.mirai.utils.NotStableForInheritance
|
||||
|
||||
/**
|
||||
* 一个已经注册的 [Extension]. 可通过 [ComponentStorage.getExtensions] 获得.
|
||||
*
|
||||
* @since 2.11
|
||||
*/
|
||||
@NotStableForInheritance
|
||||
public interface ExtensionRegistry<E : Extension> {
|
||||
/**
|
||||
* 提供该 [ExtensionRegistry] 的插件. 若为 `null` 则表示由 Mirai Console 内置或者由前端实现.
|
||||
*/
|
||||
public val plugin: Plugin?
|
||||
|
||||
/**
|
||||
* [Extension] 实例.
|
||||
*/
|
||||
public val extension: E
|
||||
}
|
||||
|
||||
internal inline val <T> ExtensionRegistry<out InstanceExtension<T>>.instance get() = extension.instance
|
||||
|
||||
internal class ExtensionRegistryImpl<E : Extension> internal constructor(
|
||||
/**
|
||||
* 提供该 [ExtensionRegistry] 的插件. 若为 `null` 则表示由 Mirai Console 内置或者由前端实现.
|
||||
*/
|
||||
override val plugin: Plugin?,
|
||||
/**
|
||||
* [Extension] 实例.
|
||||
*/
|
||||
extensionInitializer: () -> E,
|
||||
) : ExtensionRegistry<E> {
|
||||
override val extension: E by lazy(extensionInitializer)
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -13,19 +13,25 @@ import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
|
||||
import net.mamoe.mirai.console.command.resolve.CommandCallInterceptor
|
||||
import net.mamoe.mirai.console.extension.AbstractInstanceExtensionPoint
|
||||
import net.mamoe.mirai.console.extension.InstanceExtension
|
||||
import net.mamoe.mirai.utils.DeprecatedSinceMirai
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
public interface CommandCallInterceptorProvider : InstanceExtension<CommandCallInterceptor> {
|
||||
@ExperimentalCommandDescriptors
|
||||
public companion object ExtensionPoint :
|
||||
AbstractInstanceExtensionPoint<CommandCallInterceptorProvider, CommandCallInterceptor>(
|
||||
CommandCallInterceptorProvider::class
|
||||
)
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated for removal. Please implement your own CommandCallInterceptorProvider.")
|
||||
@DeprecatedSinceMirai(warningSince = "2.11") // for removal.
|
||||
@ExperimentalCommandDescriptors
|
||||
public class CommandCallInterceptorProviderImpl(override val instance: CommandCallInterceptor) :
|
||||
CommandCallInterceptorProvider
|
||||
|
||||
@Deprecated("Deprecated for removal. Please implement your own CommandCallInterceptorProvider.")
|
||||
@DeprecatedSinceMirai(warningSince = "2.11") // for removal.
|
||||
@ExperimentalCommandDescriptors
|
||||
public class CommandCallInterceptorProviderImplLazy(initializer: () -> CommandCallInterceptor) :
|
||||
CommandCallInterceptorProvider {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -11,26 +11,27 @@ package net.mamoe.mirai.console.extensions
|
||||
|
||||
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
|
||||
import net.mamoe.mirai.console.command.parse.CommandCallParser
|
||||
import net.mamoe.mirai.console.command.parse.SpaceSeparatedCommandCallParser
|
||||
import net.mamoe.mirai.console.extension.AbstractInstanceExtensionPoint
|
||||
import net.mamoe.mirai.console.extension.InstanceExtension
|
||||
import net.mamoe.mirai.utils.DeprecatedSinceMirai
|
||||
|
||||
/**
|
||||
* The provider of [CommandCallParser]
|
||||
*/
|
||||
@ExperimentalCommandDescriptors
|
||||
public interface CommandCallParserProvider : InstanceExtension<CommandCallParser> {
|
||||
@ExperimentalCommandDescriptors
|
||||
public companion object ExtensionPoint :
|
||||
AbstractInstanceExtensionPoint<CommandCallParserProvider, CommandCallParser>(
|
||||
CommandCallParserProvider::class,
|
||||
SpaceSeparatedCommandCallParser.Provider
|
||||
)
|
||||
AbstractInstanceExtensionPoint<CommandCallParserProvider, CommandCallParser>(CommandCallParserProvider::class)
|
||||
}
|
||||
|
||||
|
||||
@Deprecated("Deprecated for removal. Please implement your own CommandCallParserProvider.")
|
||||
@DeprecatedSinceMirai(warningSince = "2.11") // for removal.
|
||||
@ExperimentalCommandDescriptors
|
||||
public class CommandCallParserProviderImpl(override val instance: CommandCallParser) : CommandCallParserProvider
|
||||
|
||||
@Deprecated("Deprecated for removal. Please implement your own CommandCallParserProvider.")
|
||||
@DeprecatedSinceMirai(warningSince = "2.11") // for removal.
|
||||
@ExperimentalCommandDescriptors
|
||||
public class CommandCallParserProviderImplLazy(initializer: () -> CommandCallParser) : CommandCallParserProvider {
|
||||
override val instance: CommandCallParser by lazy(initializer)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -10,23 +10,26 @@
|
||||
package net.mamoe.mirai.console.extensions
|
||||
|
||||
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
|
||||
import net.mamoe.mirai.console.command.resolve.BuiltInCommandCallResolver
|
||||
import net.mamoe.mirai.console.command.resolve.CommandCallResolver
|
||||
import net.mamoe.mirai.console.extension.AbstractSingletonExtensionPoint
|
||||
import net.mamoe.mirai.console.extension.SingletonExtension
|
||||
import net.mamoe.mirai.console.extension.AbstractInstanceExtensionPoint
|
||||
import net.mamoe.mirai.console.extension.InstanceExtension
|
||||
import net.mamoe.mirai.utils.DeprecatedSinceMirai
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
public interface CommandCallResolverProvider : SingletonExtension<CommandCallResolver> {
|
||||
public interface CommandCallResolverProvider : InstanceExtension<CommandCallResolver> {
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
public companion object ExtensionPoint :
|
||||
AbstractSingletonExtensionPoint<CommandCallResolverProvider, CommandCallResolver>(
|
||||
CommandCallResolverProvider::class,
|
||||
{ BuiltInCommandCallResolver }
|
||||
)
|
||||
AbstractInstanceExtensionPoint<CommandCallResolverProvider, CommandCallResolver>(CommandCallResolverProvider::class)
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated for removal. Please implement your own CommandCallResolverProvider.")
|
||||
@DeprecatedSinceMirai(warningSince = "2.11") // for removal.
|
||||
@ExperimentalCommandDescriptors
|
||||
public class CommandCallResolverProviderImpl(override val instance: CommandCallResolver) : CommandCallResolverProvider
|
||||
|
||||
@Deprecated("Deprecated for removal. Please implement your own CommandCallResolverProvider.")
|
||||
@DeprecatedSinceMirai(warningSince = "2.11") // for removal.
|
||||
@ExperimentalCommandDescriptors
|
||||
public class CommandCallResolverProviderImplLazy(initializer: () -> CommandCallResolver) : CommandCallResolverProvider {
|
||||
override val instance: CommandCallResolver by lazy(initializer)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -9,55 +9,35 @@
|
||||
|
||||
package net.mamoe.mirai.console.extensions
|
||||
|
||||
import net.mamoe.mirai.console.extension.AbstractSingletonExtensionPoint
|
||||
import net.mamoe.mirai.console.extension.SingletonExtension
|
||||
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
|
||||
import net.mamoe.mirai.console.internal.permission.BuiltInPermissionService
|
||||
import net.mamoe.mirai.console.extension.AbstractInstanceExtensionPoint
|
||||
import net.mamoe.mirai.console.extension.InstanceExtension
|
||||
import net.mamoe.mirai.console.permission.PermissionService
|
||||
import net.mamoe.mirai.console.plugin.Plugin
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import net.mamoe.mirai.utils.DeprecatedSinceMirai
|
||||
|
||||
/**
|
||||
* [权限服务][PermissionService] 提供器.
|
||||
*
|
||||
* 当插件注册 [PermissionService] 后, 默认会使用插件的 [PermissionService].
|
||||
*/
|
||||
public interface PermissionServiceProvider : SingletonExtension<PermissionService<*>> {
|
||||
public interface PermissionServiceProvider : InstanceExtension<PermissionService<*>> {
|
||||
|
||||
public companion object ExtensionPoint :
|
||||
AbstractSingletonExtensionPoint<PermissionServiceProvider, PermissionService<*>>(
|
||||
PermissionServiceProvider::class,
|
||||
{ BuiltInPermissionService() }
|
||||
) {
|
||||
internal var permissionServiceOk = false
|
||||
|
||||
@ConsoleExperimentalApi
|
||||
public val providerPlugin: Plugin? by lazy {
|
||||
GlobalComponentStorage.run {
|
||||
val instance = PermissionService.INSTANCE
|
||||
if (instance is BuiltInPermissionService) return@lazy null
|
||||
PermissionServiceProvider.getExtensions().find { it.extension.instance === instance }?.plugin
|
||||
}
|
||||
}
|
||||
|
||||
@ConsoleExperimentalApi
|
||||
override val selectedInstance: PermissionService<*>
|
||||
get() {
|
||||
if (!permissionServiceOk) {
|
||||
error("PermissionService not yet loaded")
|
||||
}
|
||||
return super.selectedInstance
|
||||
}
|
||||
}
|
||||
AbstractInstanceExtensionPoint<PermissionServiceProvider, PermissionService<*>>(PermissionServiceProvider::class)
|
||||
// ! BREAKING CHANGE MADE IN 2.11: supertype changed from AbstractSingletonExtensionPoint to AbstractInstanceExtensionPoint
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PermissionServiceProvider
|
||||
*/
|
||||
@Deprecated("Please implement your own PermissionServiceProvider.")
|
||||
@DeprecatedSinceMirai(warningSince = "2.11") // for hidden.
|
||||
public class PermissionServiceProviderImpl(override val instance: PermissionService<*>) : PermissionServiceProvider
|
||||
|
||||
/**
|
||||
* @see PermissionServiceProvider
|
||||
*/
|
||||
@Deprecated("Please implement your own PermissionServiceProvider.")
|
||||
@DeprecatedSinceMirai(warningSince = "2.11") // for hidden.
|
||||
public class PermissionServiceProviderImplLazy(initializer: () -> PermissionService<*>) : PermissionServiceProvider {
|
||||
override val instance: PermissionService<*> by lazy(initializer)
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -14,6 +14,7 @@ import net.mamoe.mirai.console.extension.Extension
|
||||
import net.mamoe.mirai.console.extension.InstanceExtension
|
||||
import net.mamoe.mirai.console.extension.PluginComponentStorage
|
||||
import net.mamoe.mirai.console.plugin.loader.PluginLoader
|
||||
import net.mamoe.mirai.utils.DeprecatedSinceMirai
|
||||
|
||||
/**
|
||||
* 提供扩展 [PluginLoader]
|
||||
@ -30,8 +31,12 @@ public interface PluginLoaderProvider : InstanceExtension<PluginLoader<*, *>> {
|
||||
public companion object ExtensionPoint : AbstractExtensionPoint<PluginLoaderProvider>(PluginLoaderProvider::class)
|
||||
}
|
||||
|
||||
@Deprecated("Please implement your own PluginLoaderProvider.")
|
||||
@DeprecatedSinceMirai(warningSince = "2.11") // for hidden.
|
||||
public class PluginLoaderProviderImpl(override val instance: PluginLoader<*, *>) : PluginLoaderProvider
|
||||
|
||||
@Deprecated("Please implement your own PluginLoaderProvider.")
|
||||
@DeprecatedSinceMirai(warningSince = "2.11") // for hidden.
|
||||
public class PluginLoaderProviderImplLazy(initializer: () -> PluginLoader<*, *>) : PluginLoaderProvider {
|
||||
override val instance: PluginLoader<*, *> by lazy(initializer)
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -7,18 +7,17 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package net.mamoe.mirai.console.extensions
|
||||
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.extension.AbstractExtensionPoint
|
||||
import net.mamoe.mirai.console.extension.Extension
|
||||
import net.mamoe.mirai.console.extension.FunctionExtension
|
||||
import net.mamoe.mirai.console.extension.SingletonExtension
|
||||
import net.mamoe.mirai.console.internal.extension.SingletonExtensionSelectorImpl
|
||||
import net.mamoe.mirai.console.internal.extension.ExtensionRegistry
|
||||
import net.mamoe.mirai.console.extension.*
|
||||
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
|
||||
import net.mamoe.mirai.console.internal.extension.SingletonExtensionSelectorImpl
|
||||
import net.mamoe.mirai.console.plugin.Plugin
|
||||
import net.mamoe.mirai.console.plugin.name
|
||||
import net.mamoe.mirai.utils.DeprecatedSinceMirai
|
||||
import net.mamoe.mirai.utils.info
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@ -27,10 +26,20 @@ import kotlin.reflect.KClass
|
||||
*
|
||||
* 如有多个 [SingletonExtensionSelector] 注册, 将会停止服务器.
|
||||
*/
|
||||
@Deprecated(
|
||||
"Order of extensions is now determined by its priority property since 2.11. SingletonExtensionSelector is not needed anymore. ",
|
||||
level = DeprecationLevel.WARNING
|
||||
)
|
||||
@DeprecatedSinceMirai(warningSince = "2.11")
|
||||
public interface SingletonExtensionSelector : FunctionExtension {
|
||||
/**
|
||||
* 表示一个插件注册的 [Extension]
|
||||
*/
|
||||
@Deprecated(
|
||||
"Order of extensions is now determined by its priority property since 2.11. SingletonExtensionSelector is not needed anymore. ",
|
||||
level = DeprecationLevel.WARNING
|
||||
)
|
||||
@DeprecatedSinceMirai(warningSince = "2.11")
|
||||
public data class Registry<T : Extension>(
|
||||
val plugin: Plugin?,
|
||||
val extension: T,
|
||||
@ -44,6 +53,11 @@ public interface SingletonExtensionSelector : FunctionExtension {
|
||||
candidates: Collection<Registry<T>>,
|
||||
): T?
|
||||
|
||||
@Deprecated(
|
||||
"Order of extensions is now determined by its priority property since 2.11. SingletonExtensionSelector is not needed anymore. ",
|
||||
level = DeprecationLevel.WARNING
|
||||
)
|
||||
@DeprecatedSinceMirai(warningSince = "2.11")
|
||||
public companion object ExtensionPoint :
|
||||
AbstractExtensionPoint<SingletonExtensionSelector>(SingletonExtensionSelector::class) {
|
||||
|
||||
@ -53,16 +67,22 @@ public interface SingletonExtensionSelector : FunctionExtension {
|
||||
|
||||
internal fun init() {
|
||||
check(instanceField == null) { "Internal error: reinitialize SingletonExtensionSelector" }
|
||||
val instances = GlobalComponentStorage.run { SingletonExtensionSelector.getExtensions() }
|
||||
val instances = GlobalComponentStorage.getExtensions(ExtensionPoint).toList()
|
||||
instanceField = when {
|
||||
instances.isEmpty() -> SingletonExtensionSelectorImpl
|
||||
instances.size == 1 -> {
|
||||
instances.single().also { (plugin, ext) ->
|
||||
MiraiConsole.mainLogger.info { "Loaded SingletonExtensionSelector: $ext from ${plugin?.name ?: "<builtin>"}" }
|
||||
instances.single().also { registry ->
|
||||
MiraiConsole.mainLogger.info { "Loaded SingletonExtensionSelector: ${registry.extension} from ${registry.plugin?.name ?: "<builtin>"}" }
|
||||
}.extension
|
||||
}
|
||||
else -> {
|
||||
error("Found too many SingletonExtensionSelectors: ${instances.joinToString { (p, i) -> "'$i' from '${p?.name ?: "<builtin>"}'" }}. Check your plugins and ensure there is only one external SingletonExtensionSelectors")
|
||||
val hint = instances.joinToString { reg ->
|
||||
"'${reg.extension}' from '${reg.plugin?.name ?: "<builtin>"}'"
|
||||
}
|
||||
error(
|
||||
"Found too many SingletonExtensionSelectors: $hint. " +
|
||||
"Check your plugins and ensure there is only one external SingletonExtensionSelectors"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,13 @@ import net.mamoe.mirai.console.MiraiConsoleImplementation
|
||||
import net.mamoe.mirai.console.command.BuiltInCommands
|
||||
import net.mamoe.mirai.console.command.CommandManager
|
||||
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
||||
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
|
||||
import net.mamoe.mirai.console.command.parse.SpaceSeparatedCommandCallParser
|
||||
import net.mamoe.mirai.console.command.resolve.BuiltInCommandCallResolver
|
||||
import net.mamoe.mirai.console.extensions.CommandCallParserProvider
|
||||
import net.mamoe.mirai.console.extensions.CommandCallResolverProvider
|
||||
import net.mamoe.mirai.console.extensions.PermissionServiceProvider
|
||||
import net.mamoe.mirai.console.extensions.PostStartupExtension
|
||||
import net.mamoe.mirai.console.extensions.SingletonExtensionSelector
|
||||
import net.mamoe.mirai.console.internal.command.CommandConfig
|
||||
import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig
|
||||
import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig.Account.ConfigurationKey
|
||||
@ -32,7 +36,7 @@ import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig.Account.Pa
|
||||
import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig.Account.PasswordKind.PLAIN
|
||||
import net.mamoe.mirai.console.internal.data.builtins.LoggerConfig
|
||||
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
|
||||
import net.mamoe.mirai.console.internal.extension.SingletonExtensionSelectorImpl
|
||||
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorageImpl
|
||||
import net.mamoe.mirai.console.internal.logging.LoggerControllerImpl
|
||||
import net.mamoe.mirai.console.internal.logging.MiraiConsoleLogger
|
||||
import net.mamoe.mirai.console.internal.permission.BuiltInPermissionService
|
||||
@ -77,6 +81,9 @@ internal class MiraiConsoleImplementationBridge(
|
||||
override val version: SemVersion by MiraiConsoleBuildConstants::version
|
||||
override val pluginManager: PluginManagerImpl by lazy { PluginManagerImpl(coroutineContext) }
|
||||
|
||||
// used internally
|
||||
val globalComponentStorage: GlobalComponentStorageImpl by lazy { GlobalComponentStorageImpl() }
|
||||
|
||||
override val mainLogger: MiraiLogger by lazy { createLogger("main") }
|
||||
|
||||
init {
|
||||
@ -99,6 +106,15 @@ internal class MiraiConsoleImplementationBridge(
|
||||
internal fun doStart() {
|
||||
externalImplementation.preStart()
|
||||
|
||||
@OptIn(ExperimentalCommandDescriptors::class)
|
||||
phase("register builtin componenets") {
|
||||
GlobalComponentStorage.run {
|
||||
contributeConsole(CommandCallParserProvider, SpaceSeparatedCommandCallParser.Provider)
|
||||
contributeConsole(CommandCallResolverProvider, BuiltInCommandCallResolver.Provider)
|
||||
contributeConsole(PermissionServiceProvider, BuiltInPermissionService.Provider())
|
||||
}
|
||||
}
|
||||
|
||||
phase("setup logger controller") {
|
||||
if (loggerController === LoggerControllerImpl) {
|
||||
// Reload LoggerConfig.
|
||||
@ -159,25 +175,30 @@ internal class MiraiConsoleImplementationBridge(
|
||||
mainLogger.verbose { "${PluginManager.plugins.size} plugin(s) loaded." }
|
||||
}
|
||||
|
||||
phase("load SingletonExtensionSelector") {
|
||||
SingletonExtensionSelector.init()
|
||||
val instance = SingletonExtensionSelector.instance
|
||||
if (instance is SingletonExtensionSelectorImpl) {
|
||||
consoleDataScope.addAndReloadConfig(instance.config)
|
||||
}
|
||||
}
|
||||
// phase("load SingletonExtensionSelector") {
|
||||
// SingletonExtensionSelector.init()
|
||||
// val instance = SingletonExtensionSelector.instance
|
||||
// if (instance is SingletonExtensionSelectorImpl) {
|
||||
// consoleDataScope.addAndReloadConfig(instance.config)
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
phase("load PermissionService") {
|
||||
mainLogger.verbose { "Loading PermissionService..." }
|
||||
|
||||
PermissionServiceProvider.permissionServiceOk = true
|
||||
PermissionService.INSTANCE.let { ps ->
|
||||
if (ps is BuiltInPermissionService) {
|
||||
consoleDataScope.addAndReloadConfig(ps.config)
|
||||
mainLogger.verbose { "Reloaded PermissionService settings." }
|
||||
} else {
|
||||
mainLogger.info { "Loaded PermissionService from plugin ${PermissionServiceProvider.providerPlugin?.name}" }
|
||||
mainLogger.info {
|
||||
"Loaded PermissionService from plugin ${
|
||||
GlobalComponentStorage.getPreferredExtension(
|
||||
PermissionServiceProvider
|
||||
).plugin?.name
|
||||
}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,9 +279,7 @@ internal class MiraiConsoleImplementationBridge(
|
||||
}
|
||||
|
||||
phase("finally post") {
|
||||
GlobalComponentStorage.run {
|
||||
PostStartupExtension.useExtensions { it() } // exceptions thrown will be caught by caller of `doStart`.
|
||||
}
|
||||
globalComponentStorage.useEachExtensions(PostStartupExtension) { it.invoke() }
|
||||
}
|
||||
|
||||
externalImplementation.postStart()
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -10,140 +10,116 @@
|
||||
package net.mamoe.mirai.console.internal.extension
|
||||
|
||||
import net.mamoe.mirai.console.extension.*
|
||||
import net.mamoe.mirai.console.extensions.SingletonExtensionSelector
|
||||
import net.mamoe.mirai.console.extensions.SingletonExtensionSelector.ExtensionPoint.selectSingleton
|
||||
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
|
||||
import net.mamoe.mirai.console.internal.data.kClassQualifiedNameOrTip
|
||||
import net.mamoe.mirai.console.plugin.Plugin
|
||||
import net.mamoe.mirai.console.plugin.name
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.CopyOnWriteArraySet
|
||||
import java.util.stream.Stream
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
internal class GlobalComponentStorageImpl : AbstractConcurrentComponentStorage()
|
||||
|
||||
// source compatibility for <2.11
|
||||
internal val GlobalComponentStorage get() = MiraiConsoleImplementationBridge.globalComponentStorage
|
||||
|
||||
/**
|
||||
* The [ComponentStorage] containing all components provided by Mirai Console internals and installed plugins.
|
||||
* thread-safe.
|
||||
*/
|
||||
internal object GlobalComponentStorage : AbstractConcurrentComponentStorage()
|
||||
internal interface ExtensionRegistry<out E : Extension> {
|
||||
val plugin: Plugin?
|
||||
val extension: E
|
||||
internal abstract class AbstractConcurrentComponentStorage : ComponentStorage, ComponentStorageInternal {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// registry implementation
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
operator fun component1(): Plugin? {
|
||||
return this.plugin
|
||||
}
|
||||
/**
|
||||
* For each [ExtensionPoint]. thread-safe.
|
||||
*/
|
||||
internal class Registries<T : Extension> {
|
||||
@Volatile
|
||||
private var data: MutableCollection<ExtensionRegistry<T>> = ArrayList()
|
||||
private val lock = Any()
|
||||
|
||||
operator fun component2(): E {
|
||||
return this.extension
|
||||
}
|
||||
}
|
||||
|
||||
internal class LazyExtensionRegistry<out E : Extension>(
|
||||
override val plugin: Plugin?,
|
||||
initializer: () -> E,
|
||||
) : ExtensionRegistry<E> {
|
||||
override val extension: E by lazy { initializer() }
|
||||
}
|
||||
|
||||
internal data class DataExtensionRegistry<out E : Extension>(
|
||||
override val plugin: Plugin?,
|
||||
override val extension: E,
|
||||
) : ExtensionRegistry<E>
|
||||
|
||||
internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
||||
private val instances: MutableMap<ExtensionPoint<*>, MutableSet<ExtensionRegistry<*>>> = ConcurrentHashMap()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal fun <T : Extension> ExtensionPoint<out T>.getExtensions(): Set<ExtensionRegistry<T>> {
|
||||
val userDefined = instances.getOrPut(this, ::CopyOnWriteArraySet) as Set<ExtensionRegistry<T>>
|
||||
|
||||
val builtins = if (this is AbstractInstanceExtensionPoint<*, *>) {
|
||||
this.builtinImplementations.mapTo(HashSet()) { instance ->
|
||||
DataExtensionRegistry(
|
||||
null,
|
||||
instance()
|
||||
fun register(registry: ExtensionRegistry<T>) {
|
||||
synchronized(lock) {
|
||||
val list = PriorityQueue(
|
||||
data.size + 1,
|
||||
Comparator.comparing<ExtensionRegistry<T>, Int> { it.extension.priority }.reversed()
|
||||
)
|
||||
} as Set<ExtensionRegistry<T>>
|
||||
} else null
|
||||
|
||||
return builtins?.plus(userDefined) ?: userDefined
|
||||
}
|
||||
|
||||
// unused for now
|
||||
internal fun removeExtensionsRegisteredByPlugin(plugin: Plugin) {
|
||||
instances.forEach { (_, u) ->
|
||||
u.removeAll { it.plugin == plugin }
|
||||
list.addAll(data)
|
||||
list.add(registry)
|
||||
data = list
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return thread-safe Sequence
|
||||
*/
|
||||
fun asSequence(): Sequence<ExtensionRegistry<T>> = data.asSequence()
|
||||
|
||||
/**
|
||||
* @return thread-safe Sequence
|
||||
*/
|
||||
fun asStream(): Stream<ExtensionRegistry<T>> = data.stream()
|
||||
}
|
||||
|
||||
private val registries: MutableMap<ExtensionPoint<*>, Registries<*>> = ConcurrentHashMap()
|
||||
|
||||
private fun <T : Extension> getRegistries(ep: ExtensionPoint<T>): Registries<T> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return registries.getOrPut(ep) { Registries<T>() } as Registries<T>
|
||||
}
|
||||
|
||||
private fun <T : Extension> registerExtension(ep: ExtensionPoint<T>, registry: ExtensionRegistry<T>) {
|
||||
getRegistries(ep).register(registry)
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// public API implementation
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
internal fun mergeWith(another: AbstractConcurrentComponentStorage) {
|
||||
for ((ep, list) in another.instances) {
|
||||
for (extensionRegistry in list) {
|
||||
another.registries.forEach { (ep, registries) ->
|
||||
for (extensionRegistry in registries.asSequence()) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
ep as ExtensionPoint<Extension>
|
||||
this.contribute(ep, extensionRegistry.plugin, lazyInstance = { extensionRegistry.extension })
|
||||
registerExtension(ep, ExtensionRegistryImpl(extensionRegistry.plugin) { extensionRegistry.extension })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun <T : Extension> ExtensionPoint<out T>.withExtensions(block: T.() -> Unit) {
|
||||
return withExtensions { _ -> block() }
|
||||
}
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
@kotlin.internal.LowPriorityInOverloadResolution
|
||||
internal inline fun <T : Extension> ExtensionPoint<out T>.withExtensions(block: T.(plugin: Plugin?) -> Unit) {
|
||||
contract {
|
||||
callsInPlace(block)
|
||||
}
|
||||
for ((plugin, extension) in this.getExtensions()) {
|
||||
internal inline fun <T : Extension> useEachExtensions(
|
||||
extensionPoint: ExtensionPoint<T>,
|
||||
block: ExtensionRegistry<T>.(instance: T) -> Unit
|
||||
) {
|
||||
contract { callsInPlace(block) }
|
||||
getExtensions(extensionPoint).forEach { registry ->
|
||||
val plugin = registry.plugin
|
||||
val extension = registry.extension
|
||||
kotlin.runCatching {
|
||||
block.invoke(extension, plugin)
|
||||
block.invoke(registry, registry.extension)
|
||||
}.getOrElse { throwable ->
|
||||
throwExtensionException(extension, plugin, throwable)
|
||||
extensionPoint.throwExtensionException(extension, plugin, throwable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun <reified E : SingletonExtension<*>> ExtensionPoint<out E>.findSingleton(builtin: E): E =
|
||||
findSingleton(E::class, builtin)
|
||||
|
||||
internal fun <E : SingletonExtension<*>> ExtensionPoint<out E>.findSingleton(type: KClass<E>, builtin: E): E {
|
||||
val candidates = this.getExtensions()
|
||||
return when (candidates.size) {
|
||||
0 -> builtin
|
||||
1 -> candidates.single().extension
|
||||
else -> SingletonExtensionSelector.instance.selectSingleton(type, candidates) ?: builtin
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun <reified E : SingletonExtension<T>, T> ExtensionPoint<out E>.findSingletonInstance(noinline default: () -> T): T =
|
||||
findSingletonInstance(E::class, default)
|
||||
|
||||
internal fun <E : SingletonExtension<T>, T> ExtensionPoint<out E>.findSingletonInstance(
|
||||
type: KClass<E>,
|
||||
default: () -> T,
|
||||
): T {
|
||||
val candidates = this.getExtensions()
|
||||
return when (candidates.size) {
|
||||
0 -> default()
|
||||
1 -> candidates.single().extension.instance
|
||||
else -> SingletonExtensionSelector.instance.selectSingleton(type, candidates)?.instance ?: default()
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun <T : Extension, E> ExtensionPoint<out T>.foldExtensions(
|
||||
internal inline fun <T : Extension, E> foldExtensions(
|
||||
extensionPoint: ExtensionPoint<T>,
|
||||
initial: E,
|
||||
block: (acc: E, extension: T) -> E,
|
||||
): E {
|
||||
contract {
|
||||
callsInPlace(block)
|
||||
}
|
||||
contract { callsInPlace(block) }
|
||||
var e: E = initial
|
||||
for ((plugin, extension) in this.getExtensions()) {
|
||||
getExtensions(extensionPoint).forEach { registry ->
|
||||
val plugin = registry.plugin
|
||||
val extension = registry.extension
|
||||
kotlin.runCatching {
|
||||
e = block.invoke(e, extension)
|
||||
}.getOrElse { throwable ->
|
||||
throwExtensionException(extension, plugin, throwable)
|
||||
extensionPoint.throwExtensionException(extension, plugin, throwable)
|
||||
}
|
||||
}
|
||||
return e
|
||||
@ -153,52 +129,38 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
||||
extension: T,
|
||||
plugin: Plugin?,
|
||||
throwable: Throwable,
|
||||
) {
|
||||
): Nothing {
|
||||
throw ExtensionException(
|
||||
"Exception while executing extension '${extension.kClassQualifiedNameOrTip}' provided by plugin '${plugin?.name ?: "<builtin>"}', registered for '${this.extensionType.qualifiedName}'",
|
||||
throwable
|
||||
)
|
||||
}
|
||||
|
||||
internal inline fun <T : Extension> ExtensionPoint<T>.useExtensions(block: (extension: T) -> Unit): Unit =
|
||||
withExtensions(block)
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
@kotlin.internal.LowPriorityInOverloadResolution
|
||||
internal inline fun <T : Extension> ExtensionPoint<T>.useExtensions(block: (extension: T, plugin: Plugin?) -> Unit): Unit =
|
||||
withExtensions(block)
|
||||
|
||||
override fun <T : Extension> contribute(
|
||||
extensionPoint: ExtensionPoint<T>,
|
||||
override fun <E : Extension> contribute(
|
||||
extensionPoint: ExtensionPoint<E>,
|
||||
plugin: Plugin,
|
||||
extensionInstance: T,
|
||||
extensionInstance: E,
|
||||
) {
|
||||
instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(DataExtensionRegistry(plugin, extensionInstance))
|
||||
registerExtension(extensionPoint, ExtensionRegistryImpl(plugin) { extensionInstance })
|
||||
}
|
||||
|
||||
@JvmName("contribute1")
|
||||
fun <T : Extension> contribute(
|
||||
extensionPoint: ExtensionPoint<T>,
|
||||
plugin: Plugin?,
|
||||
extensionInstance: T,
|
||||
) {
|
||||
instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(DataExtensionRegistry(plugin, extensionInstance))
|
||||
override fun <E : Extension> contributeConsole(extensionPoint: ExtensionPoint<E>, lazyInstance: () -> E) {
|
||||
registerExtension(extensionPoint, ExtensionRegistryImpl(null, lazyInstance))
|
||||
}
|
||||
|
||||
override fun <T : Extension> contribute(
|
||||
extensionPoint: ExtensionPoint<T>,
|
||||
override fun <E : Extension> contribute(
|
||||
extensionPoint: ExtensionPoint<E>,
|
||||
plugin: Plugin,
|
||||
lazyInstance: () -> T,
|
||||
lazyInstance: () -> E,
|
||||
) {
|
||||
instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(LazyExtensionRegistry(plugin, lazyInstance))
|
||||
registerExtension(extensionPoint, ExtensionRegistryImpl(plugin, lazyInstance))
|
||||
}
|
||||
|
||||
@JvmName("contribute1")
|
||||
fun <T : Extension> contribute(
|
||||
extensionPoint: ExtensionPoint<T>,
|
||||
plugin: Plugin?,
|
||||
lazyInstance: () -> T,
|
||||
) {
|
||||
instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(LazyExtensionRegistry(plugin, lazyInstance))
|
||||
override fun <E : Extension> getExtensions(extensionPoint: ExtensionPoint<E>): Sequence<ExtensionRegistry<E>> {
|
||||
return getRegistries(extensionPoint).asSequence()
|
||||
}
|
||||
|
||||
override fun <E : Extension> getExtensionsStream(extensionPoint: ExtensionPoint<E>): Stream<ExtensionRegistry<E>> {
|
||||
return getRegistries(extensionPoint).asStream()
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -18,9 +18,16 @@ import net.mamoe.mirai.console.extensions.SingletonExtensionSelector
|
||||
import net.mamoe.mirai.console.internal.data.kClassQualifiedName
|
||||
import net.mamoe.mirai.console.plugin.name
|
||||
import net.mamoe.mirai.console.util.ConsoleInput
|
||||
import net.mamoe.mirai.utils.DeprecatedSinceMirai
|
||||
import net.mamoe.mirai.utils.info
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated(
|
||||
"Order of extensions is not determined by its priority property since 2.11. SingletonExtensionSelector is not needed anymore. ",
|
||||
level = DeprecationLevel.WARNING
|
||||
)
|
||||
@DeprecatedSinceMirai(warningSince = "2.11")
|
||||
internal object SingletonExtensionSelectorImpl : SingletonExtensionSelector {
|
||||
|
||||
internal val config: SaveData = SaveData()
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -14,6 +14,7 @@ import net.mamoe.mirai.console.data.AutoSavePluginConfig
|
||||
import net.mamoe.mirai.console.data.PluginDataExtensions
|
||||
import net.mamoe.mirai.console.data.PluginDataExtensions.withDefault
|
||||
import net.mamoe.mirai.console.data.value
|
||||
import net.mamoe.mirai.console.extensions.PermissionServiceProvider
|
||||
import net.mamoe.mirai.console.permission.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.CopyOnWriteArraySet
|
||||
@ -100,6 +101,12 @@ internal class AllDenyPermissionService : PermissionService<PermissionImpl> {
|
||||
internal class BuiltInPermissionService : AbstractConcurrentPermissionService<PermissionImpl>(),
|
||||
PermissionService<PermissionImpl> {
|
||||
|
||||
class Provider : PermissionServiceProvider {
|
||||
override val instance: PermissionService<*> by lazy {
|
||||
BuiltInPermissionService()
|
||||
}
|
||||
}
|
||||
|
||||
override val permissionType: KClass<PermissionImpl>
|
||||
get() = PermissionImpl::class
|
||||
override val permissions: ConcurrentHashMap<PermissionId, PermissionImpl> = ConcurrentHashMap()
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
@ -160,12 +160,10 @@ internal class PluginManagerImpl(
|
||||
|
||||
internal fun initExternalPluginLoaders(): Int {
|
||||
var count = 0
|
||||
GlobalComponentStorage.run {
|
||||
PluginLoaderProvider.useExtensions { ext, plugin ->
|
||||
logger.info { "Loaded PluginLoader ${ext.instance} from ${plugin?.name ?: "<builtin>"}" }
|
||||
_pluginLoaders.add(ext.instance)
|
||||
count++
|
||||
}
|
||||
GlobalComponentStorage.useEachExtensions(PluginLoaderProvider) {
|
||||
logger.info { "Loaded PluginLoader ${extension.instance} from ${plugin?.name ?: "<builtin>"}" }
|
||||
_pluginLoaders.add(extension.instance)
|
||||
count++
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE", "unused", "MemberVisibilityCanBePrivate")
|
||||
@ -13,7 +13,9 @@ package net.mamoe.mirai.console.permission
|
||||
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.COMMAND_NAME
|
||||
import net.mamoe.mirai.console.extension.instance
|
||||
import net.mamoe.mirai.console.extensions.PermissionServiceProvider
|
||||
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
|
||||
import net.mamoe.mirai.console.internal.permission.checkType
|
||||
import net.mamoe.mirai.console.permission.Permission.Companion.parentsWithSelf
|
||||
import net.mamoe.mirai.console.plugin.Plugin
|
||||
@ -140,14 +142,12 @@ public interface PermissionService<P : Permission> {
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* [PermissionService] 实例
|
||||
*
|
||||
* @see PermissionServiceProvider.selectedInstance
|
||||
* 选用的 [PermissionService] 实例.
|
||||
*/
|
||||
@get:JvmName("getInstance")
|
||||
@JvmStatic
|
||||
public val INSTANCE: PermissionService<out Permission>
|
||||
get() = PermissionServiceProvider.selectedInstance
|
||||
get() = GlobalComponentStorage.getPreferredExtension(PermissionServiceProvider).instance
|
||||
|
||||
/**
|
||||
* 获取一个权限, 失败时抛出 [NoSuchElementException]
|
||||
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.extension
|
||||
|
||||
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
|
||||
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorageImpl
|
||||
import net.mamoe.mirai.console.testFramework.AbstractConsoleInstanceTest
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class GlobalComponentStorageTest : AbstractConsoleInstanceTest() {
|
||||
class MyInstance
|
||||
|
||||
class MyExtension(override val instance: MyInstance, override val priority: Int) : InstanceExtension<MyInstance> {
|
||||
companion object EP : AbstractInstanceExtensionPoint<MyExtension, MyInstance>(MyExtension::class)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can register`() {
|
||||
GlobalComponentStorage.contributeConsole(MyExtension, MyExtension(MyInstance(), 1))
|
||||
GlobalComponentStorage.contributeConsole(MyExtension, MyExtension(MyInstance(), 2))
|
||||
GlobalComponentStorage.getExtensionsList(MyExtension).run {
|
||||
assertEquals(2, size)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can contribute`() {
|
||||
GlobalComponentStorage.contribute(MyExtension, mockPlugin, MyExtension(MyInstance(), 1))
|
||||
GlobalComponentStorage.contribute(MyExtension, mockPlugin, MyExtension(MyInstance(), 2))
|
||||
GlobalComponentStorage.getExtensionsList(MyExtension).run {
|
||||
assertEquals(2, size)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can sort by priority`() {
|
||||
GlobalComponentStorage.contributeConsole(MyExtension, MyExtension(MyInstance(), 1))
|
||||
GlobalComponentStorage.contributeConsole(MyExtension, MyExtension(MyInstance(), 2))
|
||||
GlobalComponentStorage.getExtensionsList(MyExtension).run {
|
||||
assertEquals(2, size)
|
||||
assertEquals(2, first().extension.priority)
|
||||
assertEquals(1, get(1).extension.priority)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can sort by priority 2`() {
|
||||
GlobalComponentStorage.contributeConsole(MyExtension, MyExtension(MyInstance(), 2))
|
||||
GlobalComponentStorage.contributeConsole(MyExtension, MyExtension(MyInstance(), 1))
|
||||
GlobalComponentStorage.getExtensionsList(MyExtension).run {
|
||||
assertEquals(2, size)
|
||||
assertEquals(2, first().extension.priority)
|
||||
assertEquals(1, get(1).extension.priority)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can fold`() {
|
||||
GlobalComponentStorage.contributeConsole(MyExtension, MyExtension(MyInstance(), 2))
|
||||
GlobalComponentStorage.contributeConsole(MyExtension, MyExtension(MyInstance(), 1))
|
||||
val list = GlobalComponentStorage.foldExtensions(MyExtension, listOf<MyExtension>()) { acc, extension ->
|
||||
acc + extension
|
||||
}
|
||||
assertEquals(2, list.size)
|
||||
assertEquals(2, list.first().priority)
|
||||
assertEquals(1, list[1].priority)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : Extension> GlobalComponentStorageImpl.getExtensionsList(ep: ExtensionPoint<T>): List<ExtensionRegistry<T>> {
|
||||
return getExtensions(ep).toList()
|
||||
}
|
Loading…
Reference in New Issue
Block a user