Rename JarPluginLoader to JvmPluginLoader. Rename JvmPluginLoader.Companion to JvmPluginLoader.BuiltIn

This commit is contained in:
Him188 2020-09-12 19:43:51 +08:00
parent c9ed804bf2
commit 5c6b4aa8cc
13 changed files with 43 additions and 45 deletions

View File

@ -24,7 +24,7 @@ import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
import net.mamoe.mirai.console.plugin.PluginLoader import net.mamoe.mirai.console.plugin.PluginLoader
import net.mamoe.mirai.console.plugin.PluginManager import net.mamoe.mirai.console.plugin.PluginManager
import net.mamoe.mirai.console.plugin.center.PluginCenter import net.mamoe.mirai.console.plugin.center.PluginCenter
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader
import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.console.util.ConsoleExperimentalApi
import net.mamoe.mirai.console.util.ConsoleInternalApi import net.mamoe.mirai.console.util.ConsoleInternalApi
import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScopeContext import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScopeContext
@ -64,7 +64,7 @@ public interface MiraiConsole : CoroutineScope {
public val mainLogger: MiraiLogger public val mainLogger: MiraiLogger
/** /**
* 内建加载器列表, 一般需要包含 [JarPluginLoader]. * 内建加载器列表, 一般需要包含 [JvmPluginLoader].
* *
* @return 不可变 [List] ([java.util.Collections.unmodifiableList]) * @return 不可变 [List] ([java.util.Collections.unmodifiableList])
*/ */

View File

@ -19,7 +19,7 @@ import net.mamoe.mirai.console.command.ConsoleCommandSender
import net.mamoe.mirai.console.data.PluginDataStorage import net.mamoe.mirai.console.data.PluginDataStorage
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
import net.mamoe.mirai.console.plugin.PluginLoader import net.mamoe.mirai.console.plugin.PluginLoader
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader
import net.mamoe.mirai.console.util.ConsoleInput import net.mamoe.mirai.console.util.ConsoleInput
import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.BotConfiguration
@ -72,7 +72,7 @@ public interface MiraiConsoleImplementation : CoroutineScope {
public val frontEndDescription: MiraiConsoleFrontEndDescription public val frontEndDescription: MiraiConsoleFrontEndDescription
/** /**
* 内建加载器列表, 一般需要包含 [JarPluginLoader]. * 内建加载器列表, 一般需要包含 [JvmPluginLoader].
* *
* @return 不可变的 [List], [Collections.unmodifiableList] * @return 不可变的 [List], [Collections.unmodifiableList]
*/ */

View File

@ -13,8 +13,8 @@ package net.mamoe.mirai.console.data
import net.mamoe.mirai.console.internal.data.MemoryPluginDataStorageImpl import net.mamoe.mirai.console.internal.data.MemoryPluginDataStorageImpl
import net.mamoe.mirai.console.internal.data.MultiFilePluginDataStorageImpl import net.mamoe.mirai.console.internal.data.MultiFilePluginDataStorageImpl
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader
import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.console.util.ConsoleExperimentalApi
import java.io.File import java.io.File
import java.nio.file.Path import java.nio.file.Path
@ -28,10 +28,10 @@ import java.nio.file.Path
* *
* 此为较低层的 API, 一般插件开发者不会接触. * 此为较低层的 API, 一般插件开发者不会接触.
* *
* [JarPluginLoader] 实现一个 [PluginDataStorage], 用于管理所有 [JvmPlugin] [PluginData] 实例. * [JvmPluginLoader] 实现一个 [PluginDataStorage], 用于管理所有 [JvmPlugin] [PluginData] 实例.
* *
* @see PluginDataHolder * @see PluginDataHolder
* @see JarPluginLoader.dataStorage * @see JvmPluginLoader.dataStorage
*/ */
@ConsoleExperimentalApi @ConsoleExperimentalApi
public interface PluginDataStorage { public interface PluginDataStorage {

View File

@ -26,18 +26,18 @@ import java.io.File
import java.net.URLClassLoader import java.net.URLClassLoader
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
internal object JarPluginLoaderImpl : internal object BuiltInJvmPluginLoaderImpl :
AbstractFilePluginLoader<JvmPlugin, JvmPluginDescription>(".jar"), AbstractFilePluginLoader<JvmPlugin, JvmPluginDescription>(".jar"),
CoroutineScope by MiraiConsole.childScope("JarPluginLoader", CoroutineExceptionHandler { _, throwable -> CoroutineScope by MiraiConsole.childScope("JarPluginLoader", CoroutineExceptionHandler { _, throwable ->
JarPluginLoaderImpl.logger.error("Unhandled Jar plugin exception: ${throwable.message}", throwable) BuiltInJvmPluginLoaderImpl.logger.error("Unhandled Jar plugin exception: ${throwable.message}", throwable)
}), }),
JarPluginLoader { JvmPluginLoader {
override val configStorage: PluginDataStorage override val configStorage: PluginDataStorage
get() = MiraiConsoleImplementationBridge.configStorageForJarPluginLoader get() = MiraiConsoleImplementationBridge.configStorageForJarPluginLoader
@JvmStatic @JvmStatic
internal val logger: MiraiLogger = MiraiConsole.createLogger(JarPluginLoader::class.simpleName!!) internal val logger: MiraiLogger = MiraiConsole.createLogger(JvmPluginLoader::class.simpleName!!)
override val dataStorage: PluginDataStorage override val dataStorage: PluginDataStorage
get() = MiraiConsoleImplementationBridge.dataStorageForJarPluginLoader get() = MiraiConsoleImplementationBridge.dataStorageForJarPluginLoader

View File

@ -63,7 +63,7 @@ internal abstract class JvmPluginInternal(
// region JvmPlugin // region JvmPlugin
final override val logger: MiraiLogger by lazy { final override val logger: MiraiLogger by lazy {
JarPluginLoaderImpl.logger.runCatchingLog { BuiltInJvmPluginLoaderImpl.logger.runCatchingLog {
MiraiConsole.createLogger( MiraiConsole.createLogger(
"Plugin ${this.description.name}" "Plugin ${this.description.name}"
) )
@ -149,11 +149,11 @@ internal abstract class JvmPluginInternal(
.plus( .plus(
NamedSupervisorJob( NamedSupervisorJob(
"Plugin ${(this as AbstractJvmPlugin).dataHolderName}", "Plugin ${(this as AbstractJvmPlugin).dataHolderName}",
parentCoroutineContext[Job] ?: JarPluginLoaderImpl.coroutineContext[Job]!! parentCoroutineContext[Job] ?: BuiltInJvmPluginLoaderImpl.coroutineContext[Job]!!
) )
) )
.also { .also {
JarPluginLoaderImpl.coroutineContext[Job]!!.invokeOnCompletion { BuiltInJvmPluginLoaderImpl.coroutineContext[Job]!!.invokeOnCompletion {
this.cancel() this.cancel()
} }
} }

View File

@ -11,7 +11,7 @@ package net.mamoe.mirai.console.internal.util
import net.mamoe.mirai.console.internal.data.cast import net.mamoe.mirai.console.internal.data.cast
import net.mamoe.mirai.console.internal.data.createInstanceOrNull import net.mamoe.mirai.console.internal.data.createInstanceOrNull
import net.mamoe.mirai.console.internal.plugin.JarPluginLoaderImpl import net.mamoe.mirai.console.internal.plugin.BuiltInJvmPluginLoaderImpl
import java.io.InputStream import java.io.InputStream
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import java.util.* import java.util.*
@ -65,7 +65,7 @@ internal object PluginServiceHelper {
fun <T : Any> loadAllServicesFromMemoryAndPluginClassLoaders(service: KClass<T>): List<T> { fun <T : Any> loadAllServicesFromMemoryAndPluginClassLoaders(service: KClass<T>): List<T> {
val list = ServiceLoader.load(service.java, this::class.java.classLoader).toList() val list = ServiceLoader.load(service.java, this::class.java.classLoader).toList()
return list + JarPluginLoaderImpl.classLoaders.flatMap { it.findServices(service).loadAllServices() } return list + BuiltInJvmPluginLoaderImpl.classLoaders.flatMap { it.findServices(service).loadAllServices() }
} }
} }

View File

@ -14,7 +14,7 @@ package net.mamoe.mirai.console.plugin
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.disable import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.disable
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.enable import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.enable
import net.mamoe.mirai.console.plugin.description.PluginDescription import net.mamoe.mirai.console.plugin.description.PluginDescription
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader
import java.io.File import java.io.File
import java.util.* import java.util.*
@ -26,7 +26,7 @@ import java.util.*
* 有关插件的依赖和已加载的插件列表由 [PluginManager] 维护. * 有关插件的依赖和已加载的插件列表由 [PluginManager] 维护.
* *
* ## 内建加载器 * ## 内建加载器
* - [JarPluginLoader] Jar 插件加载器 * - [JvmPluginLoader] Jar 插件加载器
* *
* ## 扩展加载器 * ## 扩展加载器
* 插件被允许扩展一个加载器. * 插件被允许扩展一个加载器.
@ -34,7 +34,7 @@ import java.util.*
* ### 实现扩展加载器 * ### 实现扩展加载器
* 直接实现接口 [PluginLoader] [FilePluginLoader], 并添加 [ServiceLoader] 相关资源文件即可. * 直接实现接口 [PluginLoader] [FilePluginLoader], 并添加 [ServiceLoader] 相关资源文件即可.
* *
* @see JarPluginLoader Jar 插件加载器 * @see JvmPluginLoader Jar 插件加载器
*/ */
public interface PluginLoader<P : Plugin, D : PluginDescription> { public interface PluginLoader<P : Plugin, D : PluginDescription> {
/** /**
@ -65,7 +65,7 @@ public interface PluginLoader<P : Plugin, D : PluginDescription> {
public val P.description: D // Java signature: `public D getDescription(P)` public val P.description: D // Java signature: `public D getDescription(P)`
/** /**
* 加载一个插件 (实例), 但不 [启用][enable] . 返回加载成功的主类实例 * 主动加载一个插件 (实例), 但不 [启用][enable] . 返回加载成功的主类实例
* *
* **实现细节**: 此函数只允许抛出 [PluginLoadException] 作为正常失败原因, 其他任意异常都属于意外错误. * **实现细节**: 此函数只允许抛出 [PluginLoadException] 作为正常失败原因, 其他任意异常都属于意外错误.
* 当异常发生时, 插件将会直接被放弃加载, 并影响依赖它的其他插件. * 当异常发生时, 插件将会直接被放弃加载, 并影响依赖它的其他插件.
@ -76,7 +76,7 @@ public interface PluginLoader<P : Plugin, D : PluginDescription> {
public fun load(plugin: P) public fun load(plugin: P)
/** /**
* 启用这个插件. * 主动启用这个插件.
* *
* **实现细节**: 此函数可抛出 [PluginLoadException] 作为正常失败原因, 其他任意异常都属于意外错误. * **实现细节**: 此函数可抛出 [PluginLoadException] 作为正常失败原因, 其他任意异常都属于意外错误.
* 当异常发生时, 插件将会直接被放弃加载, 并影响依赖它的其他插件. * 当异常发生时, 插件将会直接被放弃加载, 并影响依赖它的其他插件.
@ -89,7 +89,7 @@ public interface PluginLoader<P : Plugin, D : PluginDescription> {
public fun enable(plugin: P) public fun enable(plugin: P)
/** /**
* 禁用这个插件. * 主动禁用这个插件.
* *
* **实现细节**: 此函数可抛出 [PluginLoadException] 作为正常失败原因, 其他任意异常都属于意外错误. * **实现细节**: 此函数可抛出 [PluginLoadException] 作为正常失败原因, 其他任意异常都属于意外错误.
* 当异常发生时, 插件将会直接被放弃加载, 并影响依赖它的其他插件. * 当异常发生时, 插件将会直接被放弃加载, 并影响依赖它的其他插件.
@ -138,11 +138,11 @@ public open class PluginLoadException : RuntimeException {
* ['/plugins'][PluginManager.pluginsPath] 目录中的插件的加载器. 每个加载器需绑定一个后缀. * ['/plugins'][PluginManager.pluginsPath] 目录中的插件的加载器. 每个加载器需绑定一个后缀.
* *
* @see AbstractFilePluginLoader 默认基础实现 * @see AbstractFilePluginLoader 默认基础实现
* @see JarPluginLoader 内建的 Jar (JVM) 插件加载器. * @see JvmPluginLoader 内建的 Jar (JVM) 插件加载器.
*/ */
public interface FilePluginLoader<P : Plugin, D : PluginDescription> : PluginLoader<P, D> { public interface FilePluginLoader<P : Plugin, D : PluginDescription> : PluginLoader<P, D> {
/** /**
* 所支持的插件文件后缀, '.'. [JarPluginLoader] ".jar" * 所支持的插件文件后缀, '.', 不区分大小写. [JvmPluginLoader] ".jar"
*/ */
public val fileSuffix: String public val fileSuffix: String
} }
@ -154,9 +154,9 @@ public interface FilePluginLoader<P : Plugin, D : PluginDescription> : PluginLoa
*/ */
public abstract class AbstractFilePluginLoader<P : Plugin, D : PluginDescription>( public abstract class AbstractFilePluginLoader<P : Plugin, D : PluginDescription>(
/** /**
* 所支持的插件文件后缀, '.'. [JarPluginLoader] ".jar" * 所支持的插件文件后缀, '.', 不区分大小写. [JvmPluginLoader] ".jar"
*/ */
public override val fileSuffix: String public override val fileSuffix: String,
) : FilePluginLoader<P, D> { ) : FilePluginLoader<P, D> {
private fun pluginsFilesSequence(): Sequence<File> = private fun pluginsFilesSequence(): Sequence<File> =
PluginManager.pluginsFolder.listFiles().orEmpty().asSequence() PluginManager.pluginsFolder.listFiles().orEmpty().asSequence()
@ -173,7 +173,7 @@ public abstract class AbstractFilePluginLoader<P : Plugin, D : PluginDescription
// Not yet decided to make public API // Not yet decided to make public API
internal class DeferredPluginLoader<P : Plugin, D : PluginDescription>( internal class DeferredPluginLoader<P : Plugin, D : PluginDescription>(
initializer: () -> PluginLoader<P, D> initializer: () -> PluginLoader<P, D>,
) : PluginLoader<P, D> { ) : PluginLoader<P, D> {
private val instance by lazy(initializer) private val instance by lazy(initializer)

View File

@ -35,7 +35,7 @@ public abstract class AbstractJvmPlugin @JvmOverloads constructor(
public final override val dataHolderName: String public final override val dataHolderName: String
get() = this.description.name get() = this.description.name
public final override val loader: JarPluginLoader get() = super<JvmPluginInternal>.loader public final override val loader: JvmPluginLoader get() = super<JvmPluginInternal>.loader
public final override fun permissionId(id: String): PermissionId = PermissionId(description.id, id) public final override fun permissionId(id: String): PermissionId = PermissionId(description.id, id)

View File

@ -48,7 +48,7 @@ public interface JvmPlugin : Plugin, CoroutineScope,
/** 所属插件加载器实例 */ /** 所属插件加载器实例 */
// `final` in AbstractJvmPlugin // `final` in AbstractJvmPlugin
public override val loader: JarPluginLoader get() = JarPluginLoader public override val loader: JvmPluginLoader get() = JvmPluginLoader
/** /**
* 在插件被加载时调用. 只会被调用一次. * 在插件被加载时调用. 只会被调用一次.

View File

@ -11,30 +11,28 @@ package net.mamoe.mirai.console.plugin.jvm
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.console.data.PluginDataStorage import net.mamoe.mirai.console.data.PluginDataStorage
import net.mamoe.mirai.console.internal.plugin.JarPluginLoaderImpl import net.mamoe.mirai.console.internal.plugin.BuiltInJvmPluginLoaderImpl
import net.mamoe.mirai.console.plugin.FilePluginLoader import net.mamoe.mirai.console.plugin.FilePluginLoader
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
/** /**
* 内建的 Jar (JVM) 插件加载器 * 内建的 Jar (JVM) 插件加载器
*/ */
@ConsoleExperimentalApi("classname might change") public interface JvmPluginLoader : CoroutineScope, FilePluginLoader<JvmPlugin, JvmPluginDescription> {
public interface JarPluginLoader : CoroutineScope, FilePluginLoader<JvmPlugin, JvmPluginDescription> { public override val fileSuffix: String get() = ".jar"
/** /**
* [JvmPlugin.reloadPluginData] 默认使用的实例 * [AbstractJvmPlugin.reloadPluginData] 默认使用的实例
*/ */
@ConsoleExperimentalApi
public val dataStorage: PluginDataStorage public val dataStorage: PluginDataStorage
/** /**
* [JvmPlugin.reloadPluginData] 默认使用的实例 * [AbstractJvmPlugin.reloadPluginData] 默认使用的实例
*/ */
@ConsoleExperimentalApi
public val configStorage: PluginDataStorage public val configStorage: PluginDataStorage
public companion object INSTANCE : JarPluginLoader by JarPluginLoaderImpl { public companion object BuiltIn : JvmPluginLoader by BuiltInJvmPluginLoaderImpl {
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") @Suppress("EXTENSION_SHADOWED_BY_MEMBER")
override val JvmPlugin.description: JvmPluginDescription override val JvmPlugin.description: JvmPluginDescription
get() = JarPluginLoaderImpl.run { description } get() = BuiltInJvmPluginLoaderImpl.run { description }
} }
} }

View File

@ -17,7 +17,7 @@ import kotlin.coroutines.EmptyCoroutineContext
/** /**
* Kotlin 插件的父类. * Kotlin 插件的父类.
* *
* 必须通过 "plugin.yml" 指定主类并由 [JarPluginLoader] 加载. * 必须通过 "plugin.yml" 指定主类并由 [JvmPluginLoader] 加载.
*/ */
public abstract class KotlinPlugin @JvmOverloads constructor( public abstract class KotlinPlugin @JvmOverloads constructor(
public final override val description: JvmPluginDescription, public final override val description: JvmPluginDescription,

View File

@ -17,7 +17,7 @@ import net.mamoe.mirai.console.data.MemoryPluginDataStorage
import net.mamoe.mirai.console.data.PluginDataStorage import net.mamoe.mirai.console.data.PluginDataStorage
import net.mamoe.mirai.console.plugin.DeferredPluginLoader import net.mamoe.mirai.console.plugin.DeferredPluginLoader
import net.mamoe.mirai.console.plugin.PluginLoader import net.mamoe.mirai.console.plugin.PluginLoader
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader
import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.console.util.ConsoleExperimentalApi
import net.mamoe.mirai.console.util.ConsoleInput import net.mamoe.mirai.console.util.ConsoleInput
import net.mamoe.mirai.console.util.ConsoleInternalApi import net.mamoe.mirai.console.util.ConsoleInternalApi
@ -48,7 +48,7 @@ fun initTestEnvironment() {
get() = Semver("1.0.0") get() = Semver("1.0.0")
} }
override val builtInPluginLoaders: List<PluginLoader<*, *>> = listOf(DeferredPluginLoader { JarPluginLoader }) override val builtInPluginLoaders: List<PluginLoader<*, *>> = listOf(DeferredPluginLoader { JvmPluginLoader })
override val consoleCommandSender: MiraiConsoleImplementation.ConsoleCommandSenderImpl = override val consoleCommandSender: MiraiConsoleImplementation.ConsoleCommandSenderImpl =
object : MiraiConsoleImplementation.ConsoleCommandSenderImpl { object : MiraiConsoleImplementation.ConsoleCommandSenderImpl {
override suspend fun sendMessage(message: Message) { override suspend fun sendMessage(message: Message) {

View File

@ -32,7 +32,7 @@ import net.mamoe.mirai.console.data.MultiFilePluginDataStorage
import net.mamoe.mirai.console.data.PluginDataStorage import net.mamoe.mirai.console.data.PluginDataStorage
import net.mamoe.mirai.console.plugin.DeferredPluginLoader import net.mamoe.mirai.console.plugin.DeferredPluginLoader
import net.mamoe.mirai.console.plugin.PluginLoader import net.mamoe.mirai.console.plugin.PluginLoader
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader
import net.mamoe.mirai.console.pure.ConsoleInputImpl.requestInput import net.mamoe.mirai.console.pure.ConsoleInputImpl.requestInput
import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.console.util.ConsoleExperimentalApi
import net.mamoe.mirai.console.util.ConsoleInput import net.mamoe.mirai.console.util.ConsoleInput
@ -63,14 +63,14 @@ class MiraiConsoleImplementationPure
@JvmOverloads constructor( @JvmOverloads constructor(
override val rootPath: Path = Paths.get("."), override val rootPath: Path = Paths.get("."),
override val builtInPluginLoaders: List<PluginLoader<*, *>> = Collections.unmodifiableList( override val builtInPluginLoaders: List<PluginLoader<*, *>> = Collections.unmodifiableList(
listOf(DeferredPluginLoader { JarPluginLoader }) listOf(DeferredPluginLoader { JvmPluginLoader })
), ),
override val frontEndDescription: MiraiConsoleFrontEndDescription = ConsoleFrontEndDescImpl, override val frontEndDescription: MiraiConsoleFrontEndDescription = ConsoleFrontEndDescImpl,
override val consoleCommandSender: MiraiConsoleImplementation.ConsoleCommandSenderImpl = ConsoleCommandSenderImplPure, override val consoleCommandSender: MiraiConsoleImplementation.ConsoleCommandSenderImpl = ConsoleCommandSenderImplPure,
override val dataStorageForJarPluginLoader: PluginDataStorage = MultiFilePluginDataStorage(rootPath.resolve("data")), override val dataStorageForJarPluginLoader: PluginDataStorage = MultiFilePluginDataStorage(rootPath.resolve("data")),
override val dataStorageForBuiltIns: PluginDataStorage = MultiFilePluginDataStorage(rootPath.resolve("data")), override val dataStorageForBuiltIns: PluginDataStorage = MultiFilePluginDataStorage(rootPath.resolve("data")),
override val configStorageForJarPluginLoader: PluginDataStorage = MultiFilePluginDataStorage(rootPath.resolve("config")), override val configStorageForJarPluginLoader: PluginDataStorage = MultiFilePluginDataStorage(rootPath.resolve("config")),
override val configStorageForBuiltIns: PluginDataStorage = MultiFilePluginDataStorage(rootPath.resolve("config")) override val configStorageForBuiltIns: PluginDataStorage = MultiFilePluginDataStorage(rootPath.resolve("config")),
) : MiraiConsoleImplementation, CoroutineScope by CoroutineScope( ) : MiraiConsoleImplementation, CoroutineScope by CoroutineScope(
NamedSupervisorJob("MiraiConsoleImplementationPure") + NamedSupervisorJob("MiraiConsoleImplementationPure") +
CoroutineExceptionHandler { coroutineContext, throwable -> CoroutineExceptionHandler { coroutineContext, throwable ->