mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-10 18:40:15 +08:00
Introduce InstanceExtensionPoint
This commit is contained in:
parent
2084f8154f
commit
58af1b3354
@ -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)
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -24,6 +24,12 @@ public open class AbstractExtensionPoint<T : Extension>(
|
||||
public override val extensionType: KClass<T>,
|
||||
) : ExtensionPoint<T>
|
||||
|
||||
public open class InstanceExtensionPoint<E : InstanceExtension<T>, T>(
|
||||
extensionType: KClass<E>,
|
||||
public vararg val builtinImplementations: E,
|
||||
) : AbstractExtensionPoint<E>(extensionType)
|
||||
|
||||
|
||||
/**
|
||||
* 表示一个 [SingletonExtension] 的 [ExtensionPoint]
|
||||
*/
|
||||
|
@ -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<CommandCallParser> {
|
||||
public companion object ExtensionPoint : AbstractExtensionPoint<CommandCallParserProvider>(CommandCallParserProvider::class)
|
||||
public open class CommandCallParserProvider(override val instance: CommandCallParser) : InstanceExtension<CommandCallParser> {
|
||||
public companion object ExtensionPoint :
|
||||
InstanceExtensionPoint<CommandCallParserProvider, CommandCallParser>(CommandCallParserProvider::class, SpaceSeparatedCommandCallParser.Provider)
|
||||
}
|
@ -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<CommandCallResolver> {
|
||||
public companion object ExtensionPoint : AbstractExtensionPoint<CommandCallResolverProvider>(CommandCallResolverProvider::class)
|
||||
public open class CommandCallResolverProvider(override val instance: CommandCallResolver) : InstanceExtension<CommandCallResolver> {
|
||||
public companion object ExtensionPoint :
|
||||
InstanceExtensionPoint<CommandCallResolverProvider, CommandCallResolver>(CommandCallResolverProvider::class, BuiltInCommandCallResolver.Provider)
|
||||
}
|
@ -29,7 +29,7 @@ import kotlin.reflect.KClass
|
||||
*/
|
||||
public interface SingletonExtensionSelector : FunctionExtension {
|
||||
public data class Registry<T : Extension>(
|
||||
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 ?: "<builtin>"}" }
|
||||
}.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 ?: "<builtin>"}'" }}. Check your plugins and ensure there is only one external SingletonExtensionSelectors")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 ?: "<builtin>"}'" }
|
||||
}
|
||||
|
||||
MiraiConsole.mainLogger.info { "Please choose a number from 1 to ${candidatesList.count()}" }
|
||||
|
@ -25,10 +25,10 @@ import kotlin.reflect.KClass
|
||||
*/
|
||||
internal object GlobalComponentStorage : AbstractConcurrentComponentStorage()
|
||||
internal interface ExtensionRegistry<out E : Extension> {
|
||||
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<out E : Extension> {
|
||||
}
|
||||
|
||||
internal class LazyExtensionRegistry<out E : Extension>(
|
||||
override val plugin: Plugin,
|
||||
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 plugin: Plugin?,
|
||||
override val extension: E,
|
||||
) : ExtensionRegistry<E>
|
||||
|
||||
internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal fun <T : Extension> ExtensionPoint<out T>.getExtensions(): Set<ExtensionRegistry<T>> {
|
||||
return instances.getOrPut(this, ::CopyOnWriteArraySet) as Set<ExtensionRegistry<T>>
|
||||
val userDefined = instances.getOrPut(this, ::CopyOnWriteArraySet) as Set<ExtensionRegistry<T>>
|
||||
|
||||
val builtins = if (this is InstanceExtensionPoint<*, *>) {
|
||||
this.builtinImplementations.mapTo(HashSet()) { DataExtensionRegistry(null, it) } as Set<ExtensionRegistry<T>>
|
||||
} 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 <T : Extension> ExtensionPoint<out T>.withExtensions(block: T.(plugin: Plugin) -> Unit) {
|
||||
internal inline fun <T : Extension> ExtensionPoint<out T>.withExtensions(block: T.(plugin: Plugin?) -> Unit) {
|
||||
contract {
|
||||
callsInPlace(block)
|
||||
}
|
||||
@ -131,11 +137,11 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
||||
|
||||
internal fun <T : Extension> ExtensionPoint<out T>.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 ?: "<builtin>"}', 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 <T : Extension> ExtensionPoint<T>.useExtensions(block: (extension: T, plugin: Plugin) -> Unit): Unit =
|
||||
internal inline fun <T : Extension> ExtensionPoint<T>.useExtensions(block: (extension: T, plugin: Plugin?) -> Unit): Unit =
|
||||
withExtensions(block)
|
||||
|
||||
val instances: MutableMap<ExtensionPoint<*>, MutableSet<ExtensionRegistry<*>>> = ConcurrentHashMap()
|
||||
@ -157,6 +163,15 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
||||
instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(DataExtensionRegistry(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 <T : Extension> contribute(
|
||||
extensionPoint: ExtensionPoint<T>,
|
||||
plugin: Plugin,
|
||||
@ -164,4 +179,13 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
||||
) {
|
||||
instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(LazyExtensionRegistry(plugin, lazyInstance))
|
||||
}
|
||||
|
||||
@JvmName("contribute1")
|
||||
fun <T : Extension> contribute(
|
||||
extensionPoint: ExtensionPoint<T>,
|
||||
plugin: Plugin?,
|
||||
lazyInstance: () -> T,
|
||||
) {
|
||||
instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(LazyExtensionRegistry(plugin, lazyInstance))
|
||||
}
|
||||
}
|
@ -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 ?: "<builtin>"}" }
|
||||
_pluginLoaders.add(ext.instance)
|
||||
count++
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user