mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-25 15:40:28 +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.CommandSender
|
||||||
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
|
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.internal.command.flattenCommandComponents
|
||||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||||
import net.mamoe.mirai.message.data.MessageChain
|
import net.mamoe.mirai.message.data.MessageChain
|
||||||
@ -20,4 +21,6 @@ public object SpaceSeparatedCommandCallParser : CommandCallParser {
|
|||||||
valueArguments = flatten.drop(1).map(::InvariantCommandValueArgument)
|
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.descriptor.ArgumentAcceptance.Companion.isNotAcceptable
|
||||||
import net.mamoe.mirai.console.command.parse.CommandCall
|
import net.mamoe.mirai.console.command.parse.CommandCall
|
||||||
import net.mamoe.mirai.console.command.parse.CommandValueArgument
|
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.ConsoleExperimentalApi
|
||||||
import net.mamoe.mirai.console.util.cast
|
import net.mamoe.mirai.console.util.cast
|
||||||
import net.mamoe.mirai.console.util.safeCast
|
import net.mamoe.mirai.console.util.safeCast
|
||||||
@ -14,6 +15,8 @@ import java.util.*
|
|||||||
@ConsoleExperimentalApi
|
@ConsoleExperimentalApi
|
||||||
@ExperimentalCommandDescriptors
|
@ExperimentalCommandDescriptors
|
||||||
public object BuiltInCommandCallResolver : CommandCallResolver {
|
public object BuiltInCommandCallResolver : CommandCallResolver {
|
||||||
|
public object Provider : CommandCallResolverProvider(BuiltInCommandCallResolver)
|
||||||
|
|
||||||
override fun resolve(call: CommandCall): ResolvedCommandCall? {
|
override fun resolve(call: CommandCall): ResolvedCommandCall? {
|
||||||
val callee = CommandManager.matchCommand(call.calleeName) ?: return null
|
val callee = CommandManager.matchCommand(call.calleeName) ?: return null
|
||||||
|
|
||||||
|
@ -24,6 +24,12 @@ public open class AbstractExtensionPoint<T : Extension>(
|
|||||||
public override val extensionType: KClass<T>,
|
public override val extensionType: KClass<T>,
|
||||||
) : ExtensionPoint<T>
|
) : ExtensionPoint<T>
|
||||||
|
|
||||||
|
public open class InstanceExtensionPoint<E : InstanceExtension<T>, T>(
|
||||||
|
extensionType: KClass<E>,
|
||||||
|
public vararg val builtinImplementations: E,
|
||||||
|
) : AbstractExtensionPoint<E>(extensionType)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表示一个 [SingletonExtension] 的 [ExtensionPoint]
|
* 表示一个 [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.descriptor.ExperimentalCommandDescriptors
|
||||||
import net.mamoe.mirai.console.command.parse.CommandCallParser
|
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.InstanceExtension
|
||||||
|
import net.mamoe.mirai.console.extension.InstanceExtensionPoint
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The provider of [CommandCallParser]
|
* The provider of [CommandCallParser]
|
||||||
*/
|
*/
|
||||||
@ExperimentalCommandDescriptors
|
@ExperimentalCommandDescriptors
|
||||||
public interface CommandCallParserProvider : InstanceExtension<CommandCallParser> {
|
public open class CommandCallParserProvider(override val instance: CommandCallParser) : InstanceExtension<CommandCallParser> {
|
||||||
public companion object ExtensionPoint : AbstractExtensionPoint<CommandCallParserProvider>(CommandCallParserProvider::class)
|
public companion object ExtensionPoint :
|
||||||
|
InstanceExtensionPoint<CommandCallParserProvider, CommandCallParser>(CommandCallParserProvider::class, SpaceSeparatedCommandCallParser.Provider)
|
||||||
}
|
}
|
@ -10,11 +10,13 @@
|
|||||||
package net.mamoe.mirai.console.extensions
|
package net.mamoe.mirai.console.extensions
|
||||||
|
|
||||||
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
|
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.command.resolve.CommandCallResolver
|
||||||
import net.mamoe.mirai.console.extension.AbstractExtensionPoint
|
|
||||||
import net.mamoe.mirai.console.extension.InstanceExtension
|
import net.mamoe.mirai.console.extension.InstanceExtension
|
||||||
|
import net.mamoe.mirai.console.extension.InstanceExtensionPoint
|
||||||
|
|
||||||
@ExperimentalCommandDescriptors
|
@ExperimentalCommandDescriptors
|
||||||
public interface CommandCallResolverProvider : InstanceExtension<CommandCallResolver> {
|
public open class CommandCallResolverProvider(override val instance: CommandCallResolver) : InstanceExtension<CommandCallResolver> {
|
||||||
public companion object ExtensionPoint : AbstractExtensionPoint<CommandCallResolverProvider>(CommandCallResolverProvider::class)
|
public companion object ExtensionPoint :
|
||||||
|
InstanceExtensionPoint<CommandCallResolverProvider, CommandCallResolver>(CommandCallResolverProvider::class, BuiltInCommandCallResolver.Provider)
|
||||||
}
|
}
|
@ -29,7 +29,7 @@ import kotlin.reflect.KClass
|
|||||||
*/
|
*/
|
||||||
public interface SingletonExtensionSelector : FunctionExtension {
|
public interface SingletonExtensionSelector : FunctionExtension {
|
||||||
public data class Registry<T : Extension>(
|
public data class Registry<T : Extension>(
|
||||||
val plugin: Plugin,
|
val plugin: Plugin?,
|
||||||
val extension: T,
|
val extension: T,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -55,11 +55,11 @@ public interface SingletonExtensionSelector : FunctionExtension {
|
|||||||
instances.isEmpty() -> BuiltInSingletonExtensionSelector
|
instances.isEmpty() -> BuiltInSingletonExtensionSelector
|
||||||
instances.size == 1 -> {
|
instances.size == 1 -> {
|
||||||
instances.single().also { (plugin, ext) ->
|
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
|
}.extension
|
||||||
}
|
}
|
||||||
else -> {
|
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()
|
val candidatesList = candidates.toList()
|
||||||
|
|
||||||
for ((index, candidate) in candidatesList.withIndex()) {
|
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()}" }
|
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 object GlobalComponentStorage : AbstractConcurrentComponentStorage()
|
||||||
internal interface ExtensionRegistry<out E : Extension> {
|
internal interface ExtensionRegistry<out E : Extension> {
|
||||||
val plugin: Plugin
|
val plugin: Plugin?
|
||||||
val extension: E
|
val extension: E
|
||||||
|
|
||||||
operator fun component1(): Plugin {
|
operator fun component1(): Plugin? {
|
||||||
return this.plugin
|
return this.plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,21 +38,27 @@ internal interface ExtensionRegistry<out E : Extension> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal class LazyExtensionRegistry<out E : Extension>(
|
internal class LazyExtensionRegistry<out E : Extension>(
|
||||||
override val plugin: Plugin,
|
override val plugin: Plugin?,
|
||||||
initializer: () -> E,
|
initializer: () -> E,
|
||||||
) : ExtensionRegistry<E> {
|
) : ExtensionRegistry<E> {
|
||||||
override val extension: E by lazy { initializer() }
|
override val extension: E by lazy { initializer() }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal data class DataExtensionRegistry<out E : Extension>(
|
internal data class DataExtensionRegistry<out E : Extension>(
|
||||||
override val plugin: Plugin,
|
override val plugin: Plugin?,
|
||||||
override val extension: E,
|
override val extension: E,
|
||||||
) : ExtensionRegistry<E>
|
) : ExtensionRegistry<E>
|
||||||
|
|
||||||
internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
internal fun <T : Extension> ExtensionPoint<out T>.getExtensions(): Set<ExtensionRegistry<T>> {
|
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) {
|
internal fun mergeWith(another: AbstractConcurrentComponentStorage) {
|
||||||
@ -71,7 +77,7 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
|||||||
|
|
||||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||||
@kotlin.internal.LowPriorityInOverloadResolution
|
@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 {
|
contract {
|
||||||
callsInPlace(block)
|
callsInPlace(block)
|
||||||
}
|
}
|
||||||
@ -131,11 +137,11 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
|||||||
|
|
||||||
internal fun <T : Extension> ExtensionPoint<out T>.throwExtensionException(
|
internal fun <T : Extension> ExtensionPoint<out T>.throwExtensionException(
|
||||||
extension: T,
|
extension: T,
|
||||||
plugin: Plugin,
|
plugin: Plugin?,
|
||||||
throwable: Throwable,
|
throwable: Throwable,
|
||||||
) {
|
) {
|
||||||
throw ExtensionException(
|
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
|
throwable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -145,7 +151,7 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
|||||||
|
|
||||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||||
@kotlin.internal.LowPriorityInOverloadResolution
|
@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)
|
withExtensions(block)
|
||||||
|
|
||||||
val instances: MutableMap<ExtensionPoint<*>, MutableSet<ExtensionRegistry<*>>> = ConcurrentHashMap()
|
val instances: MutableMap<ExtensionPoint<*>, MutableSet<ExtensionRegistry<*>>> = ConcurrentHashMap()
|
||||||
@ -157,6 +163,15 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
|||||||
instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(DataExtensionRegistry(plugin, extensionInstance))
|
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(
|
override fun <T : Extension> contribute(
|
||||||
extensionPoint: ExtensionPoint<T>,
|
extensionPoint: ExtensionPoint<T>,
|
||||||
plugin: Plugin,
|
plugin: Plugin,
|
||||||
@ -164,4 +179,13 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
|||||||
) {
|
) {
|
||||||
instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(LazyExtensionRegistry(plugin, lazyInstance))
|
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
|
var count = 0
|
||||||
GlobalComponentStorage.run {
|
GlobalComponentStorage.run {
|
||||||
PluginLoaderProvider.useExtensions { ext, plugin ->
|
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)
|
_pluginLoaders.add(ext.instance)
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user