From 58af1b335449ad8f83191bc635883487faa67701 Mon Sep 17 00:00:00 2001 From: Him188 Date: Tue, 20 Oct 2020 13:47:43 +0800 Subject: [PATCH] Introduce InstanceExtensionPoint --- .../parse/SpaceSeparatedCommandCallParser.kt | 3 ++ .../resolve/BuiltInCommandCallResolver.kt | 3 ++ .../mirai/console/extension/ExtensionPoint.kt | 6 +++ .../extensions/CommandCallParserProvider.kt | 8 ++-- .../extensions/CommandCallResolverProvider.kt | 8 ++-- .../extensions/SingletonExtensionSelector.kt | 6 +-- .../BuiltInSingletonExtensionSelector.kt | 2 +- .../extension/ComponentStorageInternal.kt | 42 +++++++++++++++---- .../internal/plugin/PluginManagerImpl.kt | 2 +- 9 files changed, 60 insertions(+), 20 deletions(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/parse/SpaceSeparatedCommandCallParser.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/parse/SpaceSeparatedCommandCallParser.kt index 62e6a5370..d5812ff66 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/parse/SpaceSeparatedCommandCallParser.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/parse/SpaceSeparatedCommandCallParser.kt @@ -2,6 +2,7 @@ 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.internal.command.flattenCommandComponents import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.message.data.MessageChain @@ -20,4 +21,6 @@ public object SpaceSeparatedCommandCallParser : CommandCallParser { valueArguments = flatten.drop(1).map(::InvariantCommandValueArgument) ) } + + public object Provider : CommandCallParserProvider(SpaceSeparatedCommandCallParser) } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/resolve/BuiltInCommandCallResolver.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/resolve/BuiltInCommandCallResolver.kt index 5ff77e7dc..280c05a22 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/resolve/BuiltInCommandCallResolver.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/resolve/BuiltInCommandCallResolver.kt @@ -6,6 +6,7 @@ import net.mamoe.mirai.console.command.descriptor.* import net.mamoe.mirai.console.command.descriptor.ArgumentAcceptance.Companion.isNotAcceptable import net.mamoe.mirai.console.command.parse.CommandCall import net.mamoe.mirai.console.command.parse.CommandValueArgument +import net.mamoe.mirai.console.extensions.CommandCallResolverProvider import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.console.util.cast import net.mamoe.mirai.console.util.safeCast @@ -14,6 +15,8 @@ import java.util.* @ConsoleExperimentalApi @ExperimentalCommandDescriptors public object BuiltInCommandCallResolver : CommandCallResolver { + public object Provider : CommandCallResolverProvider(BuiltInCommandCallResolver) + override fun resolve(call: CommandCall): ResolvedCommandCall? { val callee = CommandManager.matchCommand(call.calleeName) ?: return null diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionPoint.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionPoint.kt index da9d0ff80..d076776c0 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionPoint.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionPoint.kt @@ -24,6 +24,12 @@ public open class AbstractExtensionPoint( public override val extensionType: KClass, ) : ExtensionPoint +public open class InstanceExtensionPoint, T>( + extensionType: KClass, + public vararg val builtinImplementations: E, +) : AbstractExtensionPoint(extensionType) + + /** * 表示一个 [SingletonExtension] 的 [ExtensionPoint] */ diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/CommandCallParserProvider.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/CommandCallParserProvider.kt index a3870a932..4a19a0fac 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/CommandCallParserProvider.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/CommandCallParserProvider.kt @@ -11,13 +11,15 @@ 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.extension.AbstractExtensionPoint +import net.mamoe.mirai.console.command.parse.SpaceSeparatedCommandCallParser import net.mamoe.mirai.console.extension.InstanceExtension +import net.mamoe.mirai.console.extension.InstanceExtensionPoint /** * The provider of [CommandCallParser] */ @ExperimentalCommandDescriptors -public interface CommandCallParserProvider : InstanceExtension { - public companion object ExtensionPoint : AbstractExtensionPoint(CommandCallParserProvider::class) +public open class CommandCallParserProvider(override val instance: CommandCallParser) : InstanceExtension { + public companion object ExtensionPoint : + InstanceExtensionPoint(CommandCallParserProvider::class, SpaceSeparatedCommandCallParser.Provider) } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/CommandCallResolverProvider.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/CommandCallResolverProvider.kt index 85fcfb415..e6e390d99 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/CommandCallResolverProvider.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/CommandCallResolverProvider.kt @@ -10,11 +10,13 @@ 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.AbstractExtensionPoint import net.mamoe.mirai.console.extension.InstanceExtension +import net.mamoe.mirai.console.extension.InstanceExtensionPoint @ExperimentalCommandDescriptors -public interface CommandCallResolverProvider : InstanceExtension { - public companion object ExtensionPoint : AbstractExtensionPoint(CommandCallResolverProvider::class) +public open class CommandCallResolverProvider(override val instance: CommandCallResolver) : InstanceExtension { + public companion object ExtensionPoint : + InstanceExtensionPoint(CommandCallResolverProvider::class, BuiltInCommandCallResolver.Provider) } \ No newline at end of file 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 e5fd07fb8..2dfce8f6c 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 @@ -29,7 +29,7 @@ import kotlin.reflect.KClass */ public interface SingletonExtensionSelector : FunctionExtension { public data class Registry( - val plugin: Plugin, + val plugin: Plugin?, val extension: T, ) @@ -55,11 +55,11 @@ public interface SingletonExtensionSelector : FunctionExtension { instances.isEmpty() -> BuiltInSingletonExtensionSelector instances.size == 1 -> { instances.single().also { (plugin, ext) -> - MiraiConsole.mainLogger.info { "Loaded SingletonExtensionSelector: $ext from ${plugin.name}" } + MiraiConsole.mainLogger.info { "Loaded SingletonExtensionSelector: $ext from ${plugin?.name ?: ""}" } }.extension } else -> { - error("Found too many SingletonExtensionSelectors: ${instances.joinToString { (p, i) -> "'$i' from '${p.name}'" }}. Check your plugins and ensure there is only one external SingletonExtensionSelectors") + error("Found too many SingletonExtensionSelectors: ${instances.joinToString { (p, i) -> "'$i' from '${p?.name ?: ""}'" }}. Check your plugins and ensure there is only one external SingletonExtensionSelectors") } } } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extension/BuiltInSingletonExtensionSelector.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extension/BuiltInSingletonExtensionSelector.kt index 60bb09cd8..d096341ed 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extension/BuiltInSingletonExtensionSelector.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extension/BuiltInSingletonExtensionSelector.kt @@ -52,7 +52,7 @@ internal object BuiltInSingletonExtensionSelector : SingletonExtensionSelector { val candidatesList = candidates.toList() for ((index, candidate) in candidatesList.withIndex()) { - MiraiConsole.mainLogger.info { "${index + 1}. '${candidate.extension}' from '${candidate.plugin.name}'" } + MiraiConsole.mainLogger.info { "${index + 1}. '${candidate.extension}' from '${candidate.plugin?.name ?: ""}'" } } MiraiConsole.mainLogger.info { "Please choose a number from 1 to ${candidatesList.count()}" } 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 index d84fa4022..b3072ad49 100644 --- 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 @@ -25,10 +25,10 @@ import kotlin.reflect.KClass */ internal object GlobalComponentStorage : AbstractConcurrentComponentStorage() internal interface ExtensionRegistry { - val plugin: Plugin + val plugin: Plugin? val extension: E - operator fun component1(): Plugin { + operator fun component1(): Plugin? { return this.plugin } @@ -38,21 +38,27 @@ internal interface ExtensionRegistry { } internal class LazyExtensionRegistry( - override val plugin: Plugin, + override val plugin: Plugin?, initializer: () -> E, ) : ExtensionRegistry { override val extension: E by lazy { initializer() } } internal data class DataExtensionRegistry( - override val plugin: Plugin, + 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> + val userDefined = instances.getOrPut(this, ::CopyOnWriteArraySet) as Set> + + val builtins = if (this is InstanceExtensionPoint<*, *>) { + this.builtinImplementations.mapTo(HashSet()) { DataExtensionRegistry(null, it) } as Set> + } else null + + return builtins?.plus(userDefined) ?: userDefined } internal fun mergeWith(another: AbstractConcurrentComponentStorage) { @@ -71,7 +77,7 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage { @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @kotlin.internal.LowPriorityInOverloadResolution - internal inline fun ExtensionPoint.withExtensions(block: T.(plugin: Plugin) -> Unit) { + internal inline fun ExtensionPoint.withExtensions(block: T.(plugin: Plugin?) -> Unit) { contract { callsInPlace(block) } @@ -131,11 +137,11 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage { internal fun ExtensionPoint.throwExtensionException( extension: T, - plugin: Plugin, + plugin: Plugin?, throwable: Throwable, ) { throw ExtensionException( - "Exception while executing extension '${extension.kClassQualifiedNameOrTip}' provided by plugin '${plugin.name}', registered for '${this.extensionType.qualifiedName}'", + "Exception while executing extension '${extension.kClassQualifiedNameOrTip}' provided by plugin '${plugin?.name ?: ""}', registered for '${this.extensionType.qualifiedName}'", throwable ) } @@ -145,7 +151,7 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage { @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @kotlin.internal.LowPriorityInOverloadResolution - internal inline fun ExtensionPoint.useExtensions(block: (extension: T, plugin: Plugin) -> Unit): Unit = + internal inline fun ExtensionPoint.useExtensions(block: (extension: T, plugin: Plugin?) -> Unit): Unit = withExtensions(block) val instances: MutableMap, MutableSet>> = ConcurrentHashMap() @@ -157,6 +163,15 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage { instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(DataExtensionRegistry(plugin, extensionInstance)) } + @JvmName("contribute1") + fun contribute( + extensionPoint: ExtensionPoint, + plugin: Plugin?, + extensionInstance: T, + ) { + instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(DataExtensionRegistry(plugin, extensionInstance)) + } + override fun contribute( extensionPoint: ExtensionPoint, plugin: Plugin, @@ -164,4 +179,13 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage { ) { instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(LazyExtensionRegistry(plugin, lazyInstance)) } + + @JvmName("contribute1") + 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 2f15ba42a..68045ff93 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 @@ -148,7 +148,7 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol var count = 0 GlobalComponentStorage.run { PluginLoaderProvider.useExtensions { ext, plugin -> - logger.info { "Loaded PluginLoader ${ext.instance} from ${plugin.name}" } + logger.info { "Loaded PluginLoader ${ext.instance} from ${plugin?.name ?: ""}" } _pluginLoaders.add(ext.instance) count++ }