Review extension

This commit is contained in:
Him188 2020-10-25 21:40:41 +08:00
parent 077e4055cc
commit ce0bf8d8be
9 changed files with 100 additions and 34 deletions

View File

@ -3,6 +3,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.extensions.CommandCallParserProvider
import net.mamoe.mirai.console.extensions.CommandCallParserProviderImpl
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
@ -22,5 +23,5 @@ public object SpaceSeparatedCommandCallParser : CommandCallParser {
) )
} }
public object Provider : CommandCallParserProvider(SpaceSeparatedCommandCallParser) public object Provider : CommandCallParserProvider by CommandCallParserProviderImpl(SpaceSeparatedCommandCallParser)
} }

View File

@ -7,30 +7,72 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:Suppress("unused", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @file:Suppress("unused", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "MemberVisibilityCanBePrivate")
package net.mamoe.mirai.console.extension 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 kotlin.reflect.KClass import kotlin.reflect.KClass
/** /**
* [Extension] `companion` 实现. * [Extension] 的伴生对象实现.
*
* @see AbstractExtensionPoint
*/ */
public interface ExtensionPoint<T : Extension> { public interface ExtensionPoint<T : Extension> {
/**
* 扩展实例 [T] 的类型
*/
public val extensionType: KClass<T> public val extensionType: KClass<T>
} }
public open class AbstractExtensionPoint<T : Extension>( public abstract 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]
*/ */
public interface SingletonExtensionPoint<T : SingletonExtension<*>> : ExtensionPoint<T> public interface SingletonExtensionPoint<T : SingletonExtension<*>> : ExtensionPoint<T>
/**
* 表示一个 [InstanceExtension] [ExtensionPoint]
*/
public interface InstanceExtensionPoint<T : InstanceExtension<*>> : ExtensionPoint<T>
/**
* 表示一个 [FunctionExtension] [ExtensionPoint]
*/
public interface FunctionExtensionPoint<T : FunctionExtension> : ExtensionPoint<T>
public abstract class AbstractInstanceExtensionPoint<E : InstanceExtension<T>, T>(
extensionType: KClass<E>,
/**
* 内建的实现列表.
*/
@ConsoleExperimentalApi
public vararg val builtinImplementations: E,
) : AbstractExtensionPoint<E>(extensionType)
public abstract class AbstractSingletonExtensionPoint<E : SingletonExtension<T>, T>(
extensionType: KClass<E>,
/**
* 内建的实现.
*/
@ConsoleExperimentalApi
public val builtinImplementation: T,
) : AbstractExtensionPoint<E>(extensionType), SingletonExtensionPoint<E> {
/**
* [SingletonExtensionSelector] 选择后的实例.
*/
@ConsoleExperimentalApi
public val selectedInstance: T by lazy {
GlobalComponentStorage.run { this@AbstractSingletonExtensionPoint.findSingletonInstance(extensionType, builtinImplementation) }
}
}

View File

@ -9,6 +9,8 @@
package net.mamoe.mirai.console.extension package net.mamoe.mirai.console.extension
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
import net.mamoe.mirai.console.command.parse.CommandCallParser
import net.mamoe.mirai.console.extensions.* import net.mamoe.mirai.console.extensions.*
import net.mamoe.mirai.console.internal.extension.AbstractConcurrentComponentStorage import net.mamoe.mirai.console.internal.extension.AbstractConcurrentComponentStorage
import net.mamoe.mirai.console.permission.PermissionService import net.mamoe.mirai.console.permission.PermissionService
@ -35,7 +37,7 @@ public class PluginComponentStorage(
): Unit = contribute(extensionPoint, plugin, lazyInstance) ): Unit = contribute(extensionPoint, plugin, lazyInstance)
/** /**
* 注册一个扩展 * 注册一个扩展. [E] 必须拥有伴生对象为 [ExtensionPoint].
*/ */
public inline fun <reified E : Extension> contribute( public inline fun <reified E : Extension> contribute(
noinline lazyInstance: () -> E, noinline lazyInstance: () -> E,
@ -74,16 +76,14 @@ public class PluginComponentStorage(
/** 注册一个 [PermissionServiceProvider] */ /** 注册一个 [PermissionServiceProvider] */
@OverloadResolutionByLambdaReturnType @OverloadResolutionByLambdaReturnType
public fun contributePermissionService( public fun contributePermissionService(lazyInstance: () -> PermissionService<*>): Unit =
lazyInstance: () -> PermissionService<*>, contribute(PermissionServiceProvider, plugin, LazyPermissionServiceProviderImpl(lazyInstance))
): Unit = contribute(PermissionServiceProvider, plugin, LazyPermissionServiceProviderImpl(lazyInstance))
/** 注册一个 [PermissionServiceProvider] */ /** 注册一个 [PermissionServiceProvider] */
@JvmName("contributePermissionServiceProvider") @JvmName("contributePermissionServiceProvider")
@OverloadResolutionByLambdaReturnType @OverloadResolutionByLambdaReturnType
public fun contributePermissionService( public fun contributePermissionService(lazyProvider: () -> PermissionServiceProvider): Unit =
lazyProvider: () -> PermissionServiceProvider, contribute(PermissionServiceProvider, plugin, lazyProvider)
): Unit = contribute(PermissionServiceProvider, plugin, lazyProvider)
///////////////////////////////////// /////////////////////////////////////
@ -96,5 +96,20 @@ public class PluginComponentStorage(
@JvmName("contributePluginLoaderProvider") @JvmName("contributePluginLoaderProvider")
@OverloadResolutionByLambdaReturnType @OverloadResolutionByLambdaReturnType
public fun contributePluginLoader(lazyProvider: () -> PluginLoaderProvider): Unit = public fun contributePluginLoader(lazyProvider: () -> PluginLoaderProvider): Unit =
contribute(PluginLoaderProvider, plugin, lazyProvider) contribute(PluginLoaderProvider, plugin, lazyProvider) // lazy for safety
/////////////////////////////////////
/** 注册一个 [CommandCallParserProvider] */
@ExperimentalCommandDescriptors
@OverloadResolutionByLambdaReturnType
public fun contributeCommandCallParser(lazyInstance: () -> CommandCallParser): Unit =
contribute(CommandCallParserProvider, plugin, LazyCommandCallParserProviderImpl(lazyInstance))
/** 注册一个 [CommandCallParserProvider] */
@ExperimentalCommandDescriptors
@JvmName("contributeCommandCallParserProvider")
@OverloadResolutionByLambdaReturnType
public fun contributeCommandCallParser(provider: CommandCallParserProvider): Unit =
contribute(CommandCallParserProvider, plugin, provider)
} }

View File

@ -12,14 +12,24 @@ 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.command.parse.SpaceSeparatedCommandCallParser 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.console.extension.InstanceExtension
import net.mamoe.mirai.console.extension.InstanceExtensionPoint
/** /**
* The provider of [CommandCallParser] * The provider of [CommandCallParser]
*/ */
@ExperimentalCommandDescriptors @ExperimentalCommandDescriptors
public open class CommandCallParserProvider(override val instance: CommandCallParser) : InstanceExtension<CommandCallParser> { public interface CommandCallParserProvider : InstanceExtension<CommandCallParser> {
public companion object ExtensionPoint : public companion object ExtensionPoint :
InstanceExtensionPoint<CommandCallParserProvider, CommandCallParser>(CommandCallParserProvider::class, SpaceSeparatedCommandCallParser.Provider) AbstractInstanceExtensionPoint<CommandCallParserProvider, CommandCallParser>(CommandCallParserProvider::class,
SpaceSeparatedCommandCallParser.Provider)
}
@ExperimentalCommandDescriptors
public class CommandCallParserProviderImpl(override val instance: CommandCallParser) : CommandCallParserProvider
@ExperimentalCommandDescriptors
public class LazyCommandCallParserProviderImpl(instanceCalculator: () -> CommandCallParser) : CommandCallParserProvider {
override val instance: CommandCallParser by lazy(instanceCalculator)
} }

View File

@ -12,11 +12,12 @@ 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.BuiltInCommandCallResolver
import net.mamoe.mirai.console.command.resolve.CommandCallResolver import net.mamoe.mirai.console.command.resolve.CommandCallResolver
import net.mamoe.mirai.console.extension.AbstractInstanceExtensionPoint
import net.mamoe.mirai.console.extension.InstanceExtension import net.mamoe.mirai.console.extension.InstanceExtension
import net.mamoe.mirai.console.extension.InstanceExtensionPoint
@ExperimentalCommandDescriptors @ExperimentalCommandDescriptors
public open class CommandCallResolverProvider(override val instance: CommandCallResolver) : InstanceExtension<CommandCallResolver> { public open class CommandCallResolverProvider(override val instance: CommandCallResolver) : InstanceExtension<CommandCallResolver> {
public companion object ExtensionPoint : public companion object ExtensionPoint :
InstanceExtensionPoint<CommandCallResolverProvider, CommandCallResolver>(CommandCallResolverProvider::class, BuiltInCommandCallResolver.Provider) AbstractInstanceExtensionPoint<CommandCallResolverProvider, CommandCallResolver>(CommandCallResolverProvider::class,
BuiltInCommandCallResolver.Provider)
} }

View File

@ -9,9 +9,9 @@
package net.mamoe.mirai.console.extensions package net.mamoe.mirai.console.extensions
import net.mamoe.mirai.console.extension.AbstractExtensionPoint import net.mamoe.mirai.console.extension.AbstractSingletonExtensionPoint
import net.mamoe.mirai.console.extension.SingletonExtension import net.mamoe.mirai.console.extension.SingletonExtension
import net.mamoe.mirai.console.extension.SingletonExtensionPoint import net.mamoe.mirai.console.internal.permission.BuiltInPermissionService
import net.mamoe.mirai.console.permission.PermissionService import net.mamoe.mirai.console.permission.PermissionService
/** /**
@ -21,8 +21,7 @@ import net.mamoe.mirai.console.permission.PermissionService
*/ */
public interface PermissionServiceProvider : SingletonExtension<PermissionService<*>> { public interface PermissionServiceProvider : SingletonExtension<PermissionService<*>> {
public companion object ExtensionPoint : public companion object ExtensionPoint :
AbstractExtensionPoint<PermissionServiceProvider>(PermissionServiceProvider::class), AbstractSingletonExtensionPoint<PermissionServiceProvider, PermissionService<*>>(PermissionServiceProvider::class, BuiltInPermissionService)
SingletonExtensionPoint<PermissionServiceProvider>
} }
/** /**

View File

@ -163,9 +163,7 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
phase `load PermissionService`@{ phase `load PermissionService`@{
mainLogger.verbose { "Loading PermissionService..." } mainLogger.verbose { "Loading PermissionService..." }
PermissionService.instanceField = GlobalComponentStorage.run { PermissionServiceProvider.selectedInstance // init
PermissionServiceProvider.findSingletonInstance(BuiltInPermissionService)
}
PermissionService.INSTANCE.let { ps -> PermissionService.INSTANCE.let { ps ->
if (ps is BuiltInPermissionService) { if (ps is BuiltInPermissionService) {

View File

@ -54,7 +54,7 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
internal fun <T : Extension> ExtensionPoint<out T>.getExtensions(): Set<ExtensionRegistry<T>> { internal fun <T : Extension> ExtensionPoint<out T>.getExtensions(): Set<ExtensionRegistry<T>> {
val userDefined = instances.getOrPut(this, ::CopyOnWriteArraySet) as Set<ExtensionRegistry<T>> val userDefined = instances.getOrPut(this, ::CopyOnWriteArraySet) as Set<ExtensionRegistry<T>>
val builtins = if (this is InstanceExtensionPoint<*, *>) { val builtins = if (this is AbstractInstanceExtensionPoint<*, *>) {
this.builtinImplementations.mapTo(HashSet()) { DataExtensionRegistry(null, it) } as Set<ExtensionRegistry<T>> this.builtinImplementations.mapTo(HashSet()) { DataExtensionRegistry(null, it) } as Set<ExtensionRegistry<T>>
} else null } else null

View File

@ -139,15 +139,15 @@ public interface PermissionService<P : Permission> {
public fun cancel(permitteeId: PermitteeId, permission: P, recursive: Boolean) public fun cancel(permitteeId: PermitteeId, permission: P, recursive: Boolean)
public companion object { public companion object {
internal var instanceField: PermissionService<*>? = null
/** /**
* [PermissionService] 实例 * [PermissionService] 实例
*
* @see PermissionServiceProvider.selectedInstance
*/ */
@get:JvmName("getInstance") @get:JvmName("getInstance")
@JvmStatic @JvmStatic
public val INSTANCE: PermissionService<out Permission> public val INSTANCE: PermissionService<out Permission>
get() = instanceField ?: error("PermissionService is not yet initialized therefore cannot be used.") get() = PermissionServiceProvider.selectedInstance
/** /**
* 获取一个权限, 失败时抛出 [NoSuchElementException] * 获取一个权限, 失败时抛出 [NoSuchElementException]