From debe5baae470e3733733a7f525daf07858c67ed1 Mon Sep 17 00:00:00 2001 From: Karlatemp Date: Tue, 24 Nov 2020 12:52:03 +0800 Subject: [PATCH 1/2] Improve PluginDependency.parseFromString --- .../src/plugin/description/PluginDependency.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/backend/mirai-console/src/plugin/description/PluginDependency.kt b/backend/mirai-console/src/plugin/description/PluginDependency.kt index a575e8bb4..a5645a63a 100644 --- a/backend/mirai-console/src/plugin/description/PluginDependency.kt +++ b/backend/mirai-console/src/plugin/description/PluginDependency.kt @@ -66,7 +66,7 @@ public data class PluginDependency @JvmOverloads constructor( public override fun toString(): String = buildString { append(id) versionRequirement?.let { - append(":") + append(':') append(it) } if (isOptional) { @@ -83,10 +83,14 @@ public data class PluginDependency @JvmOverloads constructor( public fun parseFromString(string: String): PluginDependency { require(string.isNotEmpty()) { "string is empty." } val optional = string.endsWith('?') - val (id, version) = string.removeSuffix("?").let { - it.substringBeforeLast(':') to it.substringAfterLast(':', "") + val (id, version) = string.removeSuffix("?").let { rule -> + if (rule.contains(':')) { + rule.substringBeforeLast(':') to rule.substringAfterLast(':') + } else { + rule to null + } } - return PluginDependency(id, version.takeIf(String::isNotBlank), optional) + return PluginDependency(id, version, optional) } } From 67206a6eeccfa5a90b89c6888480d578e0228b75 Mon Sep 17 00:00:00 2001 From: Him188 Date: Tue, 24 Nov 2020 12:52:51 +0800 Subject: [PATCH 2/2] Update docs --- docs/.images/PluginMainDeclaration.png | Bin 0 -> 4125 bytes .../PluginMainServiceNotConfigured.png | Bin 0 -> 6693 bytes docs/Plugins.md | 75 ++++++++++++++++-- 3 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 docs/.images/PluginMainDeclaration.png create mode 100644 docs/.images/PluginMainServiceNotConfigured.png diff --git a/docs/.images/PluginMainDeclaration.png b/docs/.images/PluginMainDeclaration.png new file mode 100644 index 0000000000000000000000000000000000000000..edb518af02cb92d2e92814acdb80d06fddf2c652 GIT binary patch literal 4125 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 literal 0 HcmV?d00001 diff --git a/docs/Plugins.md b/docs/Plugins.md index 63cee40f7..e4645c177 100644 --- a/docs/Plugins.md +++ b/docs/Plugins.md @@ -43,6 +43,9 @@ [为什么不支持热加载和卸载插件?]: QA.md#为什么不支持热加载和卸载插件 [使用 AutoService]: QA.md#使用-autoservice +[MCI]: ../tools/intellij-plugin/ +[MiraiPixel]: ../tools/intellij-plugin/resources/icons/pluginMainDeclaration.png + Mirai Console 运行在 [JVM],支持使用 [Kotlin] 或 [Java] 语言编写的插件。 ## 通用的插件接口 - [`Plugin`] @@ -63,23 +66,75 @@ interface Plugin : CommandOwner { // CommandOwner 是空的 interface [`Plugin`] 接口拥有强扩展性,以支持 Mirai Console 统一管理使用其他编程语言编写的插件 (详见进阶章节 [扩展 - PluginLoader](Extensions.md))。 +## 插件加载器 - [`PluginLoader`] + +Mirai Console 使用不同的插件加载器来加载不同类型插件。 + +Mirai Console 内置 [`JvmPluginLoader`] 以加载 JVM 平台插件(见下文),并允许这些插件注册扩展的插件加载器(见章节 [扩展](Extensions.md)) + ## JVM 平台插件接口 - [`JvmPlugin`] -所有的 JVM 插件都必须实现 [`JvmPlugin`](否则不会被 [`JvmPluginLoader`] 加载)。 +所有的 JVM 插件(特别地,`jar` 插件)都必须实现 [`JvmPlugin`](否则不会被 [`JvmPluginLoader`] 加载)。 Mirai Console 提供一些基础的实现,即 [`AbstractJvmPlugin`],并将 [`JvmPlugin`] 分为 [`KotlinPlugin`] 和 [`JavaPlugin`]。 -### 主类和描述 +### 主类 + +JVM 平台插件的主类应被实现为一个单例(Kotlin `object`,Java 静态初始化的类,详见下文示例)。 **Kotlin 使用者的插件主类应继承 [`KotlinPlugin`]。** **其他 JVM 语言(如 Java)使用者的插件主类应继承 [`JavaPlugin`]。** -#### 描述 -插件描述需要在主类构造器传递给 `super`。因此插件不需要 `plugin.yml`, `plugin.xml` 等配置文件来指示信息。 +#### 定义主类 -Mirai Console 使用类似 `ServiceLoader` 的机制加载插件。 -在 Kotlin,可([使用 AutoService])自动配置 service 信息。 -在 Kotlin 或其他语言,可手动创建 service 文件: 在 `jar` 内 `META-INF/services/net.mamoe.mirai.console.plugin.jvm.JvmPlugin` 文件内存放插件主类全名(以纯文本 UTF-8 存储,文件内容只包含一行插件主类全名). +Mirai Console 使用类似 Java `ServiceLoader` 但更灵活的机制加载插件。 +一个正确的主类定义可以是以下三种任一: + +1. Kotlin (`public`) `object` +```kotlin +object A : KotlinPlugin( /* 描述 */ ) +``` + +2. Java (`public`) 静态初始化单例 `class` +```java +public final class A extends JavaPlugin { + public static final A INSTANCE = new A(); // 必须 public static, 必须名为 INSTANCE + private A() { + super( /* 描述 */ ); + } +} +``` + +3. Java (`public`) `class` +注意:这种由 Mirai Console 构造插件实例的方法是不推荐的。请首选上述静态初始化方法。 +```java +public final class A extends JavaPlugin { + public A() { // 必须公开且无参 + super( /* 描述 */ ); + } +} +``` + +#### 确认主类正确定义 + +在 [Mirai Console IntelliJ 插件][MCI] 的帮助下,一个正确的插件主类定义的行号处会显示 Mirai 像素风格形象图:![MiraiPixel] + +![PluginMainDeclaration](.images/PluginMainDeclaration.png) + +#### 配置主类服务 + +[Mirai Console IntelliJ 插件][MCI] 会自动检查主类服务的配置。在没有正确配置时,IDE 将会警告并为你自动配置: +![PluginMainServiceNotConfigured](.images/PluginMainServiceNotConfigured.png) + +##### 手动配置主类服务 + +若无法使用 IntelliJ 插件,可在资源目录 `META-INF/services/net.mamoe.mirai.console.plugin.jvm.JvmPlugin` 文件内存放插件主类全名(以纯文本 UTF-8 存储,文件内容只包含一行插件主类全名)。 + +在 Kotlin,也可([使用 AutoService])自动配置 service 信息。 + +### 描述 + +插件描述需要在主类构造器传递给 `super`。可以选择直接提供或从 JAR 资源文件读取。 有关插件版本号的限制: - 插件自身的版本要求遵循 [语义化版本 2.0.0](https://semver.org/lang/zh-CN/) 规范, 合格的版本例如: `1.0.0`, `1.0`, `1.0-M1`, `1.0-pre-1` @@ -87,6 +142,10 @@ Mirai Console 使用类似 `ServiceLoader` 的机制加载插件。 有关描述的详细信息可在开发时查看源码内文档。 +### 主类的完整示例 + +基于上文,你现在有以下三种主类定义方式。 + #### 实现 Kotlin 插件主类 一个 Kotlin 插件的主类通常需: @@ -109,7 +168,7 @@ object SchedulePlugin : KotlinPlugin( } ``` -#### 实现 Java 插件 +#### 实现 Java 插件主类 一个 Java 插件的主类通常需: - 继承 [`JavaPlugin`]