From 58187f95f03fac0bc03bb0fdbe9af203189ace5c Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 11 Jul 2020 19:26:31 +0800 Subject: [PATCH] Explicit APIs --- .../console/codegen/ValueSettingCodegen.kt | 10 +- backend/mirai-console/build.gradle.kts | 13 +- .../net/mamoe/mirai/console/MiraiConsole.kt | 33 ++--- .../mirai/console/MiraiConsoleFrontEnd.kt | 14 +-- .../mirai/console/command/BuiltInCommands.kt | 37 +++--- .../mamoe/mirai/console/command/Command.kt | 35 +++--- .../console/command/CommandExecuteResult.kt | 74 ++++++------ .../command/CommandExecutionException.kt | 8 +- .../mirai/console/command/CommandManager.kt | 34 +++--- .../console/command/CommandPermission.kt | 46 +++---- .../CommandPermissionDeniedException.kt | 6 +- .../mirai/console/command/CommandSender.kt | 73 +++++------ .../mirai/console/command/CompositeCommand.kt | 21 ++-- .../mamoe/mirai/console/command/RawCommand.kt | 16 +-- .../mirai/console/command/SimpleCommand.kt | 18 +-- .../command/description/CommandArgParser.kt | 18 +-- .../description/CommandArgParserBuiltins.kt | 52 ++++---- .../description/CommandParserContext.kt | 38 +++--- .../mamoe/mirai/console/event/ConsoleEvent.kt | 2 +- .../net/mamoe/mirai/console/plugin/Plugin.kt | 15 ++- .../mirai/console/plugin/PluginLoader.kt | 37 +++--- .../mirai/console/plugin/PluginManager.kt | 113 +++++++++++------- .../console/plugin/center/PluginCenter.kt | 20 ++-- .../mamoe/mirai/console/plugin/description.kt | 45 +++---- .../plugin/internal/JvmPluginInternal.kt | 4 +- .../console/plugin/jvm/AbstractJvmPlugin.kt | 6 +- .../console/plugin/jvm/JarPluginLoader.kt | 18 ++- .../mirai/console/plugin/jvm/JavaPlugin.kt | 6 +- .../mirai/console/plugin/jvm/JvmPlugin.kt | 27 +++-- .../plugin/jvm/JvmPluginDescription.kt | 22 ++-- .../mirai/console/plugin/jvm/KotlinPlugin.kt | 22 ++-- .../mamoe/mirai/console/setting/Setting.kt | 40 +++---- .../mirai/console/setting/SettingStorage.kt | 57 ++++++--- .../net/mamoe/mirai/console/setting/Value.kt | 77 ++++++------ .../internal/_PrimitiveValueDeclarations.kt | 1 - .../setting/internal/_Setting.value.kt | 35 ++---- .../mamoe/mirai/console/utils/BotManagers.kt | 6 +- .../mamoe/mirai/console/utils/ConsoleInput.kt | 62 +++++----- .../mirai/console/utils/JavaFriendlyAPI.kt | 4 +- .../console/utils/JavaPluginScheduler.kt | 14 +-- .../mirai/console/utils/ResourceContainer.kt | 35 +++--- .../mirai/console/utils/retryCatching.kt | 19 +-- buildSrc/src/main/kotlin/Versions.kt | 2 +- 43 files changed, 651 insertions(+), 584 deletions(-) diff --git a/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/ValueSettingCodegen.kt b/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/ValueSettingCodegen.kt index fff2e95d2..440d0b18b 100644 --- a/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/ValueSettingCodegen.kt +++ b/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/ValueSettingCodegen.kt @@ -7,7 +7,7 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ -@file:Suppress("PRE_RELEASE_CLASS", "ClassName") +@file:Suppress("PRE_RELEASE_CLASS", "ClassName", "RedundantVisibilityModifier") package net.mamoe.mirai.console.codegen @@ -15,7 +15,7 @@ import kotlin.reflect.full.functions import kotlin.reflect.full.hasAnnotation import kotlin.reflect.full.isSubclassOf -object ValueSettingCodegen { +internal object ValueSettingCodegen { /** * The interface */ @@ -31,7 +31,7 @@ object ValueSettingCodegen { /** * Represents a non-null [$ktType] value. */ - interface ${ktType}Value : PrimitiveValue<$ktType> + public interface ${ktType}Value : PrimitiveValue<$ktType> """ ) } @@ -47,7 +47,7 @@ object ValueSettingCodegen { kCode( """ @JvmStatic - val ${ktType.standardName}SerializerDescriptor = ${ktType.standardName}.serializer().descriptor + internal val ${ktType.standardName}SerializerDescriptor = ${ktType.standardName}.serializer().descriptor """ ).lines().joinToString("\n") { " $it" } ) @@ -145,7 +145,7 @@ internal fun Setting.${ktType.lowerCaseName}ValueImpl(): SerializerAwareValue<${ @Suppress("unused") appendKCode( """ - fun Setting.value(default: ${ktType.standardName}): SerializerAwareValue<${ktType.standardName}> = valueImpl(default) + public fun Setting.value(default: ${ktType.standardName}): SerializerAwareValue<${ktType.standardName}> = valueImpl(default) """ ) } diff --git a/backend/mirai-console/build.gradle.kts b/backend/mirai-console/build.gradle.kts index 37503d251..12593c75c 100644 --- a/backend/mirai-console/build.gradle.kts +++ b/backend/mirai-console/build.gradle.kts @@ -23,6 +23,8 @@ tasks.withType(JavaCompile::class.java) { } kotlin { + explicitApiWarning() + sourceSets.all { target.compilations.all { kotlinOptions { @@ -46,12 +48,17 @@ kotlin { } } - sourceSets { + sourceSets.invoke { getByName("test") { languageSettings.apply { languageVersion = "1.4" } } + getByName("main") { + languageSettings.apply { + languageVersion = "1.3" + } + } } } @@ -71,7 +78,7 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter-api:5.2.0") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.2.0") } -ext { +ext.apply { // 傻逼 compileAndRuntime 没 exclude 掉 // 傻逼 gradle 第二次配置 task 会覆盖掉第一次的配置 val x: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.() -> Unit = { @@ -83,7 +90,7 @@ ext { } } } - this.set("shadowJar", x) + set("shadowJar", x) } tasks { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt index 9207be054..cc4eea42c 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt @@ -23,6 +23,7 @@ import net.mamoe.mirai.console.command.internal.InternalCommandManager import net.mamoe.mirai.console.command.primaryName import net.mamoe.mirai.console.plugin.PluginLoader import net.mamoe.mirai.console.plugin.PluginManager +import net.mamoe.mirai.console.plugin.PluginManagerImpl import net.mamoe.mirai.console.plugin.center.CuiPluginCenter import net.mamoe.mirai.console.plugin.center.PluginCenter import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader @@ -45,43 +46,47 @@ import kotlin.coroutines.CoroutineContext * * @see INSTANCE */ -interface MiraiConsole : CoroutineScope { +public interface MiraiConsole : CoroutineScope { /** * Console 运行路径 */ - val rootDir: File + public val rootDir: File /** * Console 前端接口 */ - val frontEnd: MiraiConsoleFrontEnd + public val frontEnd: MiraiConsoleFrontEnd /** * 与前端交互所使用的 Logger */ - val mainLogger: MiraiLogger + public val mainLogger: MiraiLogger /** * 内建加载器列表, 一般需要包含 [JarPluginLoader] */ - val builtInPluginLoaders: List> + public val builtInPluginLoaders: List> - val buildDate: Date + public val buildDate: Date - val version: String + public val version: String - val pluginCenter: PluginCenter + public val pluginCenter: PluginCenter @ConsoleExperimentalAPI - fun newLogger(identity: String?): MiraiLogger + public fun newLogger(identity: String?): MiraiLogger - companion object INSTANCE : MiraiConsole by MiraiConsoleInternal + public companion object INSTANCE : MiraiConsole by MiraiConsoleInternal } +public class IllegalMiraiConsoleImplementationError( + override val message: String? +) : Error() + /** * 获取 [MiraiConsole] 的 [Job] */ -val MiraiConsole.job: Job +public val MiraiConsole.job: Job get() = this.coroutineContext[Job] ?: error("Internal error: Job not found in MiraiConsole.coroutineContext") //// internal @@ -149,17 +154,13 @@ internal object MiraiConsoleInternal : CoroutineScope, IMiraiConsole, MiraiConso InternalCommandManager.commandListener // start mainLogger.info { "Loading plugins..." } - PluginManager.loadEnablePlugins() + PluginManagerImpl.loadEnablePlugins() mainLogger.info { "${PluginManager.plugins.size} plugin(s) loaded." } mainLogger.info { "mirai-console started successfully." } // Only for initialize } } -class IllegalMiraiConsoleImplementationError( - override val message: String? -) : Error() - // 前端使用 internal interface IMiraiConsole : CoroutineScope { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleFrontEnd.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleFrontEnd.kt index ecc88d453..36bb0c741 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleFrontEnd.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleFrontEnd.kt @@ -17,33 +17,33 @@ import net.mamoe.mirai.utils.MiraiLogger * 只需要实现一个这个传入 MiraiConsole 就可以绑定 UI 层与 Console 层 * 需要保证线程安全 */ -interface MiraiConsoleFrontEnd { +public interface MiraiConsoleFrontEnd { /** * 名称 */ - val name: String + public val name: String /** * 版本 */ - val version: String + public val version: String - fun loggerFor(identity: String?): MiraiLogger + public fun loggerFor(identity: String?): MiraiLogger /** * 让 UI 层接受一个新的bot * */ - fun pushBot( + public fun pushBot( bot: Bot ) /** * 让 UI 层提供一个输入, 相当于 [readLine] */ - suspend fun requestInput(hint: String): String + public suspend fun requestInput(hint: String): String /** * 由 UI 层创建一个 [LoginSolver] */ - fun createLoginSolver(): LoginSolver + public fun createLoginSolver(): LoginSolver } \ No newline at end of file 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 0cab27d62..c6a020117 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 @@ -29,7 +29,7 @@ import kotlin.system.exitProcess /** * 添加一个 [Bot] 实例到全局 Bot 列表, 但不登录. */ -fun MiraiConsole.addBot(id: Long, password: String): Bot { +public fun MiraiConsole.addBot(id: Long, password: String): Bot { return Bot(id, password) { /** @@ -65,15 +65,15 @@ fun MiraiConsole.addBot(id: Long, password: String): Bot { } @Suppress("EXPOSED_SUPER_INTERFACE") -interface BuiltInCommand : Command, BuiltInCommandInternal +public interface BuiltInCommand : Command, BuiltInCommandInternal // for identification internal interface BuiltInCommandInternal : Command @Suppress("unused") -object BuiltInCommands { +public object BuiltInCommands { - val all: Array by lazy { + public val all: Array by lazy { this::class.nestedClasses.mapNotNull { it.objectInstance as? Command }.toTypedArray() } @@ -83,7 +83,7 @@ object BuiltInCommands { } } - object Help : SimpleCommand( + public object Help : SimpleCommand( ConsoleCommandOwner, "help", description = "Gets help about the console." ), BuiltInCommand { @@ -94,13 +94,13 @@ object BuiltInCommands { } @Handler - suspend fun CommandSender.handle() { + public suspend fun CommandSender.handle() { sendMessage("现在有指令: ${allRegisteredCommands.joinToString { it.primaryName }}") sendMessage("帮助还没写, 将就一下") } } - object Stop : SimpleCommand( + public object Stop : SimpleCommand( ConsoleCommandOwner, "stop", "shutdown", "exit", description = "Stop the whole world." ), BuiltInCommand { @@ -116,7 +116,7 @@ object BuiltInCommands { private val closingLock = Mutex() @Handler - suspend fun CommandSender.handle(): Unit = closingLock.withLock { + public suspend fun CommandSender.handle(): Unit = closingLock.withLock { sendMessage("Stopping mirai-console") kotlin.runCatching { MiraiConsole.job.cancelAndJoin() @@ -131,27 +131,28 @@ object BuiltInCommands { } } - object Login : SimpleCommand( + public object Login : SimpleCommand( ConsoleCommandOwner, "login", description = "Log in a bot account." ), BuiltInCommand { @Handler - suspend fun CommandSender.handle(id: Long, password: String) { + public suspend fun CommandSender.handle(id: Long, password: String) { kotlin.runCatching { MiraiConsole.addBot(id, password).alsoLogin() }.fold( onSuccess = { sendMessage("${it.nick} ($id) Login succeed") }, onFailure = { throwable -> - sendMessage("Login failed: ${throwable.localizedMessage ?: throwable.message ?: throwable.toString()}" + - if (this is MessageEventContextAware<*>) { - this.fromEvent.selectMessagesUnit { - "stacktrace" reply { - throwable.stacktraceString + sendMessage( + "Login failed: ${throwable.localizedMessage ?: throwable.message ?: throwable.toString()}" + + if (this is MessageEventContextAware<*>) { + this.fromEvent.selectMessagesUnit { + "stacktrace" reply { + throwable.stacktraceString + } } - } - "test" - } else "") + "test" + } else "") throw throwable } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt index 5dfceb470..ea78d803a 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt @@ -22,55 +22,58 @@ import net.mamoe.mirai.message.data.SingleMessage * @see RawCommand * @see CompositeCommand */ -interface Command { +public interface Command { /** * 指令名. 需要至少有一个元素. 所有元素都不能带有空格 */ - val names: Array + public val names: Array - val usage: String + public val usage: String - val description: String + public val description: String /** * 指令权限 */ - val permission: CommandPermission + public val permission: CommandPermission /** * 为 `true` 时表示 [指令前缀][CommandPrefix] 可选 */ - val prefixOptional: Boolean + public val prefixOptional: Boolean - val owner: CommandOwner + public val owner: CommandOwner /** * @param args 指令参数. 可能是 [SingleMessage] 或 [String]. 且已经以 ' ' 分割. + * + * @see Command.execute */ // TODO: 2020/6/28 Java-friendly bridges - suspend fun CommandSender.onCommand(args: Array) + public suspend fun CommandSender.onCommand(args: Array) } /** * [Command] 的基础实现 */ -abstract class AbstractCommand @JvmOverloads constructor( - final override val owner: CommandOwner, +public abstract class AbstractCommand @JvmOverloads constructor( + public final override val owner: CommandOwner, vararg names: String, description: String = "", - final override val permission: CommandPermission = CommandPermission.Default, - final override val prefixOptional: Boolean = false + public final override val permission: CommandPermission = CommandPermission.Default, + public final override val prefixOptional: Boolean = false ) : Command { - final override val description = description.trimIndent() - final override val names: Array = + public final override val description: String = description.trimIndent() + public final override val names: Array = names.map(String::trim).filterNot(String::isEmpty).map(String::toLowerCase).also { list -> list.firstOrNull { !it.isValidSubName() }?.let { error("Invalid name: $it") } }.toTypedArray() } -suspend inline fun Command.onCommand(sender: CommandSender, args: Array) = sender.run { onCommand(args) } +public suspend inline fun Command.onCommand(sender: CommandSender, args: Array): Unit = + sender.run { onCommand(args) } /** * 主要指令名. 为 [Command.names] 的第一个元素. */ -val Command.primaryName: String get() = names[0] \ No newline at end of file +public val Command.primaryName: String get() = names[0] \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandExecuteResult.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandExecuteResult.kt index dce0724a9..55a10fc9c 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandExecuteResult.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandExecuteResult.kt @@ -20,94 +20,94 @@ import kotlin.contracts.contract * * @see CommandExecuteStatus */ -sealed class CommandExecuteResult { +public sealed class CommandExecuteResult { /** 指令最终执行状态 */ - abstract val status: CommandExecuteStatus + public abstract val status: CommandExecuteStatus /** 指令执行时发生的错误 (如果有) */ - abstract val exception: Throwable? + public abstract val exception: Throwable? /** 尝试执行的指令 (如果匹配到) */ - abstract val command: Command? + public abstract val command: Command? /** 尝试执行的指令名 (如果匹配到) */ - abstract val commandName: String? + public abstract val commandName: String? /** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */ - abstract val args: Array? + public abstract val args: Array? // abstract val to allow smart casting /** 指令执行成功 */ - class Success( + public class Success( /** 尝试执行的指令 */ - override val command: Command, + public override val command: Command, /** 尝试执行的指令名 */ - override val commandName: String, + public override val commandName: String, /** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */ - override val args: Array + public override val args: Array ) : CommandExecuteResult() { /** 指令执行时发生的错误, 总是 `null` */ - override val exception: Nothing? get() = null + public override val exception: Nothing? get() = null /** 指令最终执行状态, 总是 [CommandExecuteStatus.SUCCESSFUL] */ - override val status: CommandExecuteStatus get() = CommandExecuteStatus.SUCCESSFUL + public override val status: CommandExecuteStatus get() = CommandExecuteStatus.SUCCESSFUL } /** 指令执行过程出现了错误 */ - class ExecutionException( + public class ExecutionException( /** 指令执行时发生的错误 */ - override val exception: Throwable, + public override val exception: Throwable, /** 尝试执行的指令 */ - override val command: Command, + public override val command: Command, /** 尝试执行的指令名 */ - override val commandName: String, + public override val commandName: String, /** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */ - override val args: Array + public override val args: Array ) : CommandExecuteResult() { /** 指令最终执行状态, 总是 [CommandExecuteStatus.EXECUTION_EXCEPTION] */ - override val status: CommandExecuteStatus get() = CommandExecuteStatus.EXECUTION_EXCEPTION + public override val status: CommandExecuteStatus get() = CommandExecuteStatus.EXECUTION_EXCEPTION } /** 没有匹配的指令 */ - class CommandNotFound( + public class CommandNotFound( /** 尝试执行的指令名 */ - override val commandName: String + public override val commandName: String ) : CommandExecuteResult() { /** 指令执行时发生的错误, 总是 `null` */ - override val exception: Nothing? get() = null + public override val exception: Nothing? get() = null /** 尝试执行的指令, 总是 `null` */ - override val command: Nothing? get() = null + public override val command: Nothing? get() = null /** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */ - override val args: Nothing? get() = null + public override val args: Nothing? get() = null /** 指令最终执行状态, 总是 [CommandExecuteStatus.COMMAND_NOT_FOUND] */ - override val status: CommandExecuteStatus get() = CommandExecuteStatus.COMMAND_NOT_FOUND + public override val status: CommandExecuteStatus get() = CommandExecuteStatus.COMMAND_NOT_FOUND } /** 权限不足 */ - class PermissionDenied( + public class PermissionDenied( /** 尝试执行的指令 */ - override val command: Command, + public override val command: Command, /** 尝试执行的指令名 */ - override val commandName: String + public override val commandName: String ) : CommandExecuteResult() { /** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */ - override val args: Nothing? get() = null + public override val args: Nothing? get() = null /** 指令执行时发生的错误, 总是 `null` */ - override val exception: Nothing? get() = null + public override val exception: Nothing? get() = null /** 指令最终执行状态, 总是 [CommandExecuteStatus.PERMISSION_DENIED] */ - override val status: CommandExecuteStatus get() = CommandExecuteStatus.PERMISSION_DENIED + public override val status: CommandExecuteStatus get() = CommandExecuteStatus.PERMISSION_DENIED } /** * 指令的执行状态 */ - enum class CommandExecuteStatus { + public enum class CommandExecuteStatus { /** 指令执行成功 */ SUCCESSFUL, @@ -124,13 +124,13 @@ sealed class CommandExecuteResult { @Suppress("RemoveRedundantQualifierName") -typealias CommandExecuteStatus = CommandExecuteResult.CommandExecuteStatus +public typealias CommandExecuteStatus = CommandExecuteResult.CommandExecuteStatus /** * 当 [this] 为 [CommandExecuteResult.Success] 时返回 `true` */ @JvmSynthetic -fun CommandExecuteResult.isSuccess(): Boolean { +public fun CommandExecuteResult.isSuccess(): Boolean { contract { returns(true) implies (this@isSuccess is CommandExecuteResult.Success) returns(false) implies (this@isSuccess !is CommandExecuteResult.Success) @@ -142,7 +142,7 @@ fun CommandExecuteResult.isSuccess(): Boolean { * 当 [this] 为 [CommandExecuteResult.ExecutionException] 时返回 `true` */ @JvmSynthetic -fun CommandExecuteResult.isExecutionException(): Boolean { +public fun CommandExecuteResult.isExecutionException(): Boolean { contract { returns(true) implies (this@isExecutionException is CommandExecuteResult.ExecutionException) returns(false) implies (this@isExecutionException !is CommandExecuteResult.ExecutionException) @@ -154,7 +154,7 @@ fun CommandExecuteResult.isExecutionException(): Boolean { * 当 [this] 为 [CommandExecuteResult.ExecutionException] 时返回 `true` */ @JvmSynthetic -fun CommandExecuteResult.isPermissionDenied(): Boolean { +public fun CommandExecuteResult.isPermissionDenied(): Boolean { contract { returns(true) implies (this@isPermissionDenied is CommandExecuteResult.PermissionDenied) returns(false) implies (this@isPermissionDenied !is CommandExecuteResult.PermissionDenied) @@ -166,7 +166,7 @@ fun CommandExecuteResult.isPermissionDenied(): Boolean { * 当 [this] 为 [CommandExecuteResult.ExecutionException] 时返回 `true` */ @JvmSynthetic -fun CommandExecuteResult.isCommandNotFound(): Boolean { +public fun CommandExecuteResult.isCommandNotFound(): Boolean { contract { returns(true) implies (this@isCommandNotFound is CommandExecuteResult.CommandNotFound) returns(false) implies (this@isCommandNotFound !is CommandExecuteResult.CommandNotFound) @@ -178,7 +178,7 @@ fun CommandExecuteResult.isCommandNotFound(): Boolean { * 当 [this] 为 [CommandExecuteResult.ExecutionException] 或 [CommandExecuteResult.CommandNotFound] 时返回 `true` */ @JvmSynthetic -fun CommandExecuteResult.isFailure(): Boolean { +public fun CommandExecuteResult.isFailure(): Boolean { contract { returns(true) implies (this@isFailure !is CommandExecuteResult.Success) returns(false) implies (this@isFailure is CommandExecuteResult.Success) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandExecutionException.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandExecutionException.kt index 4faeb35fc..817e323a4 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandExecutionException.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandExecutionException.kt @@ -14,21 +14,21 @@ package net.mamoe.mirai.console.command /** * 在 [executeCommand] 中, [Command.onCommand] 抛出异常时包装的异常. */ -class CommandExecutionException( +public class CommandExecutionException( /** * 执行过程发生异常的指令 */ - val command: Command, + public val command: Command, /** * 匹配到的指令名 */ - val name: String, + public val name: String, cause: Throwable ) : RuntimeException( "Exception while executing command '${command.primaryName}'", cause ) { - override fun toString(): String = + public override fun toString(): String = "CommandExecutionException(command=$command, name='$name')" } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt index e4fb89abd..b725bc742 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt @@ -27,12 +27,12 @@ import net.mamoe.mirai.message.data.MessageChain * 指令的所有者. * @see PluginCommandOwner */ -sealed class CommandOwner +public sealed class CommandOwner /** * 插件指令所有者. 插件只能通过 [PluginCommandOwner] 管理指令. */ -abstract class PluginCommandOwner(val plugin: Plugin) : CommandOwner() { +public abstract class PluginCommandOwner(public val plugin: Plugin) : CommandOwner() { init { if (plugin is CoroutineScope) { // JVM Plugin plugin.coroutineContext[Job]?.invokeOnCompletion { @@ -45,33 +45,33 @@ abstract class PluginCommandOwner(val plugin: Plugin) : CommandOwner() { /** * 代表控制台所有者. 所有的 mirai-console 内建的指令都属于 [ConsoleCommandOwner]. */ -object ConsoleCommandOwner : CommandOwner() +public object ConsoleCommandOwner : CommandOwner() /** * 获取已经注册了的属于这个 [CommandOwner] 的指令列表. * @see JCommandManager.getRegisteredCommands Java 方法 */ -val CommandOwner.registeredCommands: List get() = InternalCommandManager.registeredCommands.filter { it.owner == this } +public val CommandOwner.registeredCommands: List get() = InternalCommandManager.registeredCommands.filter { it.owner == this } /** * 获取所有已经注册了指令列表. * @see JCommandManager.getRegisteredCommands Java 方法 */ -val allRegisteredCommands: List get() = InternalCommandManager.registeredCommands.toList() // copy +public val allRegisteredCommands: List get() = InternalCommandManager.registeredCommands.toList() // copy /** * 指令前缀, 如 '/' * @see JCommandManager.getCommandPrefix Java 方法 */ @get:JvmName("getCommandPrefix") -val CommandPrefix: String +public val CommandPrefix: String get() = InternalCommandManager.COMMAND_PREFIX /** * 取消注册所有属于 [this] 的指令 * @see JCommandManager.unregisterAllCommands Java 方法 */ -fun CommandOwner.unregisterAllCommands() { +public fun CommandOwner.unregisterAllCommands() { for (registeredCommand in registeredCommands) { registeredCommand.unregister() } @@ -94,7 +94,7 @@ fun CommandOwner.unregisterAllCommands() { * @see JCommandManager.register Java 方法 */ @JvmOverloads -fun Command.register(override: Boolean = false): Boolean { +public fun Command.register(override: Boolean = false): Boolean { if (this is CompositeCommand) this.subCommands // init InternalCommandManager.modifyLock.withLock { @@ -124,7 +124,7 @@ fun Command.register(override: Boolean = false): Boolean { * * @see JCommandManager.findDuplicate Java 方法 */ -fun Command.findDuplicate(): Command? = +public fun Command.findDuplicate(): Command? = InternalCommandManager.registeredCommands.firstOrNull { it.names intersectsIgnoringCase this.names } /** @@ -132,7 +132,7 @@ fun Command.findDuplicate(): Command? = * * @see JCommandManager.unregister Java 方法 */ -fun Command.unregister(): Boolean = InternalCommandManager.modifyLock.withLock { +public fun Command.unregister(): Boolean = InternalCommandManager.modifyLock.withLock { if (this.prefixOptional) { this.names.forEach { InternalCommandManager.optionalPrefixCommandMap.remove(it) @@ -147,7 +147,7 @@ fun Command.unregister(): Boolean = InternalCommandManager.modifyLock.withLock { /** * 当 [this] 已经 [注册][register] 后返回 `true` */ -fun Command.isRegistered(): Boolean = this in InternalCommandManager.registeredCommands +public fun Command.isRegistered(): Boolean = this in InternalCommandManager.registeredCommands //// executing without detailed result (faster) @@ -161,7 +161,7 @@ fun Command.isRegistered(): Boolean = this in InternalCommandManager.registeredC * * @see JCommandManager.executeCommand Java 方法 */ -suspend fun CommandSender.executeCommand(vararg messages: Any): Command? { +public suspend fun CommandSender.executeCommand(vararg messages: Any): Command? { if (messages.isEmpty()) return null return matchAndExecuteCommandInternal(messages, messages[0].toString().substringBefore(' ')) } @@ -175,7 +175,7 @@ suspend fun CommandSender.executeCommand(vararg messages: Any): Command? { * @see JCommandManager.executeCommand Java 方法 */ @Throws(CommandExecutionException::class) -suspend fun CommandSender.executeCommand(message: MessageChain): Command? { +public suspend fun CommandSender.executeCommand(message: MessageChain): Command? { if (message.isEmpty()) return null return matchAndExecuteCommandInternal(message, message[0].toString().substringBefore(' ')) } @@ -190,7 +190,7 @@ suspend fun CommandSender.executeCommand(message: MessageChain): Command? { */ @JvmOverloads @Throws(CommandExecutionException::class) -suspend fun Command.execute(sender: CommandSender, args: MessageChain, checkPermission: Boolean = true) { +public suspend fun Command.execute(sender: CommandSender, args: MessageChain, checkPermission: Boolean = true) { sender.executeCommandInternal( this, args.flattenCommandComponents().toTypedArray(), @@ -209,7 +209,7 @@ suspend fun Command.execute(sender: CommandSender, args: MessageChain, checkPerm */ @JvmOverloads @Throws(CommandExecutionException::class) -suspend fun Command.execute(sender: CommandSender, vararg args: Any, checkPermission: Boolean = true) { +public suspend fun Command.execute(sender: CommandSender, vararg args: Any, checkPermission: Boolean = true) { sender.executeCommandInternal( this, args.flattenCommandComponents().toTypedArray(), @@ -229,7 +229,7 @@ suspend fun Command.execute(sender: CommandSender, vararg args: Any, checkPermis * * @see JCommandManager.executeCommandDetailed Java 方法 */ -suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult { +public suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult { if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("") return executeCommandDetailedInternal(messages, messages[0].toString().substringBefore(' ')) } @@ -243,7 +243,7 @@ suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandE * * @see JCommandManager.executeCommandDetailed Java 方法 */ -suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult { +public suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult { if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("") return executeCommandDetailedInternal(messages, messages[0].toString()) } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandPermission.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandPermission.kt index 8317e3b7b..54db97295 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandPermission.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandPermission.kt @@ -22,48 +22,48 @@ import net.mamoe.mirai.contact.isOwner * * @see AnonymousCommandPermission */ -interface CommandPermission { +public interface CommandPermission { /** * 判断 [this] 是否拥有这个指令的权限 * * @see CommandSender.hasPermission * @see CommandPermission.testPermission */ - fun CommandSender.hasPermission(): Boolean + public fun CommandSender.hasPermission(): Boolean /** * 满足两个权限其中一个即可使用指令 */ // no extension for Java @JvmDefault - infix fun or(another: CommandPermission): CommandPermission = OrCommandPermission(this, another) + public infix fun or(another: CommandPermission): CommandPermission = OrCommandPermission(this, another) /** * 同时拥有两个权限才能使用指令 */ // no extension for Java @JvmDefault - infix fun and(another: CommandPermission): CommandPermission = AndCommandPermission(this, another) + public infix fun and(another: CommandPermission): CommandPermission = AndCommandPermission(this, another) /** * 任何人都可以使用这个指令 */ - object Any : CommandPermission { - override fun CommandSender.hasPermission(): Boolean = true + public object Any : CommandPermission { + public override fun CommandSender.hasPermission(): Boolean = true } /** * 任何人都不能使用这个指令. 指令只能通过调用 [Command.onCommand] 执行. */ - object None : CommandPermission { - override fun CommandSender.hasPermission(): Boolean = false + public object None : CommandPermission { + public override fun CommandSender.hasPermission(): Boolean = false } /** * 来自任何 [Bot] 的任何一个管理员或群主都可以使用这个指令 */ - object Operator : CommandPermission { - override fun CommandSender.hasPermission(): Boolean { + public object Operator : CommandPermission { + public override fun CommandSender.hasPermission(): Boolean { return this is MemberCommandSender && this.user.isOperator() } } @@ -71,8 +71,8 @@ interface CommandPermission { /** * 来自任何 [Bot] 的任何一个群主都可以使用这个指令 */ - object GroupOwner : CommandPermission { - override fun CommandSender.hasPermission(): Boolean { + public object GroupOwner : CommandPermission { + public override fun CommandSender.hasPermission(): Boolean { return this is MemberCommandSender && this.user.isOwner() } } @@ -80,8 +80,8 @@ interface CommandPermission { /** * 管理员 (不包含群主) 可以使用这个指令 */ - object Administrator : CommandPermission { - override fun CommandSender.hasPermission(): Boolean { + public object Administrator : CommandPermission { + public override fun CommandSender.hasPermission(): Boolean { return this is MemberCommandSender && this.user.isAdministrator() } } @@ -89,8 +89,8 @@ interface CommandPermission { /** * 任何 [Bot] 的 manager 都可以使用这个指令 */ - object Manager : CommandPermission { - override fun CommandSender.hasPermission(): Boolean { + public object Manager : CommandPermission { + public override fun CommandSender.hasPermission(): Boolean { return this is MemberCommandSender && this.user.isManager } } @@ -98,11 +98,11 @@ interface CommandPermission { /** * 仅控制台能使用和这个指令 */ - object Console : CommandPermission { - override fun CommandSender.hasPermission(): Boolean = this is ConsoleCommandSender + public object Console : CommandPermission { + public override fun CommandSender.hasPermission(): Boolean = this is ConsoleCommandSender } - object Default : CommandPermission by (Manager or Console) + public object Default : CommandPermission by (Manager or Console) } /** @@ -110,19 +110,19 @@ interface CommandPermission { */ @JvmSynthetic @Suppress("FunctionName") -inline fun AnonymousCommandPermission(crossinline block: CommandSender.() -> Boolean): CommandPermission { +public inline fun AnonymousCommandPermission(crossinline block: CommandSender.() -> Boolean): CommandPermission { return object : CommandPermission { override fun CommandSender.hasPermission(): Boolean = block() } } -inline fun CommandSender.hasPermission(permission: CommandPermission): Boolean = +public inline fun CommandSender.hasPermission(permission: CommandPermission): Boolean = permission.run { this@hasPermission.hasPermission() } -inline fun CommandPermission.testPermission(sender: CommandSender): Boolean = this.run { sender.hasPermission() } +public inline fun CommandPermission.testPermission(sender: CommandSender): Boolean = this.run { sender.hasPermission() } -inline fun Command.testPermission(sender: CommandSender): Boolean = sender.hasPermission(this.permission) +public inline fun Command.testPermission(sender: CommandSender): Boolean = sender.hasPermission(this.permission) internal class OrCommandPermission( private val first: CommandPermission, diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandPermissionDeniedException.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandPermissionDeniedException.kt index c8a65a23a..0e48f667b 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandPermissionDeniedException.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandPermissionDeniedException.kt @@ -14,12 +14,12 @@ package net.mamoe.mirai.console.command * * 总是作为 [CommandExecutionException.cause]. */ -class CommandPermissionDeniedException( +public class CommandPermissionDeniedException( /** * 执行过程发生异常的指令 */ - val command: Command + public val command: Command ) : RuntimeException("Permission denied while executing command '${command.primaryName}'") { - override fun toString(): String = + public override fun toString(): String = "CommandPermissionDeniedException(command=$command)" } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt index a172fb73e..9d628fb42 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt @@ -28,55 +28,55 @@ import net.mamoe.mirai.message.data.PlainText * @see UserCommandSender */ @Suppress("FunctionName") -interface CommandSender { +public interface CommandSender { /** * 与这个 [CommandSender] 相关的 [Bot]. 当通过控制台执行时为 null. */ - val bot: Bot? + public val bot: Bot? /** * 立刻发送一条消息 */ @JvmSynthetic - suspend fun sendMessage(message: Message) + public suspend fun sendMessage(message: Message) @JvmDefault @JavaFriendlyAPI @JvmName("sendMessage") - fun __sendMessageBlocking(messageChain: Message) = runBlocking { sendMessage(messageChain) } + public fun __sendMessageBlocking(messageChain: Message): Unit = runBlocking { sendMessage(messageChain) } @JvmDefault @JavaFriendlyAPI @JvmName("sendMessage") - fun __sendMessageBlocking(message: String) = runBlocking { sendMessage(message) } + public fun __sendMessageBlocking(message: String): Unit = runBlocking { sendMessage(message) } } /** * 可以知道其 [Bot] 的 [CommandSender] */ -interface BotAwareCommandSender : CommandSender { - override val bot: Bot +public interface BotAwareCommandSender : CommandSender { + public override val bot: Bot } -suspend inline fun CommandSender.sendMessage(message: String) = sendMessage(PlainText(message)) +public suspend inline fun CommandSender.sendMessage(message: String): Unit = sendMessage(PlainText(message)) /** * 控制台指令执行者. 代表由控制台执行指令 */ // 前端实现 -abstract class ConsoleCommandSender internal constructor() : CommandSender { - final override val bot: Nothing? get() = null +public abstract class ConsoleCommandSender internal constructor() : CommandSender { + public final override val bot: Nothing? get() = null - companion object { + public companion object { internal val instance get() = MiraiConsoleInternal.consoleCommandSender } } -fun Friend.asCommandSender(): FriendCommandSender = FriendCommandSender(this) +public fun Friend.asCommandSender(): FriendCommandSender = FriendCommandSender(this) -fun Member.asCommandSender(): MemberCommandSender = MemberCommandSender(this) +public fun Member.asCommandSender(): MemberCommandSender = MemberCommandSender(this) -fun User.asCommandSender(): UserCommandSender { +public fun User.asCommandSender(): UserCommandSender { return when (this) { is Friend -> this.asCommandSender() is Member -> this.asCommandSender() @@ -87,28 +87,28 @@ fun User.asCommandSender(): UserCommandSender { /** * 表示由 [MessageEvent] 触发的指令 */ -interface MessageEventContextAware : MessageEventExtensions { - val fromEvent: E +public interface MessageEventContextAware : MessageEventExtensions { + public val fromEvent: E } /** * 代表一个用户私聊机器人执行指令 * @see User.asCommandSender */ -sealed class UserCommandSender : CommandSender, BotAwareCommandSender { +public sealed class UserCommandSender : CommandSender, BotAwareCommandSender { /** * @see MessageEvent.sender */ - abstract val user: User + public abstract val user: User /** * @see MessageEvent.subject */ - abstract val subject: Contact + public abstract val subject: Contact - override val bot: Bot get() = user.bot + public override val bot: Bot get() = user.bot - final override suspend fun sendMessage(message: Message) { + public final override suspend fun sendMessage(message: Message) { subject.sendMessage(message) } } @@ -117,37 +117,39 @@ sealed class UserCommandSender : CommandSender, BotAwareCommandSender { * 代表一个用户私聊机器人执行指令 * @see Friend.asCommandSender */ -open class FriendCommandSender(final override val user: Friend) : UserCommandSender() { - override val subject: Contact get() = user +public open class FriendCommandSender(final override val user: Friend) : UserCommandSender() { + public override val subject: Contact get() = user } /** * 代表一个用户私聊机器人执行指令 * @see Friend.asCommandSender */ -class FriendCommandSenderOnMessage(override val fromEvent: FriendMessageEvent) : FriendCommandSender(fromEvent.sender), +public class FriendCommandSenderOnMessage(override val fromEvent: FriendMessageEvent) : + FriendCommandSender(fromEvent.sender), MessageEventContextAware, MessageEventExtensions by fromEvent { - override val subject: Contact get() = super.subject - override val bot: Bot get() = super.bot + public override val subject: Contact get() = super.subject + public override val bot: Bot get() = super.bot } /** * 代表一个群成员执行指令. * @see Member.asCommandSender */ -open class MemberCommandSender(final override val user: Member) : UserCommandSender() { - inline val group: Group get() = user.group - override val subject: Contact get() = group +public open class MemberCommandSender(final override val user: Member) : UserCommandSender() { + public inline val group: Group get() = user.group + public override val subject: Contact get() = group } /** * 代表一个群成员在群内执行指令. * @see Member.asCommandSender */ -class MemberCommandSenderOnMessage(override val fromEvent: GroupMessageEvent) : MemberCommandSender(fromEvent.sender), +public class MemberCommandSenderOnMessage(override val fromEvent: GroupMessageEvent) : + MemberCommandSender(fromEvent.sender), MessageEventContextAware, MessageEventExtensions by fromEvent { - override val subject: Contact get() = super.subject - override val bot: Bot get() = super.bot + public override val subject: Contact get() = super.subject + public override val bot: Bot get() = super.bot } /** @@ -155,8 +157,9 @@ class MemberCommandSenderOnMessage(override val fromEvent: GroupMessageEvent) : * @see Member.asCommandSender */ @ConsoleExperimentalAPI -class TempCommandSenderOnMessage(override val fromEvent: TempMessageEvent) : MemberCommandSender(fromEvent.sender), +public class TempCommandSenderOnMessage(override val fromEvent: TempMessageEvent) : + MemberCommandSender(fromEvent.sender), MessageEventContextAware, MessageEventExtensions by fromEvent { - override val subject: Contact get() = super.subject - override val bot: Bot get() = super.bot + public override val subject: Contact get() = super.subject + public override val bot: Bot get() = super.bot } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CompositeCommand.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CompositeCommand.kt index 9a3fbe7d1..eddc016a4 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CompositeCommand.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CompositeCommand.kt @@ -11,8 +11,8 @@ "EXPOSED_SUPER_CLASS", "NOTHING_TO_INLINE", "unused", - "WRONG_MODIFIER_TARGET", - "WRONG_MODIFIER_CONTAINING_DECLARATION" + "WRONG_MODIFIER_TARGET", "CANNOT_WEAKEN_ACCESS_PRIVILEGE", + "WRONG_MODIFIER_CONTAINING_DECLARATION", "RedundantVisibilityModifier" ) package net.mamoe.mirai.console.command @@ -29,7 +29,7 @@ import kotlin.reflect.KClass * 复合指令. */ @ConsoleExperimentalAPI -abstract class CompositeCommand @JvmOverloads constructor( +public abstract class CompositeCommand @JvmOverloads constructor( owner: CommandOwner, vararg names: String, description: String = "no description available", @@ -41,7 +41,7 @@ abstract class CompositeCommand @JvmOverloads constructor( /** * [CommandArgParser] 的环境 */ - final override val context: CommandParserContext = CommandParserContext.Builtins + overrideContext + public final override val context: CommandParserContext = CommandParserContext.Builtins + overrideContext /** * 标记一个函数为子指令, 当 [value] 为空时使用函数名. @@ -66,16 +66,17 @@ abstract class CompositeCommand @JvmOverloads constructor( @Target(AnnotationTarget.VALUE_PARAMETER) protected annotation class Name(val value: String) - override suspend fun CommandSender.onDefault(rawArgs: Array) { - sendMessage(usage) - } - - final override suspend fun CommandSender.onCommand(args: Array) { + public final override suspend fun CommandSender.onCommand(args: Array) { matchSubCommand(args)?.parseAndExecute(this, args, true) ?: kotlin.run { defaultSubCommand.onCommand(this, args) } } - final override val subCommandAnnotationResolver: SubCommandAnnotationResolver + + internal override suspend fun CommandSender.onDefault(rawArgs: Array) { + sendMessage(usage) + } + + internal final override val subCommandAnnotationResolver: SubCommandAnnotationResolver get() = CompositeCommandSubCommandAnnotationResolver } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/RawCommand.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/RawCommand.kt index fa51e152a..a17036fb5 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/RawCommand.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/RawCommand.kt @@ -1,12 +1,12 @@ package net.mamoe.mirai.console.command -abstract class RawCommand( - override val owner: CommandOwner, - override vararg val names: String, - override val usage: String = "", - override val description: String = "", - override val permission: CommandPermission = CommandPermission.Default, - override val prefixOptional: Boolean = false +public abstract class RawCommand( + public override val owner: CommandOwner, + public override vararg val names: String, + public override val usage: String = "", + public override val description: String = "", + public override val permission: CommandPermission = CommandPermission.Default, + public override val prefixOptional: Boolean = false ) : Command { - abstract override suspend fun CommandSender.onCommand(args: Array) + public abstract override suspend fun CommandSender.onCommand(args: Array) } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/SimpleCommand.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/SimpleCommand.kt index b14cfc3ae..67bb7dbf1 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/SimpleCommand.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/SimpleCommand.kt @@ -11,8 +11,8 @@ "EXPOSED_SUPER_CLASS", "NOTHING_TO_INLINE", "unused", - "WRONG_MODIFIER_TARGET", - "WRONG_MODIFIER_CONTAINING_DECLARATION" + "WRONG_MODIFIER_TARGET", "CANNOT_WEAKEN_ACCESS_PRIVILEGE", + "WRONG_MODIFIER_CONTAINING_DECLARATION", "RedundantVisibilityModifier" ) package net.mamoe.mirai.console.command @@ -24,7 +24,7 @@ import net.mamoe.mirai.console.command.description.plus import net.mamoe.mirai.console.command.internal.AbstractReflectionCommand import net.mamoe.mirai.console.command.internal.SimpleCommandSubCommandAnnotationResolver -abstract class SimpleCommand @JvmOverloads constructor( +public abstract class SimpleCommand @JvmOverloads constructor( owner: CommandOwner, vararg names: String, description: String = "no description available", @@ -34,7 +34,7 @@ abstract class SimpleCommand @JvmOverloads constructor( ) : Command, AbstractReflectionCommand(owner, names, description, permission, prefixOptional), CommandParserContextAware { - override val usage: String + public override val usage: String get() = super.usage /** @@ -42,20 +42,20 @@ abstract class SimpleCommand @JvmOverloads constructor( */ protected annotation class Handler - final override val context: CommandParserContext = CommandParserContext.Builtins + overrideContext + public final override val context: CommandParserContext = CommandParserContext.Builtins + overrideContext - override fun checkSubCommand(subCommands: Array) { + internal override fun checkSubCommand(subCommands: Array) { super.checkSubCommand(subCommands) check(subCommands.size == 1) { "There can only be exactly one function annotated with Handler at this moment as overloading is not yet supported." } } @Deprecated("prohibited", level = DeprecationLevel.HIDDEN) - override suspend fun CommandSender.onDefault(rawArgs: Array) = sendMessage(usage) + internal override suspend fun CommandSender.onDefault(rawArgs: Array) = sendMessage(usage) - final override suspend fun CommandSender.onCommand(args: Array) { + public final override suspend fun CommandSender.onCommand(args: Array) { subCommands.single().parseAndExecute(this, args, false) } - final override val subCommandAnnotationResolver: SubCommandAnnotationResolver + internal final override val subCommandAnnotationResolver: SubCommandAnnotationResolver get() = SimpleCommandSubCommandAnnotationResolver } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgParser.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgParser.kt index 737fd8c5d..a5a274eb5 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgParser.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgParser.kt @@ -20,14 +20,14 @@ import kotlin.contracts.contract * this output type of that arg * input is always String */ -interface CommandArgParser { - fun parse(raw: String, sender: CommandSender): T +public interface CommandArgParser { + public fun parse(raw: String, sender: CommandSender): T @JvmDefault - fun parse(raw: SingleMessage, sender: CommandSender): T = parse(raw.content, sender) + public fun parse(raw: SingleMessage, sender: CommandSender): T = parse(raw.content, sender) } -fun CommandArgParser.parse(raw: Any, sender: CommandSender): T { +public fun CommandArgParser.parse(raw: Any, sender: CommandSender): T { contract { returns() implies (raw is String || raw is SingleMessage) } @@ -41,12 +41,12 @@ fun CommandArgParser.parse(raw: Any, sender: CommandSender): T { @Suppress("unused") @JvmSynthetic -inline fun CommandArgParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing { +public inline fun CommandArgParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing { throw ParserException(message, cause) } @JvmSynthetic -inline fun CommandArgParser<*>.checkArgument( +public inline fun CommandArgParser<*>.checkArgument( condition: Boolean, crossinline message: () -> String = { "Check failed." } ) { @@ -61,7 +61,7 @@ inline fun CommandArgParser<*>.checkArgument( */ @Suppress("FunctionName") @JvmSynthetic -inline fun CommandArgParser( +public inline fun CommandArgParser( crossinline stringParser: CommandArgParser.(s: String, sender: CommandSender) -> T ): CommandArgParser = object : CommandArgParser { override fun parse(raw: String, sender: CommandSender): T = stringParser(raw, sender) @@ -72,7 +72,7 @@ inline fun CommandArgParser( */ @Suppress("FunctionName") @JvmSynthetic -inline fun CommandArgParser( +public inline fun CommandArgParser( crossinline stringParser: CommandArgParser.(s: String, sender: CommandSender) -> T, crossinline messageParser: CommandArgParser.(m: SingleMessage, sender: CommandSender) -> T ): CommandArgParser = object : CommandArgParser { @@ -84,4 +84,4 @@ inline fun CommandArgParser( /** * 在解析参数时遇到的 _正常_ 错误. 如参数不符合规范. */ -class ParserException(message: String, cause: Throwable? = null) : RuntimeException(message, cause) \ No newline at end of file +public class ParserException(message: String, cause: Throwable? = null) : RuntimeException(message, cause) \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgParserBuiltins.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgParserBuiltins.kt index 7ef7124f0..7154af6a6 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgParserBuiltins.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgParserBuiltins.kt @@ -23,44 +23,44 @@ import net.mamoe.mirai.message.data.SingleMessage import net.mamoe.mirai.message.data.content -object IntArgParser : CommandArgParser { - override fun parse(raw: String, sender: CommandSender): Int = +public object IntArgParser : CommandArgParser { + public override fun parse(raw: String, sender: CommandSender): Int = raw.toIntOrNull() ?: illegalArgument("无法解析 $raw 为整数") } -object LongArgParser : CommandArgParser { - override fun parse(raw: String, sender: CommandSender): Long = +public object LongArgParser : CommandArgParser { + public override fun parse(raw: String, sender: CommandSender): Long = raw.toLongOrNull() ?: illegalArgument("无法解析 $raw 为长整数") } -object ShortArgParser : CommandArgParser { - override fun parse(raw: String, sender: CommandSender): Short = +public object ShortArgParser : CommandArgParser { + public override fun parse(raw: String, sender: CommandSender): Short = raw.toShortOrNull() ?: illegalArgument("无法解析 $raw 为短整数") } -object ByteArgParser : CommandArgParser { - override fun parse(raw: String, sender: CommandSender): Byte = +public object ByteArgParser : CommandArgParser { + public override fun parse(raw: String, sender: CommandSender): Byte = raw.toByteOrNull() ?: illegalArgument("无法解析 $raw 为字节") } -object DoubleArgParser : CommandArgParser { - override fun parse(raw: String, sender: CommandSender): Double = +public object DoubleArgParser : CommandArgParser { + public override fun parse(raw: String, sender: CommandSender): Double = raw.toDoubleOrNull() ?: illegalArgument("无法解析 $raw 为小数") } -object FloatArgParser : CommandArgParser { - override fun parse(raw: String, sender: CommandSender): Float = +public object FloatArgParser : CommandArgParser { + public override fun parse(raw: String, sender: CommandSender): Float = raw.toFloatOrNull() ?: illegalArgument("无法解析 $raw 为小数") } -object StringArgParser : CommandArgParser { - override fun parse(raw: String, sender: CommandSender): String { +public object StringArgParser : CommandArgParser { + public override fun parse(raw: String, sender: CommandSender): String { return raw } } -object BooleanArgParser : CommandArgParser { - override fun parse(raw: String, sender: CommandSender): Boolean = raw.trim().let { str -> +public object BooleanArgParser : CommandArgParser { + public override fun parse(raw: String, sender: CommandSender): Boolean = raw.trim().let { str -> str.equals("true", ignoreCase = true) || str.equals("yes", ignoreCase = true) || str.equals("enabled", ignoreCase = true) @@ -73,18 +73,18 @@ object BooleanArgParser : CommandArgParser { * output: Bot * errors: String->Int convert, Bot Not Exist */ -object ExistBotArgParser : CommandArgParser { - override fun parse(raw: String, sender: CommandSender): Bot { +public object ExistBotArgParser : CommandArgParser { + public override fun parse(raw: String, sender: CommandSender): Bot { val uin = raw.toLongOrNull() ?: illegalArgument("无法识别 QQ ID: $raw") return Bot.getInstanceOrNull(uin) ?: illegalArgument("无法找到 Bot $uin") } } -object ExistFriendArgParser : CommandArgParser { +public object ExistFriendArgParser : CommandArgParser { //Bot.friend //friend //~ = self - override fun parse(raw: String, sender: CommandSender): Friend { + public override fun parse(raw: String, sender: CommandSender): Friend { if (raw == "~") { if (sender !is BotAwareCommandSender) { illegalArgument("无法解析~作为默认") @@ -115,7 +115,7 @@ object ExistFriendArgParser : CommandArgParser { } } - override fun parse(raw: SingleMessage, sender: CommandSender): Friend { + public override fun parse(raw: SingleMessage, sender: CommandSender): Friend { if (raw is At) { assert(sender is MemberCommandSender) return (sender as BotAwareCommandSender).bot.friends.getOrNull(raw.target) ?: illegalArgument("At的对象非Bot好友") @@ -125,8 +125,8 @@ object ExistFriendArgParser : CommandArgParser { } } -object ExistGroupArgParser : CommandArgParser { - override fun parse(raw: String, sender: CommandSender): Group { +public object ExistGroupArgParser : CommandArgParser { + public override fun parse(raw: String, sender: CommandSender): Group { //by default if ((raw == "" || raw == "~") && sender is MemberCommandSender) { return sender.group @@ -160,12 +160,12 @@ object ExistGroupArgParser : CommandArgParser { } } -object ExistMemberArgParser : CommandArgParser { +public object ExistMemberArgParser : CommandArgParser { //后台: Bot.Group.Member[QQ/名片] //私聊: Group.Member[QQ/名片] //群内: Q号 //群内: 名片 - override fun parse(raw: String, sender: CommandSender): Member { + public override fun parse(raw: String, sender: CommandSender): Member { if (sender !is BotAwareCommandSender) { with(raw.split(".")) { checkArgument(this.size >= 3) { @@ -226,7 +226,7 @@ object ExistMemberArgParser : CommandArgParser { } } - override fun parse(raw: SingleMessage, sender: CommandSender): Member { + public override fun parse(raw: SingleMessage, sender: CommandSender): Member { return if (raw is At) { checkArgument(sender is MemberCommandSender) (sender.group).members[raw.target] diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandParserContext.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandParserContext.kt index 459e25f54..ce7e5413b 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandParserContext.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandParserContext.kt @@ -27,20 +27,20 @@ import kotlin.reflect.full.isSubclassOf * [KClass] 到 [CommandArgParser] 的匹配 * @see CustomCommandParserContext 自定义 */ -interface CommandParserContext { - data class ParserPair( +public interface CommandParserContext { + public data class ParserPair( val klass: KClass, val parser: CommandArgParser ) - operator fun get(klass: KClass): CommandArgParser? + public operator fun get(klass: KClass): CommandArgParser? - fun toList(): List> + public fun toList(): List> /** * 内建的默认 [CommandArgParser] */ - object Builtins : CommandParserContext by (CommandParserContext { + public object Builtins : CommandParserContext by (CommandParserContext { Int::class with IntArgParser Byte::class with ByteArgParser Short::class with ShortArgParser @@ -60,19 +60,19 @@ interface CommandParserContext { /** * 拥有 [CommandParserContext] 的类 */ -interface CommandParserContextAware { +public interface CommandParserContextAware { /** * [CommandArgParser] 的环境 */ - val context: CommandParserContext + public val context: CommandParserContext } -object EmptyCommandParserContext : CommandParserContext by CustomCommandParserContext(listOf()) +public object EmptyCommandParserContext : CommandParserContext by CustomCommandParserContext(listOf()) /** * 合并两个 [CommandParserContext], [replacer] 将会替换 [this] 中重复的 parser. */ -operator fun CommandParserContext.plus(replacer: CommandParserContext): CommandParserContext { +public operator fun CommandParserContext.plus(replacer: CommandParserContext): CommandParserContext { if (replacer == EmptyCommandParserContext) return this if (this == EmptyCommandParserContext) return replacer return object : CommandParserContext { @@ -84,7 +84,7 @@ operator fun CommandParserContext.plus(replacer: CommandParserContext): CommandP /** * 合并 [this] 与 [replacer], [replacer] 将会替换 [this] 中重复的 parser. */ -operator fun CommandParserContext.plus(replacer: List>): CommandParserContext { +public operator fun CommandParserContext.plus(replacer: List>): CommandParserContext { if (replacer.isEmpty()) return this if (this == EmptyCommandParserContext) return CustomCommandParserContext(replacer) return object : CommandParserContext { @@ -97,7 +97,7 @@ operator fun CommandParserContext.plus(replacer: List>): CommandPa } @Suppress("UNCHECKED_CAST") -open class CustomCommandParserContext(val list: List>) : CommandParserContext { +public open class CustomCommandParserContext(public val list: List>) : CommandParserContext { override fun get(klass: KClass): CommandArgParser? = this.list.firstOrNull { klass.isSubclassOf(it.klass) }?.parser as CommandArgParser? @@ -125,16 +125,16 @@ open class CustomCommandParserContext(val list: List>) : CommandPa */ @Suppress("FunctionName") @JvmSynthetic -inline fun CommandParserContext(block: CommandParserContextBuilder.() -> Unit): CommandParserContext { +public inline fun CommandParserContext(block: CommandParserContextBuilder.() -> Unit): CommandParserContext { return CustomCommandParserContext(CommandParserContextBuilder().apply(block).distinctByReversed { it.klass }) } /** * @see CommandParserContext */ -class CommandParserContextBuilder : MutableList> by mutableListOf() { +public class CommandParserContextBuilder : MutableList> by mutableListOf() { @JvmName("add") - inline infix fun KClass.with(parser: CommandArgParser): ParserPair<*> = + public inline infix fun KClass.with(parser: CommandArgParser): ParserPair<*> = ParserPair(this, parser).also { add(it) } /** @@ -142,7 +142,7 @@ class CommandParserContextBuilder : MutableList> by mutableListOf( */ @JvmSynthetic @LowPriorityInOverloadResolution - inline infix fun KClass.with( + public inline infix fun KClass.with( crossinline parser: CommandArgParser.(s: String, sender: CommandSender) -> T ): ParserPair<*> = ParserPair(this, CommandArgParser(parser)).also { add(it) } @@ -150,12 +150,12 @@ class CommandParserContextBuilder : MutableList> by mutableListOf( * 添加一个指令解析器 */ @JvmSynthetic - inline infix fun KClass.with( + public inline infix fun KClass.with( crossinline parser: CommandArgParser.(s: String) -> T ): ParserPair<*> = ParserPair(this, CommandArgParser { s: String, _: CommandSender -> parser(s) }).also { add(it) } @JvmSynthetic - inline fun add(parser: CommandArgParser): ParserPair<*> = + public inline fun add(parser: CommandArgParser): ParserPair<*> = ParserPair(T::class, parser).also { add(it) } /** @@ -163,7 +163,7 @@ class CommandParserContextBuilder : MutableList> by mutableListOf( */ @ConsoleExperimentalAPI @JvmSynthetic - inline infix fun add( + public inline infix fun add( crossinline parser: CommandArgParser<*>.(s: String) -> T ): ParserPair<*> = T::class with CommandArgParser { s: String, _: CommandSender -> parser(s) } @@ -173,7 +173,7 @@ class CommandParserContextBuilder : MutableList> by mutableListOf( @ConsoleExperimentalAPI @JvmSynthetic @LowPriorityInOverloadResolution - inline infix fun add( + public inline infix fun add( crossinline parser: CommandArgParser<*>.(s: String, sender: CommandSender) -> T ): ParserPair<*> = T::class with CommandArgParser(parser) } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/event/ConsoleEvent.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/event/ConsoleEvent.kt index 50b2aeff6..d5b39d001 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/event/ConsoleEvent.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/event/ConsoleEvent.kt @@ -14,4 +14,4 @@ import net.mamoe.mirai.event.Event /** * 表示来自 mirai-console 的事件 */ -interface ConsoleEvent : Event \ No newline at end of file +public interface ConsoleEvent : Event \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/Plugin.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/Plugin.kt index a41404493..e2eeec1be 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/Plugin.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/Plugin.kt @@ -22,15 +22,16 @@ import java.io.File * * @see PluginLoader 插件加载器 */ -interface Plugin { +public interface Plugin { /** * 所属插件加载器实例, 此加载器必须能加载这个 [Plugin]. */ - val loader: PluginLoader<*, *> + public val loader: PluginLoader<*, *> } +@get:JvmSynthetic @Suppress("UNCHECKED_CAST") -inline val

P.safeLoader: PluginLoader +public inline val

P.safeLoader: PluginLoader get() = this.loader as PluginLoader /** @@ -39,15 +40,17 @@ inline val

P.safeLoader: PluginLoader * @see JvmPlugin */ @ConsoleExperimentalAPI("classname is subject to change") -interface PluginFileExtensions { +public interface PluginFileExtensions { /** * 数据目录 */ - val dataFolder: File + public val dataFolder: File /** * 从数据目录获取一个文件, 若不存在则创建文件. */ @JvmDefault - fun file(relativePath: String): File = File(dataFolder, relativePath).apply { createNewFile() } + public fun file(relativePath: String): File = File(dataFolder, relativePath).apply { createNewFile() } + + // TODO: 2020/7/11 add `fun path(...): Path` ? } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginLoader.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginLoader.kt index 2b4dc1e56..0012f7a9d 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginLoader.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginLoader.kt @@ -7,7 +7,7 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ -@file:Suppress("unused", "INAPPLICABLE_JVM_NAME") +@file:Suppress("unused", "INAPPLICABLE_JVM_NAME", "NOTHING_TO_INLINE") package net.mamoe.mirai.console.plugin @@ -23,11 +23,11 @@ import java.io.File * * @see JarPluginLoader Jar 插件加载器 */ -interface PluginLoader

{ +public interface PluginLoader

{ /** * 扫描并返回可以被加载的插件的 [描述][PluginDescription] 列表. 此函数只会被调用一次 */ - fun listPlugins(): List + public fun listPlugins(): List /** * 获取此插件的描述 @@ -36,7 +36,7 @@ interface PluginLoader

{ */ @get:JvmName("getPluginDescription") @get:Throws(PluginLoadException::class) - val P.description: D + public val P.description: D // Java signature: `public P getDescription(P)` /** * 加载一个插件 (实例), 但不 [启用][enable] 它. 返回加载成功的主类实例 @@ -44,19 +44,20 @@ interface PluginLoader

{ * @throws PluginLoadException 在加载插件遇到意料之中的错误时抛出 (如找不到主类等). */ @Throws(PluginLoadException::class) - fun load(description: D): P + public fun load(description: D): P - fun enable(plugin: P) - fun disable(plugin: P) + public fun enable(plugin: P) + public fun disable(plugin: P) } -fun PluginLoader.getDescription(plugin: P): D = plugin.description +public inline fun PluginLoader.getDescription(plugin: P): D = + plugin.description -open class PluginLoadException : RuntimeException { - constructor() : super() - constructor(message: String?) : super(message) - constructor(message: String?, cause: Throwable?) : super(message, cause) - constructor(cause: Throwable?) : super(cause) +public open class PluginLoadException : RuntimeException { + public constructor() : super() + public constructor(message: String?) : super(message) + public constructor(message: String?, cause: Throwable?) : super(message, cause) + public constructor(cause: Throwable?) : super(cause) } /** @@ -65,18 +66,18 @@ open class PluginLoadException : RuntimeException { * @see AbstractFilePluginLoader 默认基础实现 * @see JarPluginLoader 内建的 Jar (JVM) 插件加载器. */ -interface FilePluginLoader

: PluginLoader { +public interface FilePluginLoader

: PluginLoader { /** * 所支持的插件文件后缀, 含 '.'. 如 [JarPluginLoader] 为 ".jar" */ - val fileSuffix: String + public val fileSuffix: String } /** * [FilePluginLoader] 的默认基础实现 */ -abstract class AbstractFilePluginLoader

( - override val fileSuffix: String +public abstract class AbstractFilePluginLoader

( + public override val fileSuffix: String ) : FilePluginLoader { private fun pluginsFilesSequence(): Sequence = PluginManager.pluginsDir.walk().filter { it.isFile && it.name.endsWith(fileSuffix, ignoreCase = true) } @@ -86,7 +87,7 @@ abstract class AbstractFilePluginLoader

( */ protected abstract fun Sequence.mapToDescription(): List - final override fun listPlugins(): List = pluginsFilesSequence().mapToDescription() + public final override fun listPlugins(): List = pluginsFilesSequence().mapToDescription() } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginManager.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginManager.kt index 76647cef3..674f33149 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginManager.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginManager.kt @@ -18,18 +18,68 @@ import net.mamoe.mirai.utils.info import java.io.File import java.util.concurrent.locks.ReentrantLock -val Plugin.description: PluginDescription - get() = PluginManager.resolvedPlugins.firstOrNull { it == this }?.loader?.cast>() - ?.getDescription( - this - ) ?: error("Plugin is unloaded") +// TODO: 2020/7/11 top-level or in PluginManager.companion? +public val Plugin.description: PluginDescription + get() = PluginManagerImpl.resolvedPlugins.firstOrNull { it == this } + ?.loader?.cast>() + ?.getDescription(this) + ?: error("Plugin is unloaded") -inline fun PluginLoader<*, *>.register() = PluginManager.registerPluginLoader(this) -inline fun PluginLoader<*, *>.unregister() = PluginManager.unregisterPluginLoader(this) +@JvmSynthetic +public inline fun PluginLoader<*, *>.register(): Boolean = PluginManager.registerPluginLoader(this) -object PluginManager { - val pluginsDir = File(MiraiConsole.rootDir, "plugins").apply { mkdir() } - val pluginsDataFolder = File(MiraiConsole.rootDir, "data").apply { mkdir() } +@JvmSynthetic +public inline fun PluginLoader<*, *>.unregister(): Boolean = PluginManager.unregisterPluginLoader(this) + +// TODO: 2020/7/11 document +public interface PluginManager { + public val pluginsDir: File + + public val pluginsDataFolder: File + + /** + * 已加载的插件列表 + */ + public val plugins: List + + /** + * 内建的插件加载器列表. 由 [MiraiConsole] 初始化 + */ + public val builtInLoaders: List> + + /** + * 由插件创建的 [PluginLoader] + */ + public val pluginLoaders: List> + + public fun registerPluginLoader(loader: PluginLoader<*, *>): Boolean + + public fun unregisterPluginLoader(loader: PluginLoader<*, *>): Boolean + + public companion object INSTANCE : PluginManager by PluginManagerImpl +} + +public class PluginMissingDependencyException : PluginResolutionException { + public constructor() : super() + public constructor(message: String?) : super(message) + public constructor(message: String?, cause: Throwable?) : super(message, cause) + public constructor(cause: Throwable?) : super(cause) +} + +public open class PluginResolutionException : Exception { + public constructor() : super() + public constructor(message: String?) : super(message) + public constructor(message: String?, cause: Throwable?) : super(message, cause) + public constructor(cause: Throwable?) : super(cause) +} + + +// internal + + +internal object PluginManagerImpl : PluginManager { + override val pluginsDir = File(MiraiConsole.rootDir, "plugins").apply { mkdir() } + override val pluginsDataFolder = File(MiraiConsole.rootDir, "data").apply { mkdir() } @Suppress("ObjectPropertyName") private val _pluginLoaders: MutableList> = mutableListOf() @@ -38,38 +88,21 @@ object PluginManager { @JvmField internal val resolvedPlugins: MutableList = mutableListOf() - - /** - * 已加载的插件列表 - */ - @JvmStatic - val plugins: List + override val plugins: List get() = resolvedPlugins.toList() - - /** - * 内建的插件加载器列表. 由 [MiraiConsole] 初始化 - */ - @JvmStatic - val builtInLoaders: List> + override val builtInLoaders: List> get() = MiraiConsole.builtInPluginLoaders - - /** - * 由插件创建的 [PluginLoader] - */ - @JvmStatic - val pluginLoaders: List> + override val pluginLoaders: List> get() = _pluginLoaders.toList() - @JvmStatic - fun registerPluginLoader(loader: PluginLoader<*, *>): Boolean = loadersLock.withLock { + override fun registerPluginLoader(loader: PluginLoader<*, *>): Boolean = loadersLock.withLock { if (_pluginLoaders.any { it::class == loader }) { return false } _pluginLoaders.add(loader) } - @JvmStatic - fun unregisterPluginLoader(loader: PluginLoader<*, *>) = loadersLock.withLock { + override fun unregisterPluginLoader(loader: PluginLoader<*, *>) = loadersLock.withLock { _pluginLoaders.remove(loader) } @@ -177,8 +210,10 @@ object PluginManager { this.consumeLoadable().also { resultPlugins -> check(resultPlugins.size < beforeSize) { throw PluginMissingDependencyException(resultPlugins.joinToString("\n") { badPlugin -> - "Cannot load plugin ${badPlugin.name}, missing dependencies: ${badPlugin.dependencies.filterIsMissing() - .joinToString()}" + "Cannot load plugin ${badPlugin.name}, missing dependencies: ${ + badPlugin.dependencies.filterIsMissing() + .joinToString() + }" }) } }.doSort() @@ -191,16 +226,6 @@ object PluginManager { // endregion } -class PluginMissingDependencyException(message: String?) : PluginResolutionException(message) - -open class PluginResolutionException : Exception { - constructor() : super() - constructor(message: String?) : super(message) - constructor(message: String?, cause: Throwable?) : super(message, cause) - constructor(cause: Throwable?) : super(cause) -} - - internal data class PluginDescriptionWithLoader( @JvmField val loader: PluginLoader<*, PluginDescription>, // easier type @JvmField val delegate: PluginDescription diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/center/PluginCenter.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/center/PluginCenter.kt index 685fd5bba..8fd84b383 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/center/PluginCenter.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/center/PluginCenter.kt @@ -15,10 +15,11 @@ import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI import java.io.File @ConsoleExperimentalAPI -interface PluginCenter { +public interface PluginCenter { @Serializable - data class PluginInsight( + @ConsoleExperimentalAPI + public data class PluginInsight( val name: String, val version: String, @SerialName("core") @@ -31,8 +32,9 @@ interface PluginCenter { val commands: List ) + @ConsoleExperimentalAPI @Serializable - data class PluginInfo( + public data class PluginInfo( val name: String, val version: String, @SerialName("core") @@ -54,24 +56,24 @@ interface PluginCenter { * 能获取到多少由实际的 [PluginCenter] 决定 * 返回 插件名->Insight */ - suspend fun fetchPlugin(page: Int): Map + public suspend fun fetchPlugin(page: Int): Map /** * 尝试获取到某个插件 by 全名, case sensitive * null 则没有 */ - suspend fun findPlugin(name: String): PluginInfo? + public suspend fun findPlugin(name: String): PluginInfo? - suspend fun T.downloadPlugin(name: String, progressListener: T.(Float) -> Unit): File + public suspend fun T.downloadPlugin(name: String, progressListener: T.(Float) -> Unit): File - suspend fun downloadPlugin(name: String, progressListener: PluginCenter.(Float) -> Unit): File = + public suspend fun downloadPlugin(name: String, progressListener: PluginCenter.(Float) -> Unit): File = downloadPlugin(name, progressListener) /** * 刷新 */ - suspend fun refresh() + public suspend fun refresh() - val name: String + public val name: String } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/description.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/description.kt index e267c0cd8..bad00afbe 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/description.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/description.kt @@ -9,7 +9,8 @@ package net.mamoe.mirai.console.plugin -import kotlinx.serialization.* +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable import kotlinx.serialization.builtins.serializer import net.mamoe.mirai.console.setting.internal.map import net.mamoe.yamlkt.Yaml @@ -19,14 +20,14 @@ import java.io.File /** 插件类型 */ @Serializable(with = PluginKind.AsStringSerializer::class) -enum class PluginKind { +public enum class PluginKind { /** 表示此插件提供一个 [PluginLoader], 应在加载其他 [NORMAL] 类型插件前加载 */ LOADER, /** 表示此插件为一个通常的插件, 按照正常的依赖关系加载. */ NORMAL; - object AsStringSerializer : KSerializer by String.serializer().map( + public object AsStringSerializer : KSerializer by String.serializer().map( serializer = { it.name }, deserializer = { str -> values().firstOrNull { @@ -39,38 +40,38 @@ enum class PluginKind { /** * 插件描述 */ -interface PluginDescription { - val kind: PluginKind +public interface PluginDescription { + public val kind: PluginKind - val name: String - val author: String - val version: String - val info: String + public val name: String + public val author: String + public val version: String + public val info: String /** 此插件依赖的其他插件, 将会在这些插件加载之后加载此插件 */ - val dependencies: List<@Serializable(with = PluginDependency.SmartSerializer::class) PluginDependency> + public val dependencies: List<@Serializable(with = PluginDependency.SmartSerializer::class) PluginDependency> } /** 插件的一个依赖的信息 */ @Serializable -data class PluginDependency( +public data class PluginDependency( /** 依赖插件名 */ - val name: String, + public val name: String, /** * 依赖版本号. 为 null 时则为不限制版本. * @see versionKind 版本号类型 */ - val version: String? = null, + public val version: String? = null, /** 版本号类型 */ - val versionKind: VersionKind = VersionKind.AT_LEAST, + public val versionKind: VersionKind = VersionKind.AT_LEAST, /** * 若为 `false`, 插件在找不到此依赖时也能正常加载. */ - val isOptional: Boolean = false + public val isOptional: Boolean = false ) { /** 版本号类型 */ @Serializable(with = VersionKind.AsStringSerializer::class) - enum class VersionKind( + public enum class VersionKind( private vararg val serialNames: String ) { /** 要求依赖精确的版本 */ @@ -82,7 +83,7 @@ data class PluginDependency( /** 要求依赖最高版本 */ AT_MOST("at_most", "AtMost", "most", "highest", "-"); - object AsStringSerializer : KSerializer by String.serializer().map( + public object AsStringSerializer : KSerializer by String.serializer().map( serializer = { it.serialNames.first() }, deserializer = { str -> values().firstOrNull { @@ -92,7 +93,7 @@ data class PluginDependency( ) } - override fun toString(): String { + public override fun toString(): String { return "$name ${versionKind.toEnglishString()}v$version" } @@ -100,7 +101,7 @@ data class PluginDependency( /** * 可支持解析 [String] 作为 [PluginDependency.version] 或单个 [PluginDependency] */ - object SmartSerializer : KSerializer by YamlDynamicSerializer.map( + public object SmartSerializer : KSerializer by YamlDynamicSerializer.map( serializer = { it }, deserializer = { any -> when (any) { @@ -112,10 +113,10 @@ data class PluginDependency( } /** - * 基于文件的插件的描述 + * 基于文件的插件 的描述 */ -interface FilePluginDescription : PluginDescription { - val file: File +public interface FilePluginDescription : PluginDescription { + public val file: File } internal fun PluginDependency.VersionKind.toEnglishString(): String = when (this) { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/internal/JvmPluginInternal.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/internal/JvmPluginInternal.kt index e3953e0ec..add106751 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/internal/JvmPluginInternal.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/internal/JvmPluginInternal.kt @@ -39,8 +39,8 @@ internal abstract class JvmPluginInternal( ) : JvmPlugin, CoroutineScope { - private val resourceConsoleDelegate by lazy { this::class.asResourceContainer() } - override fun getResourceAsStream(name: String): InputStream = resourceConsoleDelegate.getResourceAsStream(name) + private val resourceContainerDelegate by lazy { this::class.asResourceContainer() } + override fun getResourceAsStream(name: String): InputStream = resourceContainerDelegate.getResourceAsStream(name) // region JvmPlugin /** diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt index ae6fc008a..73ea700a8 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt @@ -22,10 +22,10 @@ import kotlin.coroutines.EmptyCoroutineContext * @see JavaPlugin * @see KotlinPlugin */ -abstract class AbstractJvmPlugin @JvmOverloads constructor( +public abstract class AbstractJvmPlugin @JvmOverloads constructor( parentCoroutineContext: CoroutineContext = EmptyCoroutineContext ) : JvmPlugin, JvmPluginInternal(parentCoroutineContext) { - final override val name: String get() = this.description.name + public final override val name: String get() = this.description.name - override fun getSetting(clazz: Class): T = loader.settingStorage.load(this, clazz) + public override fun getSetting(clazz: Class): T = loader.settingStorage.load(this, clazz) } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JarPluginLoader.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JarPluginLoader.kt index 37a66942b..802f29380 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JarPluginLoader.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JarPluginLoader.kt @@ -13,6 +13,7 @@ import kotlinx.coroutines.* import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.MiraiConsoleInternal import net.mamoe.mirai.console.plugin.AbstractFilePluginLoader +import net.mamoe.mirai.console.plugin.FilePluginLoader import net.mamoe.mirai.console.plugin.PluginLoadException import net.mamoe.mirai.console.plugin.internal.JvmPluginInternal import net.mamoe.mirai.console.plugin.internal.PluginsLoader @@ -28,11 +29,24 @@ import kotlin.reflect.full.createInstance /** * 内建的 Jar (JVM) 插件加载器 */ -object JarPluginLoader : AbstractFilePluginLoader(".jar"), CoroutineScope { +public interface JarPluginLoader : CoroutineScope, FilePluginLoader { + @ConsoleExperimentalAPI + public val settingStorage: SettingStorage + + public companion object INSTANCE : JarPluginLoader by JarPluginLoaderImpl +} + + +internal object JarPluginLoaderImpl : + AbstractFilePluginLoader(".jar"), + CoroutineScope, + JarPluginLoader { + private val logger: MiraiLogger = MiraiConsole.newLogger(JarPluginLoader::class.simpleName!!) @ConsoleExperimentalAPI - val settingStorage: SettingStorage = MiraiConsoleInternal.settingStorage + override val settingStorage: SettingStorage + get() = MiraiConsoleInternal.settingStorage override val coroutineContext: CoroutineContext = MiraiConsole.coroutineContext + diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JavaPlugin.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JavaPlugin.kt index 0dac63676..ad102d633 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JavaPlugin.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JavaPlugin.kt @@ -18,14 +18,12 @@ import kotlin.coroutines.EmptyCoroutineContext /** * Java 插件的父类 */ -abstract class JavaPlugin @JvmOverloads constructor( +public abstract class JavaPlugin @JvmOverloads constructor( parentCoroutineContext: CoroutineContext = EmptyCoroutineContext ) : JvmPlugin, AbstractJvmPlugin(parentCoroutineContext) { - /** * Java API Scheduler */ - val scheduler: JavaPluginScheduler = - JavaPluginScheduler(this.coroutineContext) + public val scheduler: JavaPluginScheduler = JavaPluginScheduler(this.coroutineContext) } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPlugin.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPlugin.kt index baa63f7a6..1e5835556 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPlugin.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPlugin.kt @@ -7,7 +7,7 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ -@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "EXPOSED_SUPER_CLASS") +@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "EXPOSED_SUPER_CLASS", "NOTHING_TO_INLINE") package net.mamoe.mirai.console.plugin.jvm @@ -32,34 +32,39 @@ import kotlin.reflect.KClass * @see JvmPlugin 支持文件系统扩展 * @see ResourceContainer 支持资源获取 (如 Jar 中的资源文件) */ -interface JvmPlugin : Plugin, CoroutineScope, PluginFileExtensions, ResourceContainer, AutoSaveSettingHolder { +public interface JvmPlugin : Plugin, CoroutineScope, + PluginFileExtensions, ResourceContainer, AutoSaveSettingHolder { /** 日志 */ - val logger: MiraiLogger + public val logger: MiraiLogger /** 插件描述 */ - val description: JvmPluginDescription + public val description: JvmPluginDescription /** 所属插件加载器实例 */ - override val loader: JarPluginLoader get() = JarPluginLoader + public override val loader: JarPluginLoader get() = JarPluginLoader /** * 获取一个 [Setting] 实例 */ - fun getSetting(clazz: Class): T + public fun getSetting(clazz: Class): T + // TODO: 2020/7/11 document onLoad, onEnable, onDisable @JvmDefault - fun onLoad() { + public fun onLoad() { } @JvmDefault - fun onEnable() { + public fun onEnable() { } @JvmDefault - fun onDisable() { + public fun onDisable() { } } -fun JvmPlugin.getSetting(clazz: KClass) = this.getSetting(clazz.java) -inline fun JvmPlugin.getSetting() = this.getSetting(T::class) \ No newline at end of file +@JvmSynthetic +public inline fun JvmPlugin.getSetting(clazz: KClass): T = this.getSetting(clazz.java) + +@JvmSynthetic +public inline fun JvmPlugin.getSetting(): T = this.getSetting(T::class) \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPluginDescription.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPluginDescription.kt index 8c239b770..fb217ffb3 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPluginDescription.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPluginDescription.kt @@ -19,23 +19,23 @@ import net.mamoe.mirai.console.plugin.PluginKind import java.io.File @Serializable -class JvmPluginDescription internal constructor( - override val kind: PluginKind = PluginKind.NORMAL, - override val name: String, +public class JvmPluginDescription internal constructor( + public override val kind: PluginKind = PluginKind.NORMAL, + public override val name: String, @SerialName("main") - val mainClassName: String, - override val author: String = "", - override val version: String, - override val info: String = "", + public val mainClassName: String, + public override val author: String = "", + public override val version: String, + public override val info: String = "", @SerialName("depends") - override val dependencies: List<@Serializable(with = PluginDependency.SmartSerializer::class) PluginDependency> = listOf() + public override val dependencies: List<@Serializable(with = PluginDependency.SmartSerializer::class) PluginDependency> = listOf() ) : PluginDescription, FilePluginDescription { /** * 在手动实现时使用这个构造器. */ @Suppress("unused") - constructor( + public constructor( kind: PluginKind, name: String, mainClassName: String, author: String, version: String, info: String, depends: List, file: File @@ -43,7 +43,7 @@ class JvmPluginDescription internal constructor( this._file = file } - override val file: File + public override val file: File get() = _file ?: error("Internal error: JvmPluginDescription(name=$name)._file == null") @@ -52,7 +52,7 @@ class JvmPluginDescription internal constructor( @JvmField internal var _file: File? = null - override fun toString(): String { + public override fun toString(): String { return "JvmPluginDescription(kind=$kind, name='$name', mainClassName='$mainClassName', author='$author', version='$version', info='$info', dependencies=$dependencies, _file=$_file)" } } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/KotlinPlugin.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/KotlinPlugin.kt index b2c1873f9..a8e14e9e4 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/KotlinPlugin.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/KotlinPlugin.kt @@ -7,13 +7,10 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ -@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "EXPOSED_SUPER_CLASS") +@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "EXPOSED_SUPER_CLASS", "RedundantVisibilityModifier") package net.mamoe.mirai.console.plugin.jvm -import net.mamoe.mirai.console.setting.Setting -import net.mamoe.mirai.console.setting.getValue -import net.mamoe.mirai.console.setting.value import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext @@ -23,7 +20,7 @@ import kotlin.coroutines.EmptyCoroutineContext * * 必须通过 "plugin.yml" 指定主类并由 [JarPluginLoader] 加载. */ -abstract class KotlinPlugin @JvmOverloads constructor( +public abstract class KotlinPlugin @JvmOverloads constructor( parentCoroutineContext: CoroutineContext = EmptyCoroutineContext ) : JvmPlugin, AbstractJvmPlugin(parentCoroutineContext) @@ -32,11 +29,11 @@ abstract class KotlinPlugin @JvmOverloads constructor( * 在内存动态加载的插件. */ @ConsoleExperimentalAPI -abstract class KotlinMemoryPlugin @JvmOverloads constructor( +public abstract class KotlinMemoryPlugin @JvmOverloads constructor( description: JvmPluginDescription, parentCoroutineContext: CoroutineContext = EmptyCoroutineContext ) : JvmPlugin, AbstractJvmPlugin(parentCoroutineContext) { - final override var _description: JvmPluginDescription + internal final override var _description: JvmPluginDescription get() = super._description set(value) { super._description = value @@ -47,8 +44,11 @@ abstract class KotlinMemoryPlugin @JvmOverloads constructor( } } -object MyPlugin : KotlinPlugin() +/* -object AccountSetting : Setting by MyPlugin.getSetting() { - val s by value(1) -} \ No newline at end of file +public object MyPlugin : KotlinPlugin() + +public object AccountSetting : Setting by MyPlugin.getSetting() { + public val s by value(1) +} +*/ \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Setting.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Setting.kt index 6557b1d72..0dde7d9d5 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Setting.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Setting.kt @@ -29,11 +29,11 @@ import kotlin.reflect.KType * ``` */ // TODO: 2020/6/26 document -typealias SerialName = kotlinx.serialization.SerialName +public typealias SerialName = kotlinx.serialization.SerialName // TODO: 2020/6/26 document -abstract class AbstractSetting : Setting, SettingImpl() { - final override operator fun SerializerAwareValue.provideDelegate( +public abstract class AbstractSetting : Setting, SettingImpl() { + public final override operator fun SerializerAwareValue.provideDelegate( thisRef: Any?, property: KProperty<*> ): SerializerAwareValue { @@ -42,34 +42,34 @@ abstract class AbstractSetting : Setting, SettingImpl() { return this } - final override val updaterSerializer: KSerializer get() = super.updaterSerializer + public final override val updaterSerializer: KSerializer get() = super.updaterSerializer } // TODO: 2020/6/26 document -interface Setting { +public interface Setting { // TODO: 2020/6/26 document - operator fun SerializerAwareValue.provideDelegate( + public operator fun SerializerAwareValue.provideDelegate( thisRef: Any?, property: KProperty<*> ): SerializerAwareValue // TODO: 2020/6/26 document - val updaterSerializer: KSerializer + public val updaterSerializer: KSerializer - fun onValueChanged(value: Value<*>) + public fun onValueChanged(value: Value<*>) } //// region Setting_value_primitives CODEGEN //// -fun Setting.value(default: Byte): SerializerAwareValue = valueImpl(default) -fun Setting.value(default: Short): SerializerAwareValue = valueImpl(default) -fun Setting.value(default: Int): SerializerAwareValue = valueImpl(default) -fun Setting.value(default: Long): SerializerAwareValue = valueImpl(default) -fun Setting.value(default: Float): SerializerAwareValue = valueImpl(default) -fun Setting.value(default: Double): SerializerAwareValue = valueImpl(default) -fun Setting.value(default: Char): SerializerAwareValue = valueImpl(default) -fun Setting.value(default: Boolean): SerializerAwareValue = valueImpl(default) -fun Setting.value(default: String): SerializerAwareValue = valueImpl(default) +public fun Setting.value(default: Byte): SerializerAwareValue = valueImpl(default) +public fun Setting.value(default: Short): SerializerAwareValue = valueImpl(default) +public fun Setting.value(default: Int): SerializerAwareValue = valueImpl(default) +public fun Setting.value(default: Long): SerializerAwareValue = valueImpl(default) +public fun Setting.value(default: Float): SerializerAwareValue = valueImpl(default) +public fun Setting.value(default: Double): SerializerAwareValue = valueImpl(default) +public fun Setting.value(default: Char): SerializerAwareValue = valueImpl(default) +public fun Setting.value(default: Boolean): SerializerAwareValue = valueImpl(default) +public fun Setting.value(default: String): SerializerAwareValue = valueImpl(default) //// endregion Setting_value_primitives CODEGEN //// @@ -84,7 +84,7 @@ fun Setting.value(default: String): SerializerAwareValue = valueImpl(def */ @Suppress("UNCHECKED_CAST") @LowPriorityInOverloadResolution -inline fun Setting.value(default: T): SerializerAwareValue = valueFromKType(typeOf0(), default) +public inline fun Setting.value(default: T): SerializerAwareValue = valueFromKType(typeOf0(), default) /** * Creates a [Value] with reified type, and set default value by reflection to its no-arg public constructor. @@ -95,13 +95,13 @@ inline fun Setting.value(default: T): SerializerAwareValue = valu * (typically annotated with [kotlinx.serialization.Serializable]) */ @LowPriorityInOverloadResolution -inline fun Setting.value(): SerializerAwareValue = value(T::class.createInstance() as T) +public inline fun Setting.value(): SerializerAwareValue = value(T::class.createInstance() as T) /** * Creates a [Value] with specified [KType], and set default value. */ @Suppress("UNCHECKED_CAST") -fun Setting.valueFromKType(type: KType, default: T): SerializerAwareValue = +public fun Setting.valueFromKType(type: KType, default: T): SerializerAwareValue = (valueFromKTypeImpl(type) as SerializerAwareValue).apply { this.value = default } as SerializerAwareValue // TODO: 2020/6/24 Introduce class TypeToken for compound types for Java. \ No newline at end of file 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 ad6618046..6805460ee 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 @@ -1,3 +1,5 @@ +@file:Suppress("NOTHING_TO_INLINE") + package net.mamoe.mirai.console.setting import kotlinx.atomicfu.atomic @@ -22,19 +24,20 @@ import kotlin.reflect.full.findAnnotation /** * [Setting] 存储容器 */ -interface SettingStorage { +public interface SettingStorage { /** * 读取一个实例 */ - fun load(holder: SettingHolder, settingClass: Class): T + public fun load(holder: SettingHolder, settingClass: Class): T /** * 保存一个实例 */ - fun store(holder: SettingHolder, setting: Setting) + public fun store(holder: SettingHolder, setting: Setting) } -fun SettingStorage.load(holder: SettingHolder, settingClass: KClass): T = +// TODO: 2020/7/11 here or companion? +public inline fun SettingStorage.load(holder: SettingHolder, settingClass: KClass): T = this.load(holder, settingClass.java) /** @@ -45,17 +48,19 @@ fun SettingStorage.load(holder: SettingHolder, settingClass: KClas * * @see AutoSaveSettingHolder 自动保存 */ -interface SettingHolder { +public interface SettingHolder { /** * 保存时使用的分类名 */ - val name: String + public val name: String } /** * 可以持有相关 [AutoSaveSetting] 的对象. + * + * @see net.mamoe.mirai.console.plugin.jvm.JvmPlugin */ -interface AutoSaveSettingHolder : SettingHolder, CoroutineScope { +public interface AutoSaveSettingHolder : SettingHolder, CoroutineScope { /** * [AutoSaveSetting] 每次自动保存时间间隔 * @@ -63,8 +68,11 @@ interface AutoSaveSettingHolder : SettingHolder, CoroutineScope { * - 区间的右端点为最大间隔, 一个 [Value] 被修改后, 最多不超过这个时间段后就会被保存. * * 若 [coroutineContext] 含有 [Job], 则 [AutoSaveSetting] 会通过 [Job.invokeOnCompletion] 在 Job 完结时触发自动保存. + * + * @see LongRange Java 用户使用 [LongRange] 的构造器创建 + * @see Long.rangeTo Kotlin 用户使用 [Long.rangeTo] 创建, 如 `3000..50000` */ - val autoSaveIntervalMillis: LongRange + public val autoSaveIntervalMillis: LongRange get() = 30.secondsToMillis..10.minutesToSeconds /** @@ -75,7 +83,7 @@ interface AutoSaveSettingHolder : SettingHolder, CoroutineScope { * * @see getSetting */ - open class AutoSaveSetting(private val owner: AutoSaveSettingHolder, private val storage: SettingStorage) : + public open class AutoSaveSetting(private val owner: AutoSaveSettingHolder, private val storage: SettingStorage) : AbstractSetting() { @Volatile internal var lastAutoSaveJob: Job? = null @@ -111,7 +119,26 @@ interface AutoSaveSettingHolder : SettingHolder, CoroutineScope { } -object MemorySettingStorage : SettingStorage { +// TODO: 2020/7/11 document +public interface MemorySettingStorage : SettingStorage { + public companion object INSTANCE : MemorySettingStorage by MemorySettingStorageImpl +} + +// TODO: 2020/7/11 document +public interface MultiFileSettingStorage : SettingStorage { + public val directory: File + + public companion object { + @JvmStatic + @JvmName("create") + public operator fun invoke(directory: File): MultiFileSettingStorage = MultiFileSettingStorageImpl(directory) + } +} + + +// internal + +internal object MemorySettingStorageImpl : SettingStorage, MemorySettingStorage { private val list = mutableMapOf, Setting>() internal class MemorySettingImpl : AbstractSetting() { @@ -146,9 +173,9 @@ object MemorySettingStorage : SettingStorage { } } -class MultiFileSettingStorage( - private val directory: File -) : SettingStorage { +internal class MultiFileSettingStorageImpl( + override val directory: File +) : SettingStorage, MultiFileSettingStorage { override fun load(holder: SettingHolder, settingClass: Class): T = with(settingClass.kotlin) { val file = settingFile(holder, settingClass::class) @@ -161,7 +188,7 @@ class MultiFileSettingStorage( ) } if (holder is AutoSaveSettingHolder) { - AutoSaveSetting(holder, this@MultiFileSettingStorage) as T? + AutoSaveSetting(holder, this@MultiFileSettingStorageImpl) as T? } else null } ?: throw IllegalArgumentException( "Cannot create Setting instance. Make sure 'holder' is a AutoSaveSettingHolder, " + @@ -189,7 +216,7 @@ class MultiFileSettingStorage( } @ConsoleExperimentalAPI - override fun store(holder: SettingHolder, setting: Setting) = with(setting::class) { + override fun store(holder: SettingHolder, setting: Setting): Unit = with(setting::class) { val file = settingFile(holder, this) if (file.exists() && file.isFile && file.canRead()) { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Value.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Value.kt index 16d615474..6a6ca5c28 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Value.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Value.kt @@ -29,14 +29,14 @@ import kotlin.reflect.KProperty * @see PrimitiveValue * @see CompositeValue */ -interface Value { - var value: T +public interface Value { + public var value: T } /** * Typically returned by [Setting.value] functions. */ -class SerializableValue( +public class SerializableValue( private val delegate: Value, /** * The serializer used to update and dump [delegate] @@ -46,7 +46,7 @@ class SerializableValue( override fun toString(): String = delegate.toString() } -fun Value.serializableValueWith( +public fun Value.serializableValueWith( serializer: KSerializer ): SerializableValue { return SerializableValue( @@ -58,27 +58,30 @@ fun Value.serializableValueWith( /** * @see SerializableValue */ -interface SerializerAwareValue : Value { - val serializer: KSerializer +public interface SerializerAwareValue : Value { + public val serializer: KSerializer } -fun SerializerAwareValue.serialize(format: StringFormat): String { +public fun SerializerAwareValue.serialize(format: StringFormat): String { return format.stringify(this.serializer, Unit) } -fun SerializerAwareValue.serialize(format: BinaryFormat): ByteArray { +public fun SerializerAwareValue.serialize(format: BinaryFormat): ByteArray { return format.dump(this.serializer, Unit) } -inline operator fun Value.getValue(mySetting: Any?, property: KProperty<*>): T = value -inline operator fun Value.setValue(mySetting: Any?, property: KProperty<*>, value: T) { +@JvmSynthetic +public inline operator fun Value.getValue(mySetting: Any?, property: KProperty<*>): T = value + +@JvmSynthetic +public inline operator fun Value.setValue(mySetting: Any?, property: KProperty<*>, value: T) { this.value = value } /** * The serializer for a specific kind of [Value]. */ -typealias ValueSerializer = KSerializer> +public typealias ValueSerializer = KSerializer> /** * Represents a observable *primitive* value wrapping. @@ -92,7 +95,7 @@ typealias ValueSerializer = KSerializer> * Note: The values are actually *boxed* because of the generic type T. * *Primitive* indicates only it is one of the 9 types mentioned above. */ -interface PrimitiveValue : Value +public interface PrimitiveValue : Value //// region PrimitiveValues CODEGEN //// @@ -100,77 +103,77 @@ interface PrimitiveValue : Value /** * Represents a non-null [Byte] value. */ -interface ByteValue : PrimitiveValue +public interface ByteValue : PrimitiveValue /** * Represents a non-null [Short] value. */ -interface ShortValue : PrimitiveValue +public interface ShortValue : PrimitiveValue /** * Represents a non-null [Int] value. */ -interface IntValue : PrimitiveValue +public interface IntValue : PrimitiveValue /** * Represents a non-null [Long] value. */ -interface LongValue : PrimitiveValue +public interface LongValue : PrimitiveValue /** * Represents a non-null [Float] value. */ -interface FloatValue : PrimitiveValue +public interface FloatValue : PrimitiveValue /** * Represents a non-null [Double] value. */ -interface DoubleValue : PrimitiveValue +public interface DoubleValue : PrimitiveValue /** * Represents a non-null [Char] value. */ -interface CharValue : PrimitiveValue +public interface CharValue : PrimitiveValue /** * Represents a non-null [Boolean] value. */ -interface BooleanValue : PrimitiveValue +public interface BooleanValue : PrimitiveValue /** * Represents a non-null [String] value. */ -interface StringValue : PrimitiveValue +public interface StringValue : PrimitiveValue //// endregion PrimitiveValues CODEGEN //// @ConsoleExperimentalAPI -interface CompositeValue : Value +public interface CompositeValue : Value /** * Superclass of [CompositeListValue], [PrimitiveListValue]. */ -interface ListValue : CompositeValue> +public interface ListValue : CompositeValue> /** * Elements can by anything, wrapped as [Value]. * @param E is not primitive types. */ -interface CompositeListValue : ListValue +public interface CompositeListValue : ListValue /** * Elements can only be primitives, not wrapped. * @param E is not primitive types. */ -interface PrimitiveListValue : ListValue +public interface PrimitiveListValue : ListValue //// region PrimitiveListValue CODEGEN //// -interface PrimitiveIntListValue : PrimitiveListValue -interface PrimitiveLongListValue : PrimitiveListValue +public interface PrimitiveIntListValue : PrimitiveListValue +public interface PrimitiveLongListValue : PrimitiveListValue // TODO + codegen //// endregion PrimitiveListValue CODEGEN //// @@ -179,25 +182,25 @@ interface PrimitiveLongListValue : PrimitiveListValue /** * Superclass of [CompositeSetValue], [PrimitiveSetValue]. */ -interface SetValue : CompositeValue> +public interface SetValue : CompositeValue> /** * Elements can by anything, wrapped as [Value]. * @param E is not primitive types. */ -interface CompositeSetValue : SetValue +public interface CompositeSetValue : SetValue /** * Elements can only be primitives, not wrapped. * @param E is not primitive types. */ -interface PrimitiveSetValue : SetValue +public interface PrimitiveSetValue : SetValue //// region PrimitiveSetValue CODEGEN //// -interface PrimitiveIntSetValue : PrimitiveSetValue -interface PrimitiveLongSetValue : PrimitiveSetValue +public interface PrimitiveIntSetValue : PrimitiveSetValue +public interface PrimitiveLongSetValue : PrimitiveSetValue // TODO + codegen //// endregion PrimitiveSetValue CODEGEN //// @@ -206,17 +209,17 @@ interface PrimitiveLongSetValue : PrimitiveSetValue /** * Superclass of [CompositeMapValue], [PrimitiveMapValue]. */ -interface MapValue : CompositeValue> +public interface MapValue : CompositeValue> -interface CompositeMapValue : MapValue +public interface CompositeMapValue : MapValue -interface PrimitiveMapValue : MapValue +public interface PrimitiveMapValue : MapValue //// region PrimitiveMapValue CODEGEN //// -interface PrimitiveIntIntMapValue : PrimitiveMapValue -interface PrimitiveIntLongMapValue : PrimitiveMapValue +public interface PrimitiveIntIntMapValue : PrimitiveMapValue +public interface PrimitiveIntLongMapValue : PrimitiveMapValue // TODO + codegen //// endregion PrimitiveSetValue CODEGEN //// diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/_PrimitiveValueDeclarations.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/_PrimitiveValueDeclarations.kt index cb2898a6f..dd5b0af2e 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/_PrimitiveValueDeclarations.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/_PrimitiveValueDeclarations.kt @@ -98,7 +98,6 @@ internal abstract class ShortValueImpl : ShortValue, SerializerAwareValue else value.hashCode() * 31 } } - internal abstract class IntValueImpl : IntValue, SerializerAwareValue, KSerializer, AbstractValueImpl { constructor() constructor(default: Int) { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/_Setting.value.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/_Setting.value.kt index 3b34fe942..8415b2f58 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/_Setting.value.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/_Setting.value.kt @@ -19,31 +19,31 @@ internal object BuiltInSerializerConstants { //// region BuiltInSerializerConstantsPrimitives CODEGEN //// @JvmStatic - val ByteSerializerDescriptor = Byte.serializer().descriptor + internal val ByteSerializerDescriptor = Byte.serializer().descriptor @JvmStatic - val ShortSerializerDescriptor = Short.serializer().descriptor + internal val ShortSerializerDescriptor = Short.serializer().descriptor @JvmStatic - val IntSerializerDescriptor = Int.serializer().descriptor + internal val IntSerializerDescriptor = Int.serializer().descriptor @JvmStatic - val LongSerializerDescriptor = Long.serializer().descriptor + internal val LongSerializerDescriptor = Long.serializer().descriptor @JvmStatic - val FloatSerializerDescriptor = Float.serializer().descriptor + internal val FloatSerializerDescriptor = Float.serializer().descriptor @JvmStatic - val DoubleSerializerDescriptor = Double.serializer().descriptor + internal val DoubleSerializerDescriptor = Double.serializer().descriptor @JvmStatic - val CharSerializerDescriptor = Char.serializer().descriptor + internal val CharSerializerDescriptor = Char.serializer().descriptor @JvmStatic - val BooleanSerializerDescriptor = Boolean.serializer().descriptor + internal val BooleanSerializerDescriptor = Boolean.serializer().descriptor @JvmStatic - val StringSerializerDescriptor = String.serializer().descriptor + internal val StringSerializerDescriptor = String.serializer().descriptor //// endregion BuiltInSerializerConstantsPrimitives CODEGEN //// } @@ -76,103 +76,86 @@ internal fun Setting.valueImpl(default: Byte): SerializerAwareValue { override fun onChanged() = this@valueImpl.onValueChanged(this) } } - internal fun Setting.byteValueImpl(): SerializerAwareValue { return object : ByteValueImpl() { override fun onChanged() = this@byteValueImpl.onValueChanged(this) } } - internal fun Setting.valueImpl(default: Short): SerializerAwareValue { return object : ShortValueImpl(default) { override fun onChanged() = this@valueImpl.onValueChanged(this) } } - internal fun Setting.shortValueImpl(): SerializerAwareValue { return object : ShortValueImpl() { override fun onChanged() = this@shortValueImpl.onValueChanged(this) } } - internal fun Setting.valueImpl(default: Int): SerializerAwareValue { return object : IntValueImpl(default) { override fun onChanged() = this@valueImpl.onValueChanged(this) } } - internal fun Setting.intValueImpl(): SerializerAwareValue { return object : IntValueImpl() { override fun onChanged() = this@intValueImpl.onValueChanged(this) } } - internal fun Setting.valueImpl(default: Long): SerializerAwareValue { return object : LongValueImpl(default) { override fun onChanged() = this@valueImpl.onValueChanged(this) } } - internal fun Setting.longValueImpl(): SerializerAwareValue { return object : LongValueImpl() { override fun onChanged() = this@longValueImpl.onValueChanged(this) } } - internal fun Setting.valueImpl(default: Float): SerializerAwareValue { return object : FloatValueImpl(default) { override fun onChanged() = this@valueImpl.onValueChanged(this) } } - internal fun Setting.floatValueImpl(): SerializerAwareValue { return object : FloatValueImpl() { override fun onChanged() = this@floatValueImpl.onValueChanged(this) } } - internal fun Setting.valueImpl(default: Double): SerializerAwareValue { return object : DoubleValueImpl(default) { override fun onChanged() = this@valueImpl.onValueChanged(this) } } - internal fun Setting.doubleValueImpl(): SerializerAwareValue { return object : DoubleValueImpl() { override fun onChanged() = this@doubleValueImpl.onValueChanged(this) } } - internal fun Setting.valueImpl(default: Char): SerializerAwareValue { return object : CharValueImpl(default) { override fun onChanged() = this@valueImpl.onValueChanged(this) } } - internal fun Setting.charValueImpl(): SerializerAwareValue { return object : CharValueImpl() { override fun onChanged() = this@charValueImpl.onValueChanged(this) } } - internal fun Setting.valueImpl(default: Boolean): SerializerAwareValue { return object : BooleanValueImpl(default) { override fun onChanged() = this@valueImpl.onValueChanged(this) } } - internal fun Setting.booleanValueImpl(): SerializerAwareValue { return object : BooleanValueImpl() { override fun onChanged() = this@booleanValueImpl.onValueChanged(this) } } - internal fun Setting.valueImpl(default: String): SerializerAwareValue { return object : StringValueImpl(default) { override fun onChanged() = this@valueImpl.onValueChanged(this) } } - internal fun Setting.stringValueImpl(): SerializerAwareValue { return object : StringValueImpl() { override fun onChanged() = this@stringValueImpl.onValueChanged(this) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/BotManagers.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/BotManagers.kt index f3234a2ec..a2e258099 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/BotManagers.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/BotManagers.kt @@ -17,7 +17,7 @@ import net.mamoe.mirai.contact.User /** * 判断此用户是否为 console 管理员 */ -val User.isManager: Boolean +public val User.isManager: Boolean get() = this.bot.managers.contains(this.id) internal fun Bot.addManager(long: Long): Boolean { @@ -25,9 +25,9 @@ internal fun Bot.addManager(long: Long): Boolean { return true } -fun Bot.removeManager(long: Long) { +public fun Bot.removeManager(long: Long) { TODO() } -val Bot.managers: List +public val Bot.managers: List get() = TODO() diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/ConsoleInput.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/ConsoleInput.kt index 75f66a8b0..7a48de899 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/ConsoleInput.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/ConsoleInput.kt @@ -7,47 +7,45 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ +@file:Suppress("INAPPLICABLE_JVM_NAME", "unused") + package net.mamoe.mirai.console.utils -import kotlinx.coroutines.* +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import net.mamoe.mirai.console.MiraiConsole -import java.util.concurrent.Executors -@Suppress("unused") -object ConsoleInput { - private val inputDispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher() +/** + * Console 输入. 由于 console 接管了 stdin, [readLine] 等操作需要在这里进行. + */ +public interface ConsoleInput { + /** + * 以 [提示][hint] 向用户索要一个输入 + */ + @JvmSynthetic + public suspend fun requestInput(hint: String): String /** - * 向用户索要一个Input - * 你需要提供一个hint(提示)并等待获取一个结果 - * 具体索要方式将根据frontend不同而不同 - * 如弹出框,或一行字 + * 以 [提示][hint] 向用户索要一个输入. 仅供 Java 调用者使用 */ - suspend fun requestInput( - hint: String - ): String { - return withContext(inputDispatcher) { - MiraiConsole.frontEnd.requestInput(hint) - } + @JvmName("requestInput") + @JavaFriendlyAPI + public fun requestInputBlocking(hint: String): String + + public companion object INSTANCE : ConsoleInput by ConsoleInputImpl { + public suspend inline fun MiraiConsole.requestInput(hint: String): String = ConsoleInput.requestInput(hint) } - - fun requestInputBlocking(hint: String): String = runBlocking { requestInput(hint) } - - /** - * asnyc获取 - */ - fun requestInputAsync( - scope: CoroutineScope, - hint: String - ): Deferred { - return scope.async { - requestInput(hint) - } - } - - suspend fun MiraiConsole.requestInput(hint: String): String = requestInput(hint) } +@Suppress("unused") +internal object ConsoleInputImpl : ConsoleInput { + private val inputLock = Mutex() + override suspend fun requestInput( + hint: String + ): String = inputLock.withLock { MiraiConsole.frontEnd.requestInput(hint) } - + @JavaFriendlyAPI + override fun requestInputBlocking(hint: String): String = runBlocking { requestInput(hint) } +} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/JavaFriendlyAPI.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/JavaFriendlyAPI.kt index beb8f9966..10155feb4 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/JavaFriendlyAPI.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/JavaFriendlyAPI.kt @@ -19,7 +19,7 @@ internal annotation class JavaFriendlyAPI @RequiresOptIn(level = RequiresOptIn.Level.ERROR) @Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR, CLASS, FUNCTION, PROPERTY) @MustBeDocumented -annotation class ConsoleInternalAPI( +public annotation class ConsoleInternalAPI( val message: String = "" ) @@ -33,6 +33,6 @@ annotation class ConsoleInternalAPI( @RequiresOptIn(level = RequiresOptIn.Level.WARNING) @Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR) @MustBeDocumented -annotation class ConsoleExperimentalAPI( +public annotation class ConsoleExperimentalAPI( val message: String = "" ) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/JavaPluginScheduler.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/JavaPluginScheduler.kt index af24ad333..3029fb80e 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/JavaPluginScheduler.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/JavaPluginScheduler.kt @@ -25,8 +25,8 @@ import kotlin.coroutines.CoroutineContext * * @see JavaPlugin.scheduler 获取实例 */ -class JavaPluginScheduler internal constructor(parentCoroutineContext: CoroutineContext) : CoroutineScope { - override val coroutineContext: CoroutineContext = +public class JavaPluginScheduler internal constructor(parentCoroutineContext: CoroutineContext) : CoroutineScope { + public override val coroutineContext: CoroutineContext = parentCoroutineContext + SupervisorJob(parentCoroutineContext[Job]) /** @@ -36,7 +36,7 @@ class JavaPluginScheduler internal constructor(parentCoroutineContext: Coroutine * * @see Future.cancel 取消这个任务 */ - fun repeating(intervalMs: Long, runnable: Runnable): Future { + public fun repeating(intervalMs: Long, runnable: Runnable): Future { return this.future { while (isActive) { withContext(Dispatchers.IO) { runnable.run() } @@ -51,7 +51,7 @@ class JavaPluginScheduler internal constructor(parentCoroutineContext: Coroutine * * 在延迟 [delayMillis] 后执行 [runnable] */ - fun delayed(delayMillis: Long, runnable: Runnable): CompletableFuture { + public fun delayed(delayMillis: Long, runnable: Runnable): CompletableFuture { return future { delay(delayMillis) withContext(Dispatchers.IO) { @@ -66,7 +66,7 @@ class JavaPluginScheduler internal constructor(parentCoroutineContext: Coroutine * * 在延迟 [delayMillis] 后执行 [runnable] */ - fun delayed(delayMillis: Long, runnable: Callable): CompletableFuture { + public fun delayed(delayMillis: Long, runnable: Callable): CompletableFuture { return future { delay(delayMillis) withContext(Dispatchers.IO) { runnable.call() } @@ -77,7 +77,7 @@ class JavaPluginScheduler internal constructor(parentCoroutineContext: Coroutine /** * 异步执行一个任务, 最终返回 [Future], 与 Java 使用方法无异, 但效率更高且可以在插件关闭时停止 */ - fun async(supplier: Callable): Future { + public fun async(supplier: Callable): Future { return future { withContext(Dispatchers.IO) { supplier.call() } } @@ -86,7 +86,7 @@ class JavaPluginScheduler internal constructor(parentCoroutineContext: Coroutine /** * 异步执行一个任务, 没有返回 */ - fun async(runnable: Runnable): Future { + public fun async(runnable: Runnable): Future { return future { withContext(Dispatchers.IO) { runnable.run() } null diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/ResourceContainer.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/ResourceContainer.kt index 6f8e8b4c5..32398402a 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/ResourceContainer.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/ResourceContainer.kt @@ -10,26 +10,26 @@ import kotlin.reflect.KClass /** * 资源容器. */ -interface ResourceContainer { +public interface ResourceContainer { /** * 获取一个资源文件 */ - fun getResourceAsStream(name: String): InputStream + public fun getResourceAsStream(name: String): InputStream /** * 读取一个资源文件并以 [Charsets.UTF_8] 编码为 [String] */ @JvmDefault - fun getResource(name: String): String = getResource(name, Charsets.UTF_8) + public fun getResource(name: String): String = getResource(name, Charsets.UTF_8) /** * 读取一个资源文件并以 [charset] 编码为 [String] */ @JvmDefault - fun getResource(name: String, charset: Charset): String = + public fun getResource(name: String, charset: Charset): String = this.getResourceAsStream(name).use { it.readBytes() }.encodeToString() - companion object { + public companion object { /** * 使用 [Class.getResourceAsStream] 读取资源文件 * @@ -37,22 +37,23 @@ interface ResourceContainer { */ @JvmStatic @JavaFriendlyAPI - fun byClass(clazz: Class<*>): ResourceContainer = clazz.asResourceContainer() + public fun byClass(clazz: Class<*>): ResourceContainer = clazz.asResourceContainer() } } +/** + * 使用 [Class.getResourceAsStream] 读取资源文件 + */ +public fun KClass<*>.asResourceContainer(): ResourceContainer = ClassAsResourceContainer(this.java) + +/** + * 使用 [Class.getResourceAsStream] 读取资源文件 + */ +public fun Class<*>.asResourceContainer(): ResourceContainer = ClassAsResourceContainer(this) + + internal class ClassAsResourceContainer( private val clazz: Class<*> ) : ResourceContainer { override fun getResourceAsStream(name: String): InputStream = clazz.getResourceAsStream(name) -} - -/** - * 使用 [Class.getResourceAsStream] 读取资源文件 - */ -fun KClass<*>.asResourceContainer(): ResourceContainer = ClassAsResourceContainer(this.java) - -/** - * 使用 [Class.getResourceAsStream] 读取资源文件 - */ -fun Class<*>.asResourceContainer(): ResourceContainer = ClassAsResourceContainer(this) \ No newline at end of file +} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/retryCatching.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/retryCatching.kt index 2cdb0b423..8b2d02e9c 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/retryCatching.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/retryCatching.kt @@ -14,34 +14,25 @@ package net.mamoe.mirai.console.utils import org.jetbrains.annotations.Range import kotlin.contracts.InvocationKind import kotlin.contracts.contract +import kotlin.internal.InlineOnly /** * 执行 [n] 次 [block], 在第一次成功时返回执行结果, 在捕获到异常时返回异常. */ -@kotlin.internal.InlineOnly -inline fun retryCatching(n: @Range(from = 1, to = Long.MAX_VALUE) Int, block: () -> R): Result { +@InlineOnly +public inline fun retryCatching(n: @Range(from = 1, to = Int.MAX_VALUE.toLong()) Int, block: () -> R): Result { contract { callsInPlace(block, InvocationKind.AT_LEAST_ONCE) } - require(n >= 0) { "param n for retryCatching must not be negative" } + require(n >= 1) { "param n for retryCatching must not be negative" } var exception: Throwable? = null repeat(n) { try { return Result.success(block()) } catch (e: Throwable) { - exception?.addSuppressedMirai(e) + exception?.addSuppressed(e) exception = e } } return Result.failure(exception!!) -} - -@PublishedApi -internal fun Throwable.addSuppressedMirai(e: Throwable) { - if (e === this) { - return - } - kotlin.runCatching { - this.addSuppressed(e) - } } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index c507171cc..b9e9bbb47 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -14,7 +14,7 @@ object Versions { const val consoleTerminal = "0.1.0" const val consolePure = "0.1-dev-1" - const val kotlin = "1.3.72" + const val kotlin = "1.4-M3" const val coroutines = "1.3.7" const val serialization = "0.20.0" const val ktor = "1.3.2"