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.descriptor.ExperimentalCommandDescriptors
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.util.ConsoleExperimentalApi
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
*/
@file:Suppress("unused", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@file:Suppress("unused", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "MemberVisibilityCanBePrivate")
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
/**
* [Extension] `companion` 实现.
* [Extension] 的伴生对象实现.
*
* @see AbstractExtensionPoint
*/
public interface ExtensionPoint<T : Extension> {
/**
* 扩展实例 [T] 的类型
*/
public val extensionType: KClass<T>
}
public open class AbstractExtensionPoint<T : Extension>(
public abstract 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]
*/
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
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.internal.extension.AbstractConcurrentComponentStorage
import net.mamoe.mirai.console.permission.PermissionService
@ -35,7 +37,7 @@ public class PluginComponentStorage(
): Unit = contribute(extensionPoint, plugin, lazyInstance)
/**
* 注册一个扩展
* 注册一个扩展. [E] 必须拥有伴生对象为 [ExtensionPoint].
*/
public inline fun <reified E : Extension> contribute(
noinline lazyInstance: () -> E,
@ -74,16 +76,14 @@ public class PluginComponentStorage(
/** 注册一个 [PermissionServiceProvider] */
@OverloadResolutionByLambdaReturnType
public fun contributePermissionService(
lazyInstance: () -> PermissionService<*>,
): Unit = contribute(PermissionServiceProvider, plugin, LazyPermissionServiceProviderImpl(lazyInstance))
public fun contributePermissionService(lazyInstance: () -> PermissionService<*>): Unit =
contribute(PermissionServiceProvider, plugin, LazyPermissionServiceProviderImpl(lazyInstance))
/** 注册一个 [PermissionServiceProvider] */
@JvmName("contributePermissionServiceProvider")
@OverloadResolutionByLambdaReturnType
public fun contributePermissionService(
lazyProvider: () -> PermissionServiceProvider,
): Unit = contribute(PermissionServiceProvider, plugin, lazyProvider)
public fun contributePermissionService(lazyProvider: () -> PermissionServiceProvider): Unit =
contribute(PermissionServiceProvider, plugin, lazyProvider)
/////////////////////////////////////
@ -96,5 +96,20 @@ public class PluginComponentStorage(
@JvmName("contributePluginLoaderProvider")
@OverloadResolutionByLambdaReturnType
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.parse.CommandCallParser
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.InstanceExtensionPoint
/**
* The provider of [CommandCallParser]
*/
@ExperimentalCommandDescriptors
public open class CommandCallParserProvider(override val instance: CommandCallParser) : InstanceExtension<CommandCallParser> {
public interface CommandCallParserProvider : InstanceExtension<CommandCallParser> {
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.resolve.BuiltInCommandCallResolver
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.InstanceExtensionPoint
@ExperimentalCommandDescriptors
public open class CommandCallResolverProvider(override val instance: CommandCallResolver) : InstanceExtension<CommandCallResolver> {
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
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.SingletonExtensionPoint
import net.mamoe.mirai.console.internal.permission.BuiltInPermissionService
import net.mamoe.mirai.console.permission.PermissionService
/**
@ -21,8 +21,7 @@ import net.mamoe.mirai.console.permission.PermissionService
*/
public interface PermissionServiceProvider : SingletonExtension<PermissionService<*>> {
public companion object ExtensionPoint :
AbstractExtensionPoint<PermissionServiceProvider>(PermissionServiceProvider::class),
SingletonExtensionPoint<PermissionServiceProvider>
AbstractSingletonExtensionPoint<PermissionServiceProvider, PermissionService<*>>(PermissionServiceProvider::class, BuiltInPermissionService)
}
/**

View File

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

View File

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