From c13076eea04674fd42a7821eff1b6729b9e2e4a4 Mon Sep 17 00:00:00 2001 From: Him188 Date: Thu, 20 Aug 2020 23:46:51 +0800 Subject: [PATCH] Fix Settings --- .../console/MiraiConsoleImplementation.kt | 6 ++++ .../mirai/console/command/BuiltInCommands.kt | 2 +- .../internal/MiraiConsoleBuildConstants.kt | 4 +-- .../command/CompositeCommandInternal.kt | 21 +++++++----- .../internal/plugin/JvmPluginInternal.kt | 6 ++-- .../internal/plugin/PluginManagerImpl.kt | 8 +++++ .../setting/SettingStorage internal.kt | 34 ++++++++++++------- .../mirai/console/setting/SettingStorage.kt | 6 ++-- .../mamoe/mirai/console/pure/ConsoleThread.kt | 2 +- .../pure/MiraiConsoleImplementationPure.kt | 7 ++-- 10 files changed, 61 insertions(+), 35 deletions(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleImplementation.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleImplementation.kt index abc7cbde3..217a86de1 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleImplementation.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleImplementation.kt @@ -24,6 +24,7 @@ import net.mamoe.mirai.utils.MiraiLogger import java.io.File import java.util.concurrent.locks.ReentrantLock import kotlin.annotation.AnnotationTarget.* +import kotlin.coroutines.CoroutineContext /** @@ -44,6 +45,11 @@ public annotation class ConsoleFrontEndImplementation */ @ConsoleFrontEndImplementation public interface MiraiConsoleImplementation : CoroutineScope { + /** + * [MiraiConsole] 的 [CoroutineScope.coroutineContext] + */ + public override val coroutineContext: CoroutineContext + /** * Console 运行路径 */ diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt index b23ada2ad..9cf52e96f 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt @@ -107,7 +107,7 @@ public object BuiltInCommands { private val closingLock = Mutex() @Handler - public suspend fun CommandSender.handle(): Unit { + public suspend fun CommandSender.handle() { closingLock.withLock { sendMessage("Stopping mirai-console") kotlin.runCatching { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleBuildConstants.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleBuildConstants.kt index 3b8ff47b8..be26ca308 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleBuildConstants.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleBuildConstants.kt @@ -13,6 +13,6 @@ import java.util.* internal object MiraiConsoleBuildConstants { // auto-filled on build (task :mirai-console:fillBuildConstants) @JvmStatic - val buildDate: Date = Date(1596350800177L) // 2020-08-02 14:46:40 - const val version: String = "1.0-M1" + val buildDate: Date = Date(1597935352287L) // 2020-08-20 22:55:52 + const val version: String = "1.0-M2-1" } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/CompositeCommandInternal.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/CompositeCommandInternal.kt index bea3f95a7..e19db7a2d 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/CompositeCommandInternal.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/CompositeCommandInternal.kt @@ -24,15 +24,20 @@ import kotlin.reflect.full.* internal object CompositeCommandSubCommandAnnotationResolver : AbstractReflectionCommand.SubCommandAnnotationResolver { - override fun hasAnnotation(function: KFunction<*>) = function.hasAnnotation() - override fun getSubCommandNames(function: KFunction<*>): Array = + override fun hasAnnotation(baseCommand: AbstractReflectionCommand, function: KFunction<*>) = + function.hasAnnotation() + + override fun getSubCommandNames(baseCommand: AbstractReflectionCommand, function: KFunction<*>): Array = function.findAnnotation()!!.value } internal object SimpleCommandSubCommandAnnotationResolver : AbstractReflectionCommand.SubCommandAnnotationResolver { - override fun hasAnnotation(function: KFunction<*>) = function.hasAnnotation() - override fun getSubCommandNames(function: KFunction<*>): Array = arrayOf("") + override fun hasAnnotation(baseCommand: AbstractReflectionCommand, function: KFunction<*>) = + function.hasAnnotation() + + override fun getSubCommandNames(baseCommand: AbstractReflectionCommand, function: KFunction<*>): Array = + baseCommand.names } internal abstract class AbstractReflectionCommand @JvmOverloads constructor( @@ -74,12 +79,12 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor( } interface SubCommandAnnotationResolver { - fun hasAnnotation(function: KFunction<*>): Boolean - fun getSubCommandNames(function: KFunction<*>): Array + fun hasAnnotation(baseCommand: AbstractReflectionCommand, function: KFunction<*>): Boolean + fun getSubCommandNames(baseCommand: AbstractReflectionCommand, function: KFunction<*>): Array } internal val subCommands: Array by lazy { - this::class.declaredFunctions.filter { subCommandAnnotationResolver.hasAnnotation(it) } + this::class.declaredFunctions.filter { subCommandAnnotationResolver.hasAnnotation(this, it) } .also { subCommandFunctions -> // overloading not yet supported val overloadFunction = subCommandFunctions.groupBy { it.name }.entries.firstOrNull { it.value.size > 1 } @@ -278,7 +283,7 @@ internal fun AbstractReflectionCommand.createSubCommand( } val commandName = - subCommandAnnotationResolver.getSubCommandNames(function) + subCommandAnnotationResolver.getSubCommandNames(this, function) .let { namesFromAnnotation -> if (namesFromAnnotation.isNotEmpty()) { namesFromAnnotation diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/JvmPluginInternal.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/JvmPluginInternal.kt index 3ff46387e..575969f86 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/JvmPluginInternal.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/JvmPluginInternal.kt @@ -11,10 +11,7 @@ package net.mamoe.mirai.console.internal.plugin import kotlinx.atomicfu.AtomicLong import kotlinx.atomicfu.locks.withLock -import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.* import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.PluginManager @@ -69,6 +66,7 @@ internal abstract class JvmPluginInternal( internal fun internalOnDisable() { firstRun = false this.onDisable() + this.cancel(CancellationException("plugin disabled")) } internal fun internalOnLoad() { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/PluginManagerImpl.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/PluginManagerImpl.kt index f5f1728f8..303996e27 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/PluginManagerImpl.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/PluginManagerImpl.kt @@ -12,6 +12,8 @@ package net.mamoe.mirai.console.internal.plugin import kotlinx.atomicfu.locks.withLock +import kotlinx.coroutines.InternalCoroutinesApi +import kotlinx.coroutines.Job import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.internal.setting.cast import net.mamoe.mirai.console.plugin.* @@ -54,6 +56,12 @@ internal object PluginManagerImpl : PluginManager { _pluginLoaders.remove(loader) } + init { + @OptIn(InternalCoroutinesApi::class) + MiraiConsole.coroutineContext[Job]!!.invokeOnCompletion(true) { + plugins.forEach(Plugin::disable) + } + } // region LOADING diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/setting/SettingStorage internal.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/setting/SettingStorage internal.kt index 6b0a9d0d4..04e4fcf31 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/setting/SettingStorage internal.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/setting/SettingStorage internal.kt @@ -10,10 +10,7 @@ package net.mamoe.mirai.console.internal.setting import kotlinx.atomicfu.atomic -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch +import kotlinx.coroutines.* import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip import net.mamoe.mirai.console.internal.plugin.updateWhen import net.mamoe.mirai.console.plugin.jvm.loadSetting @@ -36,7 +33,10 @@ import kotlin.reflect.full.findAnnotation * * @see loadSetting */ -internal open class AutoSaveSetting(private val owner: AutoSaveSettingHolder) : +internal open class AutoSaveSetting( + private val owner: AutoSaveSettingHolder, + internal val originSettingClass: KClass +) : AbstractSetting() { private lateinit var storage: SettingStorage @@ -54,7 +54,8 @@ internal open class AutoSaveSetting(private val owner: AutoSaveSettingHolder) : internal var currentFirstStartTime = atomic(0L) init { - owner.coroutineContext[Job]?.invokeOnCompletion { doSave() } + @OptIn(InternalCoroutinesApi::class) + owner.coroutineContext[Job]?.invokeOnCompletion(true) { doSave() } } private val updaterBlock: suspend CoroutineScope.() -> Unit = { @@ -125,10 +126,12 @@ internal class MemorySettingStorageImpl( internal open class MultiFileSettingStorageImpl( public final override val directory: File ) : SettingStorage, MultiFileSettingStorage { + init { + directory.mkdir() + } + public override fun load(holder: SettingHolder, settingClass: Class): T = with(settingClass.kotlin) { - val file = getSettingFile(holder, this) - @Suppress("UNCHECKED_CAST") val instance = objectInstance ?: this.createInstanceOrNull() ?: kotlin.run { require(settingClass == Setting::class.java) { @@ -136,15 +139,20 @@ internal open class MultiFileSettingStorageImpl( "or has a constructor which either has no parameters or all parameters of which are optional" } if (holder is AutoSaveSettingHolder) { - AutoSaveSetting(holder) as T? + AutoSaveSetting(holder, this) as T? } else null } ?: throw IllegalArgumentException( "Cannot create Setting instance. Make sure 'holder' is a AutoSaveSettingHolder, " + "or 'setting' is an object or has a constructor which either has no parameters or all parameters of which are optional" ) + + val file = getSettingFile(holder, this) file.createNewFile() check(file.exists() && file.isFile && file.canRead()) { "${file.absolutePath} cannot be read" } - Yaml.default.decodeFromString(instance.updaterSerializer, file.readText()) + val text = file.readText() + if (text.isNotBlank()) { + Yaml.default.decodeFromString(instance.updaterSerializer, file.readText()) + } instance }.also { it.setStorage(this) } @@ -155,6 +163,7 @@ internal open class MultiFileSettingStorageImpl( if (dir.isFile) { error("Target directory ${dir.path} for holder $holder is occupied by a file therefore setting $qualifiedNameOrTip can't be saved.") } + dir.mkdir() val file = File(directory, name) if (file.isDirectory) { @@ -164,8 +173,9 @@ internal open class MultiFileSettingStorageImpl( } @ConsoleExperimentalAPI - public override fun store(holder: SettingHolder, setting: Setting): Unit = with(setting::class) { - val file = getSettingFile(holder, this) + public override fun store(holder: SettingHolder, setting: Setting) { + val file = + getSettingFile(holder, if (setting is AutoSaveSetting) setting.originSettingClass else setting::class) if (file.exists() && file.isFile && file.canRead()) { file.writeText(Yaml.default.encodeToString(setting.updaterSerializer, Unit)) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/SettingStorage.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/SettingStorage.kt index 65306eb3f..c24ed9900 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/SettingStorage.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/SettingStorage.kt @@ -178,10 +178,10 @@ public interface AutoSaveSettingHolder : SettingHolder, CoroutineScope { */ @JvmDefault public override fun newSettingInstance(type: KType): T { - val classifier = type.classifier?.cast>()?.java - require(classifier == Setting::class.java) { + val classifier = type.classifier?.cast>() + require(classifier != null && classifier.java == Setting::class.java) { "Cannot create Setting instance. AutoSaveSettingHolder supports only Setting type." } - return AutoSaveSetting(this) as T // T is always Setting + return AutoSaveSetting(this, classifier) as T // T is always Setting } } \ No newline at end of file diff --git a/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/ConsoleThread.kt b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/ConsoleThread.kt index 472f8698f..eb8548fa8 100644 --- a/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/ConsoleThread.kt +++ b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/ConsoleThread.kt @@ -46,7 +46,7 @@ internal fun startupConsoleThread() { } } - CoroutineScope(dispatch).launch { + CoroutineScope(dispatch + SupervisorJob()).launch { val consoleLogger = DefaultLogger("console") while (isActive) { try { diff --git a/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleImplementationPure.kt b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleImplementationPure.kt index 5a5fb6cd1..c59bf10b1 100644 --- a/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleImplementationPure.kt +++ b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleImplementationPure.kt @@ -48,14 +48,13 @@ class MiraiConsoleImplementationPure @JvmOverloads constructor( override val rootDir: File = File("."), override val builtInPluginLoaders: List> = Collections.unmodifiableList( - listOf( - DeferredPluginLoader { JarPluginLoader }) + listOf(DeferredPluginLoader { JarPluginLoader }) ), override val frontEnd: MiraiConsoleFrontEnd = MiraiConsoleFrontEndPure, override val mainLogger: MiraiLogger = frontEnd.loggerFor("main"), override val consoleCommandSender: ConsoleCommandSender = ConsoleCommandSenderImpl, - override val settingStorageForJarPluginLoader: SettingStorage = MultiFileSettingStorage(rootDir), - override val settingStorageForBuiltIns: SettingStorage = MultiFileSettingStorage(rootDir) + override val settingStorageForJarPluginLoader: SettingStorage = MultiFileSettingStorage(File(rootDir, "data")), + override val settingStorageForBuiltIns: SettingStorage = MultiFileSettingStorage(File(rootDir, "data")) ) : MiraiConsoleImplementation, CoroutineScope by CoroutineScope(SupervisorJob()) { init { rootDir.mkdir()