mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-10 18:40:15 +08:00
Merge branch 'master' into command
# Conflicts: # backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt
This commit is contained in:
commit
2104cc2192
6
backend/codegen/README.md
Normal file
6
backend/codegen/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Mirai Console - Backend.codegen
|
||||||
|
|
||||||
|
后端代码生成模块,用于最小化重复代码的人工成本。
|
||||||
|
|
||||||
|
- `MessageScope` 代码生成: [MessageScopeCodegen.kt: Line 33](src/main/kotlin/net/mamoe/mirai/console/codegen/MessageScopeCodegen.kt#L33)
|
||||||
|
- `Value` 和 `PluginData` 相关代码生成: [ValueSettingCodegen.kt: Line 18](src/main/kotlin/net/mamoe/mirai/console/codegen/ValuePluginDataCodegen.kt#L18)
|
3
backend/mirai-console/README.md
Normal file
3
backend/mirai-console/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Mirai Console - Backend
|
||||||
|
|
||||||
|
Mirai Console 后端模块. 发布为 `net.mamoe:mirai-console`.
|
@ -65,11 +65,9 @@ dependencies {
|
|||||||
compileAndTestRuntime(kotlinx("serialization-core", Versions.serialization))
|
compileAndTestRuntime(kotlinx("serialization-core", Versions.serialization))
|
||||||
compileAndTestRuntime(kotlin("reflect"))
|
compileAndTestRuntime(kotlin("reflect"))
|
||||||
|
|
||||||
implementation("org.jetbrains:annotations:19.0.0")
|
smartImplementation("net.mamoe.yamlkt:yamlkt:${Versions.yamlkt}")
|
||||||
|
smartImplementation("org.jetbrains:annotations:19.0.0")
|
||||||
smartApi(kotlinx("coroutines-jdk8", Versions.coroutines))
|
smartApi(kotlinx("coroutines-jdk8", Versions.coroutines))
|
||||||
smartApi("net.mamoe.yamlkt:yamlkt:${Versions.yamlkt}")
|
|
||||||
smartApi("com.vdurmont:semver4j:3.1.0")
|
|
||||||
|
|
||||||
testApi("net.mamoe:mirai-core-qqandroid:${Versions.core}")
|
testApi("net.mamoe:mirai-core-qqandroid:${Versions.core}")
|
||||||
testApi(kotlin("stdlib-jdk8"))
|
testApi(kotlin("stdlib-jdk8"))
|
||||||
@ -102,8 +100,8 @@ tasks {
|
|||||||
})"""
|
})"""
|
||||||
}
|
}
|
||||||
.replace(
|
.replace(
|
||||||
Regex("""val version: Semver = Semver\(".*", Semver.SemverType.LOOSE\)""")
|
Regex("""val version: SemVersion = SemVersion.parse\(".*"\)""")
|
||||||
) { """val version: Semver = Semver("${project.version}", Semver.SemverType.LOOSE)""" }
|
) { """val version: SemVersion = SemVersion.parse("${project.version}")""" }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console
|
package net.mamoe.mirai.console
|
||||||
|
|
||||||
import com.vdurmont.semver4j.Semver
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
@ -29,6 +28,7 @@ import net.mamoe.mirai.console.plugin.loader.PluginLoader
|
|||||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||||
import net.mamoe.mirai.console.util.ConsoleInternalApi
|
import net.mamoe.mirai.console.util.ConsoleInternalApi
|
||||||
import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScopeContext
|
import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScopeContext
|
||||||
|
import net.mamoe.mirai.console.util.SemVersion
|
||||||
import net.mamoe.mirai.utils.BotConfiguration
|
import net.mamoe.mirai.utils.BotConfiguration
|
||||||
import net.mamoe.mirai.utils.MiraiLogger
|
import net.mamoe.mirai.utils.MiraiLogger
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -79,7 +79,7 @@ public interface MiraiConsole : CoroutineScope {
|
|||||||
/**
|
/**
|
||||||
* 此 Console 后端版本号
|
* 此 Console 后端版本号
|
||||||
*/
|
*/
|
||||||
public val version: Semver
|
public val version: SemVersion
|
||||||
|
|
||||||
|
|
||||||
@ConsoleExperimentalApi
|
@ConsoleExperimentalApi
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console
|
package net.mamoe.mirai.console
|
||||||
|
|
||||||
import com.vdurmont.semver4j.Semver
|
import net.mamoe.mirai.console.util.SemVersion
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 有关前端实现的信息
|
* 有关前端实现的信息
|
||||||
@ -28,7 +29,7 @@ public interface MiraiConsoleFrontEndDescription {
|
|||||||
/**
|
/**
|
||||||
* 此前端实现的名称
|
* 此前端实现的名称
|
||||||
*/
|
*/
|
||||||
public val version: Semver
|
public val version: SemVersion
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 兼容的 [MiraiConsole] 后端版本号
|
* 兼容的 [MiraiConsole] 后端版本号
|
||||||
@ -37,7 +38,7 @@ public interface MiraiConsoleFrontEndDescription {
|
|||||||
*
|
*
|
||||||
* 返回 `null` 表示禁止 [MiraiConsole] 后端检查版本兼容性.
|
* 返回 `null` 表示禁止 [MiraiConsole] 后端检查版本兼容性.
|
||||||
*/
|
*/
|
||||||
public val compatibleBackendVersion: Semver? get() = null
|
public val compatibleBackendVersion: SemVersion? get() = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回显示在 [MiraiConsole] 启动时的信息
|
* 返回显示在 [MiraiConsole] 启动时的信息
|
||||||
|
@ -21,6 +21,8 @@ import net.mamoe.mirai.console.permission.PermitteeId
|
|||||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||||
import net.mamoe.mirai.contact.*
|
import net.mamoe.mirai.contact.*
|
||||||
import net.mamoe.mirai.message.data.MessageContent
|
import net.mamoe.mirai.message.data.MessageContent
|
||||||
|
import net.mamoe.mirai.message.data.Image
|
||||||
|
import net.mamoe.mirai.message.data.PlainText
|
||||||
import kotlin.internal.LowPriorityInOverloadResolution
|
import kotlin.internal.LowPriorityInOverloadResolution
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.full.isSubclassOf
|
import kotlin.reflect.full.isSubclassOf
|
||||||
@ -76,6 +78,9 @@ public interface CommandArgumentContext {
|
|||||||
Double::class with DoubleArgumentParser
|
Double::class with DoubleArgumentParser
|
||||||
Float::class with FloatArgumentParser
|
Float::class with FloatArgumentParser
|
||||||
|
|
||||||
|
Image::class with ImageArgumentParser
|
||||||
|
PlainText::class with PlainTextArgumentParser
|
||||||
|
|
||||||
Contact::class with ExistingContactArgumentParser
|
Contact::class with ExistingContactArgumentParser
|
||||||
User::class with ExistingUserArgumentParser
|
User::class with ExistingUserArgumentParser
|
||||||
Member::class with ExistingMemberArgumentParser
|
Member::class with ExistingMemberArgumentParser
|
||||||
|
@ -77,6 +77,35 @@ public object StringArgumentParser : InternalCommandArgumentParserExtensions<Str
|
|||||||
public override fun parse(raw: String, sender: CommandSender): String = raw
|
public override fun parse(raw: String, sender: CommandSender): String = raw
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析 [String] 通过 [Image].
|
||||||
|
*/
|
||||||
|
public object ImageArgumentParser : InternalCommandArgumentParserExtensions<Image> {
|
||||||
|
public override fun parse(raw: String, sender: CommandSender): Image {
|
||||||
|
return kotlin.runCatching {
|
||||||
|
Image(raw)
|
||||||
|
}.getOrElse {
|
||||||
|
illegalArgument("无法解析 $raw 为图片.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun parse(raw: MessageContent, sender: CommandSender): Image {
|
||||||
|
if (raw is Image) return raw
|
||||||
|
return super.parse(raw, sender)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object PlainTextArgumentParser : InternalCommandArgumentParserExtensions<PlainText> {
|
||||||
|
public override fun parse(raw: String, sender: CommandSender): PlainText {
|
||||||
|
return PlainText(raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun parse(raw: MessageContent, sender: CommandSender): PlainText {
|
||||||
|
if (raw is PlainText) return raw
|
||||||
|
return super.parse(raw, sender)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当字符串内容为(不区分大小写) "true", "yes", "enabled"
|
* 当字符串内容为(不区分大小写) "true", "yes", "enabled"
|
||||||
*/
|
*/
|
||||||
|
@ -24,7 +24,7 @@ import kotlinx.coroutines.Job
|
|||||||
* @see AutoSavePluginData
|
* @see AutoSavePluginData
|
||||||
*/
|
*/
|
||||||
public open class AutoSavePluginConfig : AutoSavePluginData, PluginConfig {
|
public open class AutoSavePluginConfig : AutoSavePluginData, PluginConfig {
|
||||||
@Deprecated("请手动指定保存名称. 此构造器将在 1.0.0 删除", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("AutoSavePluginConfig(\"改成保存的名称\")"))
|
@Deprecated("请手动指定保存名称. 此构造器将在 1.0.0 删除", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("AutoSavePluginConfig(\"把我改成保存名称\")"))
|
||||||
@Suppress("DEPRECATION_ERROR")
|
@Suppress("DEPRECATION_ERROR")
|
||||||
public constructor() : super()
|
public constructor() : super()
|
||||||
|
|
||||||
|
@ -30,7 +30,8 @@ import kotlin.reflect.full.findAnnotation
|
|||||||
* @see PluginData
|
* @see PluginData
|
||||||
*/
|
*/
|
||||||
public open class AutoSavePluginData private constructor(
|
public open class AutoSavePluginData private constructor(
|
||||||
@Suppress("UNUSED_PARAMETER") primaryConstructorMark: Any?
|
// KEEP THIS PRIMARY CONSTRUCTOR FOR FUTURE USE: WE'LL SUPPORT SERIALIZERS_MODULE FOR POLYMORPHISM
|
||||||
|
@Suppress("UNUSED_PARAMETER") primaryConstructorMark: Any?,
|
||||||
) : AbstractPluginData() {
|
) : AbstractPluginData() {
|
||||||
private lateinit var owner_: AutoSavePluginDataHolder
|
private lateinit var owner_: AutoSavePluginDataHolder
|
||||||
private val autoSaveIntervalMillis_: LongRange get() = owner_.autoSaveIntervalMillis
|
private val autoSaveIntervalMillis_: LongRange get() = owner_.autoSaveIntervalMillis
|
||||||
@ -45,7 +46,7 @@ public open class AutoSavePluginData private constructor(
|
|||||||
_saveName = saveName
|
_saveName = saveName
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("请手动指定保存名称. 此构造器将在 1.0.0 删除", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("AutoSavePluginConfig"))
|
@Deprecated("请手动指定保存名称. 此构造器将在 1.0.0 删除", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("AutoSavePluginData(\"把我改成保存名称\")"))
|
||||||
public constructor() : this(null) {
|
public constructor() : this(null) {
|
||||||
val clazz = this::class
|
val clazz = this::class
|
||||||
_saveName = clazz.findAnnotation<ValueName>()?.value
|
_saveName = clazz.findAnnotation<ValueName>()?.value
|
||||||
|
@ -9,14 +9,12 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.data
|
package net.mamoe.mirai.console.data
|
||||||
|
|
||||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 序列化之后的名称.
|
* 序列化之后的名称.
|
||||||
*
|
*
|
||||||
* 例:
|
* 例:
|
||||||
* ```
|
* ```
|
||||||
* object AccountPluginData : PluginData by ... {
|
* object AccountPluginData : AutoSavePluginData() {
|
||||||
* @ValueName("info")
|
* @ValueName("info")
|
||||||
* val map: Map<String, String> by value("a" to "b")
|
* val map: Map<String, String> by value("a" to "b")
|
||||||
* }
|
* }
|
||||||
@ -28,8 +26,10 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
|||||||
* map:
|
* map:
|
||||||
* a: b
|
* a: b
|
||||||
* ```
|
* ```
|
||||||
|
*
|
||||||
|
* @see PluginData
|
||||||
|
* @see Value
|
||||||
*/
|
*/
|
||||||
@ConsoleExperimentalApi
|
|
||||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
public annotation class ValueName(val value: String)
|
public annotation class ValueName(val value: String)
|
||||||
|
@ -38,7 +38,7 @@ import net.mamoe.mirai.console.data.PluginData
|
|||||||
* @see PluginConfig
|
* @see PluginConfig
|
||||||
*/
|
*/
|
||||||
public abstract class JAutoSavePluginConfig : AutoSavePluginConfig, PluginConfig {
|
public abstract class JAutoSavePluginConfig : AutoSavePluginConfig, PluginConfig {
|
||||||
@Deprecated("请手动指定保存名称. 此构造器将在 1.0.0 删除", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("AutoSavePluginConfig(\"改成保存的名称\")"))
|
@Deprecated("请手动指定保存名称. 此构造器将在 1.0.0 删除", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("JAutoSavePluginConfig(\"把我改成保存名称\")"))
|
||||||
@Suppress("DEPRECATION_ERROR")
|
@Suppress("DEPRECATION_ERROR")
|
||||||
public constructor() : super()
|
public constructor() : super()
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ import kotlin.reflect.full.createType
|
|||||||
* @see PluginData
|
* @see PluginData
|
||||||
*/
|
*/
|
||||||
public abstract class JAutoSavePluginData : AutoSavePluginData, PluginConfig {
|
public abstract class JAutoSavePluginData : AutoSavePluginData, PluginConfig {
|
||||||
@Deprecated("请手动指定保存名称. 此构造器将在 1.0.0 删除", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("AutoSavePluginConfig(\"改成保存的名称\")"))
|
@Deprecated("请手动指定保存名称. 此构造器将在 1.0.0 删除", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("JAutoSavePluginData(\"把我改成保存名称\")"))
|
||||||
@Suppress("DEPRECATION_ERROR")
|
@Suppress("DEPRECATION_ERROR")
|
||||||
public constructor() : super()
|
public constructor() : super()
|
||||||
|
|
||||||
|
@ -9,13 +9,13 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.internal
|
package net.mamoe.mirai.console.internal
|
||||||
|
|
||||||
import com.vdurmont.semver4j.Semver
|
import net.mamoe.mirai.console.util.SemVersion
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
internal object MiraiConsoleBuildConstants { // auto-filled on build (task :mirai-console:fillBuildConstants)
|
internal object MiraiConsoleBuildConstants { // auto-filled on build (task :mirai-console:fillBuildConstants)
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val buildDate: Instant = Instant.ofEpochSecond(1600522812)
|
val buildDate: Instant = Instant.ofEpochSecond(1600596035)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val version: Semver = Semver("1.0-RC-dev-28", Semver.SemverType.LOOSE)
|
val version: SemVersion = SemVersion("1.0-RC-dev-28")
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.internal
|
package net.mamoe.mirai.console.internal
|
||||||
|
|
||||||
import com.vdurmont.semver4j.Semver
|
|
||||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
@ -47,6 +46,7 @@ import net.mamoe.mirai.console.plugin.jvm.AbstractJvmPlugin
|
|||||||
import net.mamoe.mirai.console.plugin.loader.PluginLoader
|
import net.mamoe.mirai.console.plugin.loader.PluginLoader
|
||||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||||
import net.mamoe.mirai.console.util.ConsoleInput
|
import net.mamoe.mirai.console.util.ConsoleInput
|
||||||
|
import net.mamoe.mirai.console.util.SemVersion
|
||||||
import net.mamoe.mirai.utils.*
|
import net.mamoe.mirai.utils.*
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@ -66,7 +66,7 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
|
|||||||
|
|
||||||
private val instance: MiraiConsoleImplementation by MiraiConsoleImplementation.Companion::instance
|
private val instance: MiraiConsoleImplementation by MiraiConsoleImplementation.Companion::instance
|
||||||
override val buildDate: Instant by MiraiConsoleBuildConstants::buildDate
|
override val buildDate: Instant by MiraiConsoleBuildConstants::buildDate
|
||||||
override val version: Semver by MiraiConsoleBuildConstants::version
|
override val version: SemVersion by MiraiConsoleBuildConstants::version
|
||||||
override val rootPath: Path by instance::rootPath
|
override val rootPath: Path by instance::rootPath
|
||||||
override val frontEndDescription: MiraiConsoleFrontEndDescription by instance::frontEndDescription
|
override val frontEndDescription: MiraiConsoleFrontEndDescription by instance::frontEndDescription
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.internal.data
|
package net.mamoe.mirai.console.internal.data
|
||||||
|
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import net.mamoe.mirai.console.MiraiConsole
|
||||||
import net.mamoe.mirai.console.data.*
|
import net.mamoe.mirai.console.data.*
|
||||||
import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip
|
import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip
|
||||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||||
@ -59,23 +61,28 @@ internal open class MultiFilePluginDataStorageImpl(
|
|||||||
return file.toFile().also { it.createNewFile() }
|
return file.toFile().also { it.createNewFile() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConsoleExperimentalApi
|
private val json = Json {
|
||||||
public override fun store(holder: PluginDataHolder, instance: PluginData) {
|
|
||||||
val yaml =/* if (instance.saveName == "PermissionService") Json {
|
|
||||||
prettyPrint = true
|
prettyPrint = true
|
||||||
ignoreUnknownKeys = true
|
ignoreUnknownKeys = true
|
||||||
isLenient = true
|
isLenient = true
|
||||||
allowStructuredMapKeys = true
|
allowStructuredMapKeys = true
|
||||||
} /*Yaml(
|
}
|
||||||
configuration = YamlConfiguration(
|
|
||||||
mapSerialization = YamlConfiguration.MapSerialization.FLOW_MAP,
|
private val yaml = Yaml.default
|
||||||
listSerialization = YamlConfiguration.ListSerialization.FLOW_SEQUENCE,
|
|
||||||
classSerialization = YamlConfiguration.MapSerialization.FLOW_MAP
|
@ConsoleExperimentalApi
|
||||||
)
|
public override fun store(holder: PluginDataHolder, instance: PluginData) {
|
||||||
)*/ else */Yaml.default
|
|
||||||
getPluginDataFile(holder, instance).writeText(
|
getPluginDataFile(holder, instance).writeText(
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
yaml.encodeToString(instance.updaterSerializer, Unit)
|
yaml.encodeToString(instance.updaterSerializer, Unit)
|
||||||
|
}.recoverCatching {
|
||||||
|
// Just use mainLogger for convenience.
|
||||||
|
MiraiConsole.mainLogger.warning(
|
||||||
|
"Could not save ${instance.saveName} in YAML format due to exception in YAML encoder. " +
|
||||||
|
"Please report this exception and relevant configurations to https://github.com/mamoe/mirai-console/issues/new",
|
||||||
|
it
|
||||||
|
)
|
||||||
|
json.encodeToString(instance.updaterSerializer, Unit)
|
||||||
}.getOrElse {
|
}.getOrElse {
|
||||||
throw IllegalStateException("Exception while saving $instance, saveName=${instance.saveName}", it)
|
throw IllegalStateException("Exception while saving $instance, saveName=${instance.saveName}", it)
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import net.mamoe.mirai.console.plugin.loader.PluginLoadException
|
|||||||
import net.mamoe.mirai.console.plugin.loader.PluginLoader
|
import net.mamoe.mirai.console.plugin.loader.PluginLoader
|
||||||
import net.mamoe.mirai.console.plugin.name
|
import net.mamoe.mirai.console.plugin.name
|
||||||
import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScope
|
import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScope
|
||||||
|
import net.mamoe.mirai.console.util.SemVersion.Companion.contains
|
||||||
import net.mamoe.mirai.utils.info
|
import net.mamoe.mirai.utils.info
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
@ -26,19 +26,63 @@ internal object SemVersionInternal {
|
|||||||
private val versionMathRange =
|
private val versionMathRange =
|
||||||
"""\[([0-9]+(\.[0-9]+)+(|[\-+].+))\s*\,\s*([0-9]+(\.[0-9]+)+(|[\-+].+))\]""".toRegex()
|
"""\[([0-9]+(\.[0-9]+)+(|[\-+].+))\s*\,\s*([0-9]+(\.[0-9]+)+(|[\-+].+))\]""".toRegex()
|
||||||
private val versionRule = """^((\>\=)|(\<\=)|(\=)|(\>)|(\<))\s*([0-9]+(\.[0-9]+)+(|[\-+].+))$""".toRegex()
|
private val versionRule = """^((\>\=)|(\<\=)|(\=)|(\>)|(\<))\s*([0-9]+(\.[0-9]+)+(|[\-+].+))$""".toRegex()
|
||||||
private fun Collection<*>.dump() {
|
|
||||||
forEachIndexed { index, value ->
|
private val SEM_VERSION_REGEX =
|
||||||
println("$index, $value")
|
"""^(0|[1-9]\d*)\.(0|[1-9]\d*)(?:\.(0|[1-9]\d*))?(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$""".toRegex()
|
||||||
|
|
||||||
|
/** 解析核心版本号, eg: `1.0.0` -> IntArray[1, 0, 0] */
|
||||||
|
@JvmStatic
|
||||||
|
private fun String.parseMainVersion(): IntArray =
|
||||||
|
split('.').map { it.toInt() }.toIntArray()
|
||||||
|
|
||||||
|
|
||||||
|
fun parse(version: String): SemVersion {
|
||||||
|
if (!SEM_VERSION_REGEX.matches(version)) {
|
||||||
|
throw IllegalArgumentException("`$version` not a valid version")
|
||||||
}
|
}
|
||||||
|
var mainVersionEnd = 0
|
||||||
|
kotlin.run {
|
||||||
|
val iterator = version.iterator()
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
val next = iterator.next()
|
||||||
|
if (next == '-' || next == '+') {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
mainVersionEnd++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var identifier: String? = null
|
||||||
|
var metadata: String? = null
|
||||||
|
if (mainVersionEnd != version.length) {
|
||||||
|
when (version[mainVersionEnd]) {
|
||||||
|
'-' -> {
|
||||||
|
val metadataSplitter = version.indexOf('+', startIndex = mainVersionEnd)
|
||||||
|
if (metadataSplitter == -1) {
|
||||||
|
identifier = version.substring(mainVersionEnd + 1)
|
||||||
|
} else {
|
||||||
|
identifier = version.substring(mainVersionEnd + 1, metadataSplitter)
|
||||||
|
metadata = version.substring(metadataSplitter + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'+' -> {
|
||||||
|
metadata = version.substring(mainVersionEnd + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SemVersion(
|
||||||
|
mainVersion = version.substring(0, mainVersionEnd).parseMainVersion(),
|
||||||
|
identifier = identifier,
|
||||||
|
metadata = metadata
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
private fun String.parseRule(): SemVersion.RangeRequirement {
|
private fun String.parseRule(): SemVersion.Requirement {
|
||||||
val trimmed = trim()
|
val trimmed = trim()
|
||||||
if (directVersion.matches(trimmed)) {
|
if (directVersion.matches(trimmed)) {
|
||||||
val parsed = SemVersion.parse(trimmed)
|
val parsed = SemVersion.invoke(trimmed)
|
||||||
return SemVersion.RangeRequirement {
|
return object : SemVersion.Requirement {
|
||||||
it.compareTo(parsed) == 0
|
override fun test(version: SemVersion): Boolean = version.compareTo(parsed) == 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (versionSelect.matches(trimmed)) {
|
if (versionSelect.matches(trimmed)) {
|
||||||
@ -47,62 +91,67 @@ internal object SemVersionInternal {
|
|||||||
.replace("x", ".+") +
|
.replace("x", ".+") +
|
||||||
"$"
|
"$"
|
||||||
).toRegex()
|
).toRegex()
|
||||||
return SemVersion.RangeRequirement {
|
return object : SemVersion.Requirement {
|
||||||
regex.matches(it.toString())
|
override fun test(version: SemVersion): Boolean = regex.matches(version.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(versionRange.matchEntire(trimmed) ?: versionMathRange.matchEntire(trimmed))?.let { range ->
|
(versionRange.matchEntire(trimmed) ?: versionMathRange.matchEntire(trimmed))?.let { range ->
|
||||||
var start = SemVersion.parse(range.groupValues[1])
|
var start = SemVersion.invoke(range.groupValues[1])
|
||||||
var end = SemVersion.parse(range.groupValues[4])
|
var end = SemVersion.invoke(range.groupValues[4])
|
||||||
if (start > end) {
|
if (start > end) {
|
||||||
val c = end
|
val c = end
|
||||||
end = start
|
end = start
|
||||||
start = c
|
start = c
|
||||||
}
|
}
|
||||||
val compareRange = start..end
|
val compareRange = start..end
|
||||||
return SemVersion.RangeRequirement {
|
return object : SemVersion.Requirement {
|
||||||
it in compareRange
|
override fun test(version: SemVersion): Boolean = version in compareRange
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
versionRule.matchEntire(trimmed)?.let { result ->
|
versionRule.matchEntire(trimmed)?.let { result ->
|
||||||
val operator = result.groupValues[1]
|
val operator = result.groupValues[1]
|
||||||
val version = SemVersion.parse(result.groupValues[7])
|
val version1 = SemVersion.invoke(result.groupValues[7])
|
||||||
return when (operator) {
|
return when (operator) {
|
||||||
">=" -> {
|
">=" -> {
|
||||||
SemVersion.RangeRequirement { it >= version }
|
object : SemVersion.Requirement {
|
||||||
|
override fun test(version: SemVersion): Boolean = version >= version1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
">" -> {
|
">" -> {
|
||||||
SemVersion.RangeRequirement { it > version }
|
object : SemVersion.Requirement {
|
||||||
|
override fun test(version: SemVersion): Boolean = version > version1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"<=" -> {
|
"<=" -> {
|
||||||
SemVersion.RangeRequirement { it <= version }
|
object : SemVersion.Requirement {
|
||||||
|
override fun test(version: SemVersion): Boolean = version <= version1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"<" -> {
|
"<" -> {
|
||||||
SemVersion.RangeRequirement { it < version }
|
object : SemVersion.Requirement {
|
||||||
|
override fun test(version: SemVersion): Boolean = version < version1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"=" -> {
|
"=" -> {
|
||||||
SemVersion.RangeRequirement { it.compareTo(version) == 0 }
|
object : SemVersion.Requirement {
|
||||||
}
|
override fun test(version: SemVersion): Boolean = version.compareTo(version1) == 0
|
||||||
else -> throw AssertionError("operator=$operator, version=$version")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw UnsupportedOperationException("Cannot parse $this")
|
else -> error("operator=$operator, version=$version1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw IllegalArgumentException("Cannot parse $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun SemVersion.RangeRequirement.withRule(rule: String): SemVersion.RangeRequirement {
|
private fun SemVersion.Requirement.withRule(rule: String): SemVersion.Requirement {
|
||||||
return object : SemVersion.RangeRequirement {
|
return object : SemVersion.Requirement {
|
||||||
override fun check(version: SemVersion): Boolean {
|
override fun test(version: SemVersion): Boolean = this@withRule.test(version)
|
||||||
return this@withRule.check(version)
|
override fun toString(): String = rule
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return rule
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun parseRangeRequirement(requirement: String): SemVersion.RangeRequirement {
|
fun parseRangeRequirement(requirement: String): SemVersion.Requirement {
|
||||||
if (requirement.isBlank()) {
|
if (requirement.isBlank()) {
|
||||||
throw IllegalArgumentException("Invalid requirement: Empty requirement rule.")
|
throw IllegalArgumentException("Invalid requirement: Empty requirement rule.")
|
||||||
}
|
}
|
||||||
@ -110,33 +159,35 @@ internal object SemVersionInternal {
|
|||||||
it.parseRule().withRule(it)
|
it.parseRule().withRule(it)
|
||||||
}.let { checks ->
|
}.let { checks ->
|
||||||
if (checks.size == 1) return checks[0]
|
if (checks.size == 1) return checks[0]
|
||||||
SemVersion.RangeRequirement {
|
object : SemVersion.Requirement {
|
||||||
|
override fun test(version: SemVersion): Boolean {
|
||||||
checks.forEach { rule ->
|
checks.forEach { rule ->
|
||||||
if (rule.check(it)) return@RangeRequirement true
|
if (rule.test(version)) return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return@RangeRequirement false
|
|
||||||
}.withRule(requirement)
|
}.withRule(requirement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun SemVersion.compareInternal(other: SemVersion): Int {
|
fun compareInternal(source: SemVersion, other: SemVersion): Int {
|
||||||
// ignored metadata in comparing
|
// ignored metadata in comparing
|
||||||
|
|
||||||
// If $this equals $other (without metadata),
|
// If $this equals $other (without metadata),
|
||||||
// return same.
|
// return same.
|
||||||
if (other.mainVersion.contentEquals(mainVersion) && identifier == other.identifier) {
|
if (other.mainVersion.contentEquals(source.mainVersion) && source.identifier == other.identifier) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
fun IntArray.getSafe(index: Int) = getOrElse(index) { 0 }
|
fun IntArray.getSafe(index: Int) = getOrElse(index) { 0 }
|
||||||
|
|
||||||
// Compare main-version
|
// Compare main-version
|
||||||
for (index in 0 until (max(mainVersion.size, other.mainVersion.size))) {
|
for (index in 0 until (max(source.mainVersion.size, other.mainVersion.size))) {
|
||||||
val result = mainVersion.getSafe(index).compareTo(other.mainVersion.getSafe(index))
|
val result = source.mainVersion.getSafe(index).compareTo(other.mainVersion.getSafe(index))
|
||||||
if (result != 0) return result
|
if (result != 0) return result
|
||||||
}
|
}
|
||||||
// If main-versions are same.
|
// If main-versions are same.
|
||||||
var identifier0 = identifier
|
var identifier0 = source.identifier
|
||||||
var identifier1 = other.identifier
|
var identifier1 = other.identifier
|
||||||
// If anyone doesn't have the identifier...
|
// If anyone doesn't have the identifier...
|
||||||
if (identifier0 == null || identifier1 == null) {
|
if (identifier0 == null || identifier1 == null) {
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.plugin
|
package net.mamoe.mirai.console.plugin
|
||||||
|
|
||||||
import com.vdurmont.semver4j.Semver
|
|
||||||
import net.mamoe.mirai.console.command.CommandOwner
|
import net.mamoe.mirai.console.command.CommandOwner
|
||||||
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.disable
|
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.disable
|
||||||
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.enable
|
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.enable
|
||||||
@ -20,6 +19,7 @@ import net.mamoe.mirai.console.plugin.description.PluginDependency
|
|||||||
import net.mamoe.mirai.console.plugin.description.PluginDescription
|
import net.mamoe.mirai.console.plugin.description.PluginDescription
|
||||||
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
|
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
|
||||||
import net.mamoe.mirai.console.plugin.loader.PluginLoader
|
import net.mamoe.mirai.console.plugin.loader.PluginLoader
|
||||||
|
import net.mamoe.mirai.console.util.SemVersion
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表示一个 mirai-console 插件.
|
* 表示一个 mirai-console 插件.
|
||||||
@ -62,7 +62,7 @@ public inline val Plugin.name: String get() = this.description.name
|
|||||||
/**
|
/**
|
||||||
* 获取 [PluginDescription.version]
|
* 获取 [PluginDescription.version]
|
||||||
*/
|
*/
|
||||||
public inline val Plugin.version: Semver get() = this.description.version
|
public inline val Plugin.version: SemVersion get() = this.description.version
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 [PluginDescription.info]
|
* 获取 [PluginDescription.info]
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.plugin.description
|
package net.mamoe.mirai.console.plugin.description
|
||||||
|
|
||||||
|
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||||
|
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.PLUGIN_ID
|
||||||
|
import net.mamoe.mirai.console.util.SemVersion
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插件的一个依赖的信息.
|
* 插件的一个依赖的信息.
|
||||||
*
|
*
|
||||||
@ -20,16 +24,15 @@ public data class PluginDependency @JvmOverloads constructor(
|
|||||||
/**
|
/**
|
||||||
* 依赖插件 ID, [PluginDescription.id]
|
* 依赖插件 ID, [PluginDescription.id]
|
||||||
*/
|
*/
|
||||||
public val id: String,
|
@ResolveContext(PLUGIN_ID) public val id: String,
|
||||||
/**
|
/**
|
||||||
* 依赖版本号. 为 null 时则为不限制版本.
|
* 依赖版本号. 为 null 时则为不限制版本.
|
||||||
*
|
*
|
||||||
* 版本遵循 [语义化版本 2.0 规范](https://semver.org/lang/zh-CN/),
|
* 版本遵循 [语义化版本 2.0 规范](https://semver.org/lang/zh-CN/),
|
||||||
*
|
*
|
||||||
* ### 示例
|
* @see SemVersion.Requirement
|
||||||
* `Requirement.buildIvy("[1.0, 2.0)")`
|
|
||||||
*/
|
*/
|
||||||
public val versionRequirement: VersionRequirement? = null,
|
public val versionRequirement: SemVersion.Requirement? = null,
|
||||||
/**
|
/**
|
||||||
* 若为 `false`, 插件在找不到此依赖时也能正常加载.
|
* 若为 `false`, 插件在找不到此依赖时也能正常加载.
|
||||||
*/
|
*/
|
||||||
@ -46,7 +49,10 @@ public data class PluginDependency @JvmOverloads constructor(
|
|||||||
/**
|
/**
|
||||||
* @see PluginDependency
|
* @see PluginDependency
|
||||||
*/
|
*/
|
||||||
public constructor(name: String, isOptional: Boolean = false) : this(
|
public constructor(
|
||||||
name, null, isOptional
|
@ResolveContext(PLUGIN_ID) id: String,
|
||||||
|
isOptional: Boolean = false,
|
||||||
|
) : this(
|
||||||
|
id, null, isOptional
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -9,10 +9,10 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.plugin.description
|
package net.mamoe.mirai.console.plugin.description
|
||||||
|
|
||||||
import com.vdurmont.semver4j.Semver
|
|
||||||
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.*
|
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.*
|
||||||
import net.mamoe.mirai.console.plugin.Plugin
|
import net.mamoe.mirai.console.plugin.Plugin
|
||||||
|
import net.mamoe.mirai.console.util.SemVersion
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,7 +93,7 @@ public interface PluginDescription {
|
|||||||
* @see Semver 语义化版本. 允许 [宽松][Semver.SemverType.LOOSE] 类型版本.
|
* @see Semver 语义化版本. 允许 [宽松][Semver.SemverType.LOOSE] 类型版本.
|
||||||
*/
|
*/
|
||||||
@ResolveContext(PLUGIN_VERSION)
|
@ResolveContext(PLUGIN_VERSION)
|
||||||
public val version: Semver
|
public val version: SemVersion
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插件信息, 允许为空
|
* 插件信息, 允许为空
|
||||||
|
@ -1,242 +0,0 @@
|
|||||||
package net.mamoe.mirai.console.plugin.description
|
|
||||||
|
|
||||||
import com.vdurmont.semver4j.Requirement
|
|
||||||
import com.vdurmont.semver4j.Semver
|
|
||||||
|
|
||||||
public sealed class VersionRequirement {
|
|
||||||
public abstract operator fun contains(version: Semver): Boolean
|
|
||||||
public fun contains(version: String): Boolean = contains(Semver(version, Semver.SemverType.LOOSE))
|
|
||||||
|
|
||||||
public class Exact
|
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
constructor(
|
|
||||||
version: Semver,
|
|
||||||
) : VersionRequirement() {
|
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
public val version: Semver = version.toStrict()
|
|
||||||
|
|
||||||
@Suppress("DEPRECATION_ERROR")
|
|
||||||
public constructor(version: String) : this(Semver(version, Semver.SemverType.LOOSE))
|
|
||||||
|
|
||||||
@Suppress("DEPRECATION_ERROR")
|
|
||||||
override fun contains(version: Semver): Boolean = this.version.isEquivalentTo(version.toStrict())
|
|
||||||
}
|
|
||||||
|
|
||||||
public data class MatchesNpmPattern(
|
|
||||||
val pattern: String,
|
|
||||||
) : VersionRequirement() {
|
|
||||||
private val requirement = Requirement.buildNPM(pattern)
|
|
||||||
override fun contains(version: Semver): Boolean = requirement.isSatisfiedBy(version.toStrict())
|
|
||||||
}
|
|
||||||
|
|
||||||
public data class MatchesIvyPattern(
|
|
||||||
val pattern: String,
|
|
||||||
) : VersionRequirement() {
|
|
||||||
private val requirement = Requirement.buildIvy(pattern)
|
|
||||||
override fun contains(version: Semver): Boolean = requirement.isSatisfiedBy(version.toStrict())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public data class MatchesCocoapodsPattern(
|
|
||||||
val pattern: String,
|
|
||||||
) : VersionRequirement() {
|
|
||||||
private val requirement = Requirement.buildCocoapods(pattern)
|
|
||||||
override fun contains(version: Semver): Boolean = requirement.isSatisfiedBy(version.toStrict())
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class Custom : VersionRequirement()
|
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
|
||||||
public class InRange(
|
|
||||||
begin: Semver,
|
|
||||||
public val beginInclusive: Boolean,
|
|
||||||
end: Semver,
|
|
||||||
public val endInclusive: Boolean,
|
|
||||||
) : VersionRequirement() {
|
|
||||||
public val end: Semver = end.toStrict()
|
|
||||||
public val begin: Semver = begin.toStrict()
|
|
||||||
|
|
||||||
public constructor(
|
|
||||||
begin: String,
|
|
||||||
beginInclusive: Boolean,
|
|
||||||
end: Semver,
|
|
||||||
endInclusive: Boolean,
|
|
||||||
) : this(Semver(begin, Semver.SemverType.LOOSE), beginInclusive, end, endInclusive)
|
|
||||||
|
|
||||||
public constructor(
|
|
||||||
begin: String,
|
|
||||||
beginInclusive: Boolean,
|
|
||||||
end: String,
|
|
||||||
endInclusive: Boolean,
|
|
||||||
) : this(Semver(begin, Semver.SemverType.LOOSE),
|
|
||||||
beginInclusive,
|
|
||||||
Semver(end, Semver.SemverType.LOOSE),
|
|
||||||
endInclusive)
|
|
||||||
|
|
||||||
public constructor(
|
|
||||||
begin: Semver,
|
|
||||||
beginInclusive: Boolean,
|
|
||||||
end: String,
|
|
||||||
endInclusive: Boolean,
|
|
||||||
) : this(begin, beginInclusive, Semver(end, Semver.SemverType.LOOSE), endInclusive)
|
|
||||||
|
|
||||||
override fun contains(version: Semver): Boolean {
|
|
||||||
val strict = version.toStrict()
|
|
||||||
return if (beginInclusive) {
|
|
||||||
strict.isGreaterThanOrEqualTo(begin)
|
|
||||||
} else {
|
|
||||||
strict.isGreaterThan(begin)
|
|
||||||
} && if (endInclusive) {
|
|
||||||
strict.isLowerThanOrEqualTo(end)
|
|
||||||
} else {
|
|
||||||
strict.isLowerThan(end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return buildString {
|
|
||||||
append(if (beginInclusive) "[" else "(")
|
|
||||||
append(begin)
|
|
||||||
append(",")
|
|
||||||
append(end)
|
|
||||||
append(if (endInclusive) "]" else ")")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Suppress("unused", "DeprecatedCallableAddReplaceWith")
|
|
||||||
public class Builder {
|
|
||||||
@Suppress("DEPRECATION_ERROR")
|
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public fun exact(version: Semver): VersionRequirement = Exact(version)
|
|
||||||
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public fun exact(version: String): VersionRequirement = Exact(version)
|
|
||||||
|
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public fun custom(checker: (version: Semver) -> Boolean): VersionRequirement {
|
|
||||||
return object : Custom() {
|
|
||||||
override fun contains(version: Semver): Boolean = checker(version)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Semver.SemverType.NPM
|
|
||||||
*/
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public fun npmPattern(versionPattern: String): VersionRequirement {
|
|
||||||
return MatchesNpmPattern(versionPattern)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Semver.SemverType.IVY
|
|
||||||
*/
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public fun ivyPattern(versionPattern: String): VersionRequirement {
|
|
||||||
return MatchesIvyPattern(versionPattern)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Semver.SemverType.COCOAPODS
|
|
||||||
*/
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public fun cocoapodsPattern(versionPattern: String): VersionRequirement {
|
|
||||||
return MatchesCocoapodsPattern(versionPattern)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public fun range(
|
|
||||||
begin: Semver,
|
|
||||||
beginInclusive: Boolean,
|
|
||||||
end: Semver,
|
|
||||||
endInclusive: Boolean,
|
|
||||||
): VersionRequirement = InRange(begin, beginInclusive, end, endInclusive)
|
|
||||||
|
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public fun range(
|
|
||||||
begin: String,
|
|
||||||
beginInclusive: Boolean,
|
|
||||||
end: Semver,
|
|
||||||
endInclusive: Boolean,
|
|
||||||
): VersionRequirement = InRange(begin, beginInclusive, end, endInclusive)
|
|
||||||
|
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public fun range(
|
|
||||||
begin: Semver,
|
|
||||||
beginInclusive: Boolean,
|
|
||||||
end: String,
|
|
||||||
endInclusive: Boolean,
|
|
||||||
): VersionRequirement = InRange(begin, beginInclusive, end, endInclusive)
|
|
||||||
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public fun range(
|
|
||||||
begin: String,
|
|
||||||
beginInclusive: Boolean,
|
|
||||||
end: String,
|
|
||||||
endInclusive: Boolean,
|
|
||||||
): VersionRequirement = InRange(begin, beginInclusive, end, endInclusive)
|
|
||||||
|
|
||||||
|
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public operator fun Semver.rangeTo(endInclusive: Semver): VersionRequirement {
|
|
||||||
return InRange(this, true, endInclusive, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public operator fun Semver.rangeTo(endInclusive: String): VersionRequirement {
|
|
||||||
return InRange(this, true, Semver(endInclusive, Semver.SemverType.LOOSE), true)
|
|
||||||
}
|
|
||||||
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public operator fun String.rangeTo(endInclusive: String): VersionRequirement {
|
|
||||||
return InRange(Semver(this, Semver.SemverType.LOOSE),
|
|
||||||
true,
|
|
||||||
Semver(endInclusive, Semver.SemverType.LOOSE),
|
|
||||||
true)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public operator fun String.rangeTo(endInclusive: Semver): VersionRequirement {
|
|
||||||
return InRange(Semver(this, Semver.SemverType.LOOSE), true, endInclusive, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public infix fun Semver.until(endExclusive: Semver): VersionRequirement {
|
|
||||||
return InRange(this, true, endExclusive, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public infix fun Semver.until(endExclusive: String): VersionRequirement {
|
|
||||||
return InRange(this, true, Semver(endExclusive, Semver.SemverType.LOOSE), false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public infix fun String.until(endExclusive: String): VersionRequirement {
|
|
||||||
return InRange(Semver(this, Semver.SemverType.LOOSE),
|
|
||||||
true,
|
|
||||||
Semver(endExclusive, Semver.SemverType.LOOSE),
|
|
||||||
false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
@ILoveKafuuChinoForever
|
|
||||||
public infix fun String.until(endExclusive: Semver): VersionRequirement {
|
|
||||||
return InRange(Semver(this, Semver.SemverType.LOOSE), true, endExclusive, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("SpellCheckingInspection")
|
|
||||||
@Retention(AnnotationRetention.BINARY)
|
|
||||||
@DslMarker
|
|
||||||
internal annotation class ILoveKafuuChinoForever
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,12 +11,12 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.plugin.jvm
|
package net.mamoe.mirai.console.plugin.jvm
|
||||||
|
|
||||||
import com.vdurmont.semver4j.Semver
|
|
||||||
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.*
|
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.*
|
||||||
import net.mamoe.mirai.console.plugin.description.PluginDependency
|
import net.mamoe.mirai.console.plugin.description.PluginDependency
|
||||||
import net.mamoe.mirai.console.plugin.description.PluginDescription
|
import net.mamoe.mirai.console.plugin.description.PluginDescription
|
||||||
import net.mamoe.mirai.console.plugin.description.VersionRequirement
|
import net.mamoe.mirai.console.util.SemVersion
|
||||||
|
import net.mamoe.mirai.console.util.SemVersionRangeRequirementBuilder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JVM 插件的描述. 通常作为 `plugin.yml`
|
* JVM 插件的描述. 通常作为 `plugin.yml`
|
||||||
@ -34,6 +34,7 @@ public interface JvmPluginDescription : PluginDescription {
|
|||||||
* 构建 [JvmPluginDescription]
|
* 构建 [JvmPluginDescription]
|
||||||
* @see JvmPluginDescriptionBuilder
|
* @see JvmPluginDescriptionBuilder
|
||||||
*/
|
*/
|
||||||
|
@JvmName("create")
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
public operator fun invoke(
|
public operator fun invoke(
|
||||||
/**
|
/**
|
||||||
@ -55,8 +56,7 @@ public interface JvmPluginDescription : PluginDescription {
|
|||||||
* 构建 [JvmPluginDescription]
|
* 构建 [JvmPluginDescription]
|
||||||
* @see JvmPluginDescriptionBuilder
|
* @see JvmPluginDescriptionBuilder
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION_ERROR")
|
@JvmName("create")
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
public operator fun invoke(
|
public operator fun invoke(
|
||||||
/**
|
/**
|
||||||
@ -66,7 +66,7 @@ public interface JvmPluginDescription : PluginDescription {
|
|||||||
/**
|
/**
|
||||||
* @see [PluginDescription.version]
|
* @see [PluginDescription.version]
|
||||||
*/
|
*/
|
||||||
@ResolveContext(PLUGIN_VERSION) version: Semver,
|
@ResolveContext(PLUGIN_VERSION) version: SemVersion,
|
||||||
/**
|
/**
|
||||||
* @see [PluginDescription.name]
|
* @see [PluginDescription.name]
|
||||||
*/
|
*/
|
||||||
@ -97,17 +97,14 @@ public interface JvmPluginDescription : PluginDescription {
|
|||||||
*
|
*
|
||||||
* @see [JvmPluginDescription.invoke]
|
* @see [JvmPluginDescription.invoke]
|
||||||
*/
|
*/
|
||||||
public class JvmPluginDescriptionBuilder
|
public class JvmPluginDescriptionBuilder(
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
constructor(
|
|
||||||
private var id: String,
|
private var id: String,
|
||||||
private var version: Semver,
|
private var version: SemVersion,
|
||||||
) {
|
) {
|
||||||
@Suppress("DEPRECATION_ERROR")
|
|
||||||
public constructor(
|
public constructor(
|
||||||
@ResolveContext(PLUGIN_NAME) id: String,
|
@ResolveContext(PLUGIN_ID) id: String,
|
||||||
@ResolveContext(PLUGIN_VERSION) version: String,
|
@ResolveContext(PLUGIN_VERSION) version: String,
|
||||||
) : this(id, Semver(version, Semver.SemverType.LOOSE))
|
) : this(id, SemVersion(version))
|
||||||
|
|
||||||
private var name: String = id
|
private var name: String = id
|
||||||
private var author: String = ""
|
private var author: String = ""
|
||||||
@ -118,14 +115,12 @@ constructor(
|
|||||||
public fun name(@ResolveContext(PLUGIN_NAME) value: String): JvmPluginDescriptionBuilder =
|
public fun name(@ResolveContext(PLUGIN_NAME) value: String): JvmPluginDescriptionBuilder =
|
||||||
apply { this.name = value.trim() }
|
apply { this.name = value.trim() }
|
||||||
|
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
@ILoveKuriyamaMiraiForever
|
@ILoveKuriyamaMiraiForever
|
||||||
public fun version(@ResolveContext(PLUGIN_VERSION) value: String): JvmPluginDescriptionBuilder =
|
public fun version(@ResolveContext(PLUGIN_VERSION) value: String): JvmPluginDescriptionBuilder =
|
||||||
apply { this.version = Semver(value, Semver.SemverType.LOOSE) }
|
apply { this.version = SemVersion(value) }
|
||||||
|
|
||||||
@Deprecated("Semver 将会在 1.0-RC 被替换为 Console 自己实现的版本。请临时使用 String。", level = DeprecationLevel.ERROR)
|
|
||||||
@ILoveKuriyamaMiraiForever
|
@ILoveKuriyamaMiraiForever
|
||||||
public fun version(@ResolveContext(PLUGIN_VERSION) value: Semver): JvmPluginDescriptionBuilder =
|
public fun version(@ResolveContext(PLUGIN_VERSION) value: SemVersion): JvmPluginDescriptionBuilder =
|
||||||
apply { this.version = value }
|
apply { this.version = value }
|
||||||
|
|
||||||
@ILoveKuriyamaMiraiForever
|
@ILoveKuriyamaMiraiForever
|
||||||
@ -161,7 +156,7 @@ constructor(
|
|||||||
public fun dependsOn(
|
public fun dependsOn(
|
||||||
@ResolveContext(PLUGIN_ID) pluginId: String,
|
@ResolveContext(PLUGIN_ID) pluginId: String,
|
||||||
isOptional: Boolean = false,
|
isOptional: Boolean = false,
|
||||||
versionRequirement: VersionRequirement,
|
versionRequirement: SemVersion.Requirement,
|
||||||
): JvmPluginDescriptionBuilder = apply {
|
): JvmPluginDescriptionBuilder = apply {
|
||||||
this.dependencies.add(PluginDependency(pluginId, versionRequirement, isOptional))
|
this.dependencies.add(PluginDependency(pluginId, versionRequirement, isOptional))
|
||||||
}
|
}
|
||||||
@ -174,7 +169,7 @@ constructor(
|
|||||||
@ILoveKuriyamaMiraiForever
|
@ILoveKuriyamaMiraiForever
|
||||||
public fun dependsOn(
|
public fun dependsOn(
|
||||||
@ResolveContext(PLUGIN_ID) pluginId: String,
|
@ResolveContext(PLUGIN_ID) pluginId: String,
|
||||||
versionRequirement: VersionRequirement,
|
versionRequirement: SemVersion.Requirement,
|
||||||
): JvmPluginDescriptionBuilder = apply {
|
): JvmPluginDescriptionBuilder = apply {
|
||||||
this.dependencies.add(PluginDependency(pluginId, versionRequirement, false))
|
this.dependencies.add(PluginDependency(pluginId, versionRequirement, false))
|
||||||
}
|
}
|
||||||
@ -203,17 +198,17 @@ constructor(
|
|||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @see PluginDependency
|
* @see PluginDependency
|
||||||
* @see VersionRequirement.Builder
|
* @see SemVersionRangeRequirementBuilder
|
||||||
*/
|
*/
|
||||||
@ILoveKuriyamaMiraiForever
|
@ILoveKuriyamaMiraiForever
|
||||||
public fun dependsOn(
|
public fun dependsOn(
|
||||||
@ResolveContext(PLUGIN_ID) pluginId: String,
|
@ResolveContext(PLUGIN_ID) pluginId: String,
|
||||||
isOptional: Boolean = false,
|
isOptional: Boolean = false,
|
||||||
versionRequirement: VersionRequirement.Builder.() -> VersionRequirement,
|
versionRequirement: SemVersionRangeRequirementBuilder.() -> SemVersion.Requirement,
|
||||||
): JvmPluginDescriptionBuilder =
|
): JvmPluginDescriptionBuilder =
|
||||||
apply {
|
apply {
|
||||||
this.dependencies.add(PluginDependency(pluginId,
|
this.dependencies.add(PluginDependency(pluginId,
|
||||||
VersionRequirement.Builder().run(versionRequirement),
|
SemVersionRangeRequirementBuilder.run(versionRequirement),
|
||||||
isOptional))
|
isOptional))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,56 +231,26 @@ constructor(
|
|||||||
*
|
*
|
||||||
* @see JvmPluginDescription
|
* @see JvmPluginDescription
|
||||||
*/
|
*/
|
||||||
@Deprecated(
|
internal data class SimpleJvmPluginDescription
|
||||||
"""
|
@JvmOverloads constructor(
|
||||||
将在 1.0-RC 删除. 请使用 JvmPluginDescription.
|
override val name: String,
|
||||||
""",
|
override val version: SemVersion,
|
||||||
replaceWith = ReplaceWith(
|
override val id: String = name,
|
||||||
"JvmPluginDescription",
|
override val author: String = "",
|
||||||
"net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription"
|
override val info: String = "",
|
||||||
),
|
override val dependencies: Set<PluginDependency> = setOf(),
|
||||||
level = DeprecationLevel.ERROR
|
|
||||||
)
|
|
||||||
public data class SimpleJvmPluginDescription
|
|
||||||
@Deprecated(
|
|
||||||
"""
|
|
||||||
构造器不稳定, 将在 1.0-RC 删除. 请使用 JvmPluginDescriptionBuilder.
|
|
||||||
""",
|
|
||||||
replaceWith = ReplaceWith(
|
|
||||||
"JvmPluginDescription(name, version) {}",
|
|
||||||
"net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription.Companion.invoke"
|
|
||||||
),
|
|
||||||
level = DeprecationLevel.ERROR
|
|
||||||
)
|
|
||||||
@JvmOverloads public constructor(
|
|
||||||
public override val name: String,
|
|
||||||
public override val version: Semver,
|
|
||||||
public override val id: String = name,
|
|
||||||
public override val author: String = "",
|
|
||||||
public override val info: String = "",
|
|
||||||
public override val dependencies: Set<PluginDependency> = setOf(),
|
|
||||||
) : JvmPluginDescription {
|
) : JvmPluginDescription {
|
||||||
|
|
||||||
@Deprecated(
|
|
||||||
"""
|
|
||||||
构造器不稳定, 将在 1.0-RC 删除. 请使用 JvmPluginDescriptionBuilder.
|
|
||||||
""",
|
|
||||||
replaceWith = ReplaceWith(
|
|
||||||
"JvmPluginDescription.invoke(name, version) {}",
|
|
||||||
"net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription.Companion.invoke"
|
|
||||||
),
|
|
||||||
level = DeprecationLevel.ERROR
|
|
||||||
)
|
|
||||||
@Suppress("DEPRECATION_ERROR")
|
@Suppress("DEPRECATION_ERROR")
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
public constructor(
|
constructor(
|
||||||
name: String,
|
name: String,
|
||||||
version: String,
|
version: String,
|
||||||
id: String = name,
|
id: String = name,
|
||||||
author: String = "",
|
author: String = "",
|
||||||
info: String = "",
|
info: String = "",
|
||||||
dependencies: Set<PluginDependency> = setOf(),
|
dependencies: Set<PluginDependency> = setOf(),
|
||||||
) : this(name, Semver(version, Semver.SemverType.LOOSE), id, author, info, dependencies)
|
) : this(name, SemVersion(version), id, author, info, dependencies)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
require(!name.contains(':')) { "':' is forbidden in plugin name" }
|
require(!name.contains(':')) { "':' is forbidden in plugin name" }
|
||||||
|
@ -15,7 +15,7 @@ import net.mamoe.mirai.console.internal.plugin.BuiltInJvmPluginLoaderImpl
|
|||||||
import net.mamoe.mirai.console.plugin.loader.FilePluginLoader
|
import net.mamoe.mirai.console.plugin.loader.FilePluginLoader
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 内建的 Jar (JVM) 插件加载器
|
* JVM 插件加载器
|
||||||
*/
|
*/
|
||||||
public interface JvmPluginLoader : CoroutineScope, FilePluginLoader<JvmPlugin, JvmPluginDescription> {
|
public interface JvmPluginLoader : CoroutineScope, FilePluginLoader<JvmPlugin, JvmPluginDescription> {
|
||||||
/**
|
/**
|
||||||
|
@ -61,10 +61,9 @@ public interface PluginLoader<P : Plugin, D : PluginDescription> {
|
|||||||
* @throws PluginLoadException 在加载插件遇到意料之中的错误时抛出 (如无法读取插件信息等).
|
* @throws PluginLoadException 在加载插件遇到意料之中的错误时抛出 (如无法读取插件信息等).
|
||||||
*
|
*
|
||||||
* @see PluginDescription 插件描述
|
* @see PluginDescription 插件描述
|
||||||
* @see getPluginDescription 无 receiver, 接受参数的版本.
|
|
||||||
*/
|
*/
|
||||||
@Throws(PluginLoadException::class)
|
@Throws(PluginLoadException::class)
|
||||||
public fun getPluginDescription(plugin: P): D // Java signature: `public D getDescription(P)`
|
public fun getPluginDescription(plugin: P): D
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主动加载一个插件 (实例), 但不 [启用][enable] 它. 返回加载成功的主类实例
|
* 主动加载一个插件 (实例), 但不 [启用][enable] 它. 返回加载成功的主类实例
|
||||||
|
@ -12,29 +12,27 @@
|
|||||||
* @author Karlatemp <karlatemp@vip.qq.com> <https://github.com/Karlatemp>
|
* @author Karlatemp <karlatemp@vip.qq.com> <https://github.com/Karlatemp>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.util
|
package net.mamoe.mirai.console.util
|
||||||
|
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.Transient
|
import kotlinx.serialization.Transient
|
||||||
import kotlinx.serialization.builtins.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||||
|
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.PLUGIN_VERSION
|
||||||
import net.mamoe.mirai.console.internal.data.map
|
import net.mamoe.mirai.console.internal.data.map
|
||||||
import net.mamoe.mirai.console.internal.util.SemVersionInternal
|
import net.mamoe.mirai.console.internal.util.SemVersionInternal
|
||||||
import net.mamoe.mirai.console.util.SemVersion.Companion.equals
|
import net.mamoe.mirai.console.util.SemVersion.Companion.equals
|
||||||
|
import net.mamoe.mirai.console.util.SemVersion.Requirement
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 语义化版本支持
|
* [语义化版本](https://semver.org/lang/zh-CN/) 支持
|
||||||
*
|
*
|
||||||
* 在阅读此文件前, 请先阅读 https://semver.org/lang/zh-CN/
|
* 解析示例:
|
||||||
* 该文档说明了语义化版本是什么, 此文件不再过多描述
|
|
||||||
*
|
*
|
||||||
* ----
|
* `1.0.0-M4+c25733b8` 将会解析出三个内容, mainVersion (核心版本号), [identifier] (先行版本号) 和 [metadata] (元数据).
|
||||||
*
|
|
||||||
* 这是一个例子 `1.0.0-M4+c25733b8`
|
|
||||||
*
|
|
||||||
* 将会解析出三个内容, mainVersion(核心版本号), identifier(先行版本号) 和 metadata(元数据).
|
|
||||||
*
|
|
||||||
* 对这个例子进行解析会得到
|
|
||||||
* ```
|
* ```
|
||||||
* SemVersion(
|
* SemVersion(
|
||||||
* mainVersion = IntArray [1, 0, 0],
|
* mainVersion = IntArray [1, 0, 0],
|
||||||
@ -43,47 +41,45 @@ import net.mamoe.mirai.console.util.SemVersion.Companion.equals
|
|||||||
* )
|
* )
|
||||||
* ```
|
* ```
|
||||||
* 其中 identifier 和 metadata 都是可选的.
|
* 其中 identifier 和 metadata 都是可选的.
|
||||||
* 对于核心版本号, 此实现稍微比 semver 宽松一些, 允许 x.y 的存在.
|
|
||||||
* 但是不允许 0.0.0.0 之类的存在
|
|
||||||
*
|
*
|
||||||
|
* 对于核心版本号, 此实现稍微比 semver 宽松一些, 允许 x.y 的存在.
|
||||||
|
*
|
||||||
|
* @see Requirement
|
||||||
|
* @see SemVersion.invoke
|
||||||
*/
|
*/
|
||||||
@Serializable(with = SemVersion.SemVersionAsStringSerializer::class)
|
@Serializable(with = SemVersion.SemVersionAsStringSerializer::class)
|
||||||
public data class SemVersion internal constructor(
|
public data class SemVersion
|
||||||
|
/**
|
||||||
|
* @see SemVersion.invoke 字符串解析
|
||||||
|
*/
|
||||||
|
internal constructor(
|
||||||
/** 核心版本号, 由主版本号, 次版本号和修订号组成, 其中修订号不一定存在 */
|
/** 核心版本号, 由主版本号, 次版本号和修订号组成, 其中修订号不一定存在 */
|
||||||
public val mainVersion: IntArray,
|
public val mainVersion: IntArray,
|
||||||
/** 先行版本号识别符 */
|
/** 先行版本号识别符 */
|
||||||
public val identifier: String? = null,
|
public val identifier: String? = null,
|
||||||
/** 版本号元数据, 不参与版本号对比([compareTo]), 但是参与版本号严格对比([equals]) */
|
/** 版本号元数据, 不参与版本号对比([compareTo]), 但是参与版本号严格对比([equals]) */
|
||||||
public val metadata: String? = null
|
public val metadata: String? = null,
|
||||||
) : Comparable<SemVersion> {
|
) : Comparable<SemVersion> {
|
||||||
/**
|
/**
|
||||||
* 一条依赖规则
|
* 一条依赖规则
|
||||||
* @see [parseRangeRequirement]
|
* @see [parseRangeRequirement]
|
||||||
*/
|
*/
|
||||||
public fun interface RangeRequirement {
|
public interface Requirement {
|
||||||
/** 在 [version] 满足此要求时返回 true */
|
/** 在 [version] 满足此要求时返回 true */
|
||||||
public fun check(version: SemVersion): Boolean
|
public fun test(version: SemVersion): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
public object SemVersionAsStringSerializer : KSerializer<SemVersion> by String.serializer().map(
|
public object SemVersionAsStringSerializer : KSerializer<SemVersion> by String.serializer().map(
|
||||||
serializer = { it.toString() },
|
serializer = { it.toString() },
|
||||||
deserializer = { parse(it) }
|
deserializer = { SemVersion(it) }
|
||||||
)
|
)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
private val SEM_VERSION_REGEX =
|
|
||||||
"""^(0|[1-9]\d*)\.(0|[1-9]\d*)(?:\.(0|[1-9]\d*))?(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$""".toRegex()
|
|
||||||
|
|
||||||
/** 解析核心版本号, eg: `1.0.0` -> IntArray[1, 0, 0] */
|
|
||||||
@JvmStatic
|
|
||||||
private fun String.parseMainVersion(): IntArray =
|
|
||||||
split('.').map { it.toInt() }.toIntArray()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析一个版本号, 将会返回一个 [SemVersion],
|
* 解析一个版本号, 将会返回一个 [SemVersion],
|
||||||
* 如果发生解析错误将会抛出一个 [IllegalArgumentException] 或者 [NumberFormatException]
|
* 如果发生解析错误将会抛出一个 [IllegalArgumentException] 或者 [NumberFormatException]
|
||||||
*
|
*
|
||||||
* 对于版本号的组成, 我们有以下规定:
|
* 对于版本号的组成, 有以下规定:
|
||||||
* - 必须包含主版本号和次版本号
|
* - 必须包含主版本号和次版本号
|
||||||
* - 存在 先行版本号 的时候 先行版本号 不能为空
|
* - 存在 先行版本号 的时候 先行版本号 不能为空
|
||||||
* - 存在 元数据 的时候 元数据 不能为空
|
* - 存在 元数据 的时候 元数据 不能为空
|
||||||
@ -100,45 +96,8 @@ public data class SemVersion internal constructor(
|
|||||||
*/
|
*/
|
||||||
@Throws(IllegalArgumentException::class, NumberFormatException::class)
|
@Throws(IllegalArgumentException::class, NumberFormatException::class)
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun parse(version: String): SemVersion {
|
@JvmName("parse")
|
||||||
if (!SEM_VERSION_REGEX.matches(version)) {
|
public operator fun invoke(@ResolveContext(PLUGIN_VERSION) version: String): SemVersion = SemVersionInternal.parse(version)
|
||||||
throw IllegalArgumentException("`$version` not a valid version")
|
|
||||||
}
|
|
||||||
var mainVersionEnd: Int = 0
|
|
||||||
kotlin.run {
|
|
||||||
val iterator = version.iterator()
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
val next = iterator.next()
|
|
||||||
if (next == '-' || next == '+') {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
mainVersionEnd++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var identifier: String? = null
|
|
||||||
var metadata: String? = null
|
|
||||||
if (mainVersionEnd != version.length) {
|
|
||||||
when (version[mainVersionEnd]) {
|
|
||||||
'-' -> {
|
|
||||||
val metadataSplitter = version.indexOf('+', startIndex = mainVersionEnd)
|
|
||||||
if (metadataSplitter == -1) {
|
|
||||||
identifier = version.substring(mainVersionEnd + 1)
|
|
||||||
} else {
|
|
||||||
identifier = version.substring(mainVersionEnd + 1, metadataSplitter)
|
|
||||||
metadata = version.substring(metadataSplitter + 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'+' -> {
|
|
||||||
metadata = version.substring(mainVersionEnd + 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return SemVersion(
|
|
||||||
mainVersion = version.substring(0, mainVersionEnd).parseMainVersion(),
|
|
||||||
identifier = identifier,
|
|
||||||
metadata = metadata
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析一条依赖需求描述, 在无法解析的时候抛出 [IllegalArgumentException]
|
* 解析一条依赖需求描述, 在无法解析的时候抛出 [IllegalArgumentException]
|
||||||
@ -154,7 +113,7 @@ public data class SemVersion internal constructor(
|
|||||||
* - `< 1.0.0-RC` 要求 1.0.0-RC 之前的版本, 不能是 1.0.0-RC
|
* - `< 1.0.0-RC` 要求 1.0.0-RC 之前的版本, 不能是 1.0.0-RC
|
||||||
* - `<= 1.0.0-RC` 要求 1.0.0-RC 或之前的版本, 可以是 1.0.0-RC
|
* - `<= 1.0.0-RC` 要求 1.0.0-RC 或之前的版本, 可以是 1.0.0-RC
|
||||||
*
|
*
|
||||||
* 对于多个规则, 也允许使用 `||` 拼接在一起.
|
* 对于多个规则, 也允许使用 `||` 拼接.
|
||||||
* 例如:
|
* 例如:
|
||||||
* - `1.x || 2.x || 3.0.0`
|
* - `1.x || 2.x || 3.0.0`
|
||||||
* - `<= 0.5.3 || >= 1.0.0`
|
* - `<= 0.5.3 || >= 1.0.0`
|
||||||
@ -165,35 +124,32 @@ public data class SemVersion internal constructor(
|
|||||||
*/
|
*/
|
||||||
@Throws(IllegalArgumentException::class)
|
@Throws(IllegalArgumentException::class)
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun parseRangeRequirement(requirement: String): RangeRequirement {
|
public fun parseRangeRequirement(requirement: String): Requirement =
|
||||||
return SemVersionInternal.parseRangeRequirement(requirement)
|
SemVersionInternal.parseRangeRequirement(requirement)
|
||||||
}
|
|
||||||
|
|
||||||
/** @see [RangeRequirement.check] */
|
/** @see [Requirement.test] */
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun RangeRequirement.check(version: String): Boolean = check(parse(version))
|
public fun Requirement.test(@ResolveContext(PLUGIN_VERSION) version: String): Boolean = test(invoke(version))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当满足 [requirement] 时返回 true, 否则返回 false
|
* 当满足 [requirement] 时返回 true, 否则返回 false
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun SemVersion.satisfies(requirement: RangeRequirement): Boolean = requirement.check(this)
|
public fun SemVersion.satisfies(requirement: Requirement): Boolean = requirement.test(this)
|
||||||
|
|
||||||
/** for Kotlin only */
|
/** for Kotlin only */
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
public operator fun RangeRequirement.contains(version: SemVersion): Boolean = check(version)
|
public operator fun Requirement.contains(version: SemVersion): Boolean = test(version)
|
||||||
|
|
||||||
/** for Kotlin only */
|
/** for Kotlin only */
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
public operator fun RangeRequirement.contains(version: String): Boolean = check(version)
|
public operator fun Requirement.contains(@ResolveContext(PLUGIN_VERSION) version: String): Boolean = test(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private var toString: String? = null // For cache.
|
private val toString: String by lazy(LazyThreadSafetyMode.NONE) {
|
||||||
override fun toString(): String {
|
|
||||||
return toString ?: kotlin.run {
|
|
||||||
buildString {
|
buildString {
|
||||||
mainVersion.joinTo(this, ".")
|
mainVersion.joinTo(this, ".")
|
||||||
identifier?.let { identifier ->
|
identifier?.let { identifier ->
|
||||||
@ -204,10 +160,11 @@ public data class SemVersion internal constructor(
|
|||||||
append('+')
|
append('+')
|
||||||
append(metadata)
|
append(metadata)
|
||||||
}
|
}
|
||||||
}.also { toString = it }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = toString
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 [SemVersion] 转为 Kotlin data class 风格的 [String]
|
* 将 [SemVersion] 转为 Kotlin data class 风格的 [String]
|
||||||
*/
|
*/
|
||||||
@ -237,6 +194,6 @@ public data class SemVersion internal constructor(
|
|||||||
* if it's greater than [other].
|
* if it's greater than [other].
|
||||||
*/
|
*/
|
||||||
public override operator fun compareTo(other: SemVersion): Int {
|
public override operator fun compareTo(other: SemVersion): Int {
|
||||||
return SemVersionInternal.run { compareInternal(other) }
|
return SemVersionInternal.run { compareInternal(this@SemVersion, other) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.util
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造 [SemVersion.Requirement] 的 DSL
|
||||||
|
*/
|
||||||
|
public object SemVersionRangeRequirementBuilder {
|
||||||
|
/** @see [SemVersion.parseRangeRequirement] */
|
||||||
|
@ILoveHim188moeForever
|
||||||
|
public fun parse(rule: String): SemVersion.Requirement = SemVersion.parseRangeRequirement(rule)
|
||||||
|
|
||||||
|
@ILoveHim188moeForever
|
||||||
|
public infix fun SemVersion.Requirement.or(other: SemVersion.Requirement): SemVersion.Requirement {
|
||||||
|
return object : SemVersion.Requirement {
|
||||||
|
override fun test(version: SemVersion): Boolean {
|
||||||
|
return this@or.test(version) || other.test(version)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "(${this@or}) or ($other)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ILoveHim188moeForever
|
||||||
|
public infix fun String.or(other: String): SemVersion.Requirement = parse(this) or parse(other)
|
||||||
|
|
||||||
|
@ILoveHim188moeForever
|
||||||
|
public infix fun SemVersion.Requirement.or(other: String): SemVersion.Requirement = or(parse(other))
|
||||||
|
|
||||||
|
@ILoveHim188moeForever
|
||||||
|
public infix fun String.or(other: SemVersion.Requirement): SemVersion.Requirement = parse(this) or other
|
||||||
|
|
||||||
|
@ILoveHim188moeForever
|
||||||
|
public infix fun SemVersion.Requirement.and(other: SemVersion.Requirement): SemVersion.Requirement {
|
||||||
|
return object : SemVersion.Requirement {
|
||||||
|
override fun test(version: SemVersion): Boolean {
|
||||||
|
return this@and.test(version) && other.test(version)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "(${this@and}) or ($other)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ILoveHim188moeForever
|
||||||
|
public infix fun String.and(other: String): SemVersion.Requirement = parse(this) and parse(other)
|
||||||
|
|
||||||
|
@ILoveHim188moeForever
|
||||||
|
public infix fun SemVersion.Requirement.and(other: String): SemVersion.Requirement = and(parse(other))
|
||||||
|
|
||||||
|
@ILoveHim188moeForever
|
||||||
|
public infix fun String.and(other: SemVersion.Requirement): SemVersion.Requirement = parse(this) and other
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
@ILoveHim188moeForever
|
||||||
|
public inline fun custom(rule: SemVersion.Requirement): SemVersion.Requirement = rule
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标注一个 [SemVersionRangeRequirementBuilder] DSL
|
||||||
|
*/
|
||||||
|
@Suppress("SpellCheckingInspection")
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
@DslMarker
|
||||||
|
internal annotation class ILoveHim188moeForever
|
||||||
|
|
||||||
|
/** [SemVersionRangeRequirementBuilder] 的使用示例 */
|
||||||
|
@Suppress("unused")
|
||||||
|
private class ExampleOfBuilder {
|
||||||
|
val e1 = SemVersionRangeRequirementBuilder.run {
|
||||||
|
"1.0.0" or "1.1.5"
|
||||||
|
}
|
||||||
|
val e2 = SemVersionRangeRequirementBuilder.run {
|
||||||
|
parse("> 1.0.0") and parse("< 1.2.3")
|
||||||
|
}
|
||||||
|
val e3 = SemVersionRangeRequirementBuilder.run {
|
||||||
|
("> 1.0.0" and "< 1.2.3") or "2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console
|
package net.mamoe.mirai.console
|
||||||
|
|
||||||
import com.vdurmont.semver4j.Semver
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start
|
import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start
|
||||||
import net.mamoe.mirai.console.command.CommandManager
|
import net.mamoe.mirai.console.command.CommandManager
|
||||||
@ -20,6 +19,7 @@ import net.mamoe.mirai.console.plugin.loader.PluginLoader
|
|||||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||||
import net.mamoe.mirai.console.util.ConsoleInput
|
import net.mamoe.mirai.console.util.ConsoleInput
|
||||||
import net.mamoe.mirai.console.util.ConsoleInternalApi
|
import net.mamoe.mirai.console.util.ConsoleInternalApi
|
||||||
|
import net.mamoe.mirai.console.util.SemVersion
|
||||||
import net.mamoe.mirai.message.data.Message
|
import net.mamoe.mirai.message.data.Message
|
||||||
import net.mamoe.mirai.utils.BotConfiguration
|
import net.mamoe.mirai.utils.BotConfiguration
|
||||||
import net.mamoe.mirai.utils.LoginSolver
|
import net.mamoe.mirai.utils.LoginSolver
|
||||||
@ -43,8 +43,8 @@ fun initTestEnvironment() {
|
|||||||
get() = "Test"
|
get() = "Test"
|
||||||
override val vendor: String
|
override val vendor: String
|
||||||
get() = "Test"
|
get() = "Test"
|
||||||
override val version: Semver
|
override val version: SemVersion
|
||||||
get() = Semver("1.0.0")
|
get() = SemVersion("1.0.0")
|
||||||
|
|
||||||
}
|
}
|
||||||
override val builtInPluginLoaders: List<Lazy<PluginLoader<*, *>>> = listOf(lazy { JvmPluginLoader })
|
override val builtInPluginLoaders: List<Lazy<PluginLoader<*, *>>> = listOf(lazy { JvmPluginLoader })
|
||||||
|
@ -14,13 +14,13 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.util
|
package net.mamoe.mirai.console.util
|
||||||
|
|
||||||
import net.mamoe.mirai.console.util.SemVersion.Companion.check
|
import net.mamoe.mirai.console.util.SemVersion.Companion.test
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
internal class TestSemVersion {
|
internal class TestSemVersion {
|
||||||
@Test
|
@Test
|
||||||
internal fun testCompare() {
|
internal fun testCompare() {
|
||||||
fun String.sem(): SemVersion = SemVersion.parse(this)
|
fun String.sem(): SemVersion = SemVersion.invoke(this)
|
||||||
assert("1.0".sem() < "1.0.1".sem())
|
assert("1.0".sem() < "1.0.1".sem())
|
||||||
assert("1.0.0".sem() == "1.0".sem())
|
assert("1.0.0".sem() == "1.0".sem())
|
||||||
assert("1.1".sem() > "1.0.0".sem())
|
assert("1.1".sem() > "1.0.0".sem())
|
||||||
@ -43,13 +43,13 @@ internal class TestSemVersion {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
internal fun testRequirement() {
|
internal fun testRequirement() {
|
||||||
fun SemVersion.RangeRequirement.assert(version: String): SemVersion.RangeRequirement {
|
fun SemVersion.Requirement.assert(version: String): SemVersion.Requirement {
|
||||||
assert(check(version)) { version }
|
assert(test(version)) { version }
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SemVersion.RangeRequirement.assertFalse(version: String): SemVersion.RangeRequirement {
|
fun SemVersion.Requirement.assertFalse(version: String): SemVersion.Requirement {
|
||||||
assert(!check(version)) { version }
|
assert(!test(version)) { version }
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
SemVersion.parseRangeRequirement("1.0")
|
SemVersion.parseRangeRequirement("1.0")
|
||||||
@ -85,12 +85,12 @@ internal class TestSemVersion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun String.check() {
|
private fun String.check() {
|
||||||
val sem = SemVersion.parse(this)
|
val sem = SemVersion.invoke(this)
|
||||||
assert(this == sem.toString()) { "$this != $sem" }
|
assert(this == sem.toString()) { "$this != $sem" }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.checkInvalid() {
|
private fun String.checkInvalid() {
|
||||||
kotlin.runCatching { SemVersion.parse(this) }
|
kotlin.runCatching { SemVersion.invoke(this) }
|
||||||
.onSuccess { assert(false) { "$this not a invalid sem-version" } }
|
.onSuccess { assert(false) { "$this not a invalid sem-version" } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,9 +26,22 @@ fun DependencyHandler.compileAndTestRuntime(any: Any) {
|
|||||||
|
|
||||||
fun DependencyHandler.smartApi(
|
fun DependencyHandler.smartApi(
|
||||||
dependencyNotation: String
|
dependencyNotation: String
|
||||||
|
): ExternalModuleDependency {
|
||||||
|
return smart("api", dependencyNotation)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DependencyHandler.smartImplementation(
|
||||||
|
dependencyNotation: String
|
||||||
|
): ExternalModuleDependency {
|
||||||
|
return smart("implementation", dependencyNotation)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun DependencyHandler.smart(
|
||||||
|
configuration: String,
|
||||||
|
dependencyNotation: String
|
||||||
): ExternalModuleDependency {
|
): ExternalModuleDependency {
|
||||||
return addDependencyTo(
|
return addDependencyTo(
|
||||||
this, "api", dependencyNotation
|
this, configuration, dependencyNotation
|
||||||
) {
|
) {
|
||||||
fun exclude(group: String, module: String) {
|
fun exclude(group: String, module: String) {
|
||||||
exclude(mapOf(
|
exclude(mapOf(
|
||||||
|
@ -1,2 +1,32 @@
|
|||||||
# Mirai Console - Contributing
|
# Mirai Console - Contributing
|
||||||
|
|
||||||
|
感谢你来到这里,感谢你对 Mirai Console 做的一切贡献。
|
||||||
|
|
||||||
|
## 开发 Mirai Console
|
||||||
|
|
||||||
|
### 模块
|
||||||
|
|
||||||
|
Mirai Console 项目由四个模块组成:后端,前端,Gradle 插件,Intellij 插件。
|
||||||
|
|
||||||
|
```
|
||||||
|
/
|
||||||
|
|--- backend 后端
|
||||||
|
| |--- codegen 后端代码生成工具
|
||||||
|
| `--- mirai-console 后端主模块, 发布为 net.mamoe:mirai-console
|
||||||
|
|--- buildSrc 项目构建
|
||||||
|
|--- frontend 前端
|
||||||
|
| `--- mirai-console-terminal 终端前端,发布为 net.mamoe:mirai-console-terminal
|
||||||
|
`--- tools 开发工具
|
||||||
|
|--- compiler-common 编译器通用模块
|
||||||
|
|--- gradle-plugin Gradle 插件,发布为 net.mamoe.mirai-console
|
||||||
|
`--- intellij-plugin IntelliJ 平台 IDE 插件,发布为 Mirai Console
|
||||||
|
```
|
||||||
|
|
||||||
|
请前往各模块内的 README.md 查看详细说明。
|
||||||
|
|
||||||
|
### 构建
|
||||||
|
```shell script
|
||||||
|
gradlew build
|
||||||
|
```
|
||||||
|
|
||||||
|
首次加载和构建 mirai-console 项目可能要花费数小时时间。
|
@ -23,7 +23,6 @@
|
|||||||
package net.mamoe.mirai.console.terminal
|
package net.mamoe.mirai.console.terminal
|
||||||
|
|
||||||
|
|
||||||
import com.vdurmont.semver4j.Semver
|
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||||
import kotlinx.coroutines.CoroutineName
|
import kotlinx.coroutines.CoroutineName
|
||||||
@ -39,10 +38,7 @@ import net.mamoe.mirai.console.plugin.loader.PluginLoader
|
|||||||
import net.mamoe.mirai.console.terminal.ConsoleInputImpl.requestInput
|
import net.mamoe.mirai.console.terminal.ConsoleInputImpl.requestInput
|
||||||
import net.mamoe.mirai.console.terminal.noconsole.AllEmptyLineReader
|
import net.mamoe.mirai.console.terminal.noconsole.AllEmptyLineReader
|
||||||
import net.mamoe.mirai.console.terminal.noconsole.NoConsole
|
import net.mamoe.mirai.console.terminal.noconsole.NoConsole
|
||||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
import net.mamoe.mirai.console.util.*
|
||||||
import net.mamoe.mirai.console.util.ConsoleInput
|
|
||||||
import net.mamoe.mirai.console.util.ConsoleInternalApi
|
|
||||||
import net.mamoe.mirai.console.util.NamedSupervisorJob
|
|
||||||
import net.mamoe.mirai.utils.*
|
import net.mamoe.mirai.utils.*
|
||||||
import org.fusesource.jansi.Ansi
|
import org.fusesource.jansi.Ansi
|
||||||
import org.jline.reader.LineReader
|
import org.jline.reader.LineReader
|
||||||
@ -155,7 +151,7 @@ val terminal: Terminal = run {
|
|||||||
private object ConsoleFrontEndDescImpl : MiraiConsoleFrontEndDescription {
|
private object ConsoleFrontEndDescImpl : MiraiConsoleFrontEndDescription {
|
||||||
override val name: String get() = "Terminal"
|
override val name: String get() = "Terminal"
|
||||||
override val vendor: String get() = "Mamoe Technologies"
|
override val vendor: String get() = "Mamoe Technologies"
|
||||||
override val version: Semver = net.mamoe.mirai.console.internal.MiraiConsoleBuildConstants.version
|
override val version: SemVersion = net.mamoe.mirai.console.internal.MiraiConsoleBuildConstants.version
|
||||||
}
|
}
|
||||||
|
|
||||||
private val ANSI_RESET = Ansi().reset().toString()
|
private val ANSI_RESET = Ansi().reset().toString()
|
||||||
|
Loading…
Reference in New Issue
Block a user