mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-10 18:40:15 +08:00
New Project Wizard (#320)
* Add project wizard * Add OptionsStep * Template application fundamentals * Extract BuildSystemType from BuildSystemStep to top-level * Complete templates * Fix build * Fix build * Support Java and Groovy, fix strings in Kotlin templates * Add template for gradle.properties * Disable `depends on` field * Fix Java template * Fix build * Update tools/compiler-annotations/src/CheckerConstants.kt Co-authored-by: Karlatemp <karlatemp@vip.qq.com> * Update tools/intellij-plugin/src/creator/steps/ValidationUtil.kt Co-authored-by: Karlatemp <karlatemp@vip.qq.com> Co-authored-by: Karlatemp <karlatemp@vip.qq.com>
This commit is contained in:
parent
0a0caeeb3a
commit
41d0c16ad1
@ -9,12 +9,19 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.compiler.common
|
package net.mamoe.mirai.console.compiler.common
|
||||||
|
|
||||||
|
import org.intellij.lang.annotations.Language
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @suppress 这是内部 API. 可能在任意时刻变动
|
* @suppress 这是内部 API. 可能在任意时刻变动
|
||||||
*/
|
*/
|
||||||
public object CheckerConstants {
|
public object CheckerConstants {
|
||||||
|
@Language("RegExp")
|
||||||
|
public const val PLUGIN_ID_PATTERN: String = """([a-zA-Z]\w*(?:\.[a-zA-Z]\w*)*)\.([a-zA-Z]\w*(?:-\w+)*)"""
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
public val PLUGIN_ID_REGEX: Regex = Regex("""([a-zA-Z]\w*(?:\.[a-zA-Z]\w*)*)\.([a-zA-Z]\w*(?:-\w+)*)""")
|
public val PLUGIN_ID_REGEX: Regex = Regex(PLUGIN_ID_PATTERN)
|
||||||
|
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
public val PLUGIN_FORBIDDEN_NAMES: Array<String> = arrayOf("main", "console", "plugin", "config", "data")
|
public val PLUGIN_FORBIDDEN_NAMES: Array<String> = arrayOf("main", "console", "plugin", "config", "data")
|
||||||
}
|
}
|
1
tools/intellij-plugin/.gitignore
vendored
1
tools/intellij-plugin/.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
run/idea-sandbox
|
run/idea-sandbox
|
||||||
|
!src/creator/build
|
@ -19,21 +19,30 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven("http://maven.aliyun.com/nexus/content/groups/public/")
|
maven("https://maven.aliyun.com/repository/public")
|
||||||
}
|
}
|
||||||
|
|
||||||
version = Versions.console
|
version = Versions.console
|
||||||
description = "IntelliJ plugin for Mirai Console"
|
description = "IntelliJ plugin for Mirai Console"
|
||||||
|
|
||||||
|
// JVM fails to compile
|
||||||
|
kotlin.target.compilations.forEach { kotlinCompilation ->
|
||||||
|
kotlinCompilation.kotlinOptions.freeCompilerArgs += "-Xuse-ir"
|
||||||
|
} // don't use `useIr()`, compatibility with mirai-console dedicated builds
|
||||||
|
|
||||||
// See https://github.com/JetBrains/gradle-intellij-plugin/
|
// See https://github.com/JetBrains/gradle-intellij-plugin/
|
||||||
intellij {
|
intellij {
|
||||||
version = Versions.intellij
|
version = Versions.intellij
|
||||||
isDownloadSources = true
|
isDownloadSources = true
|
||||||
updateSinceUntilBuild = false
|
updateSinceUntilBuild = false
|
||||||
|
|
||||||
|
sandboxDirectory = projectDir.resolve("run/idea-sandbox").absolutePath
|
||||||
|
|
||||||
setPlugins(
|
setPlugins(
|
||||||
"org.jetbrains.kotlin:${Versions.kotlinIntellijPlugin}", // @eap
|
"org.jetbrains.kotlin:${Versions.kotlinIntellijPlugin}", // @eap
|
||||||
"java"
|
"java",
|
||||||
|
"gradle",
|
||||||
|
"maven"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,13 +62,6 @@ fun File.resolveMkdir(relative: String): File {
|
|||||||
return this.resolve(relative).apply { mkdirs() }
|
return this.resolve(relative).apply { mkdirs() }
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<org.jetbrains.intellij.tasks.RunIdeTask> {
|
|
||||||
// redirect config and cache files so as not to be cleared by task 'clean'
|
|
||||||
val ideaSandbox = project.file("run/idea-sandbox")
|
|
||||||
configDirectory(ideaSandbox.resolveMkdir("config"))
|
|
||||||
systemDirectory(ideaSandbox.resolveMkdir("system"))
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType<org.jetbrains.intellij.tasks.PatchPluginXmlTask> {
|
tasks.withType<org.jetbrains.intellij.tasks.PatchPluginXmlTask> {
|
||||||
sinceBuild("201.*")
|
sinceBuild("201.*")
|
||||||
untilBuild("215.*")
|
untilBuild("215.*")
|
||||||
@ -85,9 +87,17 @@ tasks.withType<org.jetbrains.intellij.tasks.PatchPluginXmlTask> {
|
|||||||
dependencies {
|
dependencies {
|
||||||
api(`jetbrains-annotations`)
|
api(`jetbrains-annotations`)
|
||||||
api(`kotlinx-coroutines-jdk8`)
|
api(`kotlinx-coroutines-jdk8`)
|
||||||
|
api(`kotlinx-coroutines-swing`)
|
||||||
|
|
||||||
api(project(":mirai-console-compiler-common"))
|
api(project(":mirai-console-compiler-common"))
|
||||||
|
|
||||||
compileOnly(`kotlin-compiler`)
|
compileOnly(`kotlin-stdlib-jdk8`)
|
||||||
|
compileOnly("com.jetbrains:ideaIC:${Versions.intellij}")
|
||||||
|
// compileOnly(`kotlin-compiler`)
|
||||||
|
|
||||||
compileOnly(files("libs/ide-common.jar"))
|
compileOnly(files("libs/ide-common.jar"))
|
||||||
|
compileOnly(fileTree("build/idea-sandbox/plugins/Kotlin/lib").filter {
|
||||||
|
!it.name.contains("stdlib")
|
||||||
|
})
|
||||||
|
compileOnly(`kotlin-reflect`)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Copyright 2019-2020 Mamoe Technologies and contributors.
|
~ Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
~
|
~
|
||||||
~ 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
~ 此源代码的使用受 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 through the following link.
|
~ Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
~
|
~
|
||||||
~ https://github.com/mamoe/mirai/blob/master/LICENSE
|
~ https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
-->
|
-->
|
||||||
@ -22,7 +22,14 @@
|
|||||||
<depends>com.intellij.modules.platform</depends>
|
<depends>com.intellij.modules.platform</depends>
|
||||||
<depends>org.jetbrains.kotlin</depends>
|
<depends>org.jetbrains.kotlin</depends>
|
||||||
|
|
||||||
|
<depends>org.jetbrains.idea.maven</depends>
|
||||||
|
<depends>com.intellij.gradle</depends>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
|
<moduleType id="MIRAI_MODULE_TYPE" implementationClass="net.mamoe.mirai.console.intellij.creator.MiraiModuleType"/>
|
||||||
|
<moduleBuilder id="MIRAI_MODULE" builderClass="net.mamoe.mirai.console.intellij.creator.MiraiModuleBuilder"/>
|
||||||
|
|
||||||
|
<fileTemplateGroup implementation="net.mamoe.mirai.console.intellij.assets.FileTemplateRegistrar"/>
|
||||||
<codeInsight.lineMarkerProvider language="JAVA"
|
<codeInsight.lineMarkerProvider language="JAVA"
|
||||||
implementationClass="net.mamoe.mirai.console.intellij.line.marker.PluginMainLineMarkerProvider"/>
|
implementationClass="net.mamoe.mirai.console.intellij.line.marker.PluginMainLineMarkerProvider"/>
|
||||||
<codeInsight.lineMarkerProvider language="kotlin"
|
<codeInsight.lineMarkerProvider language="kotlin"
|
||||||
|
123
tools/intellij-plugin/resources/fileTemplates/j2ee/.gitignore.ft
Normal file
123
tools/intellij-plugin/resources/fileTemplates/j2ee/.gitignore.ft
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# User-specific stuff
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
### Linux ###
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
### macOS ###
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
### Windows ###
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
### Gradle ###
|
||||||
|
.gradle
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Ignore Gradle GUI config
|
||||||
|
gradle-app.setting
|
||||||
|
|
||||||
|
# Cache of project
|
||||||
|
.gradletasknamecache
|
||||||
|
|
||||||
|
### Gradle Patch ###
|
||||||
|
**/build/
|
||||||
|
|
||||||
|
# Common working directory
|
||||||
|
run/
|
||||||
|
|
||||||
|
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||||
|
!gradle-wrapper.jar
|
@ -0,0 +1,14 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
~
|
||||||
|
~ 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
~ Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
~
|
||||||
|
~ https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
-->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>This is a built-in file template used to create a new .gitignore for Gradle projects.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,15 @@
|
|||||||
|
plugins {
|
||||||
|
id 'org.jetbrains.kotlin.jvm' version '$KOTLIN_VERSION'
|
||||||
|
id 'org.jetbrains.kotlin.plugin.serialization' version '$KOTLIN_VERSION'
|
||||||
|
|
||||||
|
id 'net.mamoe.mirai-console' version '$MIRAI_VERSION'
|
||||||
|
}
|
||||||
|
|
||||||
|
group = '$GROUP_ID'
|
||||||
|
version = '$VERSION'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
#if ($USE_PROXY_REPO) maven { url 'https://maven.aliyun.com/repository/public' } #end
|
||||||
|
|
||||||
|
mavenCentral()
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
~
|
||||||
|
~ 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
~ Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
~
|
||||||
|
~ https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
-->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>This is a built-in file template used to create a new build.gradle for Mirai Console Plugin projects.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,16 @@
|
|||||||
|
plugins {
|
||||||
|
val kotlinVersion = "$KOTLIN_VERSION"
|
||||||
|
kotlin("jvm") version kotlinVersion
|
||||||
|
kotlin("plugin.serialization") version kotlinVersion
|
||||||
|
|
||||||
|
id("net.mamoe.mirai-console") version "$MIRAI_VERSION"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "$GROUP_ID"
|
||||||
|
version = "$VERSION"
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
#if ($USE_PROXY_REPO) maven("https://maven.aliyun.com/repository/public") #end
|
||||||
|
|
||||||
|
mavenCentral()
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
~
|
||||||
|
~ 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
~ Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
~
|
||||||
|
~ https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
-->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>This is a built-in file template used to create a new build.gradle.kts for Mirai Console Plugin projects.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,27 @@
|
|||||||
|
package $PACKAGE_NAME;
|
||||||
|
|
||||||
|
import net.mamoe.mirai.console.plugin.jvm.JavaPlugin;
|
||||||
|
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescriptionBuilder;
|
||||||
|
|
||||||
|
public final class ${CLASS_NAME} extends JavaPlugin {
|
||||||
|
public static final ${CLASS_NAME} INSTANCE = new ${CLASS_NAME}();
|
||||||
|
|
||||||
|
#set($HAS_DETAILS = ${PLUGIN_AUTHOR} != "" || ${PLUGIN_DEPENDS_ON} != "" || ${PLUGIN_INFO} != "" || ${PLUGIN_NAME} != "")
|
||||||
|
private ${CLASS_NAME}() {
|
||||||
|
#if($HAS_DETAILS == false)
|
||||||
|
super(new JvmPluginDescriptionBuilder("$PLUGIN_ID", "$PLUGIN_VERSION").build());#end
|
||||||
|
#if($HAS_DETAILS)
|
||||||
|
super(new JvmPluginDescriptionBuilder("$PLUGIN_ID", "$PLUGIN_VERSION")
|
||||||
|
#if($PLUGIN_NAME != "").name("$PLUGIN_NAME")
|
||||||
|
#end#if($PLUGIN_INFO != "").info("$PLUGIN_INFO")
|
||||||
|
#end#if($PLUGIN_AUTHOR != "").author("$PLUGIN_AUTHOR")
|
||||||
|
#end#if($PLUGIN_DEPENDS_ON != "").dependsOn("$PLUGIN_DEPENDS_ON")
|
||||||
|
#end
|
||||||
|
.build());#end
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
getLogger().info("Plugin loaded!");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package $PACKAGE_NAME;
|
||||||
|
|
||||||
|
import net.mamoe.mirai.console.plugin.jvm.JavaPlugin;
|
||||||
|
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription;
|
||||||
|
|
||||||
|
public final class ${CLASS_NAME} extends JavaPlugin {
|
||||||
|
public static final ${CLASS_NAME} INSTANCE = new ${CLASS_NAME}();
|
||||||
|
|
||||||
|
private ${CLASS_NAME}() {
|
||||||
|
super(JvmPluginDescription.loadFromResource("plugin.yml", ${CLASS_NAME}.class.getClassLoader()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
getLogger().info("Plugin loaded!");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
~
|
||||||
|
~ 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
~ Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
~
|
||||||
|
~ https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
-->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>This is a built-in file template used to create a new plugin main class for Mirai Console Plugin projects.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,27 @@
|
|||||||
|
package $PACKAGE_NAME
|
||||||
|
|
||||||
|
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
|
||||||
|
import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin
|
||||||
|
import net.mamoe.mirai.utils.info
|
||||||
|
#set($HAS_DETAILS = ${PLUGIN_AUTHOR} != "" || ${PLUGIN_DEPENDS_ON} != "" || ${PLUGIN_INFO} != "")
|
||||||
|
object $CLASS_NAME : KotlinPlugin(
|
||||||
|
JvmPluginDescription(
|
||||||
|
id = "${PLUGIN_ID}",
|
||||||
|
#if(${PLUGIN_NAME} != "")name = "${PLUGIN_NAME}",
|
||||||
|
#end
|
||||||
|
version = "${PLUGIN_VERSION}",
|
||||||
|
) #if($HAS_DETAILS){
|
||||||
|
#end
|
||||||
|
#if(${PLUGIN_AUTHOR} != "")author("${PLUGIN_AUTHOR}")
|
||||||
|
#end
|
||||||
|
#if(${PLUGIN_DEPENDS_ON} != "")dependsOn("${PLUGIN_DEPENDS_ON}")
|
||||||
|
#end
|
||||||
|
#if(${PLUGIN_INFO} != "")info("""${PLUGIN_INFO}""")
|
||||||
|
#end
|
||||||
|
#if($HAS_DETAILS) }
|
||||||
|
#end
|
||||||
|
) {
|
||||||
|
override fun onEnable() {
|
||||||
|
logger.info { "Plugin loaded" }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
~
|
||||||
|
~ 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
~ Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
~
|
||||||
|
~ https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
-->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>This is a built-in file template used to create a new plugin main class for Mirai Console Plugin projects.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1 @@
|
|||||||
|
rootProject.name = "$ARTIFACT_ID"
|
@ -0,0 +1,14 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
~
|
||||||
|
~ 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
~ Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
~
|
||||||
|
~ https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
-->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>This is a built-in file template used to create a new settings.gradle.kts for Mirai Console Plugin projects.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1 @@
|
|||||||
|
kotlin.code.style=official
|
@ -0,0 +1,14 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
~
|
||||||
|
~ 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
~ Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
~
|
||||||
|
~ https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
-->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>This is a built-in file template used to create a new gradle.properties for Mirai Console Plugin projects.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 through the following link.
|
|
||||||
*
|
|
||||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.mamoe.mirai.console.intellij
|
|
||||||
|
|
||||||
import com.intellij.openapi.util.IconLoader
|
|
||||||
import javax.swing.Icon
|
|
||||||
|
|
||||||
object Icons {
|
|
||||||
val CommandDeclaration: Icon = IconLoader.getIcon("/icons/commandDeclaration.svg", Icons::class.java)
|
|
||||||
val PluginMainDeclaration: Icon = IconLoader.getIcon("/icons/pluginMainDeclaration.png", Icons::class.java)
|
|
||||||
}
|
|
35
tools/intellij-plugin/src/assets/Assets.kt
Normal file
35
tools/intellij-plugin/src/assets/Assets.kt
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.assets
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.IconLoader
|
||||||
|
import javax.swing.Icon
|
||||||
|
|
||||||
|
object Icons {
|
||||||
|
val CommandDeclaration: Icon = IconLoader.getIcon("/icons/commandDeclaration.svg", Icons::class.java)
|
||||||
|
val PluginMainDeclaration: Icon = IconLoader.getIcon("/icons/pluginMainDeclaration.png", Icons::class.java)
|
||||||
|
|
||||||
|
val MainIcon: Icon = PluginMainDeclaration
|
||||||
|
}
|
||||||
|
|
||||||
|
object FT { // file template
|
||||||
|
const val BuildGradleKts = "Plugin build.gradle.kts"
|
||||||
|
const val BuildGradle = "Plugin build.gradle"
|
||||||
|
|
||||||
|
const val SettingsGradleKts = "Plugin settings.gradle.kts"
|
||||||
|
const val SettingsGradle = "Plugin settings.gradle"
|
||||||
|
|
||||||
|
const val GradleProperties = "Gradle gradle.properties"
|
||||||
|
|
||||||
|
const val PluginMainKt = "Plugin main class Kotlin.kt"
|
||||||
|
const val PluginMainJava = "Plugin main class Java.java"
|
||||||
|
|
||||||
|
const val Gitignore = ".gitignore"
|
||||||
|
}
|
35
tools/intellij-plugin/src/assets/FileTemplateRegistrar.kt
Normal file
35
tools/intellij-plugin/src/assets/FileTemplateRegistrar.kt
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.assets
|
||||||
|
|
||||||
|
import com.intellij.ide.fileTemplates.FileTemplateDescriptor
|
||||||
|
import com.intellij.ide.fileTemplates.FileTemplateGroupDescriptor
|
||||||
|
|
||||||
|
class FileTemplateRegistrar : com.intellij.ide.fileTemplates.FileTemplateGroupDescriptorFactory {
|
||||||
|
override fun getFileTemplatesDescriptor(): FileTemplateGroupDescriptor {
|
||||||
|
return FileTemplateGroupDescriptor("Mirai", Icons.PluginMainDeclaration).apply {
|
||||||
|
addTemplate(FileTemplateDescriptor(FT.BuildGradleKts))
|
||||||
|
addTemplate(FileTemplateDescriptor(FT.BuildGradle))
|
||||||
|
|
||||||
|
addTemplate(FileTemplateDescriptor(FT.PluginMainKt))
|
||||||
|
addTemplate(FileTemplateDescriptor(FT.PluginMainJava))
|
||||||
|
|
||||||
|
addTemplate(FileTemplateDescriptor(FT.GradleProperties))
|
||||||
|
|
||||||
|
addTemplate(FileTemplateDescriptor(FT.SettingsGradleKts))
|
||||||
|
addTemplate(FileTemplateDescriptor(FT.SettingsGradle))
|
||||||
|
|
||||||
|
addTemplate(FileTemplateDescriptor(FT.Gitignore))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
120
tools/intellij-plugin/src/creator/MiraiModuleBuilder.kt
Normal file
120
tools/intellij-plugin/src/creator/MiraiModuleBuilder.kt
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator
|
||||||
|
|
||||||
|
import com.intellij.ide.util.projectWizard.JavaModuleBuilder
|
||||||
|
import com.intellij.ide.util.projectWizard.ModuleWizardStep
|
||||||
|
import com.intellij.ide.util.projectWizard.WizardContext
|
||||||
|
import com.intellij.openapi.Disposable
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.module.JavaModuleType
|
||||||
|
import com.intellij.openapi.module.ModuleType
|
||||||
|
import com.intellij.openapi.progress.ProgressManager
|
||||||
|
import com.intellij.openapi.project.DumbAwareRunnable
|
||||||
|
import com.intellij.openapi.project.DumbService
|
||||||
|
import com.intellij.openapi.roots.ModifiableRootModel
|
||||||
|
import com.intellij.openapi.roots.ui.configuration.ModulesProvider
|
||||||
|
import com.intellij.openapi.startup.StartupManager
|
||||||
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
|
import com.intellij.openapi.vfs.LocalFileSystem
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import net.mamoe.mirai.console.intellij.assets.Icons
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.steps.BuildSystemStep
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.steps.OptionsStep
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.steps.PluginCoordinatesStep
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.tasks.CreateProjectTask
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.nio.file.Paths
|
||||||
|
|
||||||
|
class MiraiModuleBuilder : JavaModuleBuilder() {
|
||||||
|
override fun getPresentableName() = MiraiModuleType.NAME
|
||||||
|
override fun getNodeIcon() = Icons.MainIcon
|
||||||
|
override fun getGroupName() = MiraiModuleType.NAME
|
||||||
|
override fun getWeight() = BUILD_SYSTEM_WEIGHT - 1
|
||||||
|
override fun getBuilderId() = ID
|
||||||
|
override fun getModuleType(): ModuleType<*> = JavaModuleType.getModuleType()
|
||||||
|
override fun getParentGroup() = MiraiModuleType.NAME
|
||||||
|
|
||||||
|
override fun setupRootModel(rootModel: ModifiableRootModel) {
|
||||||
|
val project = rootModel.project
|
||||||
|
val (root, vFile) = createAndGetRoot()
|
||||||
|
rootModel.addContentEntry(vFile)
|
||||||
|
|
||||||
|
if (moduleJdk != null) {
|
||||||
|
rootModel.sdk = moduleJdk
|
||||||
|
} else {
|
||||||
|
rootModel.inheritSdk()
|
||||||
|
}
|
||||||
|
|
||||||
|
val r = DumbAwareRunnable {
|
||||||
|
ProgressManager.getInstance().run(CreateProjectTask(root, rootModel.module, model))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (project.isDisposed) return
|
||||||
|
|
||||||
|
if (
|
||||||
|
ApplicationManager.getApplication().isUnitTestMode ||
|
||||||
|
ApplicationManager.getApplication().isHeadlessEnvironment
|
||||||
|
) {
|
||||||
|
r.run()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!project.isInitialized) {
|
||||||
|
StartupManager.getInstance(project).registerPostStartupActivity(r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
DumbService.getInstance(project).runWhenSmart(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createAndGetRoot(): Pair<Path, VirtualFile> {
|
||||||
|
val temp = contentEntryPath ?: throw IllegalStateException("Failed to get content entry path")
|
||||||
|
|
||||||
|
val pathName = FileUtil.toSystemIndependentName(temp)
|
||||||
|
|
||||||
|
val path = Paths.get(pathName)
|
||||||
|
Files.createDirectories(path)
|
||||||
|
val vFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(pathName)
|
||||||
|
?: throw IllegalStateException("Failed to refresh and file file: $path")
|
||||||
|
|
||||||
|
return path to vFile
|
||||||
|
}
|
||||||
|
|
||||||
|
private val scope = CoroutineScope(SupervisorJob())
|
||||||
|
private val model = MiraiProjectModel.create(scope)
|
||||||
|
|
||||||
|
override fun cleanup() {
|
||||||
|
super.cleanup()
|
||||||
|
scope.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createWizardSteps(
|
||||||
|
wizardContext: WizardContext,
|
||||||
|
modulesProvider: ModulesProvider
|
||||||
|
): Array<ModuleWizardStep> {
|
||||||
|
return arrayOf(
|
||||||
|
BuildSystemStep(model),
|
||||||
|
PluginCoordinatesStep(model),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCustomOptionsStep(context: WizardContext?, parentDisposable: Disposable?): ModuleWizardStep =
|
||||||
|
OptionsStep()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val ID = "MIRAI_MODULE"
|
||||||
|
}
|
||||||
|
}
|
32
tools/intellij-plugin/src/creator/MiraiModuleType.kt
Normal file
32
tools/intellij-plugin/src/creator/MiraiModuleType.kt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator
|
||||||
|
|
||||||
|
import com.intellij.openapi.module.JavaModuleType
|
||||||
|
import com.intellij.openapi.module.ModuleTypeManager
|
||||||
|
import net.mamoe.mirai.console.intellij.assets.Icons
|
||||||
|
|
||||||
|
class MiraiModuleType : JavaModuleType() {
|
||||||
|
override fun createModuleBuilder() = MiraiModuleBuilder()
|
||||||
|
override fun getIcon() = Icons.MainIcon
|
||||||
|
override fun getNodeIcon(isOpened: Boolean) = Icons.MainIcon
|
||||||
|
override fun getName() = NAME
|
||||||
|
override fun getDescription() =
|
||||||
|
"Modules used for developing plugins for <b>Mirai Console</b>"
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ID = "MIRAI_MODULE_TYPE"
|
||||||
|
const val NAME = "Mirai"
|
||||||
|
|
||||||
|
val instance: MiraiModuleType
|
||||||
|
get() = ModuleTypeManager.getInstance().findByID(ID) as MiraiModuleType
|
||||||
|
}
|
||||||
|
}
|
108
tools/intellij-plugin/src/creator/MiraiProjectModel.kt
Normal file
108
tools/intellij-plugin/src/creator/MiraiProjectModel.kt
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Deferred
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.MiraiVersionKind.Companion.getMiraiVersionListAsync
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.steps.BuildSystemType
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.steps.LanguageType
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.tasks.adjustToClassName
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.tasks.lateinitReadWriteProperty
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
|
data class ProjectCoordinates(
|
||||||
|
val groupId: String, // already checked by pattern
|
||||||
|
val artifactId: String,
|
||||||
|
val version: String
|
||||||
|
) {
|
||||||
|
val packageName: String get() = groupId
|
||||||
|
}
|
||||||
|
|
||||||
|
data class PluginCoordinates(
|
||||||
|
val id: String?,
|
||||||
|
val name: String?,
|
||||||
|
val author: String?,
|
||||||
|
val info: String?,
|
||||||
|
val dependsOn: String?,
|
||||||
|
)
|
||||||
|
|
||||||
|
class MiraiProjectModel private constructor() {
|
||||||
|
// STEP: ProjectCreator
|
||||||
|
|
||||||
|
var projectCoordinates: ProjectCoordinates? = null
|
||||||
|
var buildSystemType: BuildSystemType = BuildSystemType.DEFAULT
|
||||||
|
var languageType: LanguageType = LanguageType.DEFAULT
|
||||||
|
|
||||||
|
var miraiVersion: String? = null
|
||||||
|
var pluginCoordinates: PluginCoordinates? = null
|
||||||
|
|
||||||
|
var mainClassQualifiedName: String by lateinitReadWriteProperty { "$packageName.$mainClassSimpleName" }
|
||||||
|
var mainClassSimpleName: String by lateinitReadWriteProperty {
|
||||||
|
pluginCoordinates?.run {
|
||||||
|
name?.adjustToClassName() ?: id?.substringAfterLast('.')?.adjustToClassName()
|
||||||
|
} ?: "PluginMain"
|
||||||
|
}
|
||||||
|
var packageName: String by lateinitReadWriteProperty { projectCoordinates.checkNotNull("projectCoordinates").groupId }
|
||||||
|
|
||||||
|
|
||||||
|
var availableMiraiVersions: Deferred<Set<MiraiVersion>>? = null
|
||||||
|
val availableMiraiVersionsOrFail get() = availableMiraiVersions.checkNotNull("availableMiraiVersions")
|
||||||
|
|
||||||
|
fun checkValuesNotNull() {
|
||||||
|
checkNotNull(miraiVersion) { "miraiVersion" }
|
||||||
|
checkNotNull(pluginCoordinates) { "pluginCoordinates" }
|
||||||
|
checkNotNull(projectCoordinates) { "projectCoordinates" }
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun create(scope: CoroutineScope): MiraiProjectModel {
|
||||||
|
return MiraiProjectModel().apply {
|
||||||
|
availableMiraiVersions = scope.getMiraiVersionListAsync()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
val MiraiProjectModel.templateProperties: Map<String, String?>
|
||||||
|
get() {
|
||||||
|
val projectCoordinates = projectCoordinates!!
|
||||||
|
val pluginCoordinates = pluginCoordinates!!
|
||||||
|
return mapOf(
|
||||||
|
"KOTLIN_VERSION" to KotlinVersion.CURRENT.toString(),
|
||||||
|
"MIRAI_VERSION" to miraiVersion!!,
|
||||||
|
"GROUP_ID" to projectCoordinates.groupId,
|
||||||
|
"VERSION" to projectCoordinates.version,
|
||||||
|
"USE_PROXY_REPO" to "true",
|
||||||
|
"ARTIFACT_ID" to projectCoordinates.artifactId,
|
||||||
|
|
||||||
|
"PLUGIN_ID" to pluginCoordinates.id,
|
||||||
|
"PLUGIN_NAME" to languageType.escapeString(pluginCoordinates.name),
|
||||||
|
"PLUGIN_AUTHOR" to languageType.escapeString(pluginCoordinates.author),
|
||||||
|
"PLUGIN_INFO" to languageType.escapeRawString(pluginCoordinates.info),
|
||||||
|
"PLUGIN_DEPENDS_ON" to pluginCoordinates.dependsOn,
|
||||||
|
"PLUGIN_VERSION" to projectCoordinates.version,
|
||||||
|
|
||||||
|
"PACKAGE_NAME" to packageName,
|
||||||
|
"CLASS_NAME" to mainClassSimpleName,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Any> T?.checkNotNull(name: String): T {
|
||||||
|
contract {
|
||||||
|
returns() implies (this@checkNotNull != null)
|
||||||
|
}
|
||||||
|
checkNotNull(this) {
|
||||||
|
"$name is not yet initialized."
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
88
tools/intellij-plugin/src/creator/MiraiVersion.kt
Normal file
88
tools/intellij-plugin/src/creator/MiraiVersion.kt
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator
|
||||||
|
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import org.jsoup.Jsoup
|
||||||
|
|
||||||
|
typealias MiraiVersion = String
|
||||||
|
|
||||||
|
enum class MiraiVersionKind {
|
||||||
|
Stable {
|
||||||
|
override fun isThatKind(version: String): Boolean = version matches REGEX_STABLE
|
||||||
|
},
|
||||||
|
Prerelease {
|
||||||
|
override fun isThatKind(version: String): Boolean = !version.contains("-dev") // && (version.contains("-M") || version.contains("-RC"))
|
||||||
|
},
|
||||||
|
Nightly {
|
||||||
|
override fun isThatKind(version: String): Boolean = true // version.contains("-dev")
|
||||||
|
}, ;
|
||||||
|
|
||||||
|
abstract fun isThatKind(version: String): Boolean
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val DEFAULT = Stable
|
||||||
|
|
||||||
|
private val REGEX_STABLE = Regex("""^\d+\.\d+(?:\.\d+)?$""")
|
||||||
|
|
||||||
|
private suspend fun getMiraiVersionList(): Set<MiraiVersion>? {
|
||||||
|
val xml = runInterruptible {
|
||||||
|
// https://maven.aliyun.com/repository/central/net/mamoe/mirai-core/maven-metadata.xml
|
||||||
|
// https://repo.maven.apache.org/maven2/net/mamoe/mirai-core/maven-metadata.xml
|
||||||
|
kotlin.runCatching {
|
||||||
|
Jsoup.connect("https://maven.aliyun.com/repository/central/net/mamoe/mirai-core/maven-metadata.xml").get()
|
||||||
|
}.recoverCatching {
|
||||||
|
Jsoup.connect("https://repo.maven.apache.org/maven2/net/mamoe/mirai-core/maven-metadata.xml").get()
|
||||||
|
}.getOrNull()
|
||||||
|
}?.body()?.toString() ?: return null
|
||||||
|
|
||||||
|
return Regex("""<version>\s*(.*?)\s*</version>""").findAll(xml).mapNotNull { it.groupValues[1] }.toSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun CoroutineScope.getMiraiVersionListAsync(): Deferred<Set<MiraiVersion>> {
|
||||||
|
return async(CoroutineName("getMiraiVersionListAsync")) {
|
||||||
|
getMiraiVersionList()?: setOf("+")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<metadata>
|
||||||
|
<groupId>net.mamoe</groupId>
|
||||||
|
<artifactId>mirai-core</artifactId>
|
||||||
|
<versioning>
|
||||||
|
<latest>2.5.0-dev-2</latest>
|
||||||
|
<release>2.5.0-dev-2</release>
|
||||||
|
<versions>
|
||||||
|
<version>2.4-RC</version>
|
||||||
|
<version>2.4-M1-dev-publish-3</version>
|
||||||
|
<version>2.4.0-dev-publish-2</version>
|
||||||
|
<version>2.4.0</version>
|
||||||
|
<version>2.4.1</version>
|
||||||
|
<version>2.4.2</version>
|
||||||
|
<version>2.5-RC-dev-1</version>
|
||||||
|
<version>2.5-M1</version>
|
||||||
|
<version>2.5-M2-dev-2</version>
|
||||||
|
<version>2.5-M2</version>
|
||||||
|
<version>2.5.0-dev-android-1</version>
|
||||||
|
<version>2.5.0-dev-1</version>
|
||||||
|
<version>2.5.0-dev-2</version>
|
||||||
|
</versions>
|
||||||
|
<lastUpdated>20210319014025</lastUpdated>
|
||||||
|
</versioning>
|
||||||
|
</metadata>
|
||||||
|
|
||||||
|
*/
|
105
tools/intellij-plugin/src/creator/build/ProjectCreator.kt
Normal file
105
tools/intellij-plugin/src/creator/build/ProjectCreator.kt
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator.build
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.actions.ReformatCodeProcessor
|
||||||
|
import com.intellij.openapi.module.Module
|
||||||
|
import com.intellij.openapi.progress.ProgressIndicator
|
||||||
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.testFramework.writeChild
|
||||||
|
import net.mamoe.mirai.console.intellij.assets.FT
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.MiraiProjectModel
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.tasks.getTemplate
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.tasks.invokeAndWait
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.tasks.runWriteActionAndWait
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.tasks.writeChild
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.templateProperties
|
||||||
|
import org.jetbrains.kotlin.idea.core.util.toPsiFile
|
||||||
|
|
||||||
|
sealed class ProjectCreator(
|
||||||
|
val module: Module,
|
||||||
|
val root: VirtualFile,
|
||||||
|
val model: MiraiProjectModel,
|
||||||
|
) {
|
||||||
|
val project get() = module.project
|
||||||
|
|
||||||
|
init {
|
||||||
|
model.checkValuesNotNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected val filesChanged = mutableListOf<VirtualFile>()
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
protected fun addFileChanged(vf: VirtualFile) {
|
||||||
|
filesChanged.add(vf)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun getTemplate(name: String) = project.getTemplate(name, model.templateProperties)
|
||||||
|
|
||||||
|
fun doFinish(indicator: ProgressIndicator) {
|
||||||
|
indicator.text2 = "Reformatting files"
|
||||||
|
invokeAndWait {
|
||||||
|
for (file in filesChanged) {
|
||||||
|
val psi = file.toPsiFile(project) ?: continue
|
||||||
|
ReformatCodeProcessor(psi, false).run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun createProject(
|
||||||
|
module: Module,
|
||||||
|
root: VirtualFile,
|
||||||
|
model: MiraiProjectModel,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class GradleProjectCreator(
|
||||||
|
module: Module, root: VirtualFile, model: MiraiProjectModel,
|
||||||
|
) : ProjectCreator(module, root, model) {
|
||||||
|
override fun createProject(module: Module, root: VirtualFile, model: MiraiProjectModel) {
|
||||||
|
runWriteActionAndWait {
|
||||||
|
VfsUtil.createDirectoryIfMissing(root, "src/main/${model.languageType.sourceSetDirName}")
|
||||||
|
VfsUtil.createDirectoryIfMissing(root, "src/main/resources")
|
||||||
|
filesChanged += root.writeChild(model.languageType.pluginMainClassFile(this))
|
||||||
|
filesChanged += root.writeChild("src/main/resources/META-INF/services/net.mamoe.mirai.console.plugin.jvm.JvmPlugin", model.mainClassQualifiedName)
|
||||||
|
filesChanged += root.writeChild("gradle.properties", getTemplate(FT.GradleProperties))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GradleKotlinProjectCreator(
|
||||||
|
module: Module, root: VirtualFile, model: MiraiProjectModel,
|
||||||
|
) : GradleProjectCreator(
|
||||||
|
module, root, model,
|
||||||
|
) {
|
||||||
|
override fun createProject(module: Module, root: VirtualFile, model: MiraiProjectModel) {
|
||||||
|
super.createProject(module, root, model)
|
||||||
|
runWriteActionAndWait {
|
||||||
|
filesChanged += root.writeChild("build.gradle.kts", getTemplate(FT.BuildGradleKts))
|
||||||
|
filesChanged += root.writeChild("settings.gradle.kts", getTemplate(FT.SettingsGradleKts))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GradleGroovyProjectCreator(
|
||||||
|
module: Module, root: VirtualFile, model: MiraiProjectModel,
|
||||||
|
) : GradleProjectCreator(
|
||||||
|
module, root, model,
|
||||||
|
) {
|
||||||
|
override fun createProject(module: Module, root: VirtualFile, model: MiraiProjectModel) {
|
||||||
|
super.createProject(module, root, model)
|
||||||
|
runWriteActionAndWait {
|
||||||
|
filesChanged += root.writeChild("build.gradle", getTemplate(FT.BuildGradle))
|
||||||
|
filesChanged += root.writeChild("settings.gradle", getTemplate(FT.SettingsGradle))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
111
tools/intellij-plugin/src/creator/steps/BuildSystemStep.form
Normal file
111
tools/intellij-plugin/src/creator/steps/BuildSystemStep.form
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="net.mamoe.mirai.console.intellij.creator.steps.BuildSystemStep">
|
||||||
|
<grid id="27dc6" binding="panel" layout-manager="GridLayoutManager" row-count="5" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="10" vgap="10">
|
||||||
|
<margin top="10" left="10" bottom="10" right="10"/>
|
||||||
|
<constraints>
|
||||||
|
<xy x="20" y="20" width="589" height="400"/>
|
||||||
|
</constraints>
|
||||||
|
<properties/>
|
||||||
|
<border type="none" title-justification="1" title-position="3"/>
|
||||||
|
<children>
|
||||||
|
<component id="539d6" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="ArtifactId:"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="f1b7a" class="javax.swing.JTextField" binding="artifactIdField">
|
||||||
|
<constraints>
|
||||||
|
<grid row="1" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||||
|
<preferred-size width="150" height="-1"/>
|
||||||
|
</grid>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="plugin"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="2c1ec" class="javax.swing.JTextField" binding="groupIdField">
|
||||||
|
<constraints>
|
||||||
|
<grid row="0" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||||
|
<preferred-size width="150" height="-1"/>
|
||||||
|
</grid>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="org.example"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="2e485" class="javax.swing.JTextField" binding="versionField">
|
||||||
|
<constraints>
|
||||||
|
<grid row="2" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||||
|
<preferred-size width="150" height="-1"/>
|
||||||
|
</grid>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="1.0-SNAPSHOT"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="6d341" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="Version:"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<vspacer id="3151a">
|
||||||
|
<constraints>
|
||||||
|
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
</vspacer>
|
||||||
|
<hspacer id="8d42b">
|
||||||
|
<constraints>
|
||||||
|
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
|
||||||
|
<preferred-size width="229" height="11"/>
|
||||||
|
</grid>
|
||||||
|
</constraints>
|
||||||
|
</hspacer>
|
||||||
|
<component id="33f22" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="GroupId:"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="452df" class="javax.swing.JComboBox" binding="buildSystemBox">
|
||||||
|
<constraints>
|
||||||
|
<grid row="3" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<model/>
|
||||||
|
<toolTipText value="Build system"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="45fb1" class="javax.swing.JComboBox" binding="languageBox">
|
||||||
|
<constraints>
|
||||||
|
<grid row="3" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<model/>
|
||||||
|
<toolTipText value="Language"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="303a9" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="4" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value=""/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
</children>
|
||||||
|
</grid>
|
||||||
|
<buttonGroups>
|
||||||
|
<group name="radioButtonGroup">
|
||||||
|
<member id="80d0b"/>
|
||||||
|
<member id="9d2d8"/>
|
||||||
|
</group>
|
||||||
|
</buttonGroups>
|
||||||
|
</form>
|
80
tools/intellij-plugin/src/creator/steps/BuildSystemStep.kt
Normal file
80
tools/intellij-plugin/src/creator/steps/BuildSystemStep.kt
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator.steps
|
||||||
|
|
||||||
|
import com.intellij.ide.util.projectWizard.ModuleWizardStep
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.MiraiProjectModel
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.ProjectCoordinates
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.tasks.PACKAGE_PATTERN
|
||||||
|
import net.mamoe.mirai.console.intellij.diagnostics.ContextualParametersChecker.Companion.SEMANTIC_VERSIONING_PATTERN
|
||||||
|
import javax.swing.JComboBox
|
||||||
|
import javax.swing.JPanel
|
||||||
|
import javax.swing.JTextField
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see MiraiProjectModel.projectCoordinates
|
||||||
|
* @see MiraiProjectModel.languageType
|
||||||
|
* @see MiraiProjectModel.buildSystemType
|
||||||
|
*/
|
||||||
|
class BuildSystemStep(
|
||||||
|
private val model: MiraiProjectModel
|
||||||
|
) : ModuleWizardStep() {
|
||||||
|
|
||||||
|
private lateinit var panel: JPanel
|
||||||
|
|
||||||
|
@field:Validation.NotBlank("Group ID")
|
||||||
|
@field:Validation.Pattern("Group ID", PACKAGE_PATTERN)
|
||||||
|
private lateinit var groupIdField: JTextField
|
||||||
|
|
||||||
|
@field:Validation.NotBlank("Artifact ID")
|
||||||
|
@field:Validation.Pattern("Artifact ID", PACKAGE_PATTERN)
|
||||||
|
private lateinit var artifactIdField: JTextField
|
||||||
|
|
||||||
|
@field:Validation.NotBlank("Version")
|
||||||
|
@field:Validation.Pattern("Version", SEMANTIC_VERSIONING_PATTERN)
|
||||||
|
private lateinit var versionField: JTextField
|
||||||
|
|
||||||
|
private lateinit var buildSystemBox: JComboBox<BuildSystemType>
|
||||||
|
private lateinit var languageBox: JComboBox<LanguageType>
|
||||||
|
|
||||||
|
override fun getComponent() = panel
|
||||||
|
|
||||||
|
override fun updateStep() {
|
||||||
|
buildSystemBox.removeAllItems()
|
||||||
|
buildSystemBox.isEnabled = true
|
||||||
|
BuildSystemType.values().forEach { buildSystemBox.addItem(it) }
|
||||||
|
buildSystemBox.selectedItem = BuildSystemType.DEFAULT
|
||||||
|
buildSystemBox.toolTipText = """
|
||||||
|
Gradle Kotlin DSL: build.gradle.kts <br/>
|
||||||
|
Gradle Groovy DSL: build.gradle
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
languageBox.removeAllItems()
|
||||||
|
languageBox.isEnabled = true
|
||||||
|
LanguageType.values().forEach { languageBox.addItem(it) }
|
||||||
|
languageBox.selectedItem = LanguageType.DEFAULT
|
||||||
|
buildSystemBox.toolTipText = """
|
||||||
|
Language for main class.
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateDataModel() {
|
||||||
|
model.buildSystemType = this.buildSystemBox.selectedItem as BuildSystemType
|
||||||
|
model.languageType = this.languageBox.selectedItem as LanguageType
|
||||||
|
model.projectCoordinates = ProjectCoordinates(
|
||||||
|
groupId = groupIdField.text,
|
||||||
|
artifactId = artifactIdField.text,
|
||||||
|
version = versionField.text
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun validate() = Validation.doValidation(this)
|
||||||
|
}
|
38
tools/intellij-plugin/src/creator/steps/BuildSystemType.kt
Normal file
38
tools/intellij-plugin/src/creator/steps/BuildSystemType.kt
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator.steps
|
||||||
|
|
||||||
|
import com.intellij.openapi.module.Module
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.MiraiProjectModel
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.build.GradleGroovyProjectCreator
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.build.GradleKotlinProjectCreator
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.build.ProjectCreator
|
||||||
|
|
||||||
|
enum class BuildSystemType {
|
||||||
|
GradleKt {
|
||||||
|
override fun createBuildSystem(module: Module, root: VirtualFile, model: MiraiProjectModel): ProjectCreator =
|
||||||
|
GradleKotlinProjectCreator(module, root, model)
|
||||||
|
|
||||||
|
override fun toString(): String = "Gradle Kotlin DSL"
|
||||||
|
},
|
||||||
|
GradleGroovy {
|
||||||
|
override fun createBuildSystem(module: Module, root: VirtualFile, model: MiraiProjectModel): ProjectCreator =
|
||||||
|
GradleGroovyProjectCreator(module, root, model)
|
||||||
|
|
||||||
|
override fun toString(): String = "Gradle Groovy DSL"
|
||||||
|
}, ;
|
||||||
|
|
||||||
|
abstract fun createBuildSystem(module: Module, root: VirtualFile, model: MiraiProjectModel): ProjectCreator
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val DEFAULT = GradleKt
|
||||||
|
}
|
||||||
|
}
|
71
tools/intellij-plugin/src/creator/steps/LanguageType.kt
Normal file
71
tools/intellij-plugin/src/creator/steps/LanguageType.kt
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator.steps
|
||||||
|
|
||||||
|
import net.mamoe.mirai.console.intellij.assets.FT
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.build.ProjectCreator
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.tasks.getTemplate
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.templateProperties
|
||||||
|
|
||||||
|
data class NamedFile(
|
||||||
|
val path: String,
|
||||||
|
val content: String
|
||||||
|
)
|
||||||
|
|
||||||
|
interface ILanguageType {
|
||||||
|
val sourceSetDirName: String
|
||||||
|
fun pluginMainClassFile(creator: ProjectCreator): NamedFile
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class LanguageType : ILanguageType {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
fun <T: String?> escapeString(string: T): T {
|
||||||
|
string ?: return null as T
|
||||||
|
return string
|
||||||
|
.replace("\\", "\\\\")
|
||||||
|
.replace("\n", "\\n")
|
||||||
|
.replace("\"", "\\\"") as T
|
||||||
|
}
|
||||||
|
abstract fun <T: String?> escapeRawString(string: T): T
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val DEFAULT = Kotlin
|
||||||
|
fun values() = arrayOf(Kotlin, Java)
|
||||||
|
}
|
||||||
|
|
||||||
|
object Kotlin : LanguageType() {
|
||||||
|
override fun toString(): String = "Kotlin" // display in UI
|
||||||
|
override val sourceSetDirName: String get() = "kotlin"
|
||||||
|
override fun pluginMainClassFile(creator: ProjectCreator): NamedFile = creator.model.run {
|
||||||
|
return NamedFile(
|
||||||
|
path = "src/main/kotlin/$mainClassSimpleName.kt",
|
||||||
|
content = creator.project.getTemplate(FT.PluginMainKt, templateProperties)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T : String?> escapeRawString(string: T): T {
|
||||||
|
string ?: return null as T
|
||||||
|
return string.replace("$", "\${'\$'}").replace("\n", "\\n") as T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Java : LanguageType() {
|
||||||
|
override fun toString(): String = "Java" // display in UI
|
||||||
|
override val sourceSetDirName: String get() = "java"
|
||||||
|
override fun pluginMainClassFile(creator: ProjectCreator): NamedFile = creator.model.run {
|
||||||
|
return NamedFile(
|
||||||
|
path = "src/main/java/${packageName.replace('.', '/')}/$mainClassSimpleName.java",
|
||||||
|
content = creator.project.getTemplate(FT.PluginMainJava, templateProperties)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
override fun <T : String?> escapeRawString(string: T): T = escapeString(string)
|
||||||
|
}
|
||||||
|
}
|
12
tools/intellij-plugin/src/creator/steps/OptionsStep.form
Normal file
12
tools/intellij-plugin/src/creator/steps/OptionsStep.form
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="net.mamoe.mirai.console.intellij.creator.steps.OptionsStep">
|
||||||
|
<grid id="27dc6" binding="panel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
|
<constraints>
|
||||||
|
<xy x="20" y="20" width="500" height="400"/>
|
||||||
|
</constraints>
|
||||||
|
<properties/>
|
||||||
|
<border type="none"/>
|
||||||
|
<children/>
|
||||||
|
</grid>
|
||||||
|
</form>
|
26
tools/intellij-plugin/src/creator/steps/OptionsStep.kt
Normal file
26
tools/intellij-plugin/src/creator/steps/OptionsStep.kt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator.steps
|
||||||
|
|
||||||
|
import com.intellij.ide.util.projectWizard.ModuleWizardStep
|
||||||
|
import javax.swing.JComponent
|
||||||
|
import javax.swing.JPanel
|
||||||
|
|
||||||
|
class OptionsStep : ModuleWizardStep() {
|
||||||
|
private lateinit var panel: JPanel
|
||||||
|
|
||||||
|
override fun getComponent(): JComponent {
|
||||||
|
return panel
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateDataModel() {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,215 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="net.mamoe.mirai.console.intellij.creator.steps.PluginCoordinatesStep">
|
||||||
|
<grid id="27dc6" binding="panel" layout-manager="GridLayoutManager" row-count="11" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="10" vgap="10">
|
||||||
|
<margin top="10" left="10" bottom="10" right="10"/>
|
||||||
|
<constraints>
|
||||||
|
<xy x="20" y="20" width="531" height="541"/>
|
||||||
|
</constraints>
|
||||||
|
<properties/>
|
||||||
|
<border type="none" title-justification="1" title-position="3"/>
|
||||||
|
<children>
|
||||||
|
<vspacer id="3151a">
|
||||||
|
<constraints>
|
||||||
|
<grid row="10" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
</vspacer>
|
||||||
|
<component id="303a9" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="10" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value=""/>
|
||||||
|
<visible value="false"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="539d6" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="10" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value=""/>
|
||||||
|
<toolTipText value=""/>
|
||||||
|
<visible value="false"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="33f22" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="8" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="Info:"/>
|
||||||
|
<toolTipText value="描述"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<vspacer id="b4a73">
|
||||||
|
<constraints>
|
||||||
|
<grid row="9" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
</vspacer>
|
||||||
|
<component id="980c2" class="javax.swing.JTextArea" binding="infoArea">
|
||||||
|
<constraints>
|
||||||
|
<grid row="8" column="1" row-span="1" col-span="2" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||||
|
<preferred-size width="150" height="119"/>
|
||||||
|
</grid>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<dragEnabled value="true"/>
|
||||||
|
<text value=""/>
|
||||||
|
<toolTipText value="描述, 可选"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="3ca24" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="Author:"/>
|
||||||
|
<toolTipText value="作者"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="45051" class="javax.swing.JTextField" binding="authorField">
|
||||||
|
<constraints>
|
||||||
|
<grid row="6" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||||
|
<preferred-size width="150" height="-1"/>
|
||||||
|
</grid>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value=""/>
|
||||||
|
<toolTipText value="作者名称, 可选"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="c6d49" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="Name:"/>
|
||||||
|
<toolTipText value="显示名称"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="27fb6" class="javax.swing.JTextField" binding="nameField">
|
||||||
|
<constraints>
|
||||||
|
<grid row="5" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||||
|
<preferred-size width="150" height="-1"/>
|
||||||
|
</grid>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value=""/>
|
||||||
|
<toolTipText value="显示名称, 可选"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="28e8e" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="Depends on:"/>
|
||||||
|
<toolTipText value="依赖的插件列表"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="44e5c" class="javax.swing.JTextField" binding="dependsOnField">
|
||||||
|
<constraints>
|
||||||
|
<grid row="7" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||||
|
<preferred-size width="150" height="-1"/>
|
||||||
|
</grid>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<enabled value="false"/>
|
||||||
|
<text value=""/>
|
||||||
|
<toolTipText value="依赖的插件列表, 还不支持编辑, 请在创建项目后修改"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="53007" class="javax.swing.JSeparator">
|
||||||
|
<constraints>
|
||||||
|
<grid row="1" column="0" row-span="1" col-span="3" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties/>
|
||||||
|
</component>
|
||||||
|
<component id="45fb1" class="javax.swing.JComboBox" binding="miraiVersionBox">
|
||||||
|
<constraints>
|
||||||
|
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<editable value="true"/>
|
||||||
|
<enabled value="false"/>
|
||||||
|
<model>
|
||||||
|
<item value="Loading..."/>
|
||||||
|
</model>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="6d341" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<opaque value="true"/>
|
||||||
|
<text value="Mirai version:"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="452df" class="javax.swing.JComboBox" binding="miraiVersionKindBox">
|
||||||
|
<constraints>
|
||||||
|
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<enabled value="false"/>
|
||||||
|
<model>
|
||||||
|
<item value="Stable"/>
|
||||||
|
<item value="Prerelease"/>
|
||||||
|
</model>
|
||||||
|
<toolTipText value="Mirai 版本类型 <br/> Stable: 稳定 Prerelease: -M 和 -RC 测试版" noi18n="true"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="6ddd1" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="*ID:"/>
|
||||||
|
<toolTipText value=""/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="a76eb" class="javax.swing.JTextField" binding="idField">
|
||||||
|
<constraints>
|
||||||
|
<grid row="2" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||||
|
<preferred-size width="150" height="-1"/>
|
||||||
|
</grid>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value=""/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="9ee7e" class="javax.swing.JTextField" binding="mainClassField">
|
||||||
|
<constraints>
|
||||||
|
<grid row="3" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||||
|
<preferred-size width="150" height="-1"/>
|
||||||
|
</grid>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value=""/>
|
||||||
|
<toolTipText value="依赖的插件列表, 可选"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="f4c2b" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="*Main class:"/>
|
||||||
|
<toolTipText value="依赖的插件列表"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="f7d3f" class="javax.swing.JSeparator">
|
||||||
|
<constraints>
|
||||||
|
<grid row="4" column="0" row-span="1" col-span="3" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties/>
|
||||||
|
</component>
|
||||||
|
</children>
|
||||||
|
</grid>
|
||||||
|
<buttonGroups>
|
||||||
|
<group name="radioButtonGroup">
|
||||||
|
<member id="80d0b"/>
|
||||||
|
<member id="9d2d8"/>
|
||||||
|
</group>
|
||||||
|
</buttonGroups>
|
||||||
|
</form>
|
135
tools/intellij-plugin/src/creator/steps/PluginCoordinatesStep.kt
Normal file
135
tools/intellij-plugin/src/creator/steps/PluginCoordinatesStep.kt
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator.steps
|
||||||
|
|
||||||
|
import com.intellij.ide.util.projectWizard.ModuleWizardStep
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import net.mamoe.mirai.console.compiler.common.CheckerConstants.PLUGIN_ID_PATTERN
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.MiraiProjectModel
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.MiraiVersionKind
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.PluginCoordinates
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.checkNotNull
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.steps.Validation.NotBlank
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.steps.Validation.Pattern
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.tasks.QUALIFIED_CLASS_NAME_PATTERN
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.tasks.adjustToClassName
|
||||||
|
import net.mamoe.mirai.console.intellij.diagnostics.ContextualParametersChecker
|
||||||
|
import java.awt.event.ItemEvent
|
||||||
|
import java.awt.event.ItemListener
|
||||||
|
import javax.swing.*
|
||||||
|
|
||||||
|
class PluginCoordinatesStep(
|
||||||
|
private val model: MiraiProjectModel
|
||||||
|
) : ModuleWizardStep() {
|
||||||
|
|
||||||
|
private lateinit var panel: JPanel
|
||||||
|
|
||||||
|
@field:NotBlank("ID")
|
||||||
|
@field:Pattern("ID", PLUGIN_ID_PATTERN)
|
||||||
|
private lateinit var idField: JTextField
|
||||||
|
|
||||||
|
@field:NotBlank("Main class")
|
||||||
|
@field:Pattern("Main class", QUALIFIED_CLASS_NAME_PATTERN)
|
||||||
|
private lateinit var mainClassField: JTextField
|
||||||
|
private lateinit var nameField: JTextField
|
||||||
|
private lateinit var authorField: JTextField
|
||||||
|
private lateinit var dependsOnField: JTextField
|
||||||
|
private lateinit var infoArea: JTextArea
|
||||||
|
private lateinit var miraiVersionKindBox: JComboBox<MiraiVersionKind>
|
||||||
|
|
||||||
|
@field:NotBlank("Mirai version")
|
||||||
|
@field:Pattern("Mirai version", ContextualParametersChecker.SEMANTIC_VERSIONING_PATTERN)
|
||||||
|
private lateinit var miraiVersionBox: JComboBox<String>
|
||||||
|
|
||||||
|
override fun getComponent() = panel
|
||||||
|
|
||||||
|
private val versionKindChangeListener: ItemListener = ItemListener { event ->
|
||||||
|
if (event.stateChange != ItemEvent.SELECTED) return@ItemListener
|
||||||
|
|
||||||
|
updateVersionItems()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPreferredFocusedComponent(): JComponent = idField
|
||||||
|
|
||||||
|
override fun updateStep() {
|
||||||
|
miraiVersionKindBox.removeAllItems()
|
||||||
|
miraiVersionKindBox.isEnabled = true
|
||||||
|
MiraiVersionKind.values().forEach { miraiVersionKindBox.addItem(it) }
|
||||||
|
miraiVersionKindBox.selectedItem = MiraiVersionKind.DEFAULT
|
||||||
|
miraiVersionKindBox.addItemListener(versionKindChangeListener) // when selected, change versions
|
||||||
|
|
||||||
|
miraiVersionBox.removeAllItems()
|
||||||
|
miraiVersionBox.addItem(VERSION_LOADING_PLACEHOLDER)
|
||||||
|
miraiVersionBox.selectedItem = VERSION_LOADING_PLACEHOLDER
|
||||||
|
|
||||||
|
model.availableMiraiVersionsOrFail.invokeOnCompletion {
|
||||||
|
updateVersionItems()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idField.text.isNullOrEmpty()) {
|
||||||
|
model.projectCoordinates.checkNotNull("projectCoordinates").run {
|
||||||
|
idField.text = "$groupId.$artifactId"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mainClassField.text.isNullOrEmpty()) {
|
||||||
|
model.projectCoordinates.checkNotNull("projectCoordinates").run {
|
||||||
|
mainClassField.text = "$groupId.${artifactId.adjustToClassName()}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateVersionItems() {
|
||||||
|
GlobalScope.launch(Dispatchers.Main + CoroutineName("updateVersionItems")) {
|
||||||
|
if (!model.availableMiraiVersionsOrFail.isCompleted) return@launch
|
||||||
|
miraiVersionBox.removeAllItems()
|
||||||
|
val expectingKind = miraiVersionKindBox.selectedItem as? MiraiVersionKind ?: MiraiVersionKind.DEFAULT
|
||||||
|
model.availableMiraiVersionsOrFail.await()
|
||||||
|
.sortedDescending()
|
||||||
|
.filter { v ->
|
||||||
|
expectingKind.isThatKind(v)
|
||||||
|
}
|
||||||
|
.forEach { v -> miraiVersionBox.addItem(v) }
|
||||||
|
miraiVersionBox.isEnabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateDataModel() {
|
||||||
|
model.pluginCoordinates = PluginCoordinates(
|
||||||
|
id = idField.text.trim(),
|
||||||
|
author = authorField.text,
|
||||||
|
name = nameField.text?.trim(),
|
||||||
|
info = infoArea.text?.trim(),
|
||||||
|
dependsOn = dependsOnField.text?.trim(),
|
||||||
|
)
|
||||||
|
model.miraiVersion = miraiVersionBox.selectedItem?.toString()?.trim() ?: "+"
|
||||||
|
model.packageName = mainClassField.text.substringBeforeLast('.')
|
||||||
|
model.mainClassSimpleName = mainClassField.text.substringAfterLast('.')
|
||||||
|
model.mainClassQualifiedName = mainClassField.text
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun validate(): Boolean {
|
||||||
|
if (miraiVersionBox.selectedItem?.toString() == VERSION_LOADING_PLACEHOLDER) {
|
||||||
|
Validation.popup("请等待获取版本号", miraiVersionBox)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!Validation.doValidation(this)) return false
|
||||||
|
if (!mainClassField.text.contains('.')) {
|
||||||
|
Validation.popup("Main class 需要包含包名", mainClassField)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val VERSION_LOADING_PLACEHOLDER = "Loading..."
|
||||||
|
}
|
||||||
|
}
|
128
tools/intellij-plugin/src/creator/steps/ValidationUtil.kt
Normal file
128
tools/intellij-plugin/src/creator/steps/ValidationUtil.kt
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator.steps
|
||||||
|
|
||||||
|
import com.intellij.ide.util.projectWizard.ModuleWizardStep
|
||||||
|
import com.intellij.openapi.ui.MessageType
|
||||||
|
import com.intellij.openapi.ui.popup.Balloon
|
||||||
|
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||||
|
import com.intellij.ui.awt.RelativePoint
|
||||||
|
import net.mamoe.mirai.console.compiler.common.cast
|
||||||
|
import org.intellij.lang.annotations.Language
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
|
import javax.swing.JComponent
|
||||||
|
import javax.swing.text.JTextComponent
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.full.createInstance
|
||||||
|
|
||||||
|
|
||||||
|
class Validation {
|
||||||
|
|
||||||
|
annotation class WithValidator(val clazz: KClass<out Validator<WithValidator>>) {
|
||||||
|
companion object {
|
||||||
|
init {
|
||||||
|
registerValidator<WithValidator> { annotation, component ->
|
||||||
|
val instance = annotation.clazz.objectInstance ?: annotation.clazz.createInstance()
|
||||||
|
instance.validate(annotation, component)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
annotation class NotBlank(val tipName: String) {
|
||||||
|
companion object {
|
||||||
|
init {
|
||||||
|
registerValidator<NotBlank> { annotation, component ->
|
||||||
|
if (component.text.isNullOrBlank()) {
|
||||||
|
report("请填写 ${annotation.tipName}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
annotation class Pattern(val tipName: String, @Language("RegExp") val value: String) {
|
||||||
|
companion object {
|
||||||
|
init {
|
||||||
|
registerValidator<Pattern> { annotation, component ->
|
||||||
|
if (component.text?.matches(Regex(annotation.value)) != true) {
|
||||||
|
report("请正确填写 ${annotation.tipName}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun interface Validator<in A : Annotation> {
|
||||||
|
@Throws(ValidationException::class)
|
||||||
|
fun ValidationContext.validate(annotation: A, component: JTextComponent)
|
||||||
|
|
||||||
|
@Throws(ValidationException::class)
|
||||||
|
fun validate(annotation: A, component: JTextComponent) {
|
||||||
|
ValidationContext.run { validate(annotation, component) }
|
||||||
|
}
|
||||||
|
|
||||||
|
object ValidationContext {
|
||||||
|
fun report(message: String): Nothing = throw ValidationException(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ValidationException(message: String) : Exception(message)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private data class RegisteredValidator<A : Annotation>(val type: KClass<A>, val validator: Validator<A>)
|
||||||
|
|
||||||
|
private val validators: MutableCollection<RegisteredValidator<*>> = ConcurrentLinkedQueue()
|
||||||
|
|
||||||
|
private inline fun <reified A : Annotation> registerValidator(validator: Validator<A>) {
|
||||||
|
validators.add(RegisteredValidator(A::class, validator))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun popup(message: String, component: JComponent) {
|
||||||
|
JBPopupFactory.getInstance()
|
||||||
|
.createHtmlTextBalloonBuilder(message, MessageType.ERROR, null)
|
||||||
|
.setFadeoutTime(2000)
|
||||||
|
.createBalloon()
|
||||||
|
.show(RelativePoint.getSouthWestOf(component), Balloon.Position.below)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return `true` if no error
|
||||||
|
*/
|
||||||
|
fun doValidation(step: ModuleWizardStep): Boolean {
|
||||||
|
fun validateProperty(field: Field): Boolean {
|
||||||
|
field.isAccessible = true
|
||||||
|
val annotationsToValidate =
|
||||||
|
validators.associateBy { (type: KClass<out Annotation>) ->
|
||||||
|
field.annotations.find { it::class == type }
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((annotation, validator) in annotationsToValidate) {
|
||||||
|
if (annotation == null) continue
|
||||||
|
val component = field.get(step) as JTextComponent
|
||||||
|
try {
|
||||||
|
validator.validator.cast<Validator<Annotation>>().validate(annotation, component)
|
||||||
|
} catch (e: ValidationException) {
|
||||||
|
popup(e.message ?: e.toString(), component)
|
||||||
|
return false // report one error only
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
var result = true
|
||||||
|
for (prop in step::class.java.declaredFields) {
|
||||||
|
if (!validateProperty(prop)) result = false
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
tools/intellij-plugin/src/creator/tasks/CreateProjectTask.kt
Normal file
68
tools/intellij-plugin/src/creator/tasks/CreateProjectTask.kt
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator.tasks
|
||||||
|
|
||||||
|
import com.intellij.ide.ui.UISettings
|
||||||
|
import com.intellij.openapi.module.Module
|
||||||
|
import com.intellij.openapi.progress.ProgressIndicator
|
||||||
|
import com.intellij.openapi.progress.Task
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
|
import com.intellij.openapi.wm.WindowManager
|
||||||
|
import com.intellij.openapi.wm.ex.StatusBarEx
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.MiraiProjectModel
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.invokeLater
|
||||||
|
import org.jetbrains.plugins.gradle.service.project.open.linkAndRefreshGradleProject
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
class CreateProjectTask(
|
||||||
|
private val root: Path,
|
||||||
|
private val module: Module,
|
||||||
|
private val model: MiraiProjectModel,
|
||||||
|
) : Task.Backgroundable(module.project, "Creating project", false) {
|
||||||
|
override fun shouldStartInBackground() = false
|
||||||
|
|
||||||
|
override fun run(indicator: ProgressIndicator) {
|
||||||
|
if (module.isDisposed || project.isDisposed) return
|
||||||
|
|
||||||
|
Files.createDirectories(root)
|
||||||
|
|
||||||
|
invokeAndWait {
|
||||||
|
VfsUtil.markDirtyAndRefresh(false, true, true, root.vf)
|
||||||
|
}
|
||||||
|
|
||||||
|
val build = model.buildSystemType.createBuildSystem(module, root.vf, model)
|
||||||
|
|
||||||
|
build.createProject(module, root.vf, model)
|
||||||
|
build.doFinish(indicator)
|
||||||
|
|
||||||
|
invokeLater {
|
||||||
|
VfsUtil.markDirtyAndRefresh(false, true, true, root.vf)
|
||||||
|
}
|
||||||
|
|
||||||
|
invokeLater {
|
||||||
|
@Suppress("UnstableApiUsage")
|
||||||
|
(linkAndRefreshGradleProject(root.toAbsolutePath().toString(), project))
|
||||||
|
showProgress(project)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showProgress(project: Project) {
|
||||||
|
if (!UISettings.instance.showStatusBar || UISettings.instance.presentationMode) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val statusBar = WindowManager.getInstance().getStatusBar(project) as? StatusBarEx ?: return
|
||||||
|
statusBar.isProcessWindowOpen = true
|
||||||
|
}
|
149
tools/intellij-plugin/src/creator/tasks/TaskUtils.kt
Normal file
149
tools/intellij-plugin/src/creator/tasks/TaskUtils.kt
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator.tasks
|
||||||
|
|
||||||
|
import com.intellij.ide.fileTemplates.FileTemplateManager
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.application.ModalityState
|
||||||
|
import com.intellij.openapi.application.runWriteAction
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.vfs.LocalFileSystem
|
||||||
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.testFramework.writeChild
|
||||||
|
import net.mamoe.mirai.console.intellij.creator.steps.NamedFile
|
||||||
|
import org.intellij.lang.annotations.Language
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
import kotlin.properties.ReadWriteProperty
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
val Path.vfOrNull: VirtualFile?
|
||||||
|
get() = LocalFileSystem.getInstance().refreshAndFindFileByPath(this.toAbsolutePath().toString())
|
||||||
|
|
||||||
|
val Path.vf: VirtualFile
|
||||||
|
get() = vfOrNull ?: error("Failed to resolve VirtualFile ${this.toAbsolutePath()}")
|
||||||
|
|
||||||
|
fun VirtualFile.readText(): String? = if (this.exists() && !this.isDirectory) String(inputStream.use { it.readBytes() }) else null
|
||||||
|
fun VirtualFile.readChildText(relative: String): String? = this.resolve(relative)?.readText()
|
||||||
|
|
||||||
|
fun VirtualFile.resolve(relative: String): VirtualFile? = VfsUtil.findRelativeFile(
|
||||||
|
this,
|
||||||
|
*relative.replace('\\', '/').split('/').toTypedArray()
|
||||||
|
)
|
||||||
|
|
||||||
|
fun <T> invokeAndWait(modalityState: ModalityState? = null, runnable: () -> T): T {
|
||||||
|
val app = ApplicationManager.getApplication()
|
||||||
|
if (app.isDispatchThread) return runnable()
|
||||||
|
return computeDelegated {
|
||||||
|
app.invokeAndWait({ it(runnable()) }, modalityState ?: ModalityState.defaultModalityState())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> runWriteActionAndWait(modalityState: ModalityState? = null, runnable: () -> T) {
|
||||||
|
invokeAndWait(modalityState) {
|
||||||
|
runWriteAction(runnable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
internal inline fun <T> computeDelegated(executor: (setter: (T) -> Unit) -> Unit): T {
|
||||||
|
var resultRef: T? = null
|
||||||
|
executor { resultRef = it }
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return resultRef as T
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Project.getTemplate(
|
||||||
|
templateName: String,
|
||||||
|
properties: Map<String, String?>? = null
|
||||||
|
): String {
|
||||||
|
val manager = FileTemplateManager.getInstance(this)
|
||||||
|
val template = manager.getJ2eeTemplate(templateName)
|
||||||
|
|
||||||
|
val allProperties = manager.defaultProperties
|
||||||
|
properties?.let { prop -> allProperties.putAll(prop.mapValues { it.value.orEmpty() }) }
|
||||||
|
|
||||||
|
return template.getText(allProperties)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Project.getTemplate(
|
||||||
|
templateName: String,
|
||||||
|
vararg properties: Pair<String, String?>
|
||||||
|
): String = getTemplate(templateName, properties.toMap())
|
||||||
|
|
||||||
|
|
||||||
|
fun VirtualFile.writeChild(namedFile: NamedFile): VirtualFile = this.writeChild(namedFile.path, namedFile.content)
|
||||||
|
|
||||||
|
@Language("RegExp")
|
||||||
|
const val CLASS_NAME_PATTERN = "[a-zA-Z]+[0-9a-zA-Z_]*" // self written
|
||||||
|
|
||||||
|
@Language("RegExp")
|
||||||
|
const val PACKAGE_PATTERN = """[a-zA-Z]+[0-9a-zA-Z_]*(\.[a-zA-Z]+[0-9a-zA-Z_]*)*"""
|
||||||
|
|
||||||
|
@Language("RegExp")
|
||||||
|
const val QUALIFIED_CLASS_NAME_PATTERN = """($PACKAGE_PATTERN\.)?$CLASS_NAME_PATTERN""" // self written
|
||||||
|
|
||||||
|
fun String.isValidQualifiedClassName(): Boolean = this matches Regex(QUALIFIED_CLASS_NAME_PATTERN)
|
||||||
|
fun String.isValidPackageName(): Boolean = this matches Regex(PACKAGE_PATTERN)
|
||||||
|
fun String.isValidSimpleClassName(): Boolean = this matches Regex(CLASS_NAME_PATTERN)
|
||||||
|
fun String.adjustToClassName(): String? {
|
||||||
|
val result = buildString {
|
||||||
|
var doCapitalization = true
|
||||||
|
|
||||||
|
fun Char.isAllowed() = isLetterOrDigit() || this in "_-"
|
||||||
|
|
||||||
|
for (char in this@adjustToClassName) {
|
||||||
|
if (!char.isAllowed()) continue
|
||||||
|
|
||||||
|
if (doCapitalization) {
|
||||||
|
when {
|
||||||
|
char.isDigit() -> {
|
||||||
|
if (this.isEmpty()) append('_')
|
||||||
|
append(char)
|
||||||
|
}
|
||||||
|
char.isLetter() -> append(char.toUpperCase())
|
||||||
|
char == '-' -> append("_")
|
||||||
|
else -> append(char)
|
||||||
|
}
|
||||||
|
doCapitalization = false
|
||||||
|
} else {
|
||||||
|
if (char in "_-") {
|
||||||
|
doCapitalization = true
|
||||||
|
} else {
|
||||||
|
append(char)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.isValidSimpleClassName()) return result
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("RedundantNullableReturnType")
|
||||||
|
private val UNINITIALIZED: Any? = Any()
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
fun <T, R> lateinitReadWriteProperty(initializer: () -> R) = object : ReadWriteProperty<T, R> {
|
||||||
|
private var field = AtomicReference(UNINITIALIZED)
|
||||||
|
override fun setValue(thisRef: T, property: KProperty<*>, value: R) {
|
||||||
|
field.set(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override tailrec fun getValue(thisRef: T, property: KProperty<*>): R {
|
||||||
|
val v = field.get()
|
||||||
|
if (v !== UNINITIALIZED) return v as R
|
||||||
|
field.compareAndSet(UNINITIALIZED, initializer())
|
||||||
|
return getValue(thisRef, property)
|
||||||
|
}
|
||||||
|
}
|
@ -82,11 +82,13 @@ class ContextualParametersChecker : DeclarationChecker {
|
|||||||
|
|
||||||
private const val syntax = """类似于 "net.mamoe.mirai.example-plugin", 其中 "net.mamoe.mirai" 为 groupId, "example-plugin" 为插件名"""
|
private const val syntax = """类似于 "net.mamoe.mirai.example-plugin", 其中 "net.mamoe.mirai" 为 groupId, "example-plugin" 为插件名"""
|
||||||
|
|
||||||
|
const val SEMANTIC_VERSIONING_PATTERN =
|
||||||
|
"""^(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-]+)*))?${'$'}"""
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
|
* https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
|
||||||
*/
|
*/
|
||||||
private val SEMANTIC_VERSIONING_REGEX =
|
private val SEMANTIC_VERSIONING_REGEX = Regex(SEMANTIC_VERSIONING_PATTERN)
|
||||||
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-]+)*))?${'$'}""")
|
|
||||||
|
|
||||||
fun checkPluginId(inspectionTarget: KtElement, value: String): Diagnostic? {
|
fun checkPluginId(inspectionTarget: KtElement, value: String): Diagnostic? {
|
||||||
if (value.isBlank()) return ILLEGAL_PLUGIN_DESCRIPTION.on(inspectionTarget, "插件 Id 不能为空. \n插件 Id$syntax")
|
if (value.isBlank()) return ILLEGAL_PLUGIN_DESCRIPTION.on(inspectionTarget, "插件 Id 不能为空. \n插件 Id$syntax")
|
||||||
|
@ -14,7 +14,7 @@ import com.intellij.codeInsight.daemon.LineMarkerProvider
|
|||||||
import com.intellij.openapi.editor.markup.GutterIconRenderer
|
import com.intellij.openapi.editor.markup.GutterIconRenderer
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.psi.PsiMethod
|
||||||
import net.mamoe.mirai.console.intellij.Icons
|
import net.mamoe.mirai.console.intellij.assets.Icons
|
||||||
import net.mamoe.mirai.console.intellij.resolve.getElementForLineMark
|
import net.mamoe.mirai.console.intellij.resolve.getElementForLineMark
|
||||||
import net.mamoe.mirai.console.intellij.resolve.isSimpleCommandHandlerOrCompositeCommandSubCommand
|
import net.mamoe.mirai.console.intellij.resolve.isSimpleCommandHandlerOrCompositeCommandSubCommand
|
||||||
import net.mamoe.mirai.console.intellij.util.runIgnoringErrors
|
import net.mamoe.mirai.console.intellij.util.runIgnoringErrors
|
||||||
|
@ -14,7 +14,7 @@ import com.intellij.codeInsight.daemon.LineMarkerProvider
|
|||||||
import com.intellij.openapi.editor.markup.GutterIconRenderer
|
import com.intellij.openapi.editor.markup.GutterIconRenderer
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import net.mamoe.mirai.console.compiler.common.resolve.PLUGIN_FQ_NAME
|
import net.mamoe.mirai.console.compiler.common.resolve.PLUGIN_FQ_NAME
|
||||||
import net.mamoe.mirai.console.intellij.Icons
|
import net.mamoe.mirai.console.intellij.assets.Icons
|
||||||
import net.mamoe.mirai.console.intellij.resolve.allSuperNames
|
import net.mamoe.mirai.console.intellij.resolve.allSuperNames
|
||||||
import net.mamoe.mirai.console.intellij.resolve.getElementForLineMark
|
import net.mamoe.mirai.console.intellij.resolve.getElementForLineMark
|
||||||
import net.mamoe.mirai.console.intellij.util.runIgnoringErrors
|
import net.mamoe.mirai.console.intellij.util.runIgnoringErrors
|
||||||
|
62
tools/intellij-plugin/test/creator/tasks/TaskUtilsKtTest.kt
Normal file
62
tools/intellij-plugin/test/creator/tasks/TaskUtilsKtTest.kt
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij.creator.tasks
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
internal class TaskUtilsKtTest {
|
||||||
|
|
||||||
|
private fun useClassNameCases(mustBeTrue: (String) -> Boolean) {
|
||||||
|
val success = listOf("A", "A_B", "A0", "A_0", "A_B0")
|
||||||
|
val failure = listOf("", "0", "_", "-", ".", "/", "A/", "A.", "A.")
|
||||||
|
|
||||||
|
success.forEach { assertEquals(true, mustBeTrue(it), it) }
|
||||||
|
failure.forEach { assertEquals(false, mustBeTrue(it), it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidPackageName() {
|
||||||
|
useClassNameCases { it.isValidPackageName() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isValidClassName() {
|
||||||
|
useClassNameCases { it.isValidSimpleClassName() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun adjustToClassName() {
|
||||||
|
assertEquals("Test", "Test".adjustToClassName())
|
||||||
|
assertEquals("TeSt", "Te_st".adjustToClassName())
|
||||||
|
assertEquals("TeSt", "Te_St".adjustToClassName())
|
||||||
|
assertEquals("TeSt", "Te-st".adjustToClassName())
|
||||||
|
assertEquals("TeSt", "Te-St".adjustToClassName())
|
||||||
|
|
||||||
|
assertEquals("TestAA", "Test//!@#$%^&*()AA".adjustToClassName())
|
||||||
|
|
||||||
|
assertEquals(null, "0".adjustToClassName())
|
||||||
|
assertEquals(null, "_0".adjustToClassName())
|
||||||
|
assertEquals(null, "_0A".adjustToClassName())
|
||||||
|
assertEquals("A1", "A1".adjustToClassName())
|
||||||
|
|
||||||
|
assertEquals("A1", "A_1".adjustToClassName())
|
||||||
|
assertEquals("A1", "A-1".adjustToClassName())
|
||||||
|
|
||||||
|
assertEquals("MiraiConsoleExample", "mirai-console-example".adjustToClassName())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun qualifiedClassname() {
|
||||||
|
useClassNameCases { it.isValidQualifiedClassName() }
|
||||||
|
assertTrue { "a.b.c".isValidQualifiedClassName() }
|
||||||
|
}
|
||||||
|
}
|
11
tools/intellij-plugin/test/package.kt
Normal file
11
tools/intellij-plugin/test/package.kt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.intellij
|
Loading…
Reference in New Issue
Block a user