From 12d54b3188b024123957948cbe940b8429b02539 Mon Sep 17 00:00:00 2001 From: DevSrSouza Date: Sat, 29 Aug 2020 01:15:22 -0300 Subject: [PATCH] KotlinBukkitAPI wizard --- build.gradle.kts | 7 +- gradlew | 0 .../tooling/wizard/KBAPIArtifactWizard.kt | 78 ++++++++ .../tooling/wizard/KBAPIModuleBuilder.kt | 121 +++++++++++++ .../tooling/wizard/KBAPIModuleConfig.kt | 18 ++ .../tooling/wizard/KBAPIModuleType.kt | 22 +++ .../tooling/wizard/KBAPIWizardStep.kt | 91 ++++++++++ .../tooling/wizard/LibraryVersions.kt | 4 + .../tooling/wizard/Versions.kt | 40 ++++ .../tooling/wizard/bukkit/Plugin.kt | 10 + .../tooling/wizard/bukkit/PluginList.kt | 10 + .../tooling/wizard/bukkit/PluginVersion.kt | 6 + .../tooling/wizard/bukkit/ServerAPI.kt | 47 +++++ .../tooling/wizard/bukkit/ServerType.kt | 5 + .../tooling/wizard/bukkit/ServerVersion.kt | 15 ++ .../tooling/wizard/creator/GradleBuilder.kt | 132 ++++++++++++++ .../wizard/creator/PluginMainBuilder.kt | 34 ++++ .../tooling/wizard/creator/Utils.kt | 22 +++ .../wizard/utils/PluginCheckboxList.kt | 99 ++++++++++ .../tooling/wizard/utils/Project.kt | 54 ++++++ .../tooling/wizard/utils/Ui.kt | 171 ++++++++++++++++++ src/main/resources/META-INF/plugin.xml | 4 + 22 files changed, 987 insertions(+), 3 deletions(-) mode change 100644 => 100755 gradlew create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIArtifactWizard.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIModuleBuilder.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIModuleConfig.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIModuleType.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIWizardStep.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/LibraryVersions.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/Versions.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/Plugin.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/PluginList.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/PluginVersion.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/ServerAPI.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/ServerType.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/ServerVersion.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/creator/GradleBuilder.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/creator/PluginMainBuilder.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/creator/Utils.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/utils/PluginCheckboxList.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/utils/Project.kt create mode 100644 src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/utils/Ui.kt diff --git a/build.gradle.kts b/build.gradle.kts index 4993201..00aae74 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,8 @@ version = "0.0.2" repositories { jcenter() - maven("http://nexus.devsrsouza.com.br/repository/maven-public/") + //maven("http://nexus.devsrsouza.com.br/repository/maven-public/") + mavenLocal() } dependencies { @@ -27,7 +28,7 @@ dependencies { // See https://github.com/JetBrains/gradle-intellij-plugin/ intellij { - version = "2020.1.2" + version = "2020.2" setPlugins("java", "Kotlin") } @@ -44,7 +45,7 @@ tasks { kotlinOptions.jvmTarget = "1.8" } publishPlugin { - token = System.getenv("ORG_GRADLE_PROJECT_intellijPublishToken") + token(System.getenv("ORG_GRADLE_PROJECT_intellijPublishToken")) } } tasks.getByName("patchPluginXml") { diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIArtifactWizard.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIArtifactWizard.kt new file mode 100644 index 0000000..e04f4fe --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIArtifactWizard.kt @@ -0,0 +1,78 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard + +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.utils.addAtGrid +import com.intellij.ide.util.projectWizard.* +import com.intellij.uiDesigner.core.* +import javax.swing.* + +/** + * https://github.com/ktorio/ktor-init-tools/blob/master/ktor-intellij-plugin/src/io/ktor/start/intellij/KtorArtifactWizardStep.kt + */ +class KBAPIArtifactWizard(val config: KBAPIModuleConfig) : ModuleWizardStep() { + val groupId: JTextField + val artifactId: JTextField + val version: JTextField + val author: JTextField + val website: JTextField + val description: JTextField + + val panel = JPanel().apply { + layout = GridLayoutManager(8, 2) + + fun addLabelText(name: String, value: String, row: Int): JTextField { + val tfield = JTextField(value) + addAtGrid( + JLabel(name), + row = row, + column = 0, + anchor = GridConstraints.ANCHOR_WEST, + fill = GridConstraints.FILL_NONE, + HSizePolicy = GridConstraints.SIZEPOLICY_FIXED, + VSizePolicy = GridConstraints.SIZEPOLICY_FIXED + ) + addAtGrid( + tfield, + row = row, + column = 1, + anchor = GridConstraints.ANCHOR_WEST, + fill = GridConstraints.FILL_HORIZONTAL, + HSizePolicy = GridConstraints.SIZEPOLICY_CAN_GROW or GridConstraints.SIZEPOLICY_WANT_GROW, + VSizePolicy = GridConstraints.SIZEPOLICY_FIXED + ) + return tfield + } + + addAtGrid( + JLabel(""), + row = 0, + column = 0, + HSizePolicy = GridConstraints.SIZEPOLICY_FIXED, + VSizePolicy = GridConstraints.SIZEPOLICY_FIXED + ) + + groupId = addLabelText("GroupId", config.artifactGroup, row = 1) + artifactId = addLabelText("Plugin Name", config.artifactId, row = 2) + version = addLabelText("Version", config.artifactVersion, row = 3) + author = addLabelText("Author", config.author, row = 4) + website = addLabelText("Website", config.author, row = 5) + description = addLabelText("Description", config.description, row = 6) + + add(Spacer().apply {}, GridConstraints().apply { + colSpan = 2 + row = 7 + column = 0 + fill = GridConstraints.FILL_VERTICAL + }) + } + + override fun updateDataModel() { + config.artifactGroup = groupId.text + config.artifactId = artifactId.text + config.artifactVersion = version.text + config.author = author.text + config.website = website.text + config.description = description.text + } + + override fun getComponent() = panel +} diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIModuleBuilder.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIModuleBuilder.kt new file mode 100644 index 0000000..9395021 --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIModuleBuilder.kt @@ -0,0 +1,121 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard + +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.creator.* +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.utils.backgroundTask +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.utils.get +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.utils.invokeLater +import com.intellij.codeInsight.actions.ReformatCodeProcessor +import com.intellij.ide.actions.ImportModuleAction +import com.intellij.ide.util.projectWizard.JavaModuleBuilder +import com.intellij.ide.util.projectWizard.WizardContext +import com.intellij.openapi.Disposable +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.ModalityState +import com.intellij.openapi.project.DumbAwareRunnable +import com.intellij.openapi.projectRoots.JavaSdk +import com.intellij.openapi.projectRoots.SdkTypeId +import com.intellij.openapi.roots.ModifiableRootModel +import com.intellij.openapi.roots.ui.configuration.ModulesProvider +import com.intellij.openapi.util.Computable +import com.intellij.openapi.util.Ref +import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.projectImport.ProjectImportProvider +import java.io.File +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths +import javax.swing.Icon + +class KBAPIModuleBuilder : JavaModuleBuilder() { + override fun getPresentableName(): String = KBAPIModuleType.NAME + override fun getNodeIcon(): Icon = KBAPIModuleType.ICON + override fun getGroupName(): String = KBAPIModuleType.NAME + override fun getBuilderId(): String? = "KOTLINBUKKITAPI_MODULE" + override fun getWeight() = BUILD_SYSTEM_WEIGHT - 1 + override fun isSuitableSdkType(sdkType: SdkTypeId?): Boolean = sdkType === JavaSdk.getInstance() + + val config = KBAPIModuleConfig() + + override fun setupRootModel(rootModel: ModifiableRootModel) { + val project = rootModel.project + val (rootPath, vFile) = createAndGetRoot() + val root = rootPath.toFile() + rootModel.addContentEntry(vFile) + if (moduleJdk != null) rootModel.sdk = moduleJdk + + project.backgroundTask("Setting Up Project") { progress -> + progress.text = "Generating Gradle" + + val gradleBuildFile = generateGradleBuildFile(root).createIfNotExists() + val gradleSettingFile = generateGradleSettingsFile(root).createIfNotExists() + + gradleBuildFile.appendText(generateGradleBuildFileContent(config)) + gradleSettingFile.appendText(generateGradleSettingsFileContent(config)) + + progress.text = "Generating Plugin Main" + + val pluginMain = generatePluginMainFile(root, config).createIfNotExists() + + pluginMain.appendText(generatePluginMainFileContent(config)) + + progress.text = "Configuring project gradle" + vFile.refresh(false, true) + + val buildGradle = vFile["build.gradle.kts"] + if (buildGradle != null) + invokeLater { + val provider = ProjectImportProvider.PROJECT_IMPORT_PROVIDER.extensions + .firstOrNull { it.canImport(buildGradle, project) } + ?: return@invokeLater + + val wizard = ImportModuleAction.createImportWizard( + project, + null, + buildGradle, + provider + ) + + if (wizard != null && (wizard.stepCount <= 0 || wizard.showAndGet())) { + ImportModuleAction.createFromWizard(project, wizard) + } + } + } + } + override fun getParentGroup() = KBAPIModuleType.NAME + + override fun createWizardSteps(wizardContext: WizardContext, modulesProvider: ModulesProvider) = arrayOf( + KBAPIArtifactWizard(config) + ) + + override fun getCustomOptionsStep(context: WizardContext, parentDisposable: Disposable?) = + KBAPIWizardStep(config) + + + private fun createAndGetRoot(): Pair { + 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 + } + +} + +inline fun runWriteTask(crossinline func: () -> T): T { + return invokeAndWait { + ApplicationManager.getApplication().runWriteAction(Computable { func() }) + } +} + +fun invokeAndWait(func: () -> T): T { + val ref = Ref() + ApplicationManager.getApplication().invokeAndWait({ ref.set(func()) }, ModalityState.defaultModalityState()) + return ref.get() +} \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIModuleConfig.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIModuleConfig.kt new file mode 100644 index 0000000..f90d5bc --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIModuleConfig.kt @@ -0,0 +1,18 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard + +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit.Plugin +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit.ServerType +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit.ServerVersion + +data class KBAPIModuleConfig( + var artifactGroup: String = "com.example", + var artifactId: String = "myplugin", + var artifactVersion: String = "0.0.1", + var externalPlugins: List = listOf(), + var kbAPIVersion: KotlinBukkitAPIVersion = Versions.LAST, + var serverVersion: ServerVersion = ServerVersion.v1_8, + var serverType: ServerType = ServerType.PAPERMC, + var author: String = "", + var website: String = "", + var description: String = "" +) diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIModuleType.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIModuleType.kt new file mode 100644 index 0000000..645c752 --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIModuleType.kt @@ -0,0 +1,22 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard + +import br.com.devsrsouza.kotlinbukkitapi.tooling.Assets +import com.intellij.openapi.module.ModuleType +import javax.swing.Icon + +class KBAPIModuleType : ModuleType("kotlinbukkitapi") { + + companion object { + val NAME = "KotlinBukkitAPI" + val DESCRIPTION = "KotlinBukkitAPI Quick" + val ICON = Assets.KotlinBukkitAPIIcon + val INSTANCE = KBAPIModuleType() + } + + override fun createModuleBuilder(): KBAPIModuleBuilder = KBAPIModuleBuilder() + override fun getName(): String = NAME + override fun getDescription(): String = DESCRIPTION + override fun getNodeIcon(isOpened: Boolean): Icon = ICON + override fun getIcon(): Icon = ICON + +} \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIWizardStep.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIWizardStep.kt new file mode 100644 index 0000000..faec430 --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/KBAPIWizardStep.kt @@ -0,0 +1,91 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard + +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit.* +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.utils.* +import com.intellij.ide.util.projectWizard.ModuleWizardStep +import com.intellij.openapi.ui.Splitter +import com.intellij.ui.IdeBorderFactory +import java.awt.BorderLayout +import javax.swing.* + +/** + * https://github.com/ktorio/ktor-init-tools/blob/master/ktor-intellij-plugin/src/io/ktor/start/intellij/KtorModuleWizardStep.kt + */ +class KBAPIWizardStep( + val config: KBAPIModuleConfig +) : ModuleWizardStep() { + lateinit var serverApiVersionCB: JComboBox + lateinit var serverForkCB: JComboBox + lateinit var kotlinBukkitAPIVersionCB: JComboBox + lateinit var externalPluginList: PluginCheckboxList + + override fun updateDataModel() { + config.serverVersion = serverApiVersionCB.selectedItem as ServerVersion + config.externalPlugins = externalPluginList.pluginsToCheckbox.keys.filter { it.isSelected } + config.serverType = serverForkCB.selectedItem as ServerType + config.kbAPIVersion = kotlinBukkitAPIVersionCB.selectedItem as KotlinBukkitAPIVersion + } + + val panel by lazy { + JPanel().apply { + val description = JPanel().apply { + layout = BoxLayout(this, BoxLayout.Y_AXIS) + border = IdeBorderFactory.createBorder() + } + + externalPluginList = object : PluginCheckboxList(ALL_PLUGINS) { + override fun onSelected(feature: Plugin?, node: ThreeStateCheckedTreeNode) { + // TODO: Show source link? + } + override fun onChanged(feature: Plugin, node: ThreeStateCheckedTreeNode) { + feature.isSelected = !feature.isSelected + + externalPluginList.repaint() + } + } + + this.layout = BorderLayout(0, 0) + + add(table { + tr( + policy = TdSize.FIXED, + fill = TdFill.NONE, + align = TdAlign.CENTER_LEFT + ) { + td(JLabel("Server API Version:")) + td(JComboBox(ServerVersion.values()).apply { serverApiVersionCB = this }) + td(JLabel("Server:")) + td(JComboBox(ServerType.values()).apply { serverForkCB = this }) + td(JLabel("KotlinBukkitAPI:")) + td(JComboBox(Versions.ALL).apply { + kotlinBukkitAPIVersionCB = this + selectedItem = Versions.LAST + }) + } + }, BorderLayout.NORTH) + + add(Splitter(true, 0.8f, 0.2f, 0.8f).apply { + this.firstComponent = table { + tr( + policy = TdSize.FIXED, + minHeight = 24, + maxHeight = 24, + fill = TdFill.NONE, + align = TdAlign.CENTER_LEFT + ) { + td(JLabel("Plugins:")) + } + tr { + td(externalPluginList.scrollVertical()) + } + } + this.secondComponent = description + }, BorderLayout.CENTER) + } + } + + override fun getComponent(): JComponent { + return panel + } + +} \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/LibraryVersions.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/LibraryVersions.kt new file mode 100644 index 0000000..7e88740 --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/LibraryVersions.kt @@ -0,0 +1,4 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard + +const val PLUGIN_YML = "0.3.0" +const val SHADOW_PLUGIN = "6.0.0" \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/Versions.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/Versions.kt new file mode 100644 index 0000000..1dbc95f --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/Versions.kt @@ -0,0 +1,40 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard + +object Versions { + val `v0_1_0-SNAPSHOT` = KotlinBukkitAPIVersion("0.1.0-SNAPSHOT") + + val ALL = arrayOf( + `v0_1_0-SNAPSHOT` + ) + + val LAST = `v0_1_0-SNAPSHOT` + + val visitorAll = ALL.associate { it.version to it } + + fun fromString(version: String) = visitorAll[version] +} + +data class KotlinBukkitAPIVersion( + val version: String, + val kotlinVersion: String = "1.4.0" +) { + override fun toString(): String { + return version + } + + private val group = "br.com.devsrsouza.kotlinbukkitapi" + + val repositories = listOf( + "http://nexus.devsrsouza.com.br/repository/maven-public/", + "https://oss.jfrog.org/oss-snapshot-local/", + "http://nexus.okkero.com/repository/maven-releases/", + "https://repo.codemc.org/repository/maven-public" + ) + + val dependencies = listOf( + "${group}:core:$version", + "${group}:serialization:$version", + "${group}:plugins:$version", + "${group}:exposed:$version", + ) +} \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/Plugin.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/Plugin.kt new file mode 100644 index 0000000..a3bc330 --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/Plugin.kt @@ -0,0 +1,10 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit + +data class Plugin( + val name: String, + val versions: List, + val repositories: List, + val dependencies: List +) { + var isSelected = false +} \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/PluginList.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/PluginList.kt new file mode 100644 index 0000000..7b064af --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/PluginList.kt @@ -0,0 +1,10 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit + +val ALL_PLUGINS = listOf( + Plugin( + "Vault", + ServerVersion.values().map { PluginVersion("1.7", it) }, + listOf("https://jitpack.io"), + listOf("com.github.MilkBowl:VaultAPI:{version}") + ) +) \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/PluginVersion.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/PluginVersion.kt new file mode 100644 index 0000000..5dd1f8a --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/PluginVersion.kt @@ -0,0 +1,6 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit + +class PluginVersion( + val version: String, + val serverVersion: ServerVersion +) \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/ServerAPI.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/ServerAPI.kt new file mode 100644 index 0000000..4e16642 --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/ServerAPI.kt @@ -0,0 +1,47 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit + +data class ServerAPI( + val version: ServerVersion, + val serverType: ServerType +) + +val ServerAPI.dependencies: List get() { + + val versionName = when(version) { + ServerVersion.v1_8 -> "1.8.8-R0.1-SNAPSHOT" + ServerVersion.v1_9 -> "1.9.4-R0.1-SNAPSHOT" + ServerVersion.v1_12 -> "1.12.2-R0.1-SNAPSHOT" + ServerVersion.v1_13 -> "1.13.2-R0.1-SNAPSHOT" + ServerVersion.v1_14 -> "1.14.4-R0.1-SNAPSHOT" + ServerVersion.v1_15 -> "1.15.2-R0.1-SNAPSHOT" + ServerVersion.v1_16 -> "1.16.2-R0.1-SNAPSHOT" + } + + val dependency = when(serverType) { + ServerType.SPIGOT -> "org.spigotmc:spigot-api:$versionName" + ServerType.PAPERMC -> { + val v17 = "org.github.paperspigot:paperspigot-api" + val v19 = "com.destroystokyo.paper:paper-api" + + when(version) { + ServerVersion.v1_8 -> "$v17:$versionName" + else -> "$v19:$versionName" + } + } + } + + return listOf(dependency) +} + +val ServerAPI.repositories: List get() { + return when(serverType) { + ServerType.SPIGOT -> listOf( + "https://hub.spigotmc.org/nexus/content/repositories/snapshots/", + "https://oss.sonatype.org/content/repositories/snapshots/" + ) + ServerType.PAPERMC -> listOf( + "https://papermc.io/repo/repository/maven-public/", + "https://oss.sonatype.org/content/repositories/snapshots/" + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/ServerType.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/ServerType.kt new file mode 100644 index 0000000..19aa388 --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/ServerType.kt @@ -0,0 +1,5 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit + +enum class ServerType { + SPIGOT, PAPERMC +} \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/ServerVersion.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/ServerVersion.kt new file mode 100644 index 0000000..7528486 --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/bukkit/ServerVersion.kt @@ -0,0 +1,15 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit + +enum class ServerVersion(val displayName: String) { + v1_8("1.8"), + v1_9("1.9"), + v1_12("1.12"), + v1_13("1.13"), + v1_14("1.14"), + v1_15("1.15"), + v1_16("1.16"); + + override fun toString(): String { + return displayName + } +} diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/creator/GradleBuilder.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/creator/GradleBuilder.kt new file mode 100644 index 0000000..a5a6c96 --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/creator/GradleBuilder.kt @@ -0,0 +1,132 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.creator + +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.KBAPIModuleConfig +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.PLUGIN_YML +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.SHADOW_PLUGIN +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit.ServerAPI +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit.dependencies +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit.repositories +import org.jetbrains.kotlin.nj2k.replace +import java.io.File + +fun generateGradleBuildFile( + root: File +): File = File(root, "build.gradle.kts") + +fun generateGradleSettingsFile( + root: File +): File = File(root, "settings.gradle.kts") + +fun generateGradleBuildFileContent( + config: KBAPIModuleConfig +): String = with(config) { + val kbapiDependencies = kbAPIVersion.dependencies + .dependenciesAsGradle() + + val kbapiRepositories = kbAPIVersion.repositories + .repositoriesAsGradle() + + val serverApi = ServerAPI(config.serverVersion, config.serverType) + val serverRepositories = serverApi.repositories.repositoriesAsGradle() + val serverDependencies = serverApi.dependencies.dependenciesAsGradle() + + val pluginDependencies = externalPlugins + .flatMap { it.dependencies.map { dep -> dep.replace("{version}", it.versions.first { it.serverVersion == serverVersion }.version) } } + .distinct() + .dependenciesAsGradle() + + + val pluginRepositories = externalPlugins + .flatMap { it.repositories } + .distinct() + .repositoriesAsGradle() + + + val plugins = externalPlugins.joinToString { "\"${it.name}\"" } + + return """ + |plugins { + | kotlin("jvm") version "${kbAPIVersion.kotlinVersion}" + | kotlin("plugin.serialization") version "${kbAPIVersion.kotlinVersion}" + | id("net.minecrell.plugin-yml.bukkit") version "$PLUGIN_YML" + | id("com.github.johnrengelman.shadow") version "$SHADOW_PLUGIN" + |} + | + |group = "$artifactGroup" + |version = "$artifactVersion" + | + |repositories { + | jcenter() + | // minecraft + |$serverRepositories + | + | //kotlinbukkitapi with backup repo + |$kbapiRepositories + | + | //plugins + |$pluginRepositories + |} + | + |dependencies { + | //minecraft + |$serverDependencies + | + | //kotlinbukkitapi + |$kbapiDependencies + | + | //plugins + |$pluginDependencies + |} + | + |bukkit { + | main = "${packageName}.${pluginMainName}" + | depend = listOf("KotlinBukkitAPI", ${plugins}) + | ${description.mapIfNotBlank { "description = \"$it\"" }} + | ${author.mapIfNotBlank { "author = \"$it\"" }} + | ${website.mapIfNotBlank { "website = \"$it\"" }} + |} + | + |tasks { + | compileKotlin { + | kotlinOptions.jvmTarget = "1.8" + | kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.time.ExperimentalTime,kotlin.ExperimentalStdlibApi" + | } + | compileTestKotlin { + | kotlinOptions.jvmTarget = "1.8" + | kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.time.ExperimentalTime,kotlin.ExperimentalStdlibApi" + | } + | shadowJar { + | classifier = null + | } + |} + | + |configurations.all { + | resolutionStrategy.cacheChangingModulesFor(120, "seconds") + |} + """.trimMargin() +} + +private inline fun List.dependenciesAsGradle(configuration: String = "compileOnly"): String = + joinToString("\n") { + "$configuration(\"${it}\")" + }.prependIndent(DEFAULT_INDENTATION) + +private inline fun List.repositoriesAsGradle(): String = + joinToString("\n") { + "maven(\"${it}\")" + }.prependIndent(DEFAULT_INDENTATION) + +fun generateGradleSettingsFileContent( + config: KBAPIModuleConfig +): String = with(config) { + return """ + rootProject.name = "$artifactId" + """.trimSource() +} + +fun String.trimSource(): String { + val lines = lines() + val indentation = lines[1].indexOfFirst { !it.isWhitespace() } + + return lines.joinToString("\n") { it.removePrefix(" ".repeat(indentation)) } +} \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/creator/PluginMainBuilder.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/creator/PluginMainBuilder.kt new file mode 100644 index 0000000..785e373 --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/creator/PluginMainBuilder.kt @@ -0,0 +1,34 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.creator + +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.KBAPIModuleConfig +import java.io.File + +fun generatePluginPackageFolder( + root: File, + config: KBAPIModuleConfig +): File = File(root, "src/main/kotlin/${config.packageName.replace(".", "/")}") + +fun generatePluginMainFile( + root: File, + config: KBAPIModuleConfig +): File = File(generatePluginPackageFolder(root, config), "${config.pluginMainName}.kt") + +fun generatePluginMainFileContent( + config: KBAPIModuleConfig +): String = with(config) { + return """ + package $packageName + + import br.com.devsrsouza.kotlinbukkitapi.architecture.KotlinPlugin + + class $pluginMainName : KotlinPlugin() { + override fun onPluginEnable() { + + } + + override fun onPluginDisble() { + + } + } + """.trimIndent() +} \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/creator/Utils.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/creator/Utils.kt new file mode 100644 index 0000000..b59b2d3 --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/creator/Utils.kt @@ -0,0 +1,22 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.creator + +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.KBAPIModuleConfig +import java.io.File + +const val DEFAULT_INDENTATION = " " + +inline fun String.mapIfNotBlank(block: (String) -> String): String = + if(isNotBlank()) + block(this) + else + this + +fun File.createIfNotExists(): File = apply { + if(!exists()) { + parentFile.mkdirs() + createNewFile() + } +} + +val KBAPIModuleConfig.packageName get() = "${artifactGroup}.${artifactId.toLowerCase()}" +val KBAPIModuleConfig.pluginMainName get() = "${artifactId}Plugin" \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/utils/PluginCheckboxList.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/utils/PluginCheckboxList.kt new file mode 100644 index 0000000..1aa02fc --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/utils/PluginCheckboxList.kt @@ -0,0 +1,99 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.utils + +import br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.bukkit.Plugin +import com.intellij.ui.CheckboxTree +import com.intellij.ui.CheckedTreeNode +import com.intellij.ui.SimpleTextAttributes +import com.intellij.util.ui.ThreeStateCheckBox +import com.intellij.util.ui.UIUtil +import javax.swing.JTree +import javax.swing.tree.DefaultTreeModel +import javax.swing.tree.TreePath + +open class ThreeStateCheckedTreeNode : CheckedTreeNode { + constructor() : super() + constructor(userObject: Any?) : super(userObject) + + var indeterminate = false +} + +/** + * Based on Ktor FeatureCheckboxList + * https://github.com/ktorio/ktor-init-tools/blob/master/ktor-intellij-plugin/src/io/ktor/start/intellij/KtorModuleWizardStep.kt#L175 + */ +abstract class PluginCheckboxList(val plugins: List) : CheckboxTree( + object : CheckboxTree.CheckboxTreeCellRenderer() { + override fun customizeRenderer( + tree: JTree?, + value: Any?, + selected: Boolean, + expanded: Boolean, + leaf: Boolean, + row: Int, + hasFocus: Boolean + ) { + if (value is ThreeStateCheckedTreeNode) { + val plugin = value.userObject + val tscheckbox = checkbox as ThreeStateCheckBox + if (plugin is Plugin) { + val style: SimpleTextAttributes = when { + value.indeterminate -> SimpleTextAttributes.REGULAR_ITALIC_ATTRIBUTES + else -> SimpleTextAttributes.REGULAR_ATTRIBUTES + } + textRenderer.append(plugin.name, style) + textRenderer.isEnabled = true + tscheckbox.isVisible = true + tscheckbox.state = when { + value.indeterminate -> ThreeStateCheckBox.State.DONT_CARE + value.isChecked -> ThreeStateCheckBox.State.SELECTED + else -> ThreeStateCheckBox.State.NOT_SELECTED + } + textRenderer.foreground = UIUtil.getTreeForeground() + } else if (plugin is String) { + textRenderer.append(plugin) + textRenderer.isEnabled = false + isEnabled = false + tscheckbox.isVisible = false + } + } + } + }, + ThreeStateCheckedTreeNode() +) { + val CheckedTreeNode?.plugin: Plugin? get() = this?.userObject as? Plugin? + + val pluginsToCheckbox = LinkedHashMap() + val root = (this.model as DefaultTreeModel).root as ThreeStateCheckedTreeNode + init { + this.model = object : DefaultTreeModel(root) { + override fun valueForPathChanged(path: TreePath, newValue: Any) { + super.valueForPathChanged(path, newValue) + val node = path.lastPathComponent as ThreeStateCheckedTreeNode + val plugin = node.plugin + if (plugin != null) { + onChanged(plugin, node) + } + } + } + } + + init { + for (plugin in plugins) { + root.add(ThreeStateCheckedTreeNode(plugin).apply { isChecked = false; pluginsToCheckbox[plugin] = this }) + } + (this.model as DefaultTreeModel).reload(root) + + addTreeSelectionListener { e -> + val node = (e.newLeadSelectionPath.lastPathComponent as? ThreeStateCheckedTreeNode) + val plugin = node?.userObject as? Plugin? + + if (node != null) { + onSelected(plugin, node) + } + } + } + + abstract fun onSelected(feature: Plugin?, node: ThreeStateCheckedTreeNode) + open fun onChanged(feature: Plugin, node: ThreeStateCheckedTreeNode) { + } +} \ No newline at end of file diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/utils/Project.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/utils/Project.kt new file mode 100644 index 0000000..6752d87 --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/utils/Project.kt @@ -0,0 +1,54 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.utils + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.ModalityState +import com.intellij.openapi.progress.ProgressIndicator +import com.intellij.openapi.progress.ProgressManager +import com.intellij.openapi.progress.Task +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile + +/** + * https://github.com/ktorio/ktor-init-tools/blob/master/ktor-intellij-plugin/src/io/ktor/start/intellij/util/Utils.kt + */ + +operator fun VirtualFile?.get(path: String?): VirtualFile? { + if (this == null || path == null || path == "" || path == ".") return this + val parts = path.split('/', limit = 2) + val firstName = parts[0] + val lastName = parts.getOrNull(1) + val child = this.findChild(firstName) + return if (lastName != null) child[lastName] else child +} + + +fun Project.backgroundTask( + name: String, + indeterminate: Boolean = true, + cancellable: Boolean = false, + background: Boolean = false, + callback: (indicator: ProgressIndicator) -> Unit +) { + ProgressManager.getInstance().run(object : Task.Backgroundable(this, name, cancellable, { background }) { + override fun shouldStartInBackground() = background + + override fun run(indicator: ProgressIndicator) { + try { + if (indeterminate) indicator.isIndeterminate = true + callback(indicator) + } catch (e: Throwable) { + e.printStackTrace() + throw e + } + } + }) +} + +inline fun invokeLater(crossinline func: () -> Unit) { + if (ApplicationManager.getApplication().isDispatchThread) { + func() + } else { + ApplicationManager.getApplication().invokeLater({ func() }, ModalityState.defaultModalityState()) + } +} + diff --git a/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/utils/Ui.kt b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/utils/Ui.kt new file mode 100644 index 0000000..bbf202f --- /dev/null +++ b/src/main/kotlin/br/com/devsrsouza/kotlinbukkitapi/tooling/wizard/utils/Ui.kt @@ -0,0 +1,171 @@ +package br.com.devsrsouza.kotlinbukkitapi.tooling.wizard.utils + +import com.intellij.ui.ScrollPaneFactory +import com.intellij.ui.components.JBScrollPane +import com.intellij.uiDesigner.core.* +import java.awt.* +import javax.swing.* + +data class TdPos(val col: Int, val row: Int) + +@DslMarker +annotation class TableTagMarker + +@TableTagMarker +class TableBuilder { + val items = LinkedHashMap>() + var row = 0 + var col = 0 + + var fill: TdFill = TdFill.BOTH + var anchor: TdAlign = TdAlign.CENTER_CENTER + var hpolicy: TdSize = TdSize.CAN_SHRINK_GROW + var vpolicy: TdSize = TdSize.CAN_SHRINK_GROW + var minWidth: Int? = null + var minHeight: Int? = null + var maxWidth: Int? = null + var maxHeight: Int? = null + + val nrows get() = items.values.map { it.second.row + it.second.rowSpan }.max() ?: 0 + val ncols get() = items.values.map { it.second.column + it.second.colSpan }.max() ?: 0 +} + +fun table(callback: TableBuilder.() -> Unit): JPanel { + val tb = TableBuilder() + tb.callback() + val panel = JPanel(GridLayoutManager(tb.nrows, tb.ncols, Insets(0, 0, 0, 0), 0, 0, false, false)) + for (item in tb.items.values) { + panel.add(item.first, item.second) + } + //add(panel) + return panel +} + +fun TableBuilder.tr( + fill: TdFill = TdFill.BOTH, + align: TdAlign = TdAlign.CENTER_CENTER, + policy: TdSize = TdSize.CAN_SHRINK_GROW, + hpolicy: TdSize = policy, + vpolicy: TdSize = policy, + minWidth: Int? = null, + maxWidth: Int? = null, + minHeight: Int? = null, + maxHeight: Int? = null, + callback: TableBuilder.() -> Unit +) { + this.fill = fill + this.anchor = align + this.hpolicy = hpolicy + this.vpolicy = vpolicy + this.minWidth = minWidth + this.maxWidth = maxWidth + this.minHeight = minHeight + this.maxHeight = maxHeight + callback() + row++ + col = 0 +} + +//fun TableBuilder.td(colspan: Int = 1, rowspan: Int = 1, callback: TableBuilder.() -> Unit) { +// GridConstraints() +//} + +fun TableBuilder.td( + component: Component, colspan: Int = 1, rowspan: Int = 1, + fill: TdFill? = null, + anchor: TdAlign? = null, + hpolicy: TdSize? = null, + vpolicy: TdSize? = null, + minWidth: Int? = null, + maxWidth: Int? = null, + minHeight: Int? = null, + maxHeight: Int? = null +) { + items[TdPos(col, row)] = Pair( + component, GridConstraints( + row, col, + rowspan, colspan, + (anchor ?: this.anchor).value, + (fill ?: this.fill).value, + (hpolicy ?: this.hpolicy).value, + (vpolicy ?: this.vpolicy).value, + Dimension((minWidth ?: this.minWidth) ?: -1, (minHeight ?: this.minHeight) ?: -1), + Dimension(-1, -1), + Dimension((maxWidth ?: this.maxWidth) ?: -1, (maxHeight ?: this.maxHeight) ?: -1), + 0, + false + ) + ) + col++ +} + +enum class TdFill(val value: Int) { + NONE(GridConstraints.FILL_NONE), + HORIZONTAL(GridConstraints.FILL_HORIZONTAL), + VERTICAL(GridConstraints.FILL_VERTICAL), + BOTH(GridConstraints.FILL_BOTH) +} + +enum class TdAlign(val value: Int) { + TOP_LEFT(GridConstraints.ANCHOR_NORTHWEST), + TOP_CENTER(GridConstraints.ANCHOR_NORTH), + TOP_RIGHT(GridConstraints.ANCHOR_NORTHEAST), + + CENTER_LEFT(GridConstraints.ANCHOR_WEST), + CENTER_CENTER(GridConstraints.ANCHOR_CENTER), + CENTER_RIGHT(GridConstraints.ANCHOR_EAST), + + BOTTOM_LEFT(GridConstraints.ANCHOR_SOUTHWEST), + BOTTOM_CENTER(GridConstraints.ANCHOR_SOUTH), + BOTTOM_RIGHT(GridConstraints.ANCHOR_SOUTHEAST), +} + +enum class TdSize(val value: Int) { + FIXED(GridConstraints.SIZEPOLICY_FIXED), + CAN_SHRINK(GridConstraints.SIZEPOLICY_CAN_SHRINK), + CAN_GROW(GridConstraints.SIZEPOLICY_CAN_GROW), + CAN_SHRINK_GROW(GridConstraints.SIZEPOLICY_CAN_SHRINK or GridConstraints.SIZEPOLICY_CAN_SHRINK), + WANT_GROW(GridConstraints.SIZEPOLICY_WANT_GROW), +} + +val JComboBox.items get() = (0 until this.itemCount).map { getItemAt(it) } + +/** + * API from: https://github.com/ktorio/ktor-init-tools/blob/master/ktor-intellij-plugin/src/io/ktor/start/intellij/util/Utils.kt + */ + +fun JPanel.addAtGrid( + item: JComponent, + row: Int, column: Int, + rowSpan: Int = 1, colSpan: Int = 1, + anchor: Int = GridConstraints.ANCHOR_CENTER, + fill: Int = GridConstraints.FILL_NONE, + HSizePolicy: Int = GridConstraints.SIZEPOLICY_CAN_GROW or GridConstraints.SIZEPOLICY_CAN_SHRINK, + VSizePolicy: Int = GridConstraints.SIZEPOLICY_CAN_GROW or GridConstraints.SIZEPOLICY_CAN_SHRINK, + minimumSize: Dimension = Dimension(-1, -1), + preferredSize: Dimension = Dimension(-1, -1), + maximumSize: Dimension = Dimension(-1, -1) +) { + add( + item, + GridConstraints( + row, + column, + rowSpan, + colSpan, + anchor, + fill, + HSizePolicy, + VSizePolicy, + minimumSize, + preferredSize, + maximumSize + ) + ) +} + +fun Component.scrollVertical() = ScrollPaneFactory.createScrollPane( + this, + JBScrollPane.VERTICAL_SCROLLBAR_ALWAYS, + JBScrollPane.HORIZONTAL_SCROLLBAR_NEVER +) \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 7118b69..942efc2 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -7,6 +7,8 @@ on how to target different products --> com.intellij.modules.platform org.jetbrains.kotlin + com.intellij.modules.lang + com.intellij.modules.externalSystem @@ -16,6 +18,8 @@ implementationClass="br.com.devsrsouza.kotlinbukkitapi.tooling.bukkript.BukkriptFileType" /> + +