diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt index 317efebcd..8bed464da 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt @@ -18,9 +18,9 @@ import kotlinx.coroutines.Job import net.mamoe.mirai.Bot import net.mamoe.mirai.console.MiraiConsole.INSTANCE import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start -import net.mamoe.mirai.console.extension.GlobalComponentStorage import net.mamoe.mirai.console.extensions.BotConfigurationAlterer import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge +import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage import net.mamoe.mirai.console.plugin.PluginManager import net.mamoe.mirai.console.plugin.center.PluginCenter import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt index b5b286848..62b7b47c2 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt @@ -9,17 +9,9 @@ package 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.data.kClassQualifiedNameOrTip 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.console.plugin.name -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.CopyOnWriteArraySet -import kotlin.contracts.contract -import kotlin.reflect.KClass /** * 组件容器, 容纳 [Plugin] 注册的 [Extension]. @@ -41,146 +33,3 @@ public interface ComponentStorage { ) } -internal object GlobalComponentStorage : AbstractConcurrentComponentStorage() - -internal interface ExtensionRegistry { - val plugin: Plugin - val extension: E - - operator fun component1(): Plugin { - return this.plugin - } - - operator fun component2(): E { - return this.extension - } -} - -internal class LazyExtensionRegistry( - override val plugin: Plugin, - initializer: () -> E, -) : ExtensionRegistry { - override val extension: E by lazy { initializer() } -} - -internal data class DataExtensionRegistry( - override val plugin: Plugin, - override val extension: E, -) : ExtensionRegistry - -internal abstract class AbstractConcurrentComponentStorage : ComponentStorage { - @Suppress("UNCHECKED_CAST") - internal fun ExtensionPoint.getExtensions(): Set> { - return instances.getOrPut(this, ::CopyOnWriteArraySet) as Set> - } - - internal fun mergeWith(another: AbstractConcurrentComponentStorage) { - for ((ep, list) in another.instances) { - for (extensionRegistry in list) { - @Suppress("UNCHECKED_CAST") - ep as ExtensionPoint - this.contribute(ep, extensionRegistry.plugin, lazyInstance = { extensionRegistry.extension }) - } - } - } - - internal inline fun ExtensionPoint.withExtensions(block: T.() -> Unit) { - return withExtensions { _ -> block() } - } - - @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") - @kotlin.internal.LowPriorityInOverloadResolution - internal inline fun ExtensionPoint.withExtensions(block: T.(plugin: Plugin) -> Unit) { - contract { - callsInPlace(block) - } - for ((plugin, extension) in this.getExtensions()) { - kotlin.runCatching { - block.invoke(extension, plugin) - }.getOrElse { throwable -> - throwExtensionException(extension, plugin, throwable) - } - } - } - - internal inline fun > ExtensionPoint.findSingleton(builtin: E): E = - findSingleton(E::class, builtin) - - internal fun > ExtensionPoint.findSingleton(type: KClass, 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 , T> ExtensionPoint.findSingletonInstance(builtin: T): T = - findSingletonInstance(E::class, builtin) - - internal fun , T> ExtensionPoint.findSingletonInstance( - type: KClass, - builtin: T, - ): T { - val candidates = this.getExtensions() - return when (candidates.size) { - 0 -> builtin - 1 -> candidates.single().extension.instance - else -> SingletonExtensionSelector.instance.selectSingleton(type, candidates)?.instance ?: builtin - } - } - - internal inline fun ExtensionPoint.foldExtensions( - initial: E, - block: (acc: E, extension: T) -> E, - ): E { - contract { - callsInPlace(block) - } - var e: E = initial - for ((plugin, extension) in this.getExtensions()) { - kotlin.runCatching { - e = block.invoke(e, extension) - }.getOrElse { throwable -> - throwExtensionException(extension, plugin, throwable) - } - } - return e - } - - internal fun ExtensionPoint.throwExtensionException( - extension: T, - plugin: Plugin, - throwable: Throwable, - ) { - throw ExtensionException( - "Exception while executing extension '${extension.kClassQualifiedNameOrTip}' provided by plugin '${plugin.name}', registered for '${this.extensionType.qualifiedName}'", - throwable - ) - } - - internal inline fun ExtensionPoint.useExtensions(block: (extension: T) -> Unit): Unit = - withExtensions(block) - - @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") - @kotlin.internal.LowPriorityInOverloadResolution - internal inline fun ExtensionPoint.useExtensions(block: (extension: T, plugin: Plugin) -> Unit): Unit = - withExtensions(block) - - val instances: MutableMap, MutableSet>> = ConcurrentHashMap() - override fun contribute( - extensionPoint: ExtensionPoint, - plugin: Plugin, - extensionInstance: T, - ) { - instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(DataExtensionRegistry(plugin, extensionInstance)) - } - - override fun contribute( - extensionPoint: ExtensionPoint, - plugin: Plugin, - lazyInstance: () -> T, - ) { - instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(LazyExtensionRegistry(plugin, lazyInstance)) - } -} diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/PluginComponentStorage.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/PluginComponentStorage.kt index 32a51a6aa..2a6a8a63f 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/PluginComponentStorage.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/PluginComponentStorage.kt @@ -10,6 +10,7 @@ package net.mamoe.mirai.console.extension import net.mamoe.mirai.console.extensions.* +import net.mamoe.mirai.console.internal.extension.AbstractConcurrentComponentStorage import net.mamoe.mirai.console.permission.PermissionService import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.loader.PluginLoader diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/SingletonExtensionSelector.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/SingletonExtensionSelector.kt index 60c2a4ce8..e5fd07fb8 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/SingletonExtensionSelector.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/SingletonExtensionSelector.kt @@ -10,8 +10,13 @@ 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.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.BuiltInSingletonExtensionSelector +import net.mamoe.mirai.console.internal.extension.ExtensionRegistry +import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.name import net.mamoe.mirai.utils.info diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt index d063c1059..2bbad7896 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt @@ -27,7 +27,6 @@ import net.mamoe.mirai.console.command.Command.Companion.primaryName import net.mamoe.mirai.console.command.CommandManager import net.mamoe.mirai.console.command.ConsoleCommandSender import net.mamoe.mirai.console.data.PluginDataStorage -import net.mamoe.mirai.console.extension.GlobalComponentStorage import net.mamoe.mirai.console.extensions.PermissionServiceProvider import net.mamoe.mirai.console.extensions.PostStartupExtension import net.mamoe.mirai.console.extensions.SingletonExtensionSelector @@ -35,7 +34,8 @@ import net.mamoe.mirai.console.internal.command.CommandManagerImpl import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig import net.mamoe.mirai.console.internal.data.builtins.ConsoleDataScope import net.mamoe.mirai.console.internal.data.castOrNull -import net.mamoe.mirai.console.internal.extensions.BuiltInSingletonExtensionSelector +import net.mamoe.mirai.console.internal.extension.BuiltInSingletonExtensionSelector +import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage import net.mamoe.mirai.console.internal.permission.BuiltInPermissionService import net.mamoe.mirai.console.internal.plugin.PluginManagerImpl import net.mamoe.mirai.console.internal.util.autoHexToBytes diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extensions/BuiltInSingletonExtensionSelector.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extension/BuiltInSingletonExtensionSelector.kt similarity index 98% rename from backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extensions/BuiltInSingletonExtensionSelector.kt rename to backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extension/BuiltInSingletonExtensionSelector.kt index 5308ba4a3..5b50e64ca 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extensions/BuiltInSingletonExtensionSelector.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extension/BuiltInSingletonExtensionSelector.kt @@ -1,4 +1,4 @@ -package net.mamoe.mirai.console.internal.extensions +package net.mamoe.mirai.console.internal.extension import kotlinx.coroutines.runBlocking import net.mamoe.mirai.console.MiraiConsole diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extension/ComponentStorageInternal.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extension/ComponentStorageInternal.kt new file mode 100644 index 000000000..6527aadb3 --- /dev/null +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extension/ComponentStorageInternal.kt @@ -0,0 +1,164 @@ +/* + * Copyright 2020 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/master/LICENSE + */ + +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.data.kClassQualifiedNameOrTip +import net.mamoe.mirai.console.plugin.Plugin +import net.mamoe.mirai.console.plugin.name +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.CopyOnWriteArraySet +import kotlin.contracts.contract +import kotlin.reflect.KClass + +internal object GlobalComponentStorage : AbstractConcurrentComponentStorage() +internal interface ExtensionRegistry { + val plugin: Plugin + val extension: E + + operator fun component1(): Plugin { + return this.plugin + } + + operator fun component2(): E { + return this.extension + } +} + +internal class LazyExtensionRegistry( + override val plugin: Plugin, + initializer: () -> E, +) : ExtensionRegistry { + override val extension: E by lazy { initializer() } +} + +internal data class DataExtensionRegistry( + override val plugin: Plugin, + override val extension: E, +) : ExtensionRegistry + +internal abstract class AbstractConcurrentComponentStorage : ComponentStorage { + @Suppress("UNCHECKED_CAST") + internal fun ExtensionPoint.getExtensions(): Set> { + return instances.getOrPut(this, ::CopyOnWriteArraySet) as Set> + } + + internal fun mergeWith(another: AbstractConcurrentComponentStorage) { + for ((ep, list) in another.instances) { + for (extensionRegistry in list) { + @Suppress("UNCHECKED_CAST") + ep as ExtensionPoint + this.contribute(ep, extensionRegistry.plugin, lazyInstance = { extensionRegistry.extension }) + } + } + } + + internal inline fun ExtensionPoint.withExtensions(block: T.() -> Unit) { + return withExtensions { _ -> block() } + } + + @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + @kotlin.internal.LowPriorityInOverloadResolution + internal inline fun ExtensionPoint.withExtensions(block: T.(plugin: Plugin) -> Unit) { + contract { + callsInPlace(block) + } + for ((plugin, extension) in this.getExtensions()) { + kotlin.runCatching { + block.invoke(extension, plugin) + }.getOrElse { throwable -> + throwExtensionException(extension, plugin, throwable) + } + } + } + + internal inline fun > ExtensionPoint.findSingleton(builtin: E): E = + findSingleton(E::class, builtin) + + internal fun > ExtensionPoint.findSingleton(type: KClass, 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 , T> ExtensionPoint.findSingletonInstance(builtin: T): T = + findSingletonInstance(E::class, builtin) + + internal fun , T> ExtensionPoint.findSingletonInstance( + type: KClass, + builtin: T, + ): T { + val candidates = this.getExtensions() + return when (candidates.size) { + 0 -> builtin + 1 -> candidates.single().extension.instance + else -> SingletonExtensionSelector.instance.selectSingleton(type, candidates)?.instance ?: builtin + } + } + + internal inline fun ExtensionPoint.foldExtensions( + initial: E, + block: (acc: E, extension: T) -> E, + ): E { + contract { + callsInPlace(block) + } + var e: E = initial + for ((plugin, extension) in this.getExtensions()) { + kotlin.runCatching { + e = block.invoke(e, extension) + }.getOrElse { throwable -> + throwExtensionException(extension, plugin, throwable) + } + } + return e + } + + internal fun ExtensionPoint.throwExtensionException( + extension: T, + plugin: Plugin, + throwable: Throwable, + ) { + throw ExtensionException( + "Exception while executing extension '${extension.kClassQualifiedNameOrTip}' provided by plugin '${plugin.name}', registered for '${this.extensionType.qualifiedName}'", + throwable + ) + } + + internal inline fun ExtensionPoint.useExtensions(block: (extension: T) -> Unit): Unit = + withExtensions(block) + + @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + @kotlin.internal.LowPriorityInOverloadResolution + internal inline fun ExtensionPoint.useExtensions(block: (extension: T, plugin: Plugin) -> Unit): Unit = + withExtensions(block) + + val instances: MutableMap, MutableSet>> = ConcurrentHashMap() + override fun contribute( + extensionPoint: ExtensionPoint, + plugin: Plugin, + extensionInstance: T, + ) { + instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(DataExtensionRegistry(plugin, extensionInstance)) + } + + override fun contribute( + extensionPoint: ExtensionPoint, + plugin: Plugin, + lazyInstance: () -> T, + ) { + instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(LazyExtensionRegistry(plugin, lazyInstance)) + } +} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/PluginManagerImpl.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/PluginManagerImpl.kt index f6776bd8f..f84e8f4c5 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/PluginManagerImpl.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/PluginManagerImpl.kt @@ -14,10 +14,10 @@ package net.mamoe.mirai.console.internal.plugin import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import net.mamoe.mirai.console.MiraiConsole -import net.mamoe.mirai.console.extension.GlobalComponentStorage import net.mamoe.mirai.console.extensions.PluginLoaderProvider import net.mamoe.mirai.console.internal.data.cast import net.mamoe.mirai.console.internal.data.mkdir +import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.PluginManager import net.mamoe.mirai.console.plugin.description.PluginDependency