Review extensions:

Rename ScopedComponentStorage to PluginComponentStorage;
Add more extensions for PluginComponentStorage;
Misc improvements
This commit is contained in:
Him188 2020-09-12 21:13:55 +08:00
parent 9b3e96e3d3
commit 87373ef3ba
13 changed files with 170 additions and 77 deletions

View File

@ -1,24 +1,31 @@
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") /*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.console.extension package net.mamoe.mirai.console.extension
import net.mamoe.mirai.console.extensions.LazyPermissionServiceProviderImpl
import net.mamoe.mirai.console.extensions.PermissionServiceProvider
import net.mamoe.mirai.console.extensions.SingletonExtensionSelector import net.mamoe.mirai.console.extensions.SingletonExtensionSelector
import net.mamoe.mirai.console.extensions.SingletonExtensionSelector.ExtensionPoint.selectSingleton import net.mamoe.mirai.console.extensions.SingletonExtensionSelector.ExtensionPoint.selectSingleton
import net.mamoe.mirai.console.internal.data.kClassQualifiedNameOrTip import net.mamoe.mirai.console.internal.data.kClassQualifiedNameOrTip
import net.mamoe.mirai.console.permission.PermissionService
import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.Plugin
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin.Companion.onLoad
import net.mamoe.mirai.console.plugin.name import net.mamoe.mirai.console.plugin.name
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArraySet import java.util.concurrent.CopyOnWriteArraySet
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.internal.LowPriorityInOverloadResolution
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.full.companionObjectInstance
/** /**
* 组件容器, 容纳 [Plugin] 注册的 [Extension]. * 组件容器, 容纳 [Plugin] 注册的 [Extension].
*
* @see Extension
* @see JvmPlugin.onLoad
*/ */
public interface ComponentStorage { public interface ComponentStorage {
public fun <T : Extension> contribute( public fun <T : Extension> contribute(
@ -34,45 +41,6 @@ public interface ComponentStorage {
) )
} }
@Suppress("EXPOSED_SUPER_CLASS")
public class ScopedComponentStorage(
@JvmField
internal val plugin: Plugin,
) : AbstractConcurrentComponentStorage() {
/**
* 注册一个扩展
*/
public fun <E : Extension> contribute(
extensionPoint: ExtensionPoint<E>,
lazyInstance: () -> E,
) {
contribute(extensionPoint, plugin, lazyInstance)
}
/**
* 注册一个扩展
*/
public inline fun <reified E : Extension> contribute(
noinline lazyInstance: () -> E,
) {
@Suppress("UNCHECKED_CAST")
(contribute(
(E::class.companionObjectInstance as? ExtensionPoint<E>
?: error("Companion object of ${E::class.qualifiedName} is not an ExtensionPoint")),
lazyInstance
))
}
/**
* 注册一个 [PermissionService]
*/
public fun contributePermissionService(
lazyInstance: () -> PermissionService<*>,
) {
contribute(PermissionServiceProvider, plugin, LazyPermissionServiceProviderImpl(lazyInstance))
}
}
internal object GlobalComponentStorage : AbstractConcurrentComponentStorage() internal object GlobalComponentStorage : AbstractConcurrentComponentStorage()
internal interface ExtensionRegistry<out E : Extension> { internal interface ExtensionRegistry<out E : Extension> {
@ -120,7 +88,8 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
return withExtensions { _ -> block() } return withExtensions { _ -> block() }
} }
@LowPriorityInOverloadResolution @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 { contract {
callsInPlace(block) callsInPlace(block)
@ -193,7 +162,8 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
internal inline fun <T : Extension> ExtensionPoint<T>.useExtensions(block: (extension: T) -> Unit): Unit = internal inline fun <T : Extension> ExtensionPoint<T>.useExtensions(block: (extension: T) -> Unit): Unit =
withExtensions(block) withExtensions(block)
@LowPriorityInOverloadResolution @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) withExtensions(block)

View File

@ -13,18 +13,17 @@ import net.mamoe.mirai.console.extensions.PermissionServiceProvider
import net.mamoe.mirai.console.extensions.PluginLoaderProvider import net.mamoe.mirai.console.extensions.PluginLoaderProvider
import net.mamoe.mirai.console.extensions.SingletonExtensionSelector import net.mamoe.mirai.console.extensions.SingletonExtensionSelector
import net.mamoe.mirai.console.extensions.SingletonExtensionSelector.ExtensionPoint.selectSingleton import net.mamoe.mirai.console.extensions.SingletonExtensionSelector.ExtensionPoint.selectSingleton
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
/** /**
* 表示一个扩展. * 表示一个扩展.
*
* @see ComponentStorage
*/ */
@ConsoleExperimentalApi
public interface Extension public interface Extension
/** /**
* 增加一些函数 (方法)的扩展 * 增加一些函数 (方法)的扩展
*/ */
@ConsoleExperimentalApi
public interface FunctionExtension : Extension public interface FunctionExtension : Extension
/** /**
@ -34,7 +33,6 @@ public interface FunctionExtension : Extension
* *
* @see PermissionServiceProvider * @see PermissionServiceProvider
*/ */
@ConsoleExperimentalApi
public interface SingletonExtension<T> : Extension { public interface SingletonExtension<T> : Extension {
public val instance: T public val instance: T
} }
@ -44,7 +42,6 @@ public interface SingletonExtension<T> : Extension {
* *
* @see PluginLoaderProvider * @see PluginLoaderProvider
*/ */
@ConsoleExperimentalApi
public interface InstanceExtension<T> : Extension { public interface InstanceExtension<T> : Extension {
public val instance: T public val instance: T
} }

View File

@ -0,0 +1,98 @@
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.console.extension
import net.mamoe.mirai.console.extensions.*
import net.mamoe.mirai.console.permission.PermissionService
import net.mamoe.mirai.console.plugin.Plugin
import net.mamoe.mirai.console.plugin.loader.PluginLoader
import kotlin.reflect.full.companionObjectInstance
/**
* 添加一些扩展给 [Plugin] [ComponentStorage].
*
* 所有扩展都会以 'lazy' 形式注册, Console 在不同的启动阶段分别初始化各类扩展.
*/
@Suppress("EXPOSED_SUPER_CLASS", "unused", "MemberVisibilityCanBePrivate")
public class PluginComponentStorage(
@JvmField
internal val plugin: Plugin,
) : AbstractConcurrentComponentStorage() {
/**
* 注册一个扩展
*/
public fun <E : Extension> contribute(
extensionPoint: ExtensionPoint<E>,
lazyInstance: () -> E,
): Unit = contribute(extensionPoint, plugin, lazyInstance)
/**
* 注册一个扩展
*/
public inline fun <reified E : Extension> contribute(
noinline lazyInstance: () -> E,
) {
@Suppress("UNCHECKED_CAST")
(contribute(
(E::class.companionObjectInstance as? ExtensionPoint<E>
?: error("Companion object of ${E::class.qualifiedName} is not an ExtensionPoint")),
lazyInstance
))
}
///////////////////////////////////////////////////////////////////////////
// FunctionExtension
///////////////////////////////////////////////////////////////////////////
/** 注册一个 [SingletonExtensionSelector] */
public fun contributeSingletonExtensionSelector(lazyInstance: () -> SingletonExtensionSelector): Unit =
contribute(SingletonExtensionSelector, plugin, lazyInstance)
/** 注册一个 [BotConfigurationAlterer] */
public fun contributeBotConfigurationAlterer(instance: BotConfigurationAlterer): Unit =
contribute(BotConfigurationAlterer, plugin, lazyInstance = { instance })
/** 注册一个 [PostStartupExtension] */
public fun contributePostStartupExtension(instance: PostStartupExtension): Unit =
contribute(PostStartupExtension, plugin, lazyInstance = { instance })
/** 注册一个 [PostStartupExtension] */
public fun runAfterStartup(block: () -> Unit): Unit = contributePostStartupExtension(block)
///////////////////////////////////////////////////////////////////////////
// InstanceExtensions & SingletonExtensions
///////////////////////////////////////////////////////////////////////////
/** 注册一个 [PermissionServiceProvider] */
@OverloadResolutionByLambdaReturnType
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)
/////////////////////////////////////
/** 注册一个 [PluginLoaderProvider] */
@OverloadResolutionByLambdaReturnType
public fun contributePluginLoader(lazyInstance: () -> PluginLoader<*, *>): Unit =
contribute(PluginLoaderProvider, plugin, LazyPluginLoaderProviderImpl(lazyInstance))
/** 注册一个 [PluginLoaderProvider] */
@JvmName("contributePluginLoaderProvider")
@OverloadResolutionByLambdaReturnType
public fun contributePluginLoader(lazyProvider: () -> PluginLoaderProvider): Unit =
contribute(PluginLoaderProvider, plugin, lazyProvider)
}

View File

@ -1,3 +1,12 @@
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:Suppress("unused") @file:Suppress("unused")
package net.mamoe.mirai.console.extensions package net.mamoe.mirai.console.extensions
@ -12,16 +21,15 @@ import net.mamoe.mirai.utils.BotConfiguration
* *
* @see MiraiConsole.addBot * @see MiraiConsole.addBot
*/ */
public interface BotConfigurationAlterer : FunctionExtension { public fun interface BotConfigurationAlterer : FunctionExtension {
/** /**
* 修改 [configuration], 返回修改完成的 [BotConfiguration] * 修改 [configuration], 返回修改完成的 [BotConfiguration]
*/ */
@JvmDefault
public fun alterConfiguration( public fun alterConfiguration(
botId: Long, botId: Long,
configuration: BotConfiguration configuration: BotConfiguration,
): BotConfiguration = configuration ): BotConfiguration
public companion object ExtensionPoint : public companion object ExtensionPoint :
AbstractExtensionPoint<BotConfigurationAlterer>(BotConfigurationAlterer::class) AbstractExtensionPoint<BotConfigurationAlterer>(BotConfigurationAlterer::class)

View File

@ -1,3 +1,12 @@
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
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.AbstractExtensionPoint
@ -16,8 +25,14 @@ public interface PermissionServiceProvider : SingletonExtension<PermissionServic
SingletonExtensionPoint<PermissionServiceProvider> SingletonExtensionPoint<PermissionServiceProvider>
} }
/**
* @see PermissionServiceProvider
*/
public class PermissionServiceProviderImpl(override val instance: PermissionService<*>) : PermissionServiceProvider public class PermissionServiceProviderImpl(override val instance: PermissionService<*>) : PermissionServiceProvider
/**
* @see PermissionServiceProvider
*/
public class LazyPermissionServiceProviderImpl(initializer: () -> PermissionService<*>) : PermissionServiceProvider { public class LazyPermissionServiceProviderImpl(initializer: () -> PermissionService<*>) : PermissionServiceProvider {
override val instance: PermissionService<*> by lazy(initializer) override val instance: PermissionService<*> by lazy(initializer)
} }

View File

@ -1,3 +1,12 @@
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
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.AbstractExtensionPoint
@ -10,3 +19,9 @@ import net.mamoe.mirai.console.plugin.loader.PluginLoader
public interface PluginLoaderProvider : InstanceExtension<PluginLoader<*, *>> { public interface PluginLoaderProvider : InstanceExtension<PluginLoader<*, *>> {
public companion object ExtensionPoint : AbstractExtensionPoint<PluginLoaderProvider>(PluginLoaderProvider::class) public companion object ExtensionPoint : AbstractExtensionPoint<PluginLoaderProvider>(PluginLoaderProvider::class)
} }
public class PluginLoaderProviderImpl(override val instance: PluginLoader<*, *>) : PluginLoaderProvider
public class LazyPluginLoaderProviderImpl(initializer: () -> PluginLoader<*, *>) : PluginLoaderProvider {
override val instance: PluginLoader<*, *> by lazy(initializer)
}

View File

@ -16,8 +16,6 @@ import net.mamoe.mirai.console.extension.FunctionExtension
* Console 启动完成后立即在主线程调用的扩展. 用于进行一些必要的延迟初始化. * Console 启动完成后立即在主线程调用的扩展. 用于进行一些必要的延迟初始化.
* *
* 这些扩展只会, 且一定会被调用正好一次. * 这些扩展只会, 且一定会被调用正好一次.
*
* 此扩展可由所有插件提供
*/ */
public fun interface PostStartupExtension : FunctionExtension { public fun interface PostStartupExtension : FunctionExtension {
/** /**

View File

@ -14,7 +14,6 @@ import net.mamoe.mirai.console.extension.*
import net.mamoe.mirai.console.internal.extensions.BuiltInSingletonExtensionSelector import net.mamoe.mirai.console.internal.extensions.BuiltInSingletonExtensionSelector
import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.Plugin
import net.mamoe.mirai.console.plugin.name import net.mamoe.mirai.console.plugin.name
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
import net.mamoe.mirai.utils.info import net.mamoe.mirai.utils.info
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -23,7 +22,6 @@ import kotlin.reflect.KClass
* *
* 如有多个 [SingletonExtensionSelector] 注册, 将会停止服务器. * 如有多个 [SingletonExtensionSelector] 注册, 将会停止服务器.
*/ */
@ConsoleExperimentalApi
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,

View File

@ -14,7 +14,7 @@ import kotlinx.atomicfu.locks.withLock
import kotlinx.coroutines.* import kotlinx.coroutines.*
import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.MiraiConsole
import net.mamoe.mirai.console.data.runCatchingLog import net.mamoe.mirai.console.data.runCatchingLog
import net.mamoe.mirai.console.extension.ScopedComponentStorage import net.mamoe.mirai.console.extension.PluginComponentStorage
import net.mamoe.mirai.console.internal.data.mkdir import net.mamoe.mirai.console.internal.data.mkdir
import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.console.permission.Permission
import net.mamoe.mirai.console.permission.PermissionService import net.mamoe.mirai.console.permission.PermissionService
@ -46,7 +46,7 @@ internal abstract class JvmPluginInternal(
) : JvmPlugin, CoroutineScope { ) : JvmPlugin, CoroutineScope {
@Suppress("LeakingThis") @Suppress("LeakingThis")
internal val componentStorage: ScopedComponentStorage = ScopedComponentStorage(this) internal val componentStorage: PluginComponentStorage = PluginComponentStorage(this)
final override val parentPermission: Permission by lazy { final override val parentPermission: Permission by lazy {
PermissionService.INSTANCE.register( PermissionService.INSTANCE.register(
@ -104,7 +104,7 @@ internal abstract class JvmPluginInternal(
} }
@Throws(Throwable::class) @Throws(Throwable::class)
internal fun internalOnLoad(componentStorage: ScopedComponentStorage) { internal fun internalOnLoad(componentStorage: PluginComponentStorage) {
onLoad(componentStorage) onLoad(componentStorage)
} }

View File

@ -12,7 +12,7 @@ package net.mamoe.mirai.console.permission
import kotlin.annotation.AnnotationTarget.* import kotlin.annotation.AnnotationTarget.*
/** /**
* 表示一个应该由 [权限服务][PermissionService] 实现的类. * 表示一个应该由权限插件实现的类.
* *
* 这样的类不能被用户手动实现或者继承, 也不能使用属性委托或者类委托, 或者其他任意改变实现类的手段. * 这样的类不能被用户手动实现或者继承, 也不能使用属性委托或者类委托, 或者其他任意改变实现类的手段.
* 用户仅应该使用从 [PermissionService] 或其他途径获取这些对象, 而不能自行实现它们. * 用户仅应该使用从 [PermissionService] 或其他途径获取这些对象, 而不能自行实现它们.

View File

@ -24,6 +24,7 @@ import kotlin.reflect.KClass
* *
* [PermissionServiceProvider] * [PermissionServiceProvider]
*/ */
@PermissionImplementation
public interface PermissionService<P : Permission> { public interface PermissionService<P : Permission> {
/** /**
* [P] 的类型 * [P] 的类型

View File

@ -18,7 +18,7 @@
package net.mamoe.mirai.console.plugin.jvm package net.mamoe.mirai.console.plugin.jvm
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.console.extension.ScopedComponentStorage import net.mamoe.mirai.console.extension.PluginComponentStorage
import net.mamoe.mirai.console.permission.PermissionIdNamespace import net.mamoe.mirai.console.permission.PermissionIdNamespace
import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.Plugin
import net.mamoe.mirai.console.plugin.PluginFileExtensions import net.mamoe.mirai.console.plugin.PluginFileExtensions
@ -53,11 +53,13 @@ public interface JvmPlugin : Plugin, CoroutineScope,
/** /**
* 在插件被加载时调用. 只会被调用一次. * 在插件被加载时调用. 只会被调用一次.
* *
* [onLoad] 时可注册扩展 [ScopedComponentStorage.contribute] * [onLoad] 时可注册扩展 [PluginComponentStorage.contribute]
*
* @see PluginComponentStorage 查看更多信息
* *
* @receiver 组件容器 * @receiver 组件容器
*/ */
public fun @ParameterName("storage") ScopedComponentStorage.onLoad() {} public fun PluginComponentStorage.onLoad() {}
/** /**
* 在插件被启用时调用, 可能会被调用多次 * 在插件被启用时调用, 可能会被调用多次
@ -71,6 +73,6 @@ public interface JvmPlugin : Plugin, CoroutineScope,
public companion object { public companion object {
@JvmSynthetic @JvmSynthetic
public inline fun JvmPlugin.onLoad(storage: ScopedComponentStorage): Unit = storage.onLoad() public inline fun JvmPlugin.onLoad(storage: PluginComponentStorage): Unit = storage.onLoad()
} }
} }

View File

@ -10,8 +10,6 @@
package net.mamoe.mirai.console.data package net.mamoe.mirai.console.data
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin
import net.mamoe.mirai.console.util.ConsoleInternalApi import net.mamoe.mirai.console.util.ConsoleInternalApi
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -19,13 +17,6 @@ import kotlin.test.assertSame
@OptIn(ConsoleInternalApi::class) @OptIn(ConsoleInternalApi::class)
internal class PluginDataTest { internal class PluginDataTest {
object MyPlugin : KotlinPlugin(
JvmPluginDescription(
"1", "2"
)
)
class MyPluginData : AutoSavePluginData() { class MyPluginData : AutoSavePluginData() {
var int by value(1) var int by value(1)
val map: MutableMap<String, String> by value() val map: MutableMap<String, String> by value()