diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 397a6e537..27074ddfd 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -36,7 +36,6 @@ body: - Architectury - Minecraft Forge - Fabric - - Lite Loader - Velocity - Mixins - BungeeCord diff --git a/.github/ISSUE_TEMPLATE/project_wizard_outdated.yaml b/.github/ISSUE_TEMPLATE/project_wizard_outdated.yaml new file mode 100644 index 000000000..3e6ebfe25 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/project_wizard_outdated.yaml @@ -0,0 +1,47 @@ +name: Project Wizard Outdated +description: The Minecraft project wizard is outdated +labels: ["status: unverified", "type: bug"] +body: + - type: markdown + attributes: + value: PLEASE DO NOT USE THIS TEMPLATE FOR FEATURE REQUESTS, INCLUDING REQUESTS FOR NEW PLATFORMS. + - type: input + id: plugin-version + attributes: + label: Minecraft Development for IntelliJ plugin version + validations: + required: true + - type: input + id: intellij-version + attributes: + label: IntelliJ version + validations: + required: true + - type: input + id: operating-system + attributes: + label: Operating System + validations: + required: true + - type: dropdown + id: target-platform + attributes: + label: Target platform + multiple: true + options: + - Spigot + - Paper + - Sponge + - Architectury + - Minecraft Forge + - Fabric + - Velocity + - BungeeCord + - Waterfall + validations: + required: true + - type: textarea + id: description + attributes: + label: Additional description + description: If the issue isn't obvious, please be as detailed as you can. \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index f132f6935..e73b78533 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,12 +9,14 @@ */ import org.cadixdev.gradle.licenser.header.HeaderStyle +import org.cadixdev.gradle.licenser.tasks.LicenseUpdate import org.gradle.internal.jvm.Jvm import org.gradle.internal.os.OperatingSystem import org.jetbrains.gradle.ext.settings import org.jetbrains.gradle.ext.taskTriggers import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jlleitschuh.gradle.ktlint.tasks.BaseKtLintCheckTask +import org.jlleitschuh.gradle.ktlint.tasks.KtLintFormatTask plugins { kotlin("jvm") version "1.8.0" @@ -22,7 +24,7 @@ plugins { mcdev groovy idea - id("org.jetbrains.intellij") version "1.12.0" + id("org.jetbrains.intellij") version "1.13.0" id("org.cadixdev.licenser") id("org.jlleitschuh.gradle.ktlint") version "10.3.0" } @@ -81,7 +83,6 @@ dependencies { implementation(files(gradleToolingExtensionJar)) - implementation(libs.templateMakerFabric) implementation(libs.mappingIo) implementation(libs.bundles.asm) @@ -156,10 +157,11 @@ intellij { "maven", "gradle", "Groovy", + "Kotlin", "org.toml.lang:$pluginTomlVersion", "ByteCodeViewer", - // needed dependencies for unit tests "properties", + // needed dependencies for unit tests "junit" ) @@ -272,7 +274,7 @@ license { fileTree(project.projectDir) { include("*.gradle.kts", "gradle.properties") exclude("**/buildSrc/**", "**/build/**") - } + }, ) } register("buildSrc") { @@ -280,7 +282,7 @@ license { project.fileTree(project.projectDir.resolve("buildSrc")) { include("**/*.kt", "**/*.kts") exclude("**/build/**") - } + }, ) } register("grammars") { @@ -289,6 +291,9 @@ license { } } +ktlint { + disabledRules.add("filename") +} tasks.withType().configureEach { workerMaxHeapSize.set("512m") } @@ -296,9 +301,7 @@ tasks.withType().configureEach { tasks.register("format") { group = "minecraft" description = "Formats source code according to project style" - val licenseFormat by tasks.existing - val ktlintFormat by tasks.existing - dependsOn(licenseFormat, ktlintFormat) + dependsOn(tasks.withType(), tasks.withType()) } val generateAtLexer by lexer("AtLexer", "com/demonwav/mcdev/platform/mcp/at/gen") @@ -328,7 +331,7 @@ val generate by tasks.registering { generateNbttParser, generateLangLexer, generateLangParser, - generateTranslationTemplateLexer + generateTranslationTemplateLexer, ) } @@ -370,7 +373,7 @@ tasks.buildSearchableOptions { "--add-opens=java.desktop/javax.swing=ALL-UNNAMED", "--add-opens=java.desktop/sun.awt=ALL-UNNAMED", "--add-opens=java.desktop/sun.font=ALL-UNNAMED", - "--add-opens=java.desktop/sun.swing=ALL-UNNAMED" + "--add-opens=java.desktop/sun.swing=ALL-UNNAMED", ) if (OperatingSystem.current().isMacOsX) { diff --git a/gradle.properties b/gradle.properties index c7fc5c964..dcd276500 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ kotlin.code.style=official ideaVersion = 2022.3 ideaVersionName = 2022.3 -coreVersion = 1.5.23 +coreVersion = 1.6.1 downloadIdeaSources = false pluginTomlVersion = 223.7571.59 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 163239ede..ef6fbd0c1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,6 @@ coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", ve coroutines-jdk8 = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8", version.ref = "coroutines" } coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "coroutines" } -templateMakerFabric = "com.extracraftx.minecraft:TemplateMakerFabric:0.4.1" mappingIo = "net.fabricmc:mapping-io:0.2.1" # GrammarKit diff --git a/readme.md b/readme.md index 29f257d0e..9f57a1dc1 100644 --- a/readme.md +++ b/readme.md @@ -133,12 +133,12 @@ This project is licensed under [MIT](license.txt). Supported Platforms ------------------- -- [![Bukkit Icon](src/main/resources/assets/icons/platform/Bukkit.png?raw=true) **Bukkit**](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/browse) ([![Spigot Icon](src/main/resources/assets/icons/platform/Spigot.png?raw=true) Spigot](https://spigotmc.org/) and [![Paper Icon](src/main/resources/assets/icons/platform/Paper.png?raw=true) Paper](https://papermc.io/)) +- [![Spigot Icon](src/main/resources/assets/icons/platform/Spigot.png?raw=true) **Spigot**](https://spigotmc.org/) ([![Paper Icon](src/main/resources/assets/icons/platform/Paper.png?raw=true) Paper](https://papermc.io/)) - [![Sponge Icon](src/main/resources/assets/icons/platform/Sponge_dark.png?raw=true) **Sponge**](https://www.spongepowered.org/) - [![Architectury Icon](src/main/resources/assets/icons/platform/Architectury.png?raw=true) **Architectury**](https://github.com/architectury/architectury-api) - [![Forge Icon](src/main/resources/assets/icons/platform/Forge.png?raw=true) **Minecraft Forge**](https://forums.minecraftforge.net/) - [![Fabric Icon](src/main/resources/assets/icons/platform/Fabric.png?raw=true) **Fabric**](https://fabricmc.net) -- [![LiteLoader Icon](src/main/resources/assets/icons/platform/LiteLoader.png?raw=true) **LiteLoader**](http://www.liteloader.com/) -- [![MCP Icon](src/main/resources/assets/icons/platform/MCP.png?raw=true) **MCP**](http://www.modcoderpack.com/) - [![Mixins Icon](src/main/resources/assets/icons/platform/Mixins_dark.png?raw=true) **Mixins**](https://github.com/SpongePowered/Mixin) - [![BungeeCord Icon](src/main/resources/assets/icons/platform/BungeeCord.png?raw=true) **BungeeCord**](https://www.spigotmc.org/wiki/bungeecord/) ([![Waterfall Icon](src/main/resources/assets/icons/platform/Waterfall.png?raw=true) Waterfall](https://github.com/PaperMC/Waterfall)) +- [![Velocity Icon](src/main/resources/assets/icons/platform/Velocity.png?raw=true) **Velocity**](https://velocitypowered.com/) +- [![Adventure Icon](src/main/resources/assets/icons/platform/Adventure.png?raw=true) **Adventure**](https://kyori.net/) diff --git a/src/main/kotlin/MinecraftSettings.kt b/src/main/kotlin/MinecraftSettings.kt index 4aff5abac..2307bae16 100644 --- a/src/main/kotlin/MinecraftSettings.kt +++ b/src/main/kotlin/MinecraftSettings.kt @@ -24,7 +24,7 @@ class MinecraftSettings : PersistentStateComponent { var isShowEventListenerGutterIcons: Boolean = true, var isShowChatColorGutterIcons: Boolean = true, var isShowChatColorUnderlines: Boolean = false, - var underlineType: UnderlineType = UnderlineType.DOTTED + var underlineType: UnderlineType = UnderlineType.DOTTED, ) private var state = State() @@ -81,7 +81,8 @@ class MinecraftSettings : PersistentStateComponent { DOTTED("Dotted", EffectType.BOLD_DOTTED_LINE), BOXED("Boxed", EffectType.BOXED), ROUNDED_BOXED("Rounded Boxed", EffectType.ROUNDED_BOX), - WAVED("Waved", EffectType.WAVE_UNDERSCORE); + WAVED("Waved", EffectType.WAVE_UNDERSCORE), + ; override fun toString(): String { return regular diff --git a/src/main/kotlin/creator/BuildSystemWizardStep.form b/src/main/kotlin/creator/BuildSystemWizardStep.form deleted file mode 100644 index eeea01802..000000000 --- a/src/main/kotlin/creator/BuildSystemWizardStep.form +++ /dev/null @@ -1,95 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/main/kotlin/creator/BuildSystemWizardStep.kt b/src/main/kotlin/creator/BuildSystemWizardStep.kt deleted file mode 100644 index 9d21ff0b1..000000000 --- a/src/main/kotlin/creator/BuildSystemWizardStep.kt +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.creator.exception.EmptyFieldSetupException -import com.demonwav.mcdev.creator.exception.OtherSetupException -import com.demonwav.mcdev.creator.exception.SetupException -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 javax.swing.JComboBox -import javax.swing.JPanel -import javax.swing.JTextField - -class BuildSystemWizardStep(private val creator: MinecraftProjectCreator) : ModuleWizardStep() { - - private lateinit var groupIdField: JTextField - private lateinit var artifactIdField: JTextField - private lateinit var versionField: JTextField - private lateinit var panel: JPanel - private lateinit var buildSystemBox: JComboBox - - override fun getComponent() = panel - - override fun updateStep() { - val previousBuildSystem = buildSystemBox.selectedItem - buildSystemBox.removeAllItems() - buildSystemBox.isEnabled = true - - val creatorConfig = creator.config ?: return - - val types = BuildSystemType.values().filter { type -> - type.creatorType.isInstance(creatorConfig) - } - - for (type in types) { - buildSystemBox.addItem(type) - } - - if (buildSystemBox.itemCount == 1) { - buildSystemBox.isEnabled = false - return - } - - if (previousBuildSystem != null) { - buildSystemBox.selectedItem = previousBuildSystem - return - } - - buildSystemBox.selectedIndex = 0 - - creatorConfig.preferredBuildSystem?.let { buildSystemBox.selectedItem = it } - } - - override fun updateDataModel() { - creator.buildSystem = createBuildSystem() - } - - private fun createBuildSystem(): BuildSystem { - val type = buildSystemBox.selectedItem as? BuildSystemType - ?: throw IllegalStateException("Selected item is not a ${BuildSystemType::class.java.name}") - - return type.create(groupIdField.text, artifactIdField.text, versionField.text) - } - - override fun validate(): Boolean { - try { - if (groupIdField.text.isEmpty()) { - throw EmptyFieldSetupException(groupIdField) - } - - if (artifactIdField.text.isEmpty()) { - throw EmptyFieldSetupException(artifactIdField) - } - - if (versionField.text.isBlank()) { - throw EmptyFieldSetupException(versionField) - } - - if (!groupIdField.text.matches(NO_WHITESPACE)) { - throw OtherSetupException("The GroupId field cannot contain any whitespace", groupIdField) - } - - if (!artifactIdField.text.matches(NO_WHITESPACE)) { - throw OtherSetupException("The ArtifactId field cannot contain any whitespace", artifactIdField) - } - } catch (e: SetupException) { - JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(e.error, MessageType.ERROR, null) - .setFadeoutTime(2000) - .createBalloon() - .show(RelativePoint.getSouthWestOf(e.j), Balloon.Position.below) - return false - } - - return true - } - - companion object { - val NO_WHITESPACE = Regex("\\S+") - } -} diff --git a/src/main/kotlin/creator/CreatorStep.kt b/src/main/kotlin/creator/CreatorStep.kt deleted file mode 100644 index e40fbfa97..000000000 --- a/src/main/kotlin/creator/CreatorStep.kt +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.DirectorySet -import com.demonwav.mcdev.util.runWriteTask -import com.demonwav.mcdev.util.virtualFileOrError -import com.intellij.codeInsight.actions.ReformatCodeProcessor -import com.intellij.ide.util.EditorHelper -import com.intellij.openapi.application.runReadAction -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.PsiDocumentManager -import com.intellij.psi.PsiFile -import com.intellij.psi.PsiManager -import com.intellij.psi.SmartPsiElementPointer -import com.intellij.psi.util.createSmartPointer -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.Paths -import java.nio.file.StandardOpenOption.CREATE -import java.nio.file.StandardOpenOption.TRUNCATE_EXISTING -import java.nio.file.StandardOpenOption.WRITE - -/** - * Represents a discrete kind of configuration code for a project. Project creators use these to spread implementation - * out between platforms without coupling them, and allow overriding for more complex options for specific build systems - * without coupling the build system and the platform. - */ -interface CreatorStep { - - fun runStep(indicator: ProgressIndicator) - - companion object { - private val scheduledReformats: MutableList> = mutableListOf() - fun runAllReformats() { - runWriteTask { - for (scheduledReformat in scheduledReformats) { - val file = scheduledReformat.element ?: continue - PsiDocumentManager.getInstance(file.project).getDocument(file)?.setReadOnly(false) - ReformatCodeProcessor(file, false).run() - } - } - scheduledReformats.clear() - } - - fun writeTextToFile( - project: Project, - targetDir: Path, - fileName: String, - text: String - ): VirtualFile { - if (Files.notExists(targetDir)) { - Files.createDirectories(targetDir) - } - val file = targetDir.resolve(fileName) - Files.write(file, text.toByteArray(Charsets.UTF_8), WRITE, CREATE, TRUNCATE_EXISTING) - val vFile = file.virtualFileOrError - - // Reformat the code to match their code style - runReadAction { - if (project.isDisposed) { - return@runReadAction - } - PsiManager.getInstance(project).findFile(vFile)?.let { - scheduledReformats += it.createSmartPointer() - } - } - - return vFile - } - - fun writeText(file: Path, text: String, psiManager: PsiManager? = null) { - Files.write(file, text.toByteArray(Charsets.UTF_8), CREATE, TRUNCATE_EXISTING, WRITE) - psiManager?.findFile(file.virtualFileOrError)?.let { - PsiDocumentManager.getInstance(psiManager.project).getDocument(it)?.setReadOnly(false) - ReformatCodeProcessor(it, false).run() - } - } - } -} - -class BasicJavaClassStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val className: String, - private val classText: String, - private val openInEditor: Boolean = true, - private val rootProvider: (BuildSystem) -> Path = { it.dirsOrError.sourceDirectory } -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - runWriteTask { - indicator.text = "Writing class: $className" - val files = className.split(".") - val className = files.last() - - val sourceDir = getMainClassDirectory(rootProvider(buildSystem), files) - - val classFile = CreatorStep.writeTextToFile(project, sourceDir, "$className.java", classText) - - if (openInEditor) { - // Set the editor focus on the created class - PsiManager.getInstance(project).findFile(classFile)?.let { classPsi -> - EditorHelper.openInEditor(classPsi) - } - } - } - } - - private fun getMainClassDirectory(dir: Path, files: List): Path { - val directories = files.slice(0 until files.lastIndex).toTypedArray() - val outputDir = Paths.get(dir.toAbsolutePath().toString(), *directories) - Files.createDirectories(outputDir) - return outputDir - } -} - -class CreateDirectoriesStep(private val buildSystem: BuildSystem, private val directory: Path) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - buildSystem.directories = DirectorySet.create(directory) - } -} diff --git a/src/main/kotlin/creator/JdkComboBoxWithPreference.kt b/src/main/kotlin/creator/JdkComboBoxWithPreference.kt new file mode 100644 index 000000000..75a779703 --- /dev/null +++ b/src/main/kotlin/creator/JdkComboBoxWithPreference.kt @@ -0,0 +1,172 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator + +import com.intellij.ide.util.PropertiesComponent +import com.intellij.ide.util.projectWizard.ProjectWizardUtil +import com.intellij.ide.util.projectWizard.WizardContext +import com.intellij.ide.wizard.AbstractWizard +import com.intellij.openapi.Disposable +import com.intellij.openapi.observable.properties.ObservableMutableProperty +import com.intellij.openapi.project.Project +import com.intellij.openapi.projectRoots.JavaSdk +import com.intellij.openapi.projectRoots.JavaSdkVersion +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.openapi.roots.ProjectRootManager +import com.intellij.openapi.roots.ui.configuration.JdkComboBox +import com.intellij.openapi.roots.ui.configuration.SdkListItem +import com.intellij.openapi.roots.ui.configuration.SdkListModel +import com.intellij.openapi.roots.ui.configuration.SdkListModelBuilder.ModelListener +import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel +import com.intellij.openapi.roots.ui.configuration.validateSdk +import com.intellij.openapi.util.Condition +import com.intellij.openapi.util.Disposer +import com.intellij.ui.dsl.builder.Cell +import com.intellij.ui.dsl.builder.Row +import javax.swing.JComponent + +internal class JdkPreferenceData( + var jdk: JavaSdkVersion, + val sdkPathByJdk: MutableMap, + var ignoreChangesForPreference: Boolean, +) + +class JdkComboBoxWithPreference internal constructor( + project: Project?, + private val model: ProjectSdksModel, + sdkFilter: Condition?, + private val preferenceData: JdkPreferenceData, +) : JdkComboBox(project, model, null, sdkFilter, null, null, null) { + private var suggestions = emptyList() + + init { + myModel.addModelListener(object : ModelListener { + override fun syncModel(model: SdkListModel) { + suggestions = model.items.filterIsInstance() + } + }) + } + + internal fun loadSuggestions(windowChild: JComponent, disposable: Disposable) { + myModel.detectItems(windowChild, disposable) + } + + internal fun getTargetJdk(project: Project?): Sdk? { + selectedJdk?.let { return it } + + return if (project != null && isProjectJdkSelected) { + ProjectRootManager.getInstance(project).projectSdk + } else { + null + } + } + + fun setPreferredJdk(version: JavaSdkVersion) { + if (version == preferenceData.jdk) { + return + } + + preferenceData.ignoreChangesForPreference = true + try { + preferenceData.jdk = version + reloadModel() + + for (jdkVersion in version.ordinal until JavaSdkVersion.values().size) { + val jdk = JavaSdkVersion.values()[jdkVersion] + + val preferredSdkPath = preferenceData.sdkPathByJdk[jdk] + if (preferredSdkPath != null) { + val sdk = model.sdks.firstOrNull { it.homePath == preferredSdkPath } + ?: suggestions.firstOrNull { it.homePath == preferredSdkPath } + if (sdk != null) { + setSelectedItem(sdk) + return + } + } + + val sdk = model.sdks.firstOrNull { JavaSdk.getInstance().getVersion(it) == jdk } + if (sdk != null) { + setSelectedItem(sdk) + return + } + } + } finally { + preferenceData.ignoreChangesForPreference = false + } + } +} + +fun Row.jdkComboBoxWithPreference( + context: WizardContext, + sdkProperty: ObservableMutableProperty, + sdkPropertyId: String, +): Cell { + val sdkModel = ProjectSdksModel() + + Disposer.register(context.disposable) { + sdkModel.disposeUIResources() + } + + val project = context.project + sdkModel.reset(project) + + val preferenceData = JdkPreferenceData(JavaSdkVersion.JDK_17, mutableMapOf(), false) + + val sdkFilter = Condition { + val version = it.versionString?.let(JavaSdkVersion::fromVersionString) + ?: return@Condition true + version >= preferenceData.jdk + } + val comboBox = JdkComboBoxWithPreference(context.project, sdkModel, sdkFilter, preferenceData) + + val selectedJdkProperty = "jdk.selected.$sdkPropertyId" + val preferenceDataProperty = "jdk.preference.$sdkPropertyId" + val stateComponent = project?.let(PropertiesComponent::getInstance) ?: PropertiesComponent.getInstance() + + stateComponent.getList(preferenceDataProperty)?.let { preferenceDataStrs -> + for (preferenceDataStr in preferenceDataStrs) { + val parts = preferenceDataStr.split('=', limit = 2) + val jdk = parts.firstOrNull()?.toIntOrNull()?.let { JavaSdkVersion.values()[it] } ?: continue + val sdk = parts.last() + preferenceData.sdkPathByJdk[jdk] = sdk + } + } + + comboBox.addActionListener { + val sdk = comboBox.getTargetJdk(project) + if (sdk != null) { + stateComponent.setValue(selectedJdkProperty, sdk.name) + + if (!preferenceData.ignoreChangesForPreference) { + val jdk = JavaSdk.getInstance().getVersion(sdk) + val homePath = sdk.homePath + if (jdk != null && homePath != null) { + preferenceData.sdkPathByJdk[jdk] = homePath + stateComponent.setList( + preferenceDataProperty, + preferenceData.sdkPathByJdk.map { (jdk, sdk) -> "${jdk.ordinal}=$sdk" }, + ) + } + } + } + sdkProperty.set(sdk) + } + + val lastUsedSdk = stateComponent.getValue(selectedJdkProperty) + ProjectWizardUtil.preselectJdkForNewModule(project, lastUsedSdk, comboBox) { true } + + val windowChild = context.getUserData(AbstractWizard.KEY)!!.contentPanel + comboBox.loadSuggestions(windowChild, context.disposable) + + return cell(comboBox) + .validationOnApply { validateSdk(sdkProperty, sdkModel) } + .onApply { context.projectJdk = sdkProperty.get() } +} diff --git a/src/main/kotlin/creator/LicenseStep.kt b/src/main/kotlin/creator/LicenseStep.kt deleted file mode 100644 index c4a5c57c9..000000000 --- a/src/main/kotlin/creator/LicenseStep.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator - -import com.demonwav.mcdev.platform.CommonTemplate -import com.demonwav.mcdev.util.License -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.project.Project -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.StandardOpenOption - -class LicenseStep( - private val project: Project, - private val rootDirectory: Path, - private val license: License, - private val author: String -) : CreatorStep { - - override fun runStep(indicator: ProgressIndicator) { - val licenseFile = rootDirectory.resolve("LICENSE") - - val fileText = CommonTemplate.applyLicenseTemplate(project, license, author) - - Files.write( - licenseFile, - fileText.toByteArray(Charsets.UTF_8), - StandardOpenOption.CREATE, - StandardOpenOption.WRITE, - StandardOpenOption.TRUNCATE_EXISTING - ) - } -} diff --git a/src/main/kotlin/creator/MinecraftModuleBuilder.kt b/src/main/kotlin/creator/MinecraftModuleBuilder.kt index d3b859f50..68473f8b3 100644 --- a/src/main/kotlin/creator/MinecraftModuleBuilder.kt +++ b/src/main/kotlin/creator/MinecraftModuleBuilder.kt @@ -11,118 +11,43 @@ package com.demonwav.mcdev.creator import com.demonwav.mcdev.asset.PlatformAssets +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.platformtype.PlatformTypeStep +import com.demonwav.mcdev.creator.step.TemplateOutdatedStep import com.demonwav.mcdev.platform.MinecraftModuleType -import com.demonwav.mcdev.platform.architectury.creator.ArchitecturyProjectSettingsWizard -import com.demonwav.mcdev.platform.bukkit.creator.BukkitProjectSettingsWizard -import com.demonwav.mcdev.platform.bungeecord.creator.BungeeCordProjectSettingsWizard -import com.demonwav.mcdev.platform.fabric.creator.FabricProjectSettingsWizard -import com.demonwav.mcdev.platform.forge.creator.ForgeProjectSettingsWizard -import com.demonwav.mcdev.platform.liteloader.creator.LiteLoaderProjectSettingsWizard -import com.demonwav.mcdev.platform.sponge.creator.SpongeProjectSettingsWizard -import com.demonwav.mcdev.platform.velocity.creator.VelocityProjectSettingsWizard -import com.intellij.ide.util.projectWizard.JavaModuleBuilder -import com.intellij.ide.util.projectWizard.ModuleWizardStep +import com.intellij.ide.projectWizard.ProjectSettingsStep import com.intellij.ide.util.projectWizard.WizardContext -import com.intellij.openapi.Disposable -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.module.ModuleType -import com.intellij.openapi.project.DumbAwareRunnable -import com.intellij.openapi.project.DumbService +import com.intellij.ide.wizard.AbstractNewProjectWizardBuilder +import com.intellij.ide.wizard.GitNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardBaseStep +import com.intellij.ide.wizard.RootNewProjectWizardStep 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.util.registry.Registry -import com.intellij.openapi.vfs.LocalFileSystem -import com.intellij.openapi.vfs.VirtualFile -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.Paths -class MinecraftModuleBuilder : JavaModuleBuilder() { - - private val creator = MinecraftProjectCreator() +class MinecraftModuleBuilder : AbstractNewProjectWizardBuilder() { override fun getPresentableName() = MinecraftModuleType.NAME override fun getNodeIcon() = PlatformAssets.MINECRAFT_ICON override fun getGroupName() = MinecraftModuleType.NAME - override fun getWeight() = BUILD_SYSTEM_WEIGHT - 1 override fun getBuilderId() = "MINECRAFT_MODULE" - - override fun isAvailable() = true // TODO: use the new project wizard system + override fun getDescription() = "Create a new Minecraft project" override fun setupRootModel(modifiableRootModel: ModifiableRootModel) { - val project = modifiableRootModel.project - val (root, vFile) = createAndGetRoot() - modifiableRootModel.addContentEntry(vFile) - if (moduleJdk != null) { modifiableRootModel.sdk = moduleJdk } else { modifiableRootModel.inheritSdk() } - - val r = DumbAwareRunnable { - creator.create(root, modifiableRootModel.module) - } - - if (project.isDisposed) { - return - } - - if ( - ApplicationManager.getApplication().isUnitTestMode || - ApplicationManager.getApplication().isHeadlessEnvironment - ) { - r.run() - return - } - - if (!project.isInitialized) { - StartupManager.getInstance(project).runAfterOpened(r) - return - } - - DumbService.getInstance(project).runWhenSmart(r) - } - - 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 } - override fun getModuleType(): ModuleType<*> = MinecraftModuleType.instance override fun getParentGroup() = MinecraftModuleType.NAME - - override fun createWizardSteps( - wizardContext: WizardContext, - modulesProvider: ModulesProvider - ): Array { - val baseSteps = arrayOf( - BuildSystemWizardStep(creator), - BukkitProjectSettingsWizard(creator), - SpongeProjectSettingsWizard(creator), - ForgeProjectSettingsWizard(creator), - FabricProjectSettingsWizard(creator), - ArchitecturyProjectSettingsWizard(creator), - LiteLoaderProjectSettingsWizard(creator), - VelocityProjectSettingsWizard(creator), - BungeeCordProjectSettingsWizard(creator) - ) - if (Registry.`is`("mcdev.wizard.finalizer")) { - return baseSteps + ProjectSetupFinalizerWizardStep(creator, wizardContext) - } - return baseSteps - } - - override fun getCustomOptionsStep(context: WizardContext?, parentDisposable: Disposable?) = - PlatformChooserWizardStep(creator) + override fun createStep(context: WizardContext) = RootNewProjectWizardStep(context).chain( + ::NewProjectWizardBaseStep, + ::GitNewProjectWizardStep, + PlatformTypeStep::create, + ::BuildSystemPropertiesStep, + ::ProjectSetupFinalizerWizardStep, + ::TemplateOutdatedStep, + ) + + override fun getIgnoredSteps() = listOf(ProjectSettingsStep::class.java) } diff --git a/src/main/kotlin/creator/MinecraftModuleWizardStep.kt b/src/main/kotlin/creator/MinecraftModuleWizardStep.kt deleted file mode 100644 index 22f6248bf..000000000 --- a/src/main/kotlin/creator/MinecraftModuleWizardStep.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.exception.SetupException -import com.demonwav.mcdev.util.toPackageName -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 javax.swing.JTextField -import org.apache.commons.lang.WordUtils - -abstract class MinecraftModuleWizardStep : ModuleWizardStep() { - - override fun validate(): Boolean { - try { - for (field in javaClass.declaredFields) { - val annotation = field.getAnnotation(ValidatedField::class.java) ?: continue - field.isAccessible = true - val textField = field.get(this) as? JTextField ?: continue - for (validationType in annotation.value) { - validationType.validate(textField) - } - } - } catch (e: SetupException) { - JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(e.error, MessageType.ERROR, null) - .setFadeoutTime(4000) - .createBalloon() - .show(RelativePoint.getSouthWestOf(e.j), Balloon.Position.below) - return false - } - - return true - } - - inline fun generateClassName( - buildSystem: BuildSystem, - name: String, - classNameModifier: (String) -> String = { it } - ): String { - val packageNameStart = buildSystem.groupId.toPackageName() - val packageNameEnd = buildSystem.artifactId.toPackageName() - val className = classNameModifier(name.replace(" ", "")) - return "$packageNameStart.$packageNameEnd.$className" - } - - protected fun basicUpdateStep( - creator: MinecraftProjectCreator, - pluginNameField: JTextField, - mainClassField: JTextField - ) { - val buildSystem = creator.buildSystem ?: return - - val name = WordUtils.capitalize(buildSystem.artifactId.replace('-', ' ')) - pluginNameField.text = name - - mainClassField.text = generateClassName(buildSystem, name) - } -} diff --git a/src/main/kotlin/creator/MinecraftProjectCreator.kt b/src/main/kotlin/creator/MinecraftProjectCreator.kt deleted file mode 100644 index 22794a256..000000000 --- a/src/main/kotlin/creator/MinecraftProjectCreator.kt +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.exception.ProjectCreatorException -import com.demonwav.mcdev.util.invokeAndWait -import com.demonwav.mcdev.util.invokeLater -import com.demonwav.mcdev.util.virtualFileOrError -import com.intellij.openapi.module.Module -import com.intellij.openapi.progress.ProcessCanceledException -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.progress.ProgressManager -import com.intellij.openapi.progress.Task -import com.intellij.openapi.vfs.VfsUtil -import java.nio.file.Path - -class MinecraftProjectCreator { - - var buildSystem: BuildSystem? = null - - var config: ProjectConfig? = null - - fun create(root: Path, module: Module) { - val build = buildSystem ?: throw IllegalStateException("buildSystem not initialized") - ProgressManager.getInstance().run(CreateTask(root, module, build)) - } - - class WorkLogStep(val config: Any) { - private val steps = mutableListOf>() - private var currentStep: Pair? = null - - fun printState(sb: StringBuilder) { - sb.append(" ").appendLine(if (config is String) config else config.javaClass.name) - for ((step, indent) in steps) { - printStep(sb, step, " ", indent) - } - currentStep?.let { (step, indent) -> - printStep(sb, step, " > ", indent) - } - } - - private fun printStep(sb: StringBuilder, step: Any, baseIndent: String, indent: Int) { - repeat(indent) { - sb.append(" ") - } - sb.append(baseIndent).appendLine(if (step is String) step else step.javaClass.name) - } - - fun newCurrentStep(newStep: Any, indent: Int = 0) { - finishCurrentStep() - currentStep = newStep to indent - } - - fun finishCurrentStep() { - currentStep?.let { step -> - steps += step - } - currentStep = null - } - - companion object { - var currentLog: WorkLogStep? = null - } - } - - private inner class CreateTask( - private val root: Path, - private val module: Module, - private val build: BuildSystem - ) : Task.Backgroundable(module.project, "Setting up project", false) { - override fun shouldStartInBackground() = false - - override fun run(indicator: ProgressIndicator) { - if (module.isDisposed || project.isDisposed) { - return - } - - val workLog = mutableListOf() - - try { - // Should be empty, just make sure IntelliJ knows that - invokeAndWait { - VfsUtil.markDirtyAndRefresh(false, true, true, root.virtualFileOrError) - } - - val config = this@MinecraftProjectCreator.config ?: return - - build.configure(config, root) - - val log = newLog(config, workLog) - if (!build.buildCreator(config, root, module).getSteps().run(indicator, log)) { - return - } - config.type.type.performCreationSettingSetup(module.project) - CreatorStep.runAllReformats() - - // Tell IntelliJ about everything we've done - invokeLater { - VfsUtil.markDirtyAndRefresh(false, true, true, root.virtualFileOrError) - } - } catch (e: Exception) { - if (e is ProcessCanceledException || e.cause is ProcessCanceledException) { - // Do not log PCE. The second condition is there because LaterInvocator wraps PCEs in RuntimeExceptions - return - } - val workLogText = buildString { - appendLine("Build steps completed:") - for (workLogStep in workLog) { - workLogStep.printState(this) - } - } - throw ProjectCreatorException(workLogText, e) - } finally { - WorkLogStep.currentLog = null - } - } - - private fun Iterable.run(indicator: ProgressIndicator, workLog: WorkLogStep): Boolean { - for (step in this) { - if (module.isDisposed || project.isDisposed) { - return false - } - workLog.newCurrentStep(step) - step.runStep(indicator) - } - workLog.finishCurrentStep() - return true - } - - private fun newLog(obj: Any, workLog: MutableList): WorkLogStep { - val log = WorkLogStep(obj) - WorkLogStep.currentLog = log - workLog += log - return log - } - } -} diff --git a/src/main/kotlin/creator/PlatformChooserWizardStep.kt b/src/main/kotlin/creator/PlatformChooserWizardStep.kt deleted file mode 100644 index a3aea1fa4..000000000 --- a/src/main/kotlin/creator/PlatformChooserWizardStep.kt +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator - -import com.demonwav.mcdev.asset.PlatformAssets -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.platform.architectury.creator.ArchitecturyProjectConfig -import com.demonwav.mcdev.platform.bukkit.creator.BukkitProjectConfig -import com.demonwav.mcdev.platform.bungeecord.creator.BungeeCordProjectConfig -import com.demonwav.mcdev.platform.fabric.creator.FabricProjectConfig -import com.demonwav.mcdev.platform.forge.creator.ForgeProjectConfig -import com.demonwav.mcdev.platform.liteloader.creator.LiteLoaderProjectConfig -import com.demonwav.mcdev.platform.sponge.creator.SpongeProjectConfig -import com.demonwav.mcdev.platform.velocity.creator.VelocityProjectConfig -import com.intellij.ide.util.projectWizard.ModuleWizardStep -import com.intellij.ui.components.JBRadioButton -import com.intellij.util.ui.UIUtil -import javax.swing.ButtonGroup -import javax.swing.JComponent -import javax.swing.JLabel -import javax.swing.JPanel - -class PlatformChooserWizardStep(private val creator: MinecraftProjectCreator) : ModuleWizardStep() { - - private lateinit var panel: JPanel - - private lateinit var projectButtons: ButtonGroup - private lateinit var spongeIcon: JLabel - private lateinit var bukkitPluginButton: JBRadioButton - private lateinit var spigotPluginButton: JBRadioButton - private lateinit var paperPluginButton: JBRadioButton - private lateinit var spongePluginButton: JBRadioButton - private lateinit var forgeModButton: JBRadioButton - private lateinit var fabricModButton: JBRadioButton - private lateinit var architecturyModButton: JBRadioButton - private lateinit var bungeeCordPluginButton: JBRadioButton - private lateinit var waterfallPluginButton: JBRadioButton - private lateinit var velocityPluginButton: JBRadioButton - private lateinit var liteLoaderModButton: JBRadioButton - - override fun getComponent(): JComponent { - if (UIUtil.isUnderDarcula()) { - spongeIcon.icon = PlatformAssets.SPONGE_ICON_2X_DARK - } else { - spongeIcon.icon = PlatformAssets.SPONGE_ICON_2X - } - - return panel - } - - override fun updateDataModel() { - creator.config = buildConfig() - } - - override fun validate(): Boolean { - updateDataModel() - val isValid = projectButtons.selection != null - if (isValid && creator.config == null) { - throw IllegalStateException( - "A project button does not have an associated config! Make sure to add your button to buildConfig()" - ) - } - return isValid - } - - private fun buildConfig(): ProjectConfig? { - return when { - bukkitPluginButton.isSelected -> BukkitProjectConfig(PlatformType.BUKKIT) - spigotPluginButton.isSelected -> BukkitProjectConfig(PlatformType.SPIGOT) - paperPluginButton.isSelected -> BukkitProjectConfig(PlatformType.PAPER) - spongePluginButton.isSelected -> SpongeProjectConfig() - forgeModButton.isSelected -> ForgeProjectConfig() - fabricModButton.isSelected -> FabricProjectConfig() - architecturyModButton.isSelected -> ArchitecturyProjectConfig() - liteLoaderModButton.isSelected -> LiteLoaderProjectConfig() - bungeeCordPluginButton.isSelected -> BungeeCordProjectConfig(PlatformType.BUNGEECORD) - waterfallPluginButton.isSelected -> BungeeCordProjectConfig(PlatformType.WATERFALL) - velocityPluginButton.isSelected -> VelocityProjectConfig() - else -> null - } - } -} diff --git a/src/main/kotlin/creator/ProjectChooserWizardStep.form b/src/main/kotlin/creator/ProjectChooserWizardStep.form deleted file mode 100644 index 2a70ee3d3..000000000 --- a/src/main/kotlin/creator/ProjectChooserWizardStep.form +++ /dev/null @@ -1,274 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/main/kotlin/creator/ProjectConfig.kt b/src/main/kotlin/creator/ProjectConfig.kt deleted file mode 100644 index 189d1e2a8..000000000 --- a/src/main/kotlin/creator/ProjectConfig.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.platform.PlatformType -import com.intellij.util.lang.JavaVersion - -private val bracketRegex = Regex("[\\[\\]]") -private val commaRegex = Regex("\\s*,\\s*") - -abstract class ProjectConfig { - - abstract var type: PlatformType - open val preferredBuildSystem: BuildSystemType? = null - - lateinit var pluginName: String - - var website: String? = null - fun hasWebsite() = !website.isNullOrBlank() - - val authors: MutableList = mutableListOf() - fun hasAuthors() = listContainsAtLeastOne(authors) - fun setAuthors(string: String) { - authors.clear() - authors.addAll(commaSplit(string)) - } - - var description: String? = null - fun hasDescription() = description?.isNotBlank() == true - - abstract val javaVersion: JavaVersion - - protected fun commaSplit(string: String): List { - return if (!string.isBlank()) { - string.trim().replace(bracketRegex, "").split(commaRegex).toList() - } else { - emptyList() - } - } - - protected fun listContainsAtLeastOne(list: MutableList?): Boolean { - if (list.isNullOrEmpty()) { - return false - } - - list.removeIf(String::isBlank) - - return list.size != 0 - } -} diff --git a/src/main/kotlin/creator/ProjectCreator.kt b/src/main/kotlin/creator/ProjectCreator.kt deleted file mode 100644 index bde918c40..000000000 --- a/src/main/kotlin/creator/ProjectCreator.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.intellij.openapi.module.Module - -/** - * This class represents a specific configuration for a project to be created. Typically these configurations represent - * ([PlatformType][com.demonwav.mcdev.platform.PlatformType], [BuildSystem][com.demonwav.mcdev.creator.buildsystem.BuildSystem]) - * pairs, but this API does not apply any such restriction. Each `BuildSystem` defines how to create a [ProjectCreator] - * instance for the given configuration using the [buildCreator][com.demonwav.mcdev.creator.buildsystem.BuildSystem.buildCreator] - * method. - * - *   - * - * In the current implementation the creation of [ProjectCreator] instances are delegated to project configurations via - * implementing the [GradleCreator][com.demonwav.mcdev.creator.buildsystem.gradle.GradleCreator] and/or - * [MavenCreator][com.demonwav.mcdev.creator.buildsystem.maven.MavenCreator] interfaces. This allows some configurations - * to produce different [ProjectCreator] instances based on their specific configuration, such as - * [ForgeProjectConfig][com.demonwav.mcdev.platform.forge.creator.ForgeProjectConfig]. - */ -interface ProjectCreator { - - /** - * Returns the [CreatorStep]s which should be executed in order to create the project configuration represented by - * this [ProjectCreator]. - */ - fun getSteps(): Iterable -} - -typealias JavaClassTextMapper = (packageName: String, className: String) -> String - -abstract class BaseProjectCreator( - private val rootModule: Module, - private val buildSystem: BuildSystem -) : ProjectCreator { - protected val project - get() = rootModule.project - - protected fun createJavaClassStep( - qualifiedClassName: String, - mapper: JavaClassTextMapper - ): BasicJavaClassStep { - val (packageName, className) = splitPackage(qualifiedClassName) - val classText = mapper(packageName, className) - return BasicJavaClassStep(project, buildSystem, qualifiedClassName, classText) - } - - protected fun splitPackage(text: String): Pair { - val index = text.lastIndexOf('.') - val className = text.substring(index + 1) - val packageName = text.substring(0, index) - return packageName to className - } -} diff --git a/src/main/kotlin/creator/ProjectSetupFinalizerWizardStep.kt b/src/main/kotlin/creator/ProjectSetupFinalizerWizardStep.kt index f854e4e14..927d401b7 100644 --- a/src/main/kotlin/creator/ProjectSetupFinalizerWizardStep.kt +++ b/src/main/kotlin/creator/ProjectSetupFinalizerWizardStep.kt @@ -10,262 +10,144 @@ package com.demonwav.mcdev.creator -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleCreator -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.VersionRange -import com.intellij.ide.util.projectWizard.ModuleWizardStep -import com.intellij.ide.util.projectWizard.WizardContext -import com.intellij.openapi.observable.properties.PropertyGraph +import com.demonwav.mcdev.creator.ProjectSetupFinalizer.Factory +import com.demonwav.mcdev.util.mapFirstNotNull +import com.demonwav.mcdev.util.toTypedArray +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.stepSequence +import com.intellij.openapi.extensions.ExtensionPointName +import com.intellij.openapi.observable.properties.GraphProperty +import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.JavaSdk import com.intellij.openapi.projectRoots.JavaSdkVersion import com.intellij.openapi.projectRoots.Sdk -import com.intellij.openapi.roots.ui.configuration.JdkComboBox -import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel -import com.intellij.ui.SortedComboBoxModel -import com.intellij.ui.components.Label +import com.intellij.openapi.ui.ValidationInfo +import com.intellij.openapi.ui.validation.AFTER_GRAPH_PROPAGATION +import com.intellij.openapi.ui.validation.DialogValidation +import com.intellij.ui.JBColor import com.intellij.ui.dsl.builder.Panel -import com.intellij.ui.dsl.builder.Row -import com.intellij.ui.dsl.builder.bindItem -import com.intellij.ui.dsl.builder.panel -import com.intellij.util.ui.UIUtil -import javax.swing.JComponent -import org.gradle.util.GradleVersion - -class ProjectSetupFinalizerWizardStep( - val creator: MinecraftProjectCreator, - val context: WizardContext -) : ModuleWizardStep() { - - private val finalizers: List = - listOf(JdkProjectSetupFinalizer(), GradleProjectSetupFinalizer()) - private val finalizersWithRow: MutableMap = linkedMapOf() - private val applicableFinalizers: MutableSet = linkedSetOf() - - private val panel by lazy { - panel { - row(Label("Project finalization")) {} - finalizers.forEach { finalizer -> - val row = row("${finalizer.title}") { - panel { - with(finalizer) { - buildComponent(creator, context) - } - } - } - finalizersWithRow[finalizer] = row +import com.intellij.ui.dsl.builder.Placeholder +import javax.swing.JLabel +import javax.swing.JPanel + +class ProjectSetupFinalizerWizardStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { + private val finalizers: List by lazy { + val factories = ProjectSetupFinalizer.EP_NAME.extensionList + val result = mutableListOf() + if (factories.isNotEmpty()) { + var par: NewProjectWizardStep = this + for (factory in factories) { + val finalizer = factory.create(par) + result += finalizer + par = finalizer } } + result + } + private val step by lazy { + if (finalizers.isEmpty()) { + null + } else { + stepSequence(finalizers[0], *finalizers.asSequence().drop(1).toTypedArray()) + } } - override fun isStepVisible(): Boolean = true - - override fun getComponent(): JComponent = panel - - override fun updateStep() { - applicableFinalizers.clear() - for ((finalizer, row) in finalizersWithRow) { - if (finalizer.isApplicable(creator, context)) { - applicableFinalizers.add(finalizer) - finalizer.validateConfigs(creator, context) - row.visible(true) - } else { - row.visible(false) + override fun setupUI(builder: Panel) { + step?.setupUI(builder) + if (finalizers.isNotEmpty()) { + builder.row { + cell(JPanel()) + .validationRequestor(AFTER_GRAPH_PROPAGATION(propertyGraph)) + .validation( + DialogValidation { + finalizers.mapFirstNotNull(ProjectSetupFinalizer::validate)?.let(::ValidationInfo) + } + ) } } } - override fun updateDataModel(): Unit = applicableFinalizers.forEach { it.apply(creator, context) } - - override fun validate(): Boolean = applicableFinalizers.all { it.validateChanges(creator, context) } + override fun setupProject(project: Project) { + step?.setupProject(project) + } } /** - * Used to adjust project configurations before project creation begins, or simply display a summary. - * Can also block project creation if problems are found with the configurations (such as version incompatibilities.) + * A step applied after all other steps for all Minecraft project creators. These steps can also block project creation + * by providing extra validations. + * + * To add custom project setup finalizers, register a [Factory] to the + * `com.demonwav.minecraft-dev.projectSetupFinalizer` extension point. */ -interface ProjectSetupFinalizer { - - val title: String - - /** - * Builds the component to display in a titled row ([title]) - */ - fun Panel.buildComponent(creator: MinecraftProjectCreator, context: WizardContext) - - /** - * Whether this finalizer makes sense to appear in the given context. - * - * If `false` is returned the component of this finalizer will not be shown, and [validateConfigs], - * [validateChanges] and [apply] won't be called until it returns `true`. - * - * @return `true` if this finalizer applies to the given context, `false` otherwise - */ - fun isApplicable(creator: MinecraftProjectCreator, context: WizardContext): Boolean - - /** - * Validates the existing [ProjectConfig]s of this wizard. You can also initialize - * - * Finalizers are expected to display errors in their own component. - * - * @return `true` if the project setup is valid, `false` otherwise. - */ - fun validateConfigs(creator: MinecraftProjectCreator, context: WizardContext): Boolean +interface ProjectSetupFinalizer : NewProjectWizardStep { + companion object { + val EP_NAME = ExtensionPointName("com.demonwav.minecraft-dev.projectSetupFinalizer") + } /** - * Validates the changes made in this finalizer's component. + * Validates the existing settings of this wizard. * - * @return `true` if the changes are valid, `false` otherwise. - */ - fun validateChanges(creator: MinecraftProjectCreator, context: WizardContext): Boolean - - /** - * Applies the changes validated in [validateChanges] to the project configuration. + * @return `null` if the settings are valid, or an error message if they are invalid. */ - fun apply(creator: MinecraftProjectCreator, context: WizardContext) -} + fun validate(): String? = null -class JdkProjectSetupFinalizer : ProjectSetupFinalizer { - - private val errorLabel = Label("", fontColor = UIUtil.FontColor.BRIGHTER) - .apply { - icon = UIUtil.getErrorIcon() - isVisible = false - } - private val sdksModel = ProjectSdksModel() - private lateinit var jdkBox: JdkComboBox - private var minimumVersion: JavaSdkVersion = JavaSdkVersion.JDK_1_8 - - private fun highestJDKVersionRequired(creator: MinecraftProjectCreator): JavaSdkVersion? { - val javaVersionRequired = creator.config?.javaVersion ?: return null - return JavaSdkVersion.fromJavaVersion(javaVersionRequired).also { - minimumVersion = it ?: JavaSdkVersion.JDK_1_8 - } + interface Factory { + fun create(parent: NewProjectWizardStep): ProjectSetupFinalizer } +} - private fun isUsingCompatibleJdk(creator: MinecraftProjectCreator, sdk: Sdk): Boolean { - val requiredJdkVersion = highestJDKVersionRequired(creator) ?: return false - return JavaSdk.getInstance().isOfVersionOrHigher(sdk, requiredJdkVersion) - } +class JdkProjectSetupFinalizer( + parent: NewProjectWizardStep, +) : AbstractNewProjectWizardStep(parent), ProjectSetupFinalizer { + private val sdkProperty: GraphProperty = propertyGraph.property(null) + private var sdk by sdkProperty + private var sdkComboBox: JdkComboBoxWithPreference? = null + private var preferredJdkLabel: Placeholder? = null + private var preferredJdkReason = "these settings" - override val title: String = "JDK" + var preferredJdk: JavaSdkVersion = JavaSdkVersion.JDK_17 + private set - override fun Panel.buildComponent(creator: MinecraftProjectCreator, context: WizardContext) { - row(errorLabel) {} - jdkBox = JdkComboBox( - context.project, - sdksModel, - { it is JavaSdk }, - { JavaSdk.getInstance().isOfVersionOrHigher(it, minimumVersion) }, - null, - null, - ) - reloadJdkBox(context) - if (jdkBox.itemCount > 0) { - jdkBox.selectedIndex = 0 - } - row("JDK version:") { - cell(jdkBox) - } - } - - override fun isApplicable(creator: MinecraftProjectCreator, context: WizardContext): Boolean { - reloadJdkBox(context) - return true + fun setPreferredJdk(value: JavaSdkVersion, reason: String) { + preferredJdk = value + preferredJdkReason = reason + sdkComboBox?.setPreferredJdk(value) + updatePreferredJdkLabel() } - private fun reloadJdkBox(context: WizardContext) { - sdksModel.syncSdks() - sdksModel.reset(context.project) - jdkBox.reloadModel() - } + init { + storeToData() - private fun updateUi(usingCompatibleJdk: Boolean) { - if (usingCompatibleJdk) { - errorLabel.text = "" - errorLabel.isVisible = false - return + sdkProperty.afterChange { + updatePreferredJdkLabel() } - - errorLabel.text = "Project requires at least Java ${minimumVersion.description}" - errorLabel.isVisible = true } - override fun validateConfigs(creator: MinecraftProjectCreator, context: WizardContext): Boolean { - val projectJdk = context.projectJdk ?: return true - val usingCompatibleJdk = isUsingCompatibleJdk(creator, projectJdk) - if (!usingCompatibleJdk) { - jdkBox.setInvalidJdk(projectJdk.name) + private fun updatePreferredJdkLabel() { + val sdk = this.sdk ?: return + val version = JavaSdk.getInstance().getVersion(sdk) ?: return + if (version == preferredJdk) { + preferredJdkLabel?.component = null } else { - jdkBox.selectedJdk = sdksModel.findSdk(projectJdk.name) - } - updateUi(usingCompatibleJdk) - return usingCompatibleJdk - } - - override fun validateChanges(creator: MinecraftProjectCreator, context: WizardContext): Boolean { - return isUsingCompatibleJdk(creator, jdkBox.selectedJdk ?: return false) - } - - override fun apply(creator: MinecraftProjectCreator, context: WizardContext) { - val selectedJdk = jdkBox.selectedJdk - if (selectedJdk != null) { - context.projectJdk = selectedJdk + preferredJdkLabel?.component = + JLabel("Java ${preferredJdk.description} is recommended for $preferredJdkReason") + .also { it.foreground = JBColor.YELLOW } } } -} - -class GradleProjectSetupFinalizer : ProjectSetupFinalizer { - private val model = SortedComboBoxModel(Comparator.naturalOrder()) - - private val propertyGraph = PropertyGraph("GradleProjectSetupFinalizer graph") - var gradleVersionProperty = propertyGraph.lazyProperty { SemanticVersion.release() } - var gradleVersion: SemanticVersion by gradleVersionProperty - private var config: ProjectConfig? = null - - private var gradleVersionRange: VersionRange? = null - - override val title: String = "Gradle" - - override fun Panel.buildComponent(creator: MinecraftProjectCreator, context: WizardContext) { - row("Gradle version:") { - comboBox(model) - .bindItem(gradleVersionProperty) - .enabled(false) // TODO load compatible Gradle versions list - } - } - - override fun isApplicable(creator: MinecraftProjectCreator, context: WizardContext): Boolean { - val buildSystem = creator.buildSystem - return buildSystem is GradleBuildSystem - } - - override fun validateConfigs(creator: MinecraftProjectCreator, context: WizardContext): Boolean { - config = creator.config - - if (creator.buildSystem !is GradleBuildSystem) { - return true - } - - val range = (creator.config as? GradleCreator)?.compatibleGradleVersions - gradleVersionRange = range - - gradleVersion = range?.upper ?: SemanticVersion.parse(GradleVersion.current().version) - model.clear() - model.add(gradleVersion) - model.selectedItem = gradleVersion - return true - } - - override fun validateChanges(creator: MinecraftProjectCreator, context: WizardContext): Boolean { - if (creator.buildSystem !is GradleBuildSystem) { - return true + override fun setupUI(builder: Panel) { + with(builder) { + row("JDK:") { + val sdkComboBox = jdkComboBoxWithPreference(context, sdkProperty, "${javaClass.name}.sdk") + this@JdkProjectSetupFinalizer.sdkComboBox = sdkComboBox.component + this@JdkProjectSetupFinalizer.preferredJdkLabel = placeholder() + updatePreferredJdkLabel() + } } - return gradleVersionRange == null || gradleVersion.parts.isNotEmpty() } - override fun apply(creator: MinecraftProjectCreator, context: WizardContext) { - (creator.buildSystem as? GradleBuildSystem)?.gradleVersion = gradleVersion + class Factory : ProjectSetupFinalizer.Factory { + override fun create(parent: NewProjectWizardStep) = JdkProjectSetupFinalizer(parent) } } diff --git a/src/main/kotlin/creator/buildsystem/AbstractBuildSystemStep.kt b/src/main/kotlin/creator/buildsystem/AbstractBuildSystemStep.kt new file mode 100644 index 000000000..82a02e15e --- /dev/null +++ b/src/main/kotlin/creator/buildsystem/AbstractBuildSystemStep.kt @@ -0,0 +1,106 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.buildsystem + +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.storeToData +import com.intellij.ide.util.projectWizard.WizardContext +import com.intellij.ide.wizard.AbstractNewProjectWizardMultiStep +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardMultiStepFactory +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.extensions.ExtensionPointName +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import com.intellij.ui.dsl.builder.Panel + +abstract class AbstractBuildSystemStep( + parent: NewProjectWizardStep, +) : AbstractNewProjectWizardMultiStep(parent, EP_NAME) { + companion object { + private val PLATFORM_NAME_KEY = Key.create("mcdev.platformName") + val EP_NAME = ExtensionPointName("com.demonwav.minecraft-dev.buildSystemWizard") + } + + init { + storeToData(javaClass) + } + + abstract val platformName: String + + override val self get() = this + override val label = "Build System:" + + override fun initSteps(): LinkedHashMap { + context.putUserData(PLATFORM_NAME_KEY, platformName) + return super.initSteps() + } + + override fun setupSwitcherUi(builder: Panel) { + if (steps.size > 1) { + super.setupSwitcherUi(builder) + } + } + + override fun setupUI(builder: Panel) { + val stepUninitialized = step.isEmpty() + super.setupUI(builder) + + // if no value was previously set for the step (i.e. not saved from when the user previously used this wizard) + // then set the build system to the preferred one for this platform, if one exists + if (stepUninitialized) { + for (buildSystem in steps.keys) { + if (BuildSystemSupport.getInstance(platformName, buildSystem)?.preferred == true) { + step = buildSystem + break + } + } + } + } + + interface Factory : NewProjectWizardMultiStepFactory { + override fun isEnabled(context: WizardContext): Boolean { + val platformName = context.getUserData(PLATFORM_NAME_KEY) + ?: throw IllegalStateException("Platform name not set") + return BuildSystemSupport.getInstance(platformName, name) != null + } + + override fun createStep(parent: AbstractBuildSystemStep): NewProjectWizardStep { + val platformName = parent.context.getUserData(PLATFORM_NAME_KEY) + ?: throw IllegalStateException("Platform name not set") + val buildSystemSupport = BuildSystemSupport.getInstance(platformName, name) + ?: throw IllegalStateException("Build system unsupported, this factory should have been filtered out") + return buildSystemSupport.createStep(BuildSystemSupport.PRE_STEP, parent) + } + } +} + +class GradleBuildSystem : AbstractBuildSystemStep.Factory { + override val name = "Gradle" +} + +class MavenBuildSystem : AbstractBuildSystemStep.Factory { + override val name = "Maven" +} + +abstract class AbstractRunBuildSystemStep( + parent: NewProjectWizardStep, + private val buildSystemStepClass: Class, +) : AbstractNewProjectWizardStep(parent) { + abstract val step: String + + override fun setupProject(project: Project) { + val buildSystemStep = findStep(buildSystemStepClass) + val buildSystemSupport = BuildSystemSupport.getInstance(buildSystemStep.platformName, buildSystemStep.step) + ?: throw IllegalStateException("Build system unsupported, this should have been filtered out") + buildSystemSupport.createStep(step, this).setupProject(project) + } +} diff --git a/src/main/kotlin/creator/buildsystem/BuildSystem.kt b/src/main/kotlin/creator/buildsystem/BuildSystem.kt index d6ca23dca..722079c21 100644 --- a/src/main/kotlin/creator/buildsystem/BuildSystem.kt +++ b/src/main/kotlin/creator/buildsystem/BuildSystem.kt @@ -10,107 +10,11 @@ package com.demonwav.mcdev.creator.buildsystem -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.ProjectCreator -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleCreator -import com.demonwav.mcdev.creator.buildsystem.maven.MavenBuildSystem -import com.demonwav.mcdev.creator.buildsystem.maven.MavenCreator -import com.demonwav.mcdev.platform.PlatformType -import com.intellij.openapi.module.Module -import java.nio.file.Path import java.util.EnumSet -import kotlin.reflect.KClass -/** - * Base class for build system project creation. - */ -abstract class BuildSystem( - val groupId: String, - val artifactId: String, - val version: String -) { - open val parent: BuildSystem? = null - val parentOrError: BuildSystem - get() = parent ?: throw IllegalStateException("Sub-module build system does not have a parent") - - abstract val type: BuildSystemType - - abstract fun buildCreator(obj: Any, rootDirectory: Path, module: Module): ProjectCreator - open fun configure(config: ProjectConfig, rootDirectory: Path) {} - - var repositories: MutableList = mutableListOf() - var dependencies: MutableList = mutableListOf() - - var directories: DirectorySet? = null - val dirsOrError: DirectorySet - get() = directories ?: throw IllegalStateException("Project structure is not yet created") - - val commonModuleName: String - get() = parentOrError.artifactId + "-common" - - /** - * Initial [CreatorStep]s to execute when creating the base of a multi-module project for this build system type. - * These steps run before the platform-specific submodule steps run. - * - * @see com.demonwav.mcdev.creator.MinecraftProjectCreator.CreateTask.run - */ - abstract fun multiModuleBaseSteps( - module: Module, - types: List, - rootDirectory: Path - ): Iterable - - /** - * Finalizer [CreatorStep]s to execute when finishing a multi-module project for this build system type. These steps - * are run after the platform-specific submodule steps are run, as well as after [multiModuleCommonSteps]. - * - * @see com.demonwav.mcdev.creator.MinecraftProjectCreator.CreateTask.run - */ - abstract fun multiModuleBaseFinalizer( - module: Module, - rootDirectory: Path - ): Iterable - - /** - * [CreatorStep]s for creating the shared common module for a multi-module project for this build system type. These - * steps run after the platform-specific submodule steps are run, and before [multiModuleBaseFinalizer]. - * - * @see com.demonwav.mcdev.creator.MinecraftProjectCreator.CreateTask.run - */ - abstract fun multiModuleCommonSteps( - module: Module, - rootDirectory: Path - ): Iterable - - /** - * Using the given [artifactId] create a new child [BuildSystem] instance which shares all of the other properties - * as this instance, except for the `artifactId`. - */ - abstract fun createSub(artifactId: String): BuildSystem -} - -enum class BuildSystemType(private val readableName: String, val creatorType: KClass<*>) { - MAVEN("Maven", MavenCreator::class) { - override fun create(groupId: String, artifactId: String, version: String): BuildSystem { - return MavenBuildSystem(groupId, artifactId, version) - } - }, - GRADLE("Gradle", GradleCreator::class) { - override fun create(groupId: String, artifactId: String, version: String): BuildSystem { - return GradleBuildSystem(groupId, artifactId, version) - } - }; - - /** - * Create a new [BuildSystem] instance using the provided artifact definition. - */ - abstract fun create(groupId: String, artifactId: String, version: String): BuildSystem - - override fun toString(): String { - return readableName - } +enum class BuildSystemType { + MAVEN, + GRADLE, } data class BuildDependency( @@ -118,11 +22,11 @@ data class BuildDependency( val artifactId: String = "", val version: String = "", val mavenScope: String? = null, - val gradleConfiguration: String? = null + val gradleConfiguration: String? = null, ) data class BuildRepository( var id: String = "", var url: String = "", - val buildSystems: EnumSet = EnumSet.allOf(BuildSystemType::class.java) + val buildSystems: EnumSet = EnumSet.allOf(BuildSystemType::class.java), ) diff --git a/src/main/kotlin/creator/buildsystem/BuildSystemPropertiesStep.kt b/src/main/kotlin/creator/buildsystem/BuildSystemPropertiesStep.kt new file mode 100644 index 000000000..a7a4c7dcd --- /dev/null +++ b/src/main/kotlin/creator/buildsystem/BuildSystemPropertiesStep.kt @@ -0,0 +1,83 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.buildsystem + +import com.demonwav.mcdev.creator.storeToData +import com.demonwav.mcdev.util.SemanticVersion +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardBaseData +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.observable.util.bindStorage +import com.intellij.openapi.ui.validation.AFTER_GRAPH_PROPAGATION +import com.intellij.openapi.ui.validation.CHECK_ARTIFACT_ID +import com.intellij.openapi.ui.validation.CHECK_GROUP_ID +import com.intellij.openapi.ui.validation.CHECK_NON_EMPTY +import com.intellij.openapi.ui.validation.validationErrorIf +import com.intellij.ui.dsl.builder.COLUMNS_MEDIUM +import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.bindText +import com.intellij.ui.dsl.builder.columns +import com.intellij.ui.dsl.builder.textValidation + +private val nonExampleValidation = validationErrorIf("Group ID must be changed from \"org.example\"") { + it == "org.example" +} + +private val versionValidation = validationErrorIf("Version must be a valid semantic version") { + SemanticVersion.tryParse(it) == null +} + +class BuildSystemPropertiesStep(private val parent: ParentStep) : AbstractNewProjectWizardStep(parent) + where ParentStep : NewProjectWizardStep, ParentStep : NewProjectWizardBaseData { + + val groupIdProperty = propertyGraph.property("org.example") + .bindStorage("${javaClass.name}.groupId") + val artifactIdProperty = propertyGraph.lazyProperty(::suggestArtifactId) + private val versionProperty = propertyGraph.property("1.0-SNAPSHOT") + .bindStorage("${javaClass.name}.version") + + var groupId by groupIdProperty + var artifactId by artifactIdProperty + var version by versionProperty + + init { + artifactIdProperty.dependsOn(parent.nameProperty, ::suggestArtifactId) + storeToData() + } + + private fun suggestArtifactId() = parent.name + + override fun setupUI(builder: Panel) { + builder.collapsibleGroup("Build System Properties") { + row("Group ID:") { + textField() + .bindText(groupIdProperty) + .columns(COLUMNS_MEDIUM) + .validationRequestor(AFTER_GRAPH_PROPAGATION(propertyGraph)) + .textValidation(CHECK_NON_EMPTY, CHECK_GROUP_ID, nonExampleValidation) + } + row("Artifact ID:") { + textField() + .bindText(artifactIdProperty) + .columns(COLUMNS_MEDIUM) + .validationRequestor(AFTER_GRAPH_PROPAGATION(propertyGraph)) + .textValidation(CHECK_NON_EMPTY, CHECK_ARTIFACT_ID) + } + row("Version:") { + textField() + .bindText(versionProperty) + .columns(COLUMNS_MEDIUM) + .validationRequestor(AFTER_GRAPH_PROPAGATION(propertyGraph)) + .textValidation(versionValidation) + } + }.expanded = true + } +} diff --git a/src/main/kotlin/creator/buildsystem/BuildSystemSupport.kt b/src/main/kotlin/creator/buildsystem/BuildSystemSupport.kt new file mode 100644 index 000000000..f7567f59d --- /dev/null +++ b/src/main/kotlin/creator/buildsystem/BuildSystemSupport.kt @@ -0,0 +1,56 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.buildsystem + +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.extensions.ExtensionPointName +import com.intellij.openapi.extensions.RequiredElement +import com.intellij.openapi.util.KeyedExtensionCollector +import com.intellij.serviceContainer.BaseKeyedLazyInstance +import com.intellij.util.KeyedLazyInstance +import com.intellij.util.xmlb.annotations.Attribute + +interface BuildSystemSupport { + companion object { + private val EP_NAME = ExtensionPointName>( + "com.demonwav.minecraft-dev.buildSystemSupport", + ) + private val COLLECTOR = KeyedExtensionCollector>(EP_NAME) + + fun getInstance(platform: String, buildSystem: String): BuildSystemSupport? = + COLLECTOR.findSingle(platform to buildSystem) + + const val PRE_STEP = "pre" + const val POST_STEP = "post" + } + + fun createStep(step: String, parent: NewProjectWizardStep): NewProjectWizardStep + + val preferred get() = false +} + +class BuildSystemSupportEntry : BaseKeyedLazyInstance(), KeyedLazyInstance { + @Attribute("implementation") + @RequiredElement + lateinit var implementation: String + + @Attribute("platform") + @RequiredElement + lateinit var platform: String + + @Attribute("buildSystem") + @RequiredElement + lateinit var buildSystem: String + + override fun getKey() = (platform to buildSystem).toString() + + override fun getImplementationClassName() = implementation +} diff --git a/src/main/kotlin/creator/buildsystem/BuildSystemTemplate.kt b/src/main/kotlin/creator/buildsystem/BuildSystemTemplate.kt deleted file mode 100644 index 2087ff7fc..000000000 --- a/src/main/kotlin/creator/buildsystem/BuildSystemTemplate.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator.buildsystem - -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenStep -import com.demonwav.mcdev.platform.BaseTemplate -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.GRADLE_GITIGNORE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.MAVEN_GITIGNORE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.MULTI_MODULE_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.MULTI_MODULE_COMMON_POM_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.MULTI_MODULE_GRADLE_PROPERTIES_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.MULTI_MODULE_POM_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.MULTI_MODULE_SETTINGS_GRADLE_TEMPLATE -import com.intellij.openapi.project.Project - -object BuildSystemTemplate : BaseTemplate() { - - fun applyPom(project: Project): String { - return project.applyTemplate(MULTI_MODULE_POM_TEMPLATE, BasicMavenStep.pluginVersions) - } - - fun applyCommonPom(project: Project): String { - return project.applyTemplate(MULTI_MODULE_COMMON_POM_TEMPLATE, BasicMavenStep.pluginVersions) - } - - fun applyBuildGradle(project: Project, buildSystem: BuildSystem): String { - val props = mapOf( - "GROUP_ID" to buildSystem.groupId, - "PLUGIN_VERSION" to buildSystem.version - ) - - return project.applyTemplate(MULTI_MODULE_BUILD_GRADLE_TEMPLATE, props) - } - - fun applyGradleProp(project: Project): String { - return project.applyTemplate(MULTI_MODULE_GRADLE_PROPERTIES_TEMPLATE) - } - - fun applySettingsGradle(project: Project, buildSystem: BuildSystem, subProjects: List): String { - val props = mapOf( - "ARTIFACT_ID" to buildSystem.artifactId, - "INCLUDES" to subProjects.joinToString(", ") { "'$it'" } - ) - - return project.applyTemplate(MULTI_MODULE_SETTINGS_GRADLE_TEMPLATE, props) - } - - fun applyGradleGitignore(project: Project): String { - return project.applyTemplate(GRADLE_GITIGNORE_TEMPLATE) - } - - fun applyMavenGitignore(project: Project): String { - return project.applyTemplate(MAVEN_GITIGNORE_TEMPLATE) - } -} diff --git a/src/main/kotlin/creator/buildsystem/DirectorySet.kt b/src/main/kotlin/creator/buildsystem/DirectorySet.kt deleted file mode 100644 index 04c812fdf..000000000 --- a/src/main/kotlin/creator/buildsystem/DirectorySet.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator.buildsystem - -import java.nio.file.Files -import java.nio.file.Path - -data class DirectorySet( - val sourceDirectory: Path, - val resourceDirectory: Path, - val testSourceDirectory: Path, - val testResourceDirectory: Path -) { - companion object { - fun create(dir: Path): DirectorySet { - val sourceDirectory = dir.resolve("src/main/java") - val resourceDirectory = dir.resolve("src/main/resources") - val testSourceDirectory = dir.resolve("src/test/java") - val testResourceDirectory = dir.resolve("src/test/resources") - Files.createDirectories(sourceDirectory) - Files.createDirectories(resourceDirectory) - Files.createDirectories(testSourceDirectory) - Files.createDirectories(testResourceDirectory) - return DirectorySet(sourceDirectory, resourceDirectory, testSourceDirectory, testResourceDirectory) - } - } -} diff --git a/src/main/kotlin/creator/buildsystem/gradle-steps.kt b/src/main/kotlin/creator/buildsystem/gradle-steps.kt new file mode 100644 index 000000000..bc4819008 --- /dev/null +++ b/src/main/kotlin/creator/buildsystem/gradle-steps.kt @@ -0,0 +1,468 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.buildsystem + +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.step.AbstractLongRunningStep +import com.demonwav.mcdev.creator.step.AbstractReformatFilesStep +import com.demonwav.mcdev.creator.step.FixedAssetsNewProjectWizardStep +import com.demonwav.mcdev.util.MinecraftTemplates.Companion.GRADLE_WRAPPER_PROPERTIES +import com.demonwav.mcdev.util.SemanticVersion +import com.demonwav.mcdev.util.childrenOfType +import com.demonwav.mcdev.util.invokeAndWait +import com.demonwav.mcdev.util.invokeLater +import com.demonwav.mcdev.util.mapFirstNotNull +import com.demonwav.mcdev.util.runGradleTaskAndWait +import com.demonwav.mcdev.util.runWriteAction +import com.demonwav.mcdev.util.runWriteTask +import com.demonwav.mcdev.util.virtualFileOrError +import com.intellij.execution.RunManager +import com.intellij.ide.ui.UISettings +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.lang.properties.psi.PropertiesFile +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.fileEditor.FileDocumentManager +import com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessProvider +import com.intellij.openapi.project.Project +import com.intellij.openapi.startup.StartupManager +import com.intellij.openapi.util.Key +import com.intellij.openapi.util.text.StringUtil +import com.intellij.openapi.vfs.VfsUtil +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.wm.WindowManager +import com.intellij.openapi.wm.ex.StatusBarEx +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiManager +import java.nio.file.Path +import java.util.concurrent.CountDownLatch +import org.jetbrains.kotlin.psi.KtBinaryExpression +import org.jetbrains.kotlin.psi.KtBlockExpression +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtNameReferenceExpression +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.psi.KtScriptInitializer +import org.jetbrains.plugins.gradle.service.execution.GradleExternalTaskConfigurationType +import org.jetbrains.plugins.gradle.service.execution.GradleRunConfiguration +import org.jetbrains.plugins.gradle.service.project.open.canLinkAndRefreshGradleProject +import org.jetbrains.plugins.gradle.service.project.open.linkAndRefreshGradleProject +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression +import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner + +val DEFAULT_GRADLE_VERSION = SemanticVersion.release(7, 3, 3) +val GRADLE_VERSION_KEY = Key.create("mcdev.gradleVersion") + +fun FixedAssetsNewProjectWizardStep.addGradleWrapperProperties(project: Project) { + val gradleVersion = data.getUserData(GRADLE_VERSION_KEY) ?: DEFAULT_GRADLE_VERSION + addTemplateProperties("GRADLE_WRAPPER_VERSION" to gradleVersion) + addTemplates(project, "gradle/wrapper/gradle-wrapper.properties" to GRADLE_WRAPPER_PROPERTIES) +} + +abstract class AbstractRunGradleTaskStep(parent: NewProjectWizardStep) : AbstractLongRunningStep(parent) { + abstract val task: String + override val description get() = "Running Gradle task: '$task'" + + override fun perform(project: Project) { + val outputDirectory = context.projectFileDirectory + runGradleTaskAndWait(project, Path.of(outputDirectory)) { settings -> + settings.taskNames = listOf(task) + } + } +} + +class GradleWrapperStep(parent: NewProjectWizardStep) : AbstractRunGradleTaskStep(parent) { + override val task = "wrapper" +} + +abstract class AbstractPatchGradleFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningStep(parent) { + override val description = "Patching Gradle files" + + abstract fun patch(project: Project, gradleFiles: GradleFiles) + + protected fun addRepositories(project: Project, buildGradle: GradleFile?, repositories: List) { + if (buildGradle == null || repositories.isEmpty()) { + return + } + + buildGradle.psi.runWriteAction { + when (buildGradle) { + is GroovyGradleFile -> { + val reposBlock = findOrCreateGroovyBlock(project, buildGradle.psi, "repositories") + val elementFactory = GroovyPsiElementFactory.getInstance(project) + for (repo in repositories) { + if (BuildSystemType.GRADLE !in repo.buildSystems) { + continue + } + val mavenBlock = + elementFactory.createStatementFromText("maven {\n}", reposBlock) as GrMethodCallExpression + val mavenClosure = mavenBlock.closureArguments[0] + if (repo.id.isNotBlank()) { + val idStatement = + elementFactory.createStatementFromText("name = ${makeStringLiteral(repo.id)}") + mavenClosure.addStatementBefore(idStatement, null) + } + val urlStatement = + elementFactory.createStatementFromText("url = ${makeStringLiteral(repo.url)}") + mavenClosure.addStatementBefore(urlStatement, null) + reposBlock.addStatementBefore(mavenBlock, null) + } + } + + is KotlinGradleFile -> { + val script = buildGradle.psi.script?.blockExpression ?: return@runWriteAction + val reposBlock = findOrCreateKotlinBlock(project, script, "repositories") + val elementFactory = KtPsiFactory(project) + for (repo in repositories) { + if (BuildSystemType.GRADLE !in repo.buildSystems) { + continue + } + val mavenBlock = elementFactory.createExpression("maven {\n}") as KtCallExpression + val mavenLambda = mavenBlock.lambdaArguments[0].getLambdaExpression()!!.bodyExpression!! + if (repo.id.isNotBlank()) { + val idStatement = elementFactory.createAssignment("name = ${makeStringLiteral(repo.id)}") + mavenLambda.addBefore(idStatement, mavenLambda.rBrace) + } + val urlStatement = elementFactory.createAssignment("url = uri(${makeStringLiteral(repo.url)})") + mavenLambda.addBefore(urlStatement, mavenLambda.rBrace) + reposBlock.addBefore(mavenBlock, reposBlock.rBrace) + } + } + } + } + } + + protected fun addDependencies(project: Project, buildGradle: GradleFile?, dependencies: List) { + if (buildGradle == null || dependencies.isEmpty()) { + return + } + + buildGradle.psi.runWriteAction { + when (buildGradle) { + is GroovyGradleFile -> { + val depsBlock = findOrCreateGroovyBlock(project, buildGradle.psi, "dependencies") + val elementFactory = GroovyPsiElementFactory.getInstance(project) + for (dep in dependencies) { + val gradleConfig = dep.gradleConfiguration ?: continue + val stmt = elementFactory.createStatementFromText( + "$gradleConfig \"${escapeGString(dep.groupId)}:${ + escapeGString(dep.artifactId) + }:${escapeGString(dep.version)}\"", + depsBlock, + ) + depsBlock.addStatementBefore(stmt, null) + } + } + + is KotlinGradleFile -> { + val script = buildGradle.psi.script?.blockExpression ?: return@runWriteAction + val depsBlock = findOrCreateKotlinBlock(project, script, "dependencies") + val elementFactory = KtPsiFactory(project) + for (dep in dependencies) { + val gradleConfig = dep.gradleConfiguration ?: continue + val stmt = elementFactory.createExpression( + "$gradleConfig(\"${escapeGString(dep.groupId)}:${ + escapeGString(dep.artifactId) + }:${escapeGString(dep.version)}\")", + ) + depsBlock.addBefore(stmt, depsBlock.rBrace) + } + } + } + } + } + + protected fun addPlugins(project: Project, buildGradle: GradleFile?, plugins: List) { + if (buildGradle == null || plugins.isEmpty()) { + return + } + + buildGradle.psi.runWriteAction { + fun makePluginStatement(plugin: GradlePlugin, kotlin: Boolean): String { + return buildString { + if (kotlin) { + append("id(${makeStringLiteral(plugin.id)})") + } else { + append("id ${makeStringLiteral(plugin.id)}") + } + plugin.version?.let { append(" version ${makeStringLiteral(it)}") } + if (!plugin.apply) { + append(" apply false") + } + } + } + + when (buildGradle) { + is GroovyGradleFile -> { + val pluginsBlock = findOrCreateGroovyBlock(project, buildGradle.psi, "plugins", first = true) + val elementFactory = GroovyPsiElementFactory.getInstance(project) + for (plugin in plugins) { + val stmt = elementFactory.createStatementFromText(makePluginStatement(plugin, false)) + pluginsBlock.addStatementBefore(stmt, null) + } + } + is KotlinGradleFile -> { + val script = buildGradle.psi.script?.blockExpression ?: return@runWriteAction + val pluginsBlock = findOrCreateKotlinBlock(project, script, "plugins", first = true) + val elementFactory = KtPsiFactory(project) + for (plugin in plugins) { + val stmt = elementFactory.createExpression(makePluginStatement(plugin, true)) + pluginsBlock.addBefore(stmt, pluginsBlock.rBrace) + } + } + } + } + } + + protected fun makeStringLiteral(str: String): String { + return "\"${escapeGString(str)}\"" + } + + private fun escapeGString(str: String): String { + return StringUtil.escapeStringCharacters(str.length, str, "\"\$", StringBuilder()).toString() + } + + protected fun findGroovyBlock(element: GrStatementOwner, name: String): GrClosableBlock? { + return element.statements + .mapFirstNotNull { call -> + if (call is GrMethodCallExpression && call.callReference?.methodName == name) { + call.closureArguments.firstOrNull() + } else { + null + } + } + } + + protected fun findOrCreateGroovyBlock( + project: Project, + element: GrStatementOwner, + name: String, + first: Boolean = false, + ): GrClosableBlock { + findGroovyBlock(element, name)?.let { return it } + val block = GroovyPsiElementFactory.getInstance(project).createStatementFromText("$name {\n}", element) + val anchor = if (first) { + element.statements.firstOrNull() + } else { + null + } + return (element.addStatementBefore(block, anchor) as GrMethodCallExpression).closureArguments.first() + } + + protected fun findKotlinBlock(element: KtBlockExpression, name: String): KtBlockExpression? { + return element.childrenOfType() + .flatMap { it.childrenOfType() } + .mapFirstNotNull { call -> + if ((call.calleeExpression as? KtNameReferenceExpression)?.getReferencedName() == name) { + call.lambdaArguments.firstOrNull()?.getLambdaExpression()?.bodyExpression + } else { + null + } + } + } + + protected fun findOrCreateKotlinBlock( + project: Project, + element: KtBlockExpression, + name: String, + first: Boolean = false, + ): KtBlockExpression { + findKotlinBlock(element, name)?.let { return it } + val block = KtPsiFactory(project).createExpression("$name {\n}") + val addedBlock = if (first) { + element.addAfter(block, element.lBrace) + } else { + element.addBefore(block, element.rBrace) + } + return (addedBlock as KtCallExpression).lambdaArguments.first().getLambdaExpression()!!.bodyExpression!! + } + + protected fun KtPsiFactory.createAssignment(text: String): KtBinaryExpression { + return this.createBlock(text).firstStatement as KtBinaryExpression + } + + override fun perform(project: Project) { + invokeAndWait { + if (project.isDisposed) { + return@invokeAndWait + } + + runWriteTask { + val rootDir = VfsUtil.findFile(Path.of(context.projectFileDirectory), true) + ?: return@runWriteTask + val gradleFiles = GradleFiles(project, rootDir) + NonProjectFileWritingAccessProvider.disableChecksDuring { + patch(project, gradleFiles) + gradleFiles.commit() + } + } + } + } + + class GradleFiles( + private val project: Project, + private val rootDir: VirtualFile, + ) { + private val lazyBuildGradle = lazy { + val file = rootDir.findChild("build.gradle") ?: rootDir.findChild("build.gradle.kts") + ?: return@lazy null + makeGradleFile(file) + } + private val lazySettingsGradle = lazy { + val file = rootDir.findChild("settings.gradle") ?: rootDir.findChild("settings.gradle.kts") + ?: return@lazy null + makeGradleFile(file) + } + private val lazyGradleProperties = lazy { + val file = rootDir.findChild("gradle.properties") ?: return@lazy null + PsiManager.getInstance(project).findFile(file) as? PropertiesFile + } + + val buildGradle by lazyBuildGradle + val settingsGradle by lazySettingsGradle + val gradleProperties by lazyGradleProperties + + private fun makeGradleFile(virtualFile: VirtualFile): GradleFile? { + val psi = PsiManager.getInstance(project).findFile(virtualFile) ?: return null + return when (psi) { + is GroovyFile -> GroovyGradleFile(psi) + is KtFile -> KotlinGradleFile(psi) + else -> null + } + } + + fun commit() { + val files = mutableListOf() + if (lazyBuildGradle.isInitialized()) { + buildGradle?.psi?.let { files += it } + } + if (lazySettingsGradle.isInitialized()) { + settingsGradle?.psi?.let { files += it } + } + if (lazyGradleProperties.isInitialized()) { + (gradleProperties as? PsiFile)?.let { files += it } + } + + val psiDocumentManager = PsiDocumentManager.getInstance(project) + val fileDocumentManager = FileDocumentManager.getInstance() + for (file in files) { + val document = psiDocumentManager.getDocument(file) ?: continue + fileDocumentManager.saveDocument(document) + } + } + } + + sealed class GradleFile { + abstract val psi: PsiFile + } + class GroovyGradleFile(override val psi: GroovyFile) : GradleFile() + class KotlinGradleFile(override val psi: KtFile) : GradleFile() +} + +open class GradleImportStep(parent: NewProjectWizardStep) : AbstractLongRunningStep(parent) { + override val description = "Importing Gradle project" + + open val additionalRunTasks = emptyList() + + override fun perform(project: Project) { + val rootDirectory = Path.of(context.projectFileDirectory) + val buildSystemProps = findStep>() + + // Tell IntelliJ to import this project + rootDirectory.virtualFileOrError.refresh(false, true) + + val latch = CountDownLatch(1) + + invokeLater(project.disposed) { + val path = rootDirectory.toAbsolutePath().toString() + if (canLinkAndRefreshGradleProject(path, project, false)) { + linkAndRefreshGradleProject(path, project) + showProgress(project) + } + + StartupManager.getInstance(project).runAfterOpened { + latch.countDown() + } + } + + // Set up the run config + // Get the gradle external task type, this is what sets it as a gradle task + addRunTaskConfiguration(project, rootDirectory, buildSystemProps, "build") + for (tasks in additionalRunTasks) { + addRunTaskConfiguration(project, rootDirectory, buildSystemProps, tasks) + } + + if (!ApplicationManager.getApplication().isDispatchThread) { + latch.await() + } + } + + private fun addRunTaskConfiguration( + project: Project, + rootDirectory: Path, + buildSystemProps: BuildSystemPropertiesStep<*>, + task: String, + ) { + val gradleType = GradleExternalTaskConfigurationType.getInstance() + + val runManager = RunManager.getInstance(project) + val runConfigName = buildSystemProps.artifactId + ' ' + task + + val runConfiguration = GradleRunConfiguration(project, gradleType.factory, runConfigName) + + // Set relevant gradle values + runConfiguration.settings.externalProjectPath = rootDirectory.toAbsolutePath().toString() + runConfiguration.settings.executionName = runConfigName + runConfiguration.settings.taskNames = listOf(task) + + runConfiguration.isAllowRunningInParallel = false + + val settings = runManager.createConfiguration( + runConfiguration, + gradleType.factory, + ) + + settings.isActivateToolWindowBeforeRun = true + settings.storeInLocalWorkspace() + + runManager.addConfiguration(settings) + if (runManager.selectedConfiguration == null) { + runManager.selectedConfiguration = settings + } + } +} + +class ReformatBuildGradleStep(parent: NewProjectWizardStep) : AbstractReformatFilesStep(parent) { + override fun addFilesToReformat() { + addFileToReformat("build.gradle") + addFileToReformat("build.gradle.kts") + } +} + +// Show the background processes window for setup tasks +private fun showProgress(project: Project) { + if (!UISettings.getInstance().showStatusBar || UISettings.getInstance().presentationMode) { + return + } + + val statusBar = WindowManager.getInstance().getStatusBar(project) as? StatusBarEx ?: return + statusBar.isProcessWindowOpen = true +} + +data class GradlePlugin( + val id: String, + val version: String? = null, + val apply: Boolean = true, +) diff --git a/src/main/kotlin/creator/buildsystem/gradle/GradleBuildSystem.kt b/src/main/kotlin/creator/buildsystem/gradle/GradleBuildSystem.kt deleted file mode 100644 index c56e9c9ee..000000000 --- a/src/main/kotlin/creator/buildsystem/gradle/GradleBuildSystem.kt +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator.buildsystem.gradle - -import com.demonwav.mcdev.creator.CreateDirectoriesStep -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.ProjectCreator -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.BuildSystemTemplate -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.VersionRange -import com.intellij.openapi.module.Module -import java.nio.file.Path -import java.util.Locale - -class GradleBuildSystem( - groupId: String, - artifactId: String, - version: String, - override val parent: GradleBuildSystem? = null -) : BuildSystem(groupId, artifactId, version) { - - override val type = BuildSystemType.GRADLE - - var gradleVersion: SemanticVersion = DEFAULT_WRAPPER_VERSION - - override fun createSub(artifactId: String): BuildSystem { - return GradleBuildSystem(this.groupId, artifactId, this.version, this) - } - - override fun multiModuleBaseSteps( - module: Module, - types: List, - rootDirectory: Path - ): Iterable { - val project = module.project - - val baseName = artifactId.lowercase(Locale.ENGLISH) - val names = mutableListOf("$baseName-common") - names += types.map { "$baseName-${it.name.lowercase(Locale.ENGLISH)}" } - - val buildText = BuildSystemTemplate.applyBuildGradle(project, this) - val propText = BuildSystemTemplate.applyGradleProp(project) - val settingsText = BuildSystemTemplate.applySettingsGradle(project, this, names) - val files = GradleFiles(buildText, propText, settingsText) - - return listOf( - GradleSetupStep(project, rootDirectory, this, files), - GradleWrapperStep(project, rootDirectory, this) - ) - } - - override fun multiModuleBaseFinalizer(module: Module, rootDirectory: Path): Iterable { - return listOf( - GradleGitignoreStep(module.project, rootDirectory), - BasicGradleFinalizerStep(module, rootDirectory, this) - ) - } - - override fun multiModuleCommonSteps(module: Module, rootDirectory: Path): Iterable { - return listOf(CreateDirectoriesStep(this, rootDirectory)) - } - - override fun buildCreator(obj: Any, rootDirectory: Path, module: Module): ProjectCreator { - if (obj !is GradleCreator) { - throw IllegalStateException("Cannot create a Gradle module from ${obj.javaClass.name}") - } - return obj.buildGradleCreator(rootDirectory, module, this) - } - - override fun configure(config: ProjectConfig, rootDirectory: Path) { - if (config is GradleCreator) { - config.configureRootGradle(rootDirectory, this) - } - } - - companion object { - val DEFAULT_WRAPPER_VERSION = SemanticVersion.release(7, 3, 3) - } -} - -/** - * A [ProjectConfig][com.demonwav.mcdev.creator.ProjectConfig] must implement this interface in order to support - * creating `Gradle` projects. - */ -interface GradleCreator { - - val compatibleGradleVersions: VersionRange? - - fun buildGradleCreator(rootDirectory: Path, module: Module, buildSystem: GradleBuildSystem): ProjectCreator - - /** - * This method allows extra configuration of the root [GradleBuildSystem] before any [CreatorStep]s have been - * created or executed. Not typically needed. - */ - fun configureRootGradle(rootDirectory: Path, buildSystem: GradleBuildSystem) {} -} - -data class GradlePlugin( - val id: String, - val version: String? = null, - val apply: Boolean = true, -) diff --git a/src/main/kotlin/creator/buildsystem/gradle/gradle-steps.kt b/src/main/kotlin/creator/buildsystem/gradle/gradle-steps.kt deleted file mode 100644 index 4462e970b..000000000 --- a/src/main/kotlin/creator/buildsystem/gradle/gradle-steps.kt +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator.buildsystem.gradle - -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.CreatorStep.Companion.writeText -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.BuildSystemTemplate -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.creator.buildsystem.DirectorySet -import com.demonwav.mcdev.util.ifNotEmpty -import com.demonwav.mcdev.util.invokeLater -import com.demonwav.mcdev.util.runGradleTaskAndWait -import com.demonwav.mcdev.util.runWriteAction -import com.demonwav.mcdev.util.runWriteTask -import com.demonwav.mcdev.util.virtualFileOrError -import com.intellij.codeInsight.actions.ReformatCodeProcessor -import com.intellij.execution.RunManager -import com.intellij.ide.ui.UISettings -import com.intellij.openapi.module.Module -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.project.Project -import com.intellij.openapi.wm.WindowManager -import com.intellij.openapi.wm.ex.StatusBarEx -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.psi.PsiFileFactory -import com.intellij.psi.PsiManager -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.StandardOpenOption.CREATE -import java.nio.file.StandardOpenOption.TRUNCATE_EXISTING -import java.nio.file.StandardOpenOption.WRITE -import org.jetbrains.plugins.gradle.service.execution.GradleExternalTaskConfigurationType -import org.jetbrains.plugins.gradle.service.execution.GradleRunConfiguration -import org.jetbrains.plugins.gradle.service.project.open.canLinkAndRefreshGradleProject -import org.jetbrains.plugins.gradle.service.project.open.linkAndRefreshGradleProject -import org.jetbrains.plugins.groovy.GroovyLanguage -import org.jetbrains.plugins.groovy.lang.psi.GroovyFile -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory -import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression - -class SimpleGradleSetupStep( - private val project: Project, - private val rootDirectory: Path, - private val buildSystem: BuildSystem, - private val gradleFiles: GradleFiles, - private val kotlinScript: Boolean = false -) : CreatorStep { - - override fun runStep(indicator: ProgressIndicator) { - runWriteTask { - if (project.isDisposed) { - return@runWriteTask - } - - buildSystem.directories = - DirectorySet.create(rootDirectory) - val (buildGradle, gradleProp, settingsGradle) = setupGradleFiles( - rootDirectory, - gradleFiles, - kotlinScript - ) - - val psiManager = PsiManager.getInstance(project) - writeText( - buildGradle, - gradleFiles.buildGradle, - psiManager - ) - if (gradleProp != null && gradleFiles.gradleProperties != null) { - writeText( - gradleProp, - gradleFiles.gradleProperties, - psiManager - ) - } - if (settingsGradle != null && gradleFiles.settingsGradle != null) { - writeText( - settingsGradle, - gradleFiles.settingsGradle, - psiManager - ) - } - } - } -} - -class GradleSetupStep( - private val project: Project, - private val rootDirectory: Path, - private val buildSystem: BuildSystem, - private val gradleFiles: GradleFiles, - private val kotlinScript: Boolean = false -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val (_, gradleProp, settingsGradle) = setupGradleFiles(rootDirectory, gradleFiles, kotlinScript) - - runWriteTask { - if (project.isDisposed) { - return@runWriteTask - } - - val buildGradlePsi = addBuildGradleDependencies(project, buildSystem, gradleFiles.buildGradle, kotlinScript) - val psiManager = PsiManager.getInstance(project) - psiManager.findDirectory(rootDirectory.virtualFileOrError)?.let { dir -> - dir.findFile(buildGradlePsi.name)?.delete() - val newFile = dir.add(buildGradlePsi) as? PsiFile ?: return@let - ReformatCodeProcessor(newFile, false).run() - } - - if (gradleProp != null && gradleFiles.gradleProperties != null) { - writeText(gradleProp, gradleFiles.gradleProperties, psiManager) - } - if (settingsGradle != null && gradleFiles.settingsGradle != null) { - writeText(settingsGradle, gradleFiles.settingsGradle, psiManager) - } - } - } -} - -data class GradleFiles( - val buildGradle: T, - val gradleProperties: T?, - val settingsGradle: T? -) - -fun setupGradleFiles(dir: Path, givenFiles: GradleFiles, kotlinScript: Boolean = false): GradleFiles { - return GradleFiles( - dir.resolve(if (kotlinScript) "build.gradle.kts" else "build.gradle"), - givenFiles.gradleProperties?.let { dir.resolve("gradle.properties") }, - givenFiles.settingsGradle?.let { dir.resolve(if (kotlinScript) "settings.gradle.kts" else "settings.gradle") }, - ).apply { - Files.deleteIfExists(buildGradle) - Files.createFile(buildGradle) - gradleProperties?.let { Files.deleteIfExists(it); Files.createFile(it) } - settingsGradle?.let { Files.deleteIfExists(it); Files.createFile(it) } - } -} - -fun addBuildGradleDependencies( - project: Project, - buildSystem: BuildSystem, - text: String, - kotlinScript: Boolean = false -): PsiFile { - val file = PsiFileFactory.getInstance(project).createFileFromText(GroovyLanguage, text) - return file.runWriteAction { - val fileName = if (kotlinScript) "build.gradle.kts" else "build.gradle" - file.name = fileName - - val groovyFile = file as GroovyFile - - buildSystem.repositories.asSequence() - .filter { it.buildSystems.contains(BuildSystemType.GRADLE) } - .map { "maven {name = '${it.id}'\nurl = '${it.url}'\n}" } - .toList() - .ifNotEmpty { reps -> appendExpressions(project, groovyFile, "repositories", reps) } - - buildSystem.dependencies.asSequence() - .filter { it.gradleConfiguration != null } - .map { "${it.gradleConfiguration} '${it.groupId}:${it.artifactId}:${it.version}'" } - .toList() - .ifNotEmpty { deps -> appendExpressions(project, groovyFile, "dependencies", deps) } - - return@runWriteAction file - } -} - -class AddGradlePluginStep( - private val project: Project, - private val rootDirectory: Path, - private val plugins: Collection, - private val kotlinScript: Boolean = false -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val fileName = if (kotlinScript) "build.gradle.kts" else "build.gradle" - val virtualFile = rootDirectory.resolve(fileName).virtualFileOrError - runWriteTask { - if (project.isDisposed) { - return@runWriteTask - } - - val file = PsiManager.getInstance(project).findFile(virtualFile) - ?: throw IllegalStateException("Could not find $fileName") - file.runWriteAction { - if (project.isDisposed) { - return@runWriteAction - } - - val groovyFile = file as GroovyFile - - plugins.asSequence() - .map { plugin -> - buildString { - append("id \"${plugin.id}\"") - plugin.version?.let { append(" version \"$it\"") } - if (!plugin.apply) { - append(" apply false") - } - } - } - .toList() - .ifNotEmpty { plugins -> appendExpressions(project, groovyFile, "plugins", plugins) } - - ReformatCodeProcessor(file, false).run() - } - } - } -} - -private fun appendExpressions( - project: Project, - file: GroovyFile, - name: String, - expressions: Iterable -) { - // Get the block so we can start working with it - val block = getClosableBlockByName(file, name) - ?: throw IllegalStateException("Failed to parse build.gradle files") - - // Create a super expression with all the expressions tied together - val expressionText = expressions.joinToString("\n") - - // We can't create each expression and add them to the file...that won't work. Groovy requires a new line - // from one method call expression to another, and there's no way to (easily) put whitespace in Psi because Psi is - // stupid. So instead we make the whole thing as one big clump and insert it into the block. - val fakeFile = GroovyPsiElementFactory.getInstance(project).createGroovyFile(expressionText, false, null) - val last = block.children.last() - block.addBefore(fakeFile, last) -} - -private fun getClosableBlockByName(element: PsiElement, name: String) = - element.children.asSequence() - .filter { - // We want to find the child which has a GrReferenceExpression with the right name - it.children.any { child -> child is GrReferenceExpression && child.text == name } - }.map { - // We want to find the grandchild which is a GrClosable block - it.children.mapNotNull { child -> child as? GrClosableBlock }.firstOrNull() - }.filterNotNull() - .firstOrNull() - -class BasicGradleFinalizerStep( - private val module: Module, - private val rootDirectory: Path, - private val buildSystem: BuildSystem, - private vararg val additionalRunTasks: String -) : CreatorStep { - private val project - get() = module.project - - override fun runStep(indicator: ProgressIndicator) { - // Tell IntelliJ to import this project - rootDirectory.virtualFileOrError.refresh(false, true) - - invokeLater(module.disposed) { - val path = rootDirectory.toAbsolutePath().toString() - if (canLinkAndRefreshGradleProject(path, project, false)) { - linkAndRefreshGradleProject(path, project) - showProgress(project) - } - } - - // Set up the run config - // Get the gradle external task type, this is what sets it as a gradle task - addRunTaskConfiguration("build") - for (tasks in additionalRunTasks) { - addRunTaskConfiguration(tasks) - } - } - - private fun addRunTaskConfiguration(task: String) { - val gradleType = GradleExternalTaskConfigurationType.getInstance() - - val runManager = RunManager.getInstance(project) - val runConfigName = buildSystem.artifactId + ' ' + task - - val runConfiguration = GradleRunConfiguration(project, gradleType.factory, runConfigName) - - // Set relevant gradle values - runConfiguration.settings.externalProjectPath = rootDirectory.toAbsolutePath().toString() - runConfiguration.settings.executionName = runConfigName - runConfiguration.settings.taskNames = listOf(task) - - runConfiguration.isAllowRunningInParallel = false - - val settings = runManager.createConfiguration( - runConfiguration, - gradleType.factory - ) - - settings.isActivateToolWindowBeforeRun = true - settings.storeInLocalWorkspace() - - runManager.addConfiguration(settings) - if (runManager.selectedConfiguration == null) { - runManager.selectedConfiguration = settings - } - } -} - -class GradleWrapperStep( - private val project: Project, - private val rootDirectory: Path, - private val buildSystem: GradleBuildSystem -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val wrapperVersion = buildSystem.gradleVersion - - // Setup gradle wrapper - // We'll write the properties file to ensure it sets up with the right version - val wrapperDir = rootDirectory.resolve("gradle/wrapper") - Files.createDirectories(wrapperDir) - val wrapperProp = wrapperDir.resolve("gradle-wrapper.properties") - - val text = "distributionUrl=https\\://services.gradle.org/distributions/gradle-$wrapperVersion-bin.zip\n" - - Files.write(wrapperProp, text.toByteArray(Charsets.UTF_8), CREATE, WRITE, TRUNCATE_EXISTING) - - indicator.text = "Setting up Gradle Wrapper" - indicator.text2 = "Running Gradle task: 'wrapper'" - runGradleTaskAndWait(project, rootDirectory) { settings -> - settings.taskNames = listOf("wrapper") - } - indicator.text2 = null - } -} - -// Show the background processes window for setup tasks -private fun showProgress(project: Project) { - if (!UISettings.getInstance().showStatusBar || UISettings.getInstance().presentationMode) { - return - } - - val statusBar = WindowManager.getInstance().getStatusBar(project) as? StatusBarEx ?: return - statusBar.isProcessWindowOpen = true -} - -class GradleGitignoreStep( - private val project: Project, - private val rootDirectory: Path -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val gitignoreFile = rootDirectory.resolve(".gitignore") - - val fileText = BuildSystemTemplate.applyGradleGitignore(project) - - Files.write(gitignoreFile, fileText.toByteArray(Charsets.UTF_8), CREATE, WRITE, TRUNCATE_EXISTING) - } -} diff --git a/src/main/kotlin/creator/buildsystem/maven-steps.kt b/src/main/kotlin/creator/buildsystem/maven-steps.kt new file mode 100644 index 000000000..d7d77a639 --- /dev/null +++ b/src/main/kotlin/creator/buildsystem/maven-steps.kt @@ -0,0 +1,169 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.buildsystem + +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.getVersionJson +import com.demonwav.mcdev.creator.step.AbstractLongRunningStep +import com.demonwav.mcdev.creator.step.AbstractModNameStep +import com.demonwav.mcdev.creator.step.AbstractReformatFilesStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.FixedAssetsNewProjectWizardStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.util.invokeAndWait +import com.demonwav.mcdev.util.runWriteAction +import com.demonwav.mcdev.util.runWriteTask +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.fileEditor.FileDocumentManager +import com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessProvider +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VfsUtil +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiManager +import com.intellij.psi.xml.XmlFile +import com.intellij.psi.xml.XmlTag +import com.intellij.util.xml.DomManager +import java.nio.file.Path +import java.util.concurrent.TimeUnit +import kotlinx.coroutines.runBlocking +import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel +import org.jetbrains.idea.maven.project.importing.MavenImportingManager + +private val pluginVersions by lazy { + runBlocking { + getVersionJson>("maven.json") + } +} + +fun FixedAssetsNewProjectWizardStep.addDefaultMavenProperties() { + addTemplateProperties(pluginVersions) +} + +abstract class AbstractPatchPomStep(parent: NewProjectWizardStep) : AbstractLongRunningStep(parent) { + override val description = "Patching pom.xml" + + open fun patchPom(model: MavenDomProjectModel, root: XmlTag) { + setupCore(model) + setupName(model) + setupInfo(root) + } + + protected fun setupCore(model: MavenDomProjectModel) { + val buildSystemProps = findStep>() + model.groupId.value = buildSystemProps.groupId + model.artifactId.value = buildSystemProps.artifactId + model.version.value = buildSystemProps.version + } + + protected fun setupName(model: MavenDomProjectModel) { + val name = data.getUserData(AbstractModNameStep.KEY) ?: return + model.name.value = name + } + + protected fun setupInfo(root: XmlTag) { + val website = data.getUserData(WebsiteStep.KEY) + val description = data.getUserData(DescriptionStep.KEY) + + val properties = root.findFirstSubTag("properties") + if (!website.isNullOrBlank()) { + val url = root.createChildTag("url", null, website, false) + root.addAfter(url, properties) + } + + if (!description.isNullOrBlank()) { + val descriptionTag = root.createChildTag("description", null, description, false) + root.addBefore(descriptionTag, properties) + } + } + + protected fun setupDependencies( + model: MavenDomProjectModel, + repositories: List, + dependencies: List, + ) { + for ((id, url, types) in repositories) { + if (!types.contains(BuildSystemType.MAVEN)) { + continue + } + val repository = model.repositories.addRepository() + repository.id.value = id + repository.url.value = url + } + + for ((depGroupId, depArtifactId, depVersion, scope) in dependencies) { + if (scope == null) { + continue + } + val dependency = model.dependencies.addDependency() + dependency.groupId.value = depGroupId + dependency.artifactId.value = depArtifactId + dependency.version.value = depVersion + dependency.scope.value = scope + } + } + + override fun perform(project: Project) { + invokeAndWait { + if (project.isDisposed) { + return@invokeAndWait + } + + runWriteTask { + val pomFile = VfsUtil.findFile(Path.of(context.projectFileDirectory, "pom.xml"), true) + ?: return@runWriteTask + val pomPsi = PsiManager.getInstance(project).findFile(pomFile) as? XmlFile ?: return@runWriteTask + + pomPsi.name = "pom.xml" + + NonProjectFileWritingAccessProvider.disableChecksDuring { + pomPsi.runWriteAction { + val manager = DomManager.getDomManager(project) + val mavenProjectXml = + manager.getFileElement(pomPsi, MavenDomProjectModel::class.java)?.rootElement + ?: return@runWriteAction + + val root = pomPsi.rootTag ?: return@runWriteAction + + patchPom(mavenProjectXml, root) + + // The maven importer requires that the document is saved to disk + val document = PsiDocumentManager.getInstance(project).getDocument(pomPsi) + ?: return@runWriteAction + FileDocumentManager.getInstance().saveDocument(document) + } + } + } + } + } +} + +class ReformatPomStep(parent: NewProjectWizardStep) : AbstractReformatFilesStep(parent) { + override fun addFilesToReformat() { + addFileToReformat("pom.xml") + } +} + +class MavenImportStep(parent: NewProjectWizardStep) : AbstractLongRunningStep(parent) { + override val description = "Importing Maven project" + + override fun perform(project: Project) { + val pomFile = VfsUtil.findFile(Path.of(context.projectFileDirectory).resolve("pom.xml"), true) + ?: return + val promise = invokeAndWait { + if (project.isDisposed) { + return@invokeAndWait null + } + MavenImportingManager.getInstance(project).linkAndImportFile(pomFile) + } ?: return + + promise.finishPromise.blockingGet(Int.MAX_VALUE, TimeUnit.SECONDS) + } +} diff --git a/src/main/kotlin/creator/buildsystem/maven/MavenBuildSystem.kt b/src/main/kotlin/creator/buildsystem/maven/MavenBuildSystem.kt deleted file mode 100644 index 373893307..000000000 --- a/src/main/kotlin/creator/buildsystem/maven/MavenBuildSystem.kt +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator.buildsystem.maven - -import com.demonwav.mcdev.creator.CreateDirectoriesStep -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.ProjectCreator -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.BuildSystemTemplate -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.platform.PlatformType -import com.intellij.openapi.module.Module -import java.nio.file.Path -import java.util.Locale - -class MavenBuildSystem( - groupId: String, - artifactId: String, - version: String, - override val parent: MavenBuildSystem? = null -) : BuildSystem(groupId, artifactId, version) { - - override val type = BuildSystemType.MAVEN - - override fun createSub(artifactId: String): BuildSystem { - return MavenBuildSystem(this.groupId, artifactId, this.version, this) - } - - override fun multiModuleBaseSteps( - module: Module, - types: List, - rootDirectory: Path - ): Iterable { - val project = module.project - val pomText = BuildSystemTemplate.applyPom(project) - - val baseName = artifactId.lowercase(Locale.ENGLISH) - val moduleNames = mutableListOf("$baseName-common") - moduleNames += types.map { "$baseName-${it.name.lowercase(Locale.ENGLISH)}" } - - return listOf( - BasicMavenStep( - project = project, - rootDirectory = rootDirectory, - buildSystem = this, - config = null, - pomText = pomText, - parts = listOf(BasicMavenStep.setupCore(), BasicMavenStep.setupModules(moduleNames)) - ) - ) - } - - override fun multiModuleBaseFinalizer(module: Module, rootDirectory: Path): Iterable { - return listOf( - MavenGitignoreStep(module.project, rootDirectory), - BasicMavenFinalizerStep(module, rootDirectory) - ) - } - - override fun multiModuleCommonSteps(module: Module, rootDirectory: Path): Iterable { - val project = module.project - val pomText = BuildSystemTemplate.applyCommonPom(project) - return listOf( - CreateDirectoriesStep(this, rootDirectory), - BasicMavenStep( - project = project, - rootDirectory = rootDirectory, - buildSystem = this, - config = null, - pomText = pomText, - parts = listOf(BasicMavenStep.setupSubCore(this.parentOrError.artifactId)) - ) - ) - } - - override fun buildCreator(obj: Any, rootDirectory: Path, module: Module): ProjectCreator { - if (obj !is MavenCreator) { - throw IllegalStateException("Cannot create a Maven module from ${obj.javaClass.name}") - } - return obj.buildMavenCreator(rootDirectory, module, this) - } - - override fun configure(config: ProjectConfig, rootDirectory: Path) { - if (config is MavenCreator) { - config.configureRootMaven(rootDirectory, this) - } - } -} - -/** - * A [ProjectConfig][com.demonwav.mcdev.creator.ProjectConfig] must implement this interface in order to support - * creating `Maven` projects. - */ -interface MavenCreator { - fun buildMavenCreator(rootDirectory: Path, module: Module, buildSystem: MavenBuildSystem): ProjectCreator - - /** - * This method allows extra configuration of the root [MavenBuildSystem] before any [CreatorStep]s have been - * created or executed. Not typically needed. - */ - fun configureRootMaven(rootDirectory: Path, buildSystem: MavenBuildSystem) {} -} diff --git a/src/main/kotlin/creator/buildsystem/maven/maven-steps.kt b/src/main/kotlin/creator/buildsystem/maven/maven-steps.kt deleted file mode 100644 index 7bfb06e04..000000000 --- a/src/main/kotlin/creator/buildsystem/maven/maven-steps.kt +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator.buildsystem.maven - -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.MinecraftProjectCreator -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.buildsystem.BuildDependency -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.BuildSystemTemplate -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.creator.buildsystem.DirectorySet -import com.demonwav.mcdev.creator.getVersionJson -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.util.invokeLater -import com.demonwav.mcdev.util.runWriteAction -import com.demonwav.mcdev.util.runWriteTask -import com.demonwav.mcdev.util.virtualFile -import com.intellij.codeInsight.actions.ReformatCodeProcessor -import com.intellij.execution.RunManager -import com.intellij.lang.xml.XMLLanguage -import com.intellij.openapi.module.Module -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.project.Project -import com.intellij.psi.PsiFileFactory -import com.intellij.psi.PsiManager -import com.intellij.psi.xml.XmlFile -import com.intellij.psi.xml.XmlTag -import com.intellij.util.xml.DomManager -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.StandardOpenOption.CREATE -import java.nio.file.StandardOpenOption.TRUNCATE_EXISTING -import java.nio.file.StandardOpenOption.WRITE -import kotlinx.coroutines.runBlocking -import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel -import org.jetbrains.idea.maven.execution.MavenRunConfigurationType -import org.jetbrains.idea.maven.execution.MavenRunnerParameters -import org.jetbrains.idea.maven.project.MavenProjectsManager - -typealias MavenStepFunc = (BasicMavenStep, MavenDomProjectModel, XmlTag) -> Unit - -class BasicMavenStep( - private val project: Project, - private val rootDirectory: Path, - private val buildSystem: BuildSystem, - private val config: ProjectConfig?, - private val pomText: String, - private val parts: Iterable = defaultParts -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - Files.createDirectories(rootDirectory) - - runWriteTask { - if (project.isDisposed) { - return@runWriteTask - } - val pomPsi = PsiFileFactory.getInstance(project).createFileFromText(XMLLanguage.INSTANCE, pomText) - ?: return@runWriteTask - - pomPsi.name = "pom.xml" - - val pomXmlPsi = pomPsi as XmlFile - pomPsi.runWriteAction { - if (project.isDisposed) { - return@runWriteAction - } - val manager = DomManager.getDomManager(project) - val mavenProjectXml = manager.getFileElement(pomXmlPsi, MavenDomProjectModel::class.java)?.rootElement - ?: return@runWriteAction - - val root = pomXmlPsi.rootTag ?: return@runWriteAction - - for (part in parts) { - MinecraftProjectCreator.WorkLogStep.currentLog?.newCurrentStep(part, 1) - part(this, mavenProjectXml, root) - } - MinecraftProjectCreator.WorkLogStep.currentLog?.finishCurrentStep() - - val vRootDir = rootDirectory.virtualFile - ?: throw IllegalStateException("Unable to find root directory: $rootDirectory") - val dir = PsiManager.getInstance(project).findDirectory(vRootDir) ?: return@runWriteAction - dir.findFile(pomPsi.name)?.delete() - dir.add(pomPsi) - - vRootDir.refresh(false, false) - val pomFile = vRootDir.findChild(pomPsi.name) ?: return@runWriteAction - - // Reformat the code to match their code style - PsiManager.getInstance(project).findFile(pomFile)?.let { - ReformatCodeProcessor(it, false).run() - } - } - } - } - - companion object { - val pluginVersions by lazy { - runBlocking { - getVersionJson>("maven.json") - } - } - - private val defaultParts = listOf(setupDirs(), setupCore(), setupName(), setupInfo(), setupDependencies()) - - fun setupDirs(): MavenStepFunc = { step, _, _ -> - step.buildSystem.directories = DirectorySet.create(step.rootDirectory) - } - - fun setupCore(): MavenStepFunc = { step, model, _ -> - model.groupId.value = step.buildSystem.groupId - model.artifactId.value = step.buildSystem.artifactId - model.version.value = step.buildSystem.version - } - - fun setupSubCore(parentArtifactId: String): MavenStepFunc { - return { step, model, _ -> - model.mavenParent.groupId.value = step.buildSystem.groupId - model.mavenParent.artifactId.value = parentArtifactId - model.mavenParent.version.value = step.buildSystem.version - model.artifactId.value = step.buildSystem.artifactId - } - } - - @Suppress("MemberVisibilityCanBePrivate") - fun setupName(): MavenStepFunc = { step, model, _ -> - model.name.value = step.config?.pluginName - } - - fun setupSubName(type: PlatformType): MavenStepFunc = { step, model, _ -> - model.name.value = step.config?.pluginName + " " + type.normalName - } - - fun setupInfo(): MavenStepFunc = { step, _, root -> - val properties = root.findFirstSubTag("properties") - - if (step.config?.hasWebsite() == true) { - val url = root.createChildTag("url", null, step.config.website, false) - root.addAfter(url, properties) - } - - if (step.config?.hasDescription() == true) { - val description = root.createChildTag("description", null, step.config.description, false) - root.addBefore(description, properties) - } - } - - fun setupDependencies(): MavenStepFunc = { step, model, _ -> - for ((id, url, types) in step.buildSystem.repositories) { - if (!types.contains(BuildSystemType.MAVEN)) { - continue - } - val repository = model.repositories.addRepository() - repository.id.value = id - repository.url.value = url - } - - for ((depGroupId, depArtifactId, depVersion, scope) in step.buildSystem.dependencies) { - if (scope == null) { - continue - } - val dependency = model.dependencies.addDependency() - dependency.groupId.value = depGroupId - dependency.artifactId.value = depArtifactId - dependency.version.value = depVersion - dependency.scope.value = scope - } - } - - fun setupModules(moduleNames: Iterable): MavenStepFunc = { _, model, _ -> - for (moduleName in moduleNames) { - val mod = model.modules.addModule() - mod.stringValue = moduleName - } - } - } -} - -class BasicMavenFinalizerStep( - private val rootModule: Module, - private val rootDirectory: Path -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - if (rootModule.isDisposed || rootModule.project.isDisposed) { - return - } - - val project = rootModule.project - - val pomFile = rootDirectory.resolve("pom.xml") - val vPomFile = pomFile.virtualFile ?: throw IllegalStateException("Could not find file: $pomFile") - - // Force Maven to setup the project - invokeLater(project.disposed) { - val manager = MavenProjectsManager.getInstance(project) - manager.addManagedFilesOrUnignore(listOf(vPomFile)) - manager.importingSettings.isDownloadDocsAutomatically = true - manager.importingSettings.isDownloadSourcesAutomatically = true - - // Setup the default Maven run config - val params = MavenRunnerParameters() - params.workingDirPath = rootDirectory.toAbsolutePath().toString() - params.goals = listOf("clean", "package") - val runnerSettings = MavenRunConfigurationType - .createRunnerAndConfigurationSettings(null, null, params, project) - runnerSettings.name = rootModule.name + " build" - runnerSettings.storeInLocalWorkspace() - - val runManager = RunManager.getInstance(project) - runManager.addConfiguration(runnerSettings) - if (runManager.selectedConfiguration == null) { - runManager.selectedConfiguration = runnerSettings - } - } - } -} - -class CommonModuleDependencyStep(private val buildSystem: BuildSystem) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - buildSystem.dependencies.add( - BuildDependency( - buildSystem.groupId, - buildSystem.commonModuleName, - "\${project.version}", - mavenScope = "compile" - ) - ) - } -} - -class MavenGitignoreStep( - private val project: Project, - private val rootDirectory: Path -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val gitignoreFile = rootDirectory.resolve(".gitignore") - - val fileText = BuildSystemTemplate.applyMavenGitignore(project) - - Files.write(gitignoreFile, fileText.toByteArray(Charsets.UTF_8), CREATE, WRITE, TRUNCATE_EXISTING) - } -} diff --git a/src/main/kotlin/creator/creator-utils.kt b/src/main/kotlin/creator/creator-utils.kt new file mode 100644 index 000000000..822403bc5 --- /dev/null +++ b/src/main/kotlin/creator/creator-utils.kt @@ -0,0 +1,355 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator + +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.FixedAssetsNewProjectWizardStep +import com.demonwav.mcdev.creator.step.LicenseStep +import com.demonwav.mcdev.util.MinecraftTemplates +import com.intellij.ide.fileTemplates.FileTemplateManager +import com.intellij.ide.starters.local.GeneratorTemplateFile +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.GitNewProjectWizardData +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.stepSequence +import com.intellij.openapi.observable.properties.ObservableMutableProperty +import com.intellij.openapi.observable.properties.ObservableProperty +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import com.intellij.openapi.util.RecursionManager +import java.time.ZonedDateTime + +val NewProjectWizardStep.gitEnabled + get() = data.getUserData(GitNewProjectWizardData.KEY)!!.git + +fun FixedAssetsNewProjectWizardStep.addGradleGitignore(project: Project) { + addTemplates(project, ".gitignore" to MinecraftTemplates.GRADLE_GITIGNORE_TEMPLATE) +} + +fun FixedAssetsNewProjectWizardStep.addMavenGitignore(project: Project) { + addTemplates(project, ".gitignore" to MinecraftTemplates.MAVEN_GITIGNORE_TEMPLATE) +} + +fun FixedAssetsNewProjectWizardStep.addTemplates(project: Project, vararg templates: Pair) { + addTemplates(project, templates.toMap()) +} + +fun FixedAssetsNewProjectWizardStep.addTemplates(project: Project, templates: Map) { + val manager = FileTemplateManager.getInstance(project) + addAssets(templates.map { (path, template) -> GeneratorTemplateFile(path, manager.getJ2eeTemplate(template)) }) +} + +fun FixedAssetsNewProjectWizardStep.addLicense(project: Project) { + val license = data.getUserData(LicenseStep.KEY) ?: return + val authors = data.getUserData(AuthorsStep.KEY) ?: return + addTemplateProperties( + "YEAR" to ZonedDateTime.now().year, + "AUTHOR" to authors.joinToString(", "), + ) + addTemplates(project, "LICENSE" to "${license.id}.txt") +} + +fun splitPackage(text: String): Pair { + val index = text.lastIndexOf('.') + val className = text.substring(index + 1) + val packageName = text.substring(0, index) + return packageName to className +} + +private val stepClassToKey = mutableMapOf, Key<*>>() + +@Suppress("UNCHECKED_CAST") +@PublishedApi +internal fun getOrCreateClassKey(clazz: Class) = + stepClassToKey.computeIfAbsent(clazz) { + Key.create(it.name) + } as Key + +private val stepClassToWhenAvailableKey = mutableMapOf, Key<*>>() + +@Suppress("UNCHECKED_CAST") +@PublishedApi +internal fun getWhenAvailableKey(clazz: Class) = + stepClassToWhenAvailableKey[clazz] as Key Unit>>? + +@Suppress("UNCHECKED_CAST") +@PublishedApi +internal fun getOrCreateWhenAvailableKey(clazz: Class) = + stepClassToWhenAvailableKey.computeIfAbsent(clazz) { + Key.create(it.name) + } as Key Unit>> + +inline fun T.storeToData() { + storeToData(T::class.java) +} + +fun T.storeToData(clazz: Class) { + data.putUserData(getOrCreateClassKey(clazz), this) + getWhenAvailableKey(clazz)?.let { whenAvailableKey -> + data.getUserData(whenAvailableKey)?.let { whenAvailable -> + for (func in whenAvailable) { + func(this) + } + data.putUserData(whenAvailableKey, null) + } + } +} + +inline fun NewProjectWizardStep.findStep(): T { + return findStep(T::class.java) +} + +fun NewProjectWizardStep.findStep(clazz: Class): T { + return data.getUserData(getOrCreateClassKey(clazz)) + ?: throw IllegalStateException("Could not find required step ${clazz.name}") +} + +inline fun NewProjectWizardStep.whenStepAvailable(noinline func: (T) -> Unit) { + val value = data.getUserData(getOrCreateClassKey(T::class.java)) + if (value != null) { + func(value) + } else { + val whenAvailableKey = getOrCreateWhenAvailableKey(T::class.java) + val whenAvailable = data.getUserData(whenAvailableKey) + ?: mutableListOf<(T) -> Unit>().also { data.putUserData(whenAvailableKey, it) } + whenAvailable += func + } +} + +private val updateWhenChangedGuard = + RecursionManager.createGuard>("mcdev.updateWhenChangedGuard") + +fun ObservableMutableProperty.updateWhenChanged(dependency: ObservableProperty<*>, suggestor: () -> T) { + dependency.afterChange { + updateWhenChangedGuard.doPreventingRecursion(this, false) { + set(suggestor()) + } + } +} + +class EmptyStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) + +@Suppress("DuplicatedCode") +fun T1.chain( + f1: (T1) -> T2, + f2: (T2) -> T3, + f3: (T3) -> T4, + f4: (T4) -> T5, + f5: (T5) -> T6, +): NewProjectWizardStep + where T1 : NewProjectWizardStep, + T2 : NewProjectWizardStep, + T3 : NewProjectWizardStep, + T4 : NewProjectWizardStep, + T5 : NewProjectWizardStep, + T6 : NewProjectWizardStep { + val s1 = f1(this) + val s2 = f2(s1) + val s3 = f3(s2) + val s4 = f4(s3) + val s5 = f5(s4) + return stepSequence(this, s1, s2, s3, s4, s5) +} + +@Suppress("DuplicatedCode") +fun T1.chain( + f1: (T1) -> T2, + f2: (T2) -> T3, + f3: (T3) -> T4, + f4: (T4) -> T5, + f5: (T5) -> T6, + f6: (T6) -> T7, +): NewProjectWizardStep + where T1 : NewProjectWizardStep, + T2 : NewProjectWizardStep, + T3 : NewProjectWizardStep, + T4 : NewProjectWizardStep, + T5 : NewProjectWizardStep, + T6 : NewProjectWizardStep, + T7 : NewProjectWizardStep { + val s1 = f1(this) + val s2 = f2(s1) + val s3 = f3(s2) + val s4 = f4(s3) + val s5 = f5(s4) + val s6 = f6(s5) + return stepSequence(this, s1, s2, s3, s4, s5, s6) +} + +@Suppress("DuplicatedCode") +fun T1.chain( + f1: (T1) -> T2, + f2: (T2) -> T3, + f3: (T3) -> T4, + f4: (T4) -> T5, + f5: (T5) -> T6, + f6: (T6) -> T7, + f7: (T7) -> T8, +): NewProjectWizardStep + where T1 : NewProjectWizardStep, + T2 : NewProjectWizardStep, + T3 : NewProjectWizardStep, + T4 : NewProjectWizardStep, + T5 : NewProjectWizardStep, + T6 : NewProjectWizardStep, + T7 : NewProjectWizardStep, + T8 : NewProjectWizardStep { + val s1 = f1(this) + val s2 = f2(s1) + val s3 = f3(s2) + val s4 = f4(s3) + val s5 = f5(s4) + val s6 = f6(s5) + val s7 = f7(s6) + return stepSequence(this, s1, s2, s3, s4, s5, s6, s7) +} + +@Suppress("DuplicatedCode") +fun T1.chain( + f1: (T1) -> T2, + f2: (T2) -> T3, + f3: (T3) -> T4, + f4: (T4) -> T5, + f5: (T5) -> T6, + f6: (T6) -> T7, + f7: (T7) -> T8, + f8: (T8) -> T9, +): NewProjectWizardStep + where T1 : NewProjectWizardStep, + T2 : NewProjectWizardStep, + T3 : NewProjectWizardStep, + T4 : NewProjectWizardStep, + T5 : NewProjectWizardStep, + T6 : NewProjectWizardStep, + T7 : NewProjectWizardStep, + T8 : NewProjectWizardStep, + T9 : NewProjectWizardStep { + val s1 = f1(this) + val s2 = f2(s1) + val s3 = f3(s2) + val s4 = f4(s3) + val s5 = f5(s4) + val s6 = f6(s5) + val s7 = f7(s6) + val s8 = f8(s7) + return stepSequence(this, s1, s2, s3, s4, s5, s6, s7, s8) +} + +@Suppress("DuplicatedCode") +fun T1.chain( + f1: (T1) -> T2, + f2: (T2) -> T3, + f3: (T3) -> T4, + f4: (T4) -> T5, + f5: (T5) -> T6, + f6: (T6) -> T7, + f7: (T7) -> T8, + f8: (T8) -> T9, + f9: (T9) -> T10, +): NewProjectWizardStep + where T1 : NewProjectWizardStep, + T2 : NewProjectWizardStep, + T3 : NewProjectWizardStep, + T4 : NewProjectWizardStep, + T5 : NewProjectWizardStep, + T6 : NewProjectWizardStep, + T7 : NewProjectWizardStep, + T8 : NewProjectWizardStep, + T9 : NewProjectWizardStep, + T10 : NewProjectWizardStep { + val s1 = f1(this) + val s2 = f2(s1) + val s3 = f3(s2) + val s4 = f4(s3) + val s5 = f5(s4) + val s6 = f6(s5) + val s7 = f7(s6) + val s8 = f8(s7) + val s9 = f9(s8) + return stepSequence(this, s1, s2, s3, s4, s5, s6, s7, s8, s9) +} + +@Suppress("DuplicatedCode") +fun T1.chain( + f1: (T1) -> T2, + f2: (T2) -> T3, + f3: (T3) -> T4, + f4: (T4) -> T5, + f5: (T5) -> T6, + f6: (T6) -> T7, + f7: (T7) -> T8, + f8: (T8) -> T9, + f9: (T9) -> T10, + f10: (T10) -> T11, +): NewProjectWizardStep + where T1 : NewProjectWizardStep, + T2 : NewProjectWizardStep, + T3 : NewProjectWizardStep, + T4 : NewProjectWizardStep, + T5 : NewProjectWizardStep, + T6 : NewProjectWizardStep, + T7 : NewProjectWizardStep, + T8 : NewProjectWizardStep, + T9 : NewProjectWizardStep, + T10 : NewProjectWizardStep, + T11 : NewProjectWizardStep { + val s1 = f1(this) + val s2 = f2(s1) + val s3 = f3(s2) + val s4 = f4(s3) + val s5 = f5(s4) + val s6 = f6(s5) + val s7 = f7(s6) + val s8 = f8(s7) + val s9 = f9(s8) + val s10 = f10(s9) + return stepSequence(this, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) +} + +@Suppress("DuplicatedCode") +fun T1.chain( + f1: (T1) -> T2, + f2: (T2) -> T3, + f3: (T3) -> T4, + f4: (T4) -> T5, + f5: (T5) -> T6, + f6: (T6) -> T7, + f7: (T7) -> T8, + f8: (T8) -> T9, + f9: (T9) -> T10, + f10: (T10) -> T11, + f11: (T11) -> T12, +): NewProjectWizardStep + where T1 : NewProjectWizardStep, + T2 : NewProjectWizardStep, + T3 : NewProjectWizardStep, + T4 : NewProjectWizardStep, + T5 : NewProjectWizardStep, + T6 : NewProjectWizardStep, + T7 : NewProjectWizardStep, + T8 : NewProjectWizardStep, + T9 : NewProjectWizardStep, + T10 : NewProjectWizardStep, + T11 : NewProjectWizardStep, + T12 : NewProjectWizardStep { + val s1 = f1(this) + val s2 = f2(s1) + val s3 = f3(s2) + val s4 = f4(s3) + val s5 = f5(s4) + val s6 = f6(s5) + val s7 = f7(s6) + val s8 = f8(s7) + val s9 = f9(s8) + val s10 = f10(s9) + val s11 = f11(s10) + return stepSequence(this, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11) +} diff --git a/src/main/kotlin/creator/exception/ProjectCreatorException.kt b/src/main/kotlin/creator/exception/ProjectCreatorException.kt deleted file mode 100644 index 0e99fac70..000000000 --- a/src/main/kotlin/creator/exception/ProjectCreatorException.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator.exception - -class ProjectCreatorException(message: String, cause: Throwable) : Exception(message, cause) diff --git a/src/main/kotlin/creator/exception/SetupException.kt b/src/main/kotlin/creator/exception/SetupException.kt deleted file mode 100644 index 54b40dd87..000000000 --- a/src/main/kotlin/creator/exception/SetupException.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.creator.exception - -import javax.swing.JComponent - -sealed class SetupException(val j: JComponent) : Exception() { - - abstract val error: String -} - -class EmptyFieldSetupException(j: JComponent) : SetupException(j) { - override val error: String - get() = "Please fill in all required fields" -} - -class BadListSetupException(j: JComponent) : SetupException(j) { - override val error: String - get() = "Please enter as a comma separated list" -} - -class EmptyInputSetupException(j: JComponent) : SetupException(j) { - override val error: String - get() = "Please fill in all required fields" -} - -class InvalidClassNameException(j: JComponent) : SetupException(j) { - override val error: String - get() = "Class Name must be a valid Java identifier and cannot be the default package" -} - -class OtherSetupException(private val msg: String, j: JComponent) : SetupException(j) { - override val error: String - get() = "$msg" -} diff --git a/src/main/kotlin/creator/field-validation.kt b/src/main/kotlin/creator/field-validation.kt index 53d3807e2..3377e7fbc 100644 --- a/src/main/kotlin/creator/field-validation.kt +++ b/src/main/kotlin/creator/field-validation.kt @@ -10,41 +10,7 @@ package com.demonwav.mcdev.creator -import com.demonwav.mcdev.creator.exception.BadListSetupException -import com.demonwav.mcdev.creator.exception.EmptyInputSetupException -import com.demonwav.mcdev.creator.exception.InvalidClassNameException import com.demonwav.mcdev.util.isJavaKeyword -import javax.swing.JTextField - -@Target(AnnotationTarget.FIELD) -@Retention(AnnotationRetention.RUNTIME) -annotation class ValidatedField(vararg val value: ValidatedFieldType) - -enum class ValidatedFieldType { - NON_BLANK { - override fun validate(field: JTextField) { - if (field.text.isBlank()) { - throw EmptyInputSetupException(field) - } - } - }, - CLASS_NAME { - override fun validate(field: JTextField) { - if (!isValidClassName(field.text)) { - throw InvalidClassNameException(field) - } - } - }, - LIST { - override fun validate(field: JTextField) { - if (!field.text.matches(listPattern)) { - throw BadListSetupException(field) - } - } - }; - - abstract fun validate(field: JTextField) -} fun isValidClassName(className: String): Boolean { // default package @@ -66,11 +32,5 @@ fun isValidClassName(className: String): Boolean { return false } // keyword identifier - if (fieldNameSplit.any { it.isJavaKeyword() }) { - return false - } - - return true + return !fieldNameSplit.any { it.isJavaKeyword() } } - -private val listPattern = Regex("""(\s*(\w+)\s*(,\s*\w+\s*)*,?|\[?\s*(\w+)\s*(,\s*\w+\s*)*])?""") diff --git a/src/main/kotlin/creator/platformtype/ModPlatformStep.kt b/src/main/kotlin/creator/platformtype/ModPlatformStep.kt new file mode 100644 index 000000000..adb897516 --- /dev/null +++ b/src/main/kotlin/creator/platformtype/ModPlatformStep.kt @@ -0,0 +1,40 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.platformtype + +import com.demonwav.mcdev.creator.platformtype.ModPlatformStep.Factory +import com.intellij.ide.wizard.AbstractNewProjectWizardMultiStep +import com.intellij.ide.wizard.NewProjectWizardMultiStepFactory +import com.intellij.openapi.extensions.ExtensionPointName + +/** + * The step to select a mod platform. + * + * To add custom mod platforms, register a [Factory] to the `com.demonwav.minecraft-dev.modPlatformWizard` extension + * point. + */ +class ModPlatformStep( + parent: PlatformTypeStep, +) : AbstractNewProjectWizardMultiStep(parent, EP_NAME) { + companion object { + val EP_NAME = ExtensionPointName("com.demonwav.minecraft-dev.modPlatformWizard") + } + + override val self = this + override val label = "Platform:" + + class TypeFactory : PlatformTypeStep.Factory { + override val name = "Mod" + override fun createStep(parent: PlatformTypeStep) = ModPlatformStep(parent) + } + + interface Factory : NewProjectWizardMultiStepFactory +} diff --git a/src/main/kotlin/creator/platformtype/PlatformTypeStep.kt b/src/main/kotlin/creator/platformtype/PlatformTypeStep.kt new file mode 100644 index 000000000..9bb14ad33 --- /dev/null +++ b/src/main/kotlin/creator/platformtype/PlatformTypeStep.kt @@ -0,0 +1,41 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.platformtype + +import com.demonwav.mcdev.creator.platformtype.PlatformTypeStep.Factory +import com.intellij.ide.wizard.AbstractNewProjectWizardMultiStep +import com.intellij.ide.wizard.NewProjectWizardBaseData +import com.intellij.ide.wizard.NewProjectWizardMultiStepFactory +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.extensions.ExtensionPointName + +/** + * The step to select the platform type (mod/plugin). + * + * To add custom platform types, register a [Factory] to the `com.demonwav.minecraft-dev.platformTypeWizard` extension + * point. + */ +class PlatformTypeStep private constructor( + parent: NewProjectWizardStep, +) : AbstractNewProjectWizardMultiStep(parent, EP_NAME), + NewProjectWizardBaseData by parent as NewProjectWizardBaseData { + companion object { + val EP_NAME = ExtensionPointName("com.demonwav.minecraft-dev.platformTypeWizard") + + fun

create(parent: P) where P : NewProjectWizardStep, P : NewProjectWizardBaseData = + PlatformTypeStep(parent) + } + + override val self = this + override val label = "Platform Type:" + + interface Factory : NewProjectWizardMultiStepFactory +} diff --git a/src/main/kotlin/creator/platformtype/PluginPlatformStep.kt b/src/main/kotlin/creator/platformtype/PluginPlatformStep.kt new file mode 100644 index 000000000..b3f25537d --- /dev/null +++ b/src/main/kotlin/creator/platformtype/PluginPlatformStep.kt @@ -0,0 +1,40 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.platformtype + +import com.demonwav.mcdev.creator.platformtype.PluginPlatformStep.Factory +import com.intellij.ide.wizard.AbstractNewProjectWizardMultiStep +import com.intellij.ide.wizard.NewProjectWizardMultiStepFactory +import com.intellij.openapi.extensions.ExtensionPointName + +/** + * The step to select a mod platform. + * + * To add custom mod platforms, register a [Factory] to the `com.demonwav.minecraft-dev.pluginPlatformWizard` extension + * point. + */ +class PluginPlatformStep( + parent: PlatformTypeStep, +) : AbstractNewProjectWizardMultiStep(parent, EP_NAME) { + companion object { + val EP_NAME = ExtensionPointName("com.demonwav.minecraft-dev.pluginPlatformWizard") + } + + override val self = this + override val label = "Platform:" + + class TypeFactory : PlatformTypeStep.Factory { + override val name = "Plugin" + override fun createStep(parent: PlatformTypeStep) = PluginPlatformStep(parent) + } + + interface Factory : NewProjectWizardMultiStepFactory +} diff --git a/src/main/kotlin/creator/step/AbstractCollapsibleStep.kt b/src/main/kotlin/creator/step/AbstractCollapsibleStep.kt new file mode 100644 index 000000000..efe11725d --- /dev/null +++ b/src/main/kotlin/creator/step/AbstractCollapsibleStep.kt @@ -0,0 +1,36 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.project.Project +import com.intellij.ui.dsl.builder.Panel + +abstract class AbstractCollapsibleStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { + private val child by lazy { createStep() } + + abstract val title: String + + protected abstract fun createStep(): NewProjectWizardStep + + override fun setupUI(builder: Panel) { + with(builder) { + collapsibleGroup(title) { + child.setupUI(this) + } + } + } + + override fun setupProject(project: Project) { + child.setupProject(project) + } +} diff --git a/src/main/kotlin/creator/step/AbstractLatentStep.kt b/src/main/kotlin/creator/step/AbstractLatentStep.kt new file mode 100644 index 000000000..97b415e00 --- /dev/null +++ b/src/main/kotlin/creator/step/AbstractLatentStep.kt @@ -0,0 +1,153 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.demonwav.mcdev.util.asyncIO +import com.demonwav.mcdev.util.capitalize +import com.demonwav.mcdev.util.invokeLater +import com.demonwav.mcdev.util.onHidden +import com.demonwav.mcdev.util.onShown +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.Disposable +import com.intellij.openapi.diagnostic.logger +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.ValidationInfo +import com.intellij.openapi.ui.validation.AFTER_GRAPH_PROPAGATION +import com.intellij.openapi.ui.validation.DialogValidation +import com.intellij.openapi.util.Disposer +import com.intellij.ui.JBColor +import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.Placeholder +import com.intellij.ui.dsl.builder.panel +import com.intellij.util.ui.AsyncProcessIcon +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.swing.Swing + +/** + * Used for when a long-running task is required to fully construct the wizard steps, for example when downloading + * Minecraft versions. + */ +abstract class AbstractLatentStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { + companion object { + private val LOGGER = logger>() + } + + private var hasComputedData = false + private var step: NewProjectWizardStep? = null + + /** + * Description of this step displayed to the user. + * + * This should be in sentence case starting with a lower case letter, and starting with a verb in the present tense, + * like a Git commit message. + * + * For example, "download Minecraft versions" would be an appropriate description. + */ + protected abstract val description: String + + private fun doComputeData(placeholder: Placeholder, lifetime: Disposable) { + if (hasComputedData) { + return + } + hasComputedData = true + + var disposed = false + Disposer.register(lifetime) { + hasComputedData = false + disposed = true + } + + CoroutineScope(Dispatchers.Swing).launch { + if (disposed) { + return@launch + } + + val result = asyncIO { + try { + computeData() + } catch (e: Throwable) { + LOGGER.error(e) + null + } + }.await() + + if (disposed) { + return@launch + } + + invokeLater { + if (disposed) { + return@invokeLater + } + + if (result == null) { + placeholder.component = panel { + row { + val label = label("Unable to $description") + .validationRequestor(AFTER_GRAPH_PROPAGATION(propertyGraph)) + .validation(DialogValidation { ValidationInfo("Unable to $description") }) + label.component.foreground = JBColor.RED + } + } + } else { + val s = createStep(result) + step = s + val panel = panel { + s.setupUI(this) + } + placeholder.component = panel + } + } + } + } + + protected abstract suspend fun computeData(): T? + + protected abstract fun createStep(data: T): NewProjectWizardStep + + override fun setupUI(builder: Panel) { + lateinit var placeholder: Placeholder + with(builder) { + row { + placeholder = placeholder() + } + } + placeholder.component = panel { + row(description.capitalize()) { + cell( + AsyncProcessIcon("$javaClass.computeData").also { component -> + var lifetime: Disposable? = null + component.onShown { + lifetime?.let(Disposer::dispose) + lifetime = Disposer.newDisposable().also { lifetime -> + Disposer.register(context.disposable, lifetime) + doComputeData(placeholder, lifetime) + } + } + component.onHidden { + lifetime?.let(Disposer::dispose) + lifetime = null + } + }, + ) + .validationRequestor(AFTER_GRAPH_PROPAGATION(propertyGraph)) + .validation(DialogValidation { ValidationInfo("Haven't finished $description") }) + } + } + } + + override fun setupProject(project: Project) { + step?.setupProject(project) + } +} diff --git a/src/main/kotlin/creator/step/AbstractLongRunningAssetsStep.kt b/src/main/kotlin/creator/step/AbstractLongRunningAssetsStep.kt new file mode 100644 index 000000000..e0f88df9c --- /dev/null +++ b/src/main/kotlin/creator/step/AbstractLongRunningAssetsStep.kt @@ -0,0 +1,29 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.project.Project + +abstract class AbstractLongRunningAssetsStep(parent: NewProjectWizardStep) : AbstractLongRunningStep(parent) { + protected val assets = object : FixedAssetsNewProjectWizardStep(parent) { + override fun setupAssets(project: Project) { + outputDirectory = context.projectFileDirectory + this@AbstractLongRunningAssetsStep.setupAssets(project) + } + } + + abstract fun setupAssets(project: Project) + + override fun perform(project: Project) { + assets.setupProject(project) + } +} diff --git a/src/main/kotlin/creator/step/AbstractLongRunningStep.kt b/src/main/kotlin/creator/step/AbstractLongRunningStep.kt new file mode 100644 index 000000000..5df2f2f17 --- /dev/null +++ b/src/main/kotlin/creator/step/AbstractLongRunningStep.kt @@ -0,0 +1,84 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardStep +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.util.Key +import com.intellij.openapi.util.UserDataHolderEx +import java.util.concurrent.ConcurrentLinkedQueue + +private typealias TaskQueue = ConcurrentLinkedQueue + +/** + * Creator steps that either take a long time to complete, or need to be run after other steps that take a long time to + * complete. + * + * These steps show an indeterminate progress bar to the user while they are running. + */ +abstract class AbstractLongRunningStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { + + /** + * The text to display on the progress bar + */ + abstract val description: String + + abstract fun perform(project: Project) + + final override fun setupProject(project: Project) { + val newQueue = TaskQueue() + val queue = (data as UserDataHolderEx).putUserDataIfAbsent(TASK_QUEUE_KEY, newQueue) + queue += this + if (queue === newQueue) { + startTaskQueue(project, queue) + } + } + + private fun startTaskQueue(project: Project, queue: TaskQueue) { + ProgressManager.getInstance().run(object : Task.Backgroundable(project, "Your project is being created") { + override fun run(indicator: ProgressIndicator) { + if (project.isDisposed) { + return + } + + indicator.text = "Your project is being created" + var currentQueue = queue + while (true) { + while (true) { + val task = currentQueue.poll() ?: break + indicator.text2 = task.description + if (project.isDisposed) { + return + } + task.perform(project) + if (project.isDisposed) { + return + } + } + if ((data as UserDataHolderEx).replace(TASK_QUEUE_KEY, currentQueue, null)) { + break + } + currentQueue = data.getUserData(TASK_QUEUE_KEY) ?: break + } + indicator.text2 = null + } + }, + ) + } + + companion object { + private val TASK_QUEUE_KEY = Key.create("${AbstractLongRunningStep::class.java.name}.queue") + } +} diff --git a/src/main/kotlin/creator/step/AbstractReformatFilesStep.kt b/src/main/kotlin/creator/step/AbstractReformatFilesStep.kt new file mode 100644 index 000000000..cf17af577 --- /dev/null +++ b/src/main/kotlin/creator/step/AbstractReformatFilesStep.kt @@ -0,0 +1,53 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.demonwav.mcdev.util.runWriteTask +import com.intellij.codeInsight.actions.ReformatCodeProcessor +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.application.ReadAction +import com.intellij.openapi.command.WriteCommandAction +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VfsUtil +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiManager +import java.nio.file.Path + +abstract class AbstractReformatFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningStep(parent) { + override val description = "Reformatting files" + + private val filesToReformat = mutableListOf() + + fun addFileToReformat(file: String) { + filesToReformat += file + } + + abstract fun addFilesToReformat() + + override fun perform(project: Project) { + addFilesToReformat() + + val rootDir = VfsUtil.findFile(Path.of(context.projectFileDirectory), true) ?: return + val psiManager = PsiManager.getInstance(project) + val files = ReadAction.compute, Throwable> { + filesToReformat.mapNotNull { path -> + VfsUtil.findRelativeFile(rootDir, *path.split('/').toTypedArray())?.let(psiManager::findFile) + }.toTypedArray() + } + files.ifEmpty { return } + + runWriteTask { + WriteCommandAction.writeCommandAction(project, *files).withGlobalUndo().run { + ReformatCodeProcessor(project, files, null, false).run() + } + } + } +} diff --git a/src/main/kotlin/creator/step/AbstractSelectVersionStep.kt b/src/main/kotlin/creator/step/AbstractSelectVersionStep.kt new file mode 100644 index 000000000..1dd425ca2 --- /dev/null +++ b/src/main/kotlin/creator/step/AbstractSelectVersionStep.kt @@ -0,0 +1,62 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.intellij.ide.util.PropertiesComponent +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.observable.util.bindStorage +import com.intellij.openapi.ui.ComboBox +import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.Row +import com.intellij.ui.dsl.builder.bindItem + +abstract class AbstractSelectVersionStep>( + parent: NewProjectWizardStep, + val versions: List, +) : AbstractNewProjectWizardStep(parent) { + protected abstract val label: String + + val versionProperty = propertyGraph.property("") + .bindStorage("${javaClass.name}.selectedVersion") + var version by versionProperty + + protected lateinit var versionBox: ComboBox + + override fun setupUI(builder: Panel) { + with(builder) { + row(label) { + setupRow(this) + } + } + } + + open fun setupRow(builder: Row) { + with(builder) { + val box = comboBox(versions.sortedDescending().map(Any::toString)).bindItem(versionProperty) + val selectedItem = box.component.selectedItem + if (selectedItem is String) { + version = selectedItem + } + versionBox = box.component + + // fix the selection to the latest version if it was previously at the latest version + val props = PropertiesComponent.getInstance() + val latestVersionProp = "${javaClass.name}.latestVersion" + val prevLatestVersion = props.getValue(latestVersionProp) + val latestVersion = versions.maxOrNull()?.toString() + if (version == prevLatestVersion) { + version = latestVersion ?: "" + } + props.setValue(latestVersionProp, latestVersion) + } + } +} diff --git a/src/main/kotlin/creator/step/AbstractVersionChainStep.kt b/src/main/kotlin/creator/step/AbstractVersionChainStep.kt new file mode 100644 index 000000000..2364894c9 --- /dev/null +++ b/src/main/kotlin/creator/step/AbstractVersionChainStep.kt @@ -0,0 +1,216 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.intellij.ide.wizard.AbstractNewProjectWizardMultiStepBase +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.components.PersistentStateComponent +import com.intellij.openapi.components.RoamingType +import com.intellij.openapi.components.Service +import com.intellij.openapi.components.State +import com.intellij.openapi.components.Storage +import com.intellij.openapi.components.service +import com.intellij.openapi.observable.properties.ObservableMutableProperty +import com.intellij.openapi.ui.ComboBox +import com.intellij.ui.CollectionComboBoxModel +import com.intellij.ui.dsl.builder.Cell +import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.Row +import com.intellij.ui.dsl.builder.bindItem + +private class VersionProperties( + val step: AbstractVersionChainStep, + val versionProperties: Array>>, + val preferredVersions: Array>, Comparable<*>>>, +) { + init { + loadPreferredVersions() + + var propertyChangeCount = 0L + + for ((i, prop) in versionProperties.withIndex()) { + prop.afterChange { value -> + val prevPropertyChangeCount = ++propertyChangeCount + + val versionsAbove = versionProperties.take(i).map(ObservableMutableProperty>::get) + val newestVersion = step.getAvailableVersions(versionsAbove).sortedDescending().first() + if (value == newestVersion) { + preferredVersions[i].remove(versionsAbove) + } else { + preferredVersions[i][versionsAbove] = value + } + + for (j in (i + 1) until versionProperties.size) { + val versionsAboveChild = + versionProperties.take(j).map(ObservableMutableProperty>::get) + val preferredVersion = preferredVersions[j][versionsAboveChild] + step.comboBoxes?.let { comboBoxes -> + step.setSelectableItems(j, step.getAvailableVersions(versionsAboveChild).sortedDescending()) + if (preferredVersion != null) { + comboBoxes[j].selectedItem = preferredVersion + } else { + comboBoxes[j].selectedIndex = 0 + } + } ?: run { + versionProperties[j].set( + preferredVersion ?: step.getAvailableVersions(versionsAboveChild).first(), + ) + } + + // the above code could have triggered a recursive property change which would have dealt with the + // rest of what we're going to do here + if (propertyChangeCount != prevPropertyChangeCount) { + return@afterChange + } + } + + savePreferredVersions() + } + } + } + + private fun savePreferredVersions() { + val stateComponent = PreferredVersionStateComponent.getInstance() + val preferredVersions = this.preferredVersions.map { m -> + m.map { (key, value) -> key.map(Comparable<*>::toString) to value.toString() }.toMap() + } + stateComponent.set("${step.javaClass.name}.preferredVersions", preferredVersions) + } + + private fun loadPreferredVersions() { + val stateComponent = PreferredVersionStateComponent.getInstance() + val preferredVersions = stateComponent.get("${step.javaClass.name}.preferredVersions") ?: return + for ((i, preferences) in preferredVersions.withIndex()) { + if (i >= this.preferredVersions.size) { + break + } + + preferenceEntryLoop@ + for ((versionsAbove, version) in preferences) { + if (versionsAbove.size != i) { + continue@preferenceEntryLoop + } + + val parsedVersionsAbove = mutableListOf>() + for (versionAbove in versionsAbove) { + parsedVersionsAbove += step.getAvailableVersions(parsedVersionsAbove) + .firstOrNull { it.toString() == versionAbove } + ?: continue@preferenceEntryLoop + } + val parsedVersion = step.getAvailableVersions(parsedVersionsAbove) + .firstOrNull { it.toString() == version } + ?: continue@preferenceEntryLoop + + this.preferredVersions[i][parsedVersionsAbove] = parsedVersion + } + + val preferredVersion = + this.preferredVersions[i][versionProperties.take(i).map(ObservableMutableProperty>::get)] + if (preferredVersion != null) { + versionProperties[i].set(preferredVersion) + } + } + } +} + +/** + * This class replaces chains of [AbstractNewProjectWizardMultiStepBase]s. The problem with the latter approach is that + * widgets become improperly aligned. + */ +abstract class AbstractVersionChainStep( + parent: NewProjectWizardStep, + private vararg val labels: String, +) : AbstractNewProjectWizardStep(parent) { + private val versionProperties by lazy { + val versionProperties = mutableListOf>>() + for (i in labels.indices) { + versionProperties += propertyGraph.property( + getAvailableVersions(versionProperties.map(ObservableMutableProperty>::get)).first(), + ) + } + val preferredVersions = labels.indices.map { mutableMapOf>, Comparable<*>>() } + VersionProperties(this, versionProperties.toTypedArray(), preferredVersions.toTypedArray()) + } + + internal var comboBoxes: Array>>? = null + + abstract fun getAvailableVersions(versionsAbove: List>): List> + + fun getVersionProperty(index: Int) = versionProperties.versionProperties[index] + + fun getVersion(index: Int) = versionProperties.versionProperties[index].get() + + fun getVersionBox(index: Int) = comboBoxes?.let { it[index] } + + open fun setSelectableItems(index: Int, items: List>) { + getVersionBox(index)!!.model = CollectionComboBoxModel(items) + } + + open fun createComboBox(row: Row, index: Int, items: List>): Cell>> { + return row.comboBox(items) + } + + override fun setupUI(builder: Panel) { + val comboBoxes = mutableListOf>>() + with(builder) { + for ((i, label) in labels.withIndex()) { + row(label) { + val comboBox = createComboBox( + this, + i, + getAvailableVersions( + versionProperties.versionProperties + .take(i).map(ObservableMutableProperty>::get), + ).sortedDescending(), + ).bindItem(versionProperties.versionProperties[i]) + comboBoxes += comboBox.component + } + } + } + this.comboBoxes = comboBoxes.toTypedArray() + } +} + +private typealias PreferredVersionStateValue = List, String>> + +@Service +@State( + name = "PreferredVersions", + storages = [Storage("mcdev.CreatorPreferredVersions.xml", roamingType = RoamingType.DISABLED)], +) +class PreferredVersionStateComponent : PersistentStateComponent> { + private var state = mutableMapOf() + + fun get(key: String) = state[key] + + fun set(key: String, value: PreferredVersionStateValue) { + state[key] = value + } + + override fun getState() = state + override fun loadState(state: MutableMap) { + this.state = state + } + + companion object { + fun getInstance() = service() + } +} + +private fun List>.sortedDescending(): List> { + fun > sortImpl(list: List>): List> { + @Suppress("UNCHECKED_CAST") + return (list as List).sortedByDescending { it } + } + // pretend we're strings to make the compiler happy + return sortImpl(this) +} diff --git a/src/main/kotlin/creator/step/FixedAssetsNewProjectWizardStep.kt b/src/main/kotlin/creator/step/FixedAssetsNewProjectWizardStep.kt new file mode 100644 index 000000000..ca8fc6231 --- /dev/null +++ b/src/main/kotlin/creator/step/FixedAssetsNewProjectWizardStep.kt @@ -0,0 +1,180 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.intellij.codeInsight.actions.ReformatCodeProcessor +import com.intellij.ide.projectView.ProjectView +import com.intellij.ide.projectWizard.generators.AssetsNewProjectWizardStep +import com.intellij.ide.starters.local.GeneratorAsset +import com.intellij.ide.starters.local.GeneratorEmptyDirectory +import com.intellij.ide.starters.local.GeneratorResourceFile +import com.intellij.ide.starters.local.GeneratorTemplateFile +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.WriteAction +import com.intellij.openapi.fileEditor.FileEditorManager +import com.intellij.openapi.project.Project +import com.intellij.openapi.startup.StartupManager +import com.intellij.openapi.util.io.NioFiles +import com.intellij.openapi.vfs.VfsUtil +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiManager +import java.io.IOException +import java.nio.file.Files +import java.nio.file.Path + +/** + * Fixed version of [AssetsNewProjectWizardStep], to be removed in 2022.3 when + * [IDEA-297489 is fixed](https://github.com/JetBrains/intellij-community/commit/fefae70bf621f3181ee9f2d0815c43d0325cd6c4). + * + * Written to be drop-in replaced with [AssetsNewProjectWizardStep] when it's ready. + */ +abstract class FixedAssetsNewProjectWizardStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { + lateinit var outputDirectory: String + private val assets = arrayListOf() + val templateProperties = hashMapOf() + private val filesToOpen = hashSetOf() + + fun addAssets(vararg assets: Any) = addAssets(assets.toList()) + + fun addAssets(assets: Iterable) { + assets.mapTo(this.assets) { asset -> + when (asset) { + is GeneratorAsset -> GeneratorAssetDelegate(asset) + is FixedGeneratorAsset -> asset + else -> throw IllegalArgumentException("$asset is not a valid asset") + } + } + } + + fun addTemplateProperties(vararg properties: Pair) = addTemplateProperties(properties.toMap()) + + fun addTemplateProperties(properties: Map) = templateProperties.putAll(properties) + + fun addFilesToOpen(vararg relativeCanonicalPaths: String) = addFilesToOpen(relativeCanonicalPaths.toList()) + + fun addFilesToOpen(relativeCanonicalPaths: Iterable) { + relativeCanonicalPaths.mapTo(filesToOpen) { "$outputDirectory/$it" } + } + + abstract fun setupAssets(project: Project) + + override fun setupProject(project: Project) { + setupAssets(project) + + WriteAction.runAndWait { + val generatedFiles = mutableSetOf() + for (asset in assets) { + generateFile(asset)?.let { generatedFiles += it } + } + + runWhenCreated(project) { + fixupFiles(project, generatedFiles) + } + } + } + + fun runWhenCreated(project: Project, action: () -> Unit) { + if (ApplicationManager.getApplication().isUnitTestMode) { + action() + } else { + StartupManager.getInstance(project).runAfterOpened { + ApplicationManager.getApplication().invokeLater(action, project.disposed) + } + } + } + + private fun generateFile(asset: FixedGeneratorAsset): VirtualFile? { + return when (asset) { + is GeneratorAssetDelegate -> when (val delegate = asset.delegate) { + is GeneratorTemplateFile -> generateFile(delegate) + is GeneratorResourceFile -> generateFile(delegate) + is GeneratorEmptyDirectory -> generateFile(delegate) + } + is GeneratorFile -> generateFile(asset) + } + } + + private fun generateFile(asset: GeneratorTemplateFile): VirtualFile? { + val code = try { + asset.template.getText(templateProperties) + } catch (e: Exception) { + throw IOException("Unable to process template", e) + } + + val pathStr = "$outputDirectory/${asset.targetFileName}" + val path = Path.of(pathStr) + path.parent?.let(NioFiles::createDirectories) + Files.writeString(path, code) + + return VfsUtil.findFile(path, true) + } + + private fun generateFile(asset: GeneratorResourceFile): VirtualFile? { + val content = asset.resource.openStream().use { it.readAllBytes() } + + val pathStr = "$outputDirectory/${asset.targetFileName}" + val path = Path.of(pathStr) + path.parent?.let(NioFiles::createDirectories) + Files.write(path, content) + + return VfsUtil.findFile(path, true) + } + + private fun generateFile(asset: GeneratorEmptyDirectory): VirtualFile? { + val pathStr = "$outputDirectory/${asset.targetFileName}" + val path = Path.of(pathStr) + NioFiles.createDirectories(path) + return VfsUtil.findFile(path, true) + } + + private fun generateFile(asset: GeneratorFile): VirtualFile? { + val pathStr = "$outputDirectory/${asset.targetFileName}" + val path = Path.of(pathStr) + path.parent?.let(NioFiles::createDirectories) + Files.write(path, asset.content) + + return VfsUtil.findFile(path, true) + } + + private fun fixupFiles(project: Project, generatedFiles: Iterable) { + val psiManager = PsiManager.getInstance(project) + val psiFiles = generatedFiles.mapNotNull { psiManager.findFile(it) } + + ReformatCodeProcessor(project, psiFiles.toTypedArray(), null, false).run() + + val fileEditorManager = FileEditorManager.getInstance(project) + val projectView = ProjectView.getInstance(project) + for (file in generatedFiles) { + if (file.path in filesToOpen) { + fileEditorManager.openFile(file, true) + projectView.select(null, file, false) + } + } + } +} + +// This can be removed when https://github.com/JetBrains/intellij-community/pull/2304 is merged +sealed class FixedGeneratorAsset { + abstract val targetFileName: String +} + +data class GeneratorAssetDelegate(val delegate: GeneratorAsset) : FixedGeneratorAsset() { + override val targetFileName get() = delegate.targetFileName +} + +class GeneratorFile( + override val targetFileName: String, + val content: ByteArray, +) : FixedGeneratorAsset() { + constructor(targetFileName: String, contents: String) : this(targetFileName, contents.encodeToByteArray()) +} diff --git a/src/main/kotlin/creator/step/LicenseStep.kt b/src/main/kotlin/creator/step/LicenseStep.kt new file mode 100644 index 000000000..9d9dd6ffd --- /dev/null +++ b/src/main/kotlin/creator/step/LicenseStep.kt @@ -0,0 +1,44 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.demonwav.mcdev.util.License +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.observable.util.bindStorage +import com.intellij.openapi.observable.util.transform +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.bindItem + +class LicenseStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { + val licenseProperty = propertyGraph.property(License.ALL_RIGHTS_RESERVED.id) + .bindStorage("${javaClass.name}.license") + var license by licenseProperty + + override fun setupUI(builder: Panel) { + with(builder) { + row("License:") { + comboBox(License.values().toList()) + .bindItem(licenseProperty.transform({ License.byId(it) ?: License.ALL_RIGHTS_RESERVED }) { it.id }) + } + } + } + + override fun setupProject(project: Project) { + data.putUserData(KEY, License.byId(license)) + } + + companion object { + val KEY = Key.create("${LicenseStep::class.java.name}.license") + } +} diff --git a/src/main/kotlin/creator/step/MainClassStep.kt b/src/main/kotlin/creator/step/MainClassStep.kt new file mode 100644 index 000000000..8200fabfa --- /dev/null +++ b/src/main/kotlin/creator/step/MainClassStep.kt @@ -0,0 +1,82 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.updateWhenChanged +import com.demonwav.mcdev.creator.whenStepAvailable +import com.demonwav.mcdev.util.toJavaClassName +import com.demonwav.mcdev.util.toPackageName +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import com.intellij.ui.dsl.builder.COLUMNS_LARGE +import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.bindText +import com.intellij.ui.dsl.builder.columns + +class MainClassStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { + private fun suggestMainClassName(): String { + val buildSystemProps = findStep>() + + if (buildSystemProps.artifactId.contains('.')) { + // if the artifact id is invalid, don't confuse ourselves by copying its dots + return className + } + + return buildSystemProps.groupId.toPackageName() + + ".${buildSystemProps.artifactId.toPackageName()}" + + ".${findStep().name.toJavaClassName()}" + } + + private fun suggestGroupId(): String { + val parts = className.split('.').dropLast(2) + return if (parts.isEmpty()) { + findStep>().groupId + } else { + parts.joinToString(".") + } + } + + val classNameProperty = propertyGraph.lazyProperty(::suggestMainClassName) + var className by classNameProperty + init { + whenStepAvailable> { buildSystemStep -> + classNameProperty.updateWhenChanged(buildSystemStep.groupIdProperty, ::suggestMainClassName) + classNameProperty.updateWhenChanged(buildSystemStep.artifactIdProperty, ::suggestMainClassName) + + buildSystemStep.groupIdProperty.updateWhenChanged(classNameProperty, ::suggestGroupId) + } + whenStepAvailable { modNameStep -> + classNameProperty.updateWhenChanged(modNameStep.nameProperty, ::suggestMainClassName) + } + } + + override fun setupUI(builder: Panel) { + with(builder) { + row("Main Class:") { + textField() + .columns(COLUMNS_LARGE) + .bindText(classNameProperty) + } + } + } + + override fun setupProject(project: Project) { + data.putUserData(KEY, className) + } + + companion object { + val KEY = Key.create("${MainClassStep::class.java.name}.className") + } +} diff --git a/src/main/kotlin/creator/step/McVersionStep.kt b/src/main/kotlin/creator/step/McVersionStep.kt new file mode 100644 index 000000000..64e7cab8e --- /dev/null +++ b/src/main/kotlin/creator/step/McVersionStep.kt @@ -0,0 +1,87 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.demonwav.mcdev.creator.JdkProjectSetupFinalizer +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.util.MinecraftVersions +import com.demonwav.mcdev.util.SemanticVersion +import com.demonwav.mcdev.util.onShown +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import com.intellij.ui.dsl.builder.Panel + +class SimpleMcVersionStep( + parent: NewProjectWizardStep, + versions: List, +) : AbstractSelectVersionStep(parent, versions) { + override val label = "Minecraft Version:" + + override fun setupUI(builder: Panel) { + super.setupUI(builder) + versionProperty.afterChange { + applyJdkVersion() + } + versionBox.onShown { + applyJdkVersion() + } + } + + override fun setupProject(project: Project) { + data.putUserData(KEY, SemanticVersion.tryParse(version)) + applyJdkVersion() + } + + private fun applyJdkVersion() { + val version = SemanticVersion.tryParse(version) ?: return + findStep().setPreferredJdk( + MinecraftVersions.requiredJavaVersion(version), + "Minecraft $version", + ) + } + + companion object { + val KEY = Key.create("${SimpleMcVersionStep::class.java.name}.version") + } +} + +abstract class AbstractMcVersionChainStep( + parent: NewProjectWizardStep, + vararg otherLabels: String, +) : AbstractVersionChainStep(parent, *(listOf("Minecraft Version:") + otherLabels).toTypedArray()) { + companion object { + const val MINECRAFT_VERSION = 0 + } + + override fun setupUI(builder: Panel) { + super.setupUI(builder) + getVersionProperty(MINECRAFT_VERSION).afterChange { + applyJdkVersion() + } + getVersionBox(MINECRAFT_VERSION)!!.onShown { + applyJdkVersion() + } + } + + override fun setupProject(project: Project) { + super.setupProject(project) + applyJdkVersion() + } + + private fun applyJdkVersion() { + val version = SemanticVersion.tryParse(getVersion(MINECRAFT_VERSION).toString()) ?: return + findStep().setPreferredJdk( + MinecraftVersions.requiredJavaVersion(version), + "Minecraft ${getVersion(MINECRAFT_VERSION)}", + ) + } +} diff --git a/src/main/kotlin/creator/step/ModNameStep.kt b/src/main/kotlin/creator/step/ModNameStep.kt new file mode 100644 index 000000000..6181b524f --- /dev/null +++ b/src/main/kotlin/creator/step/ModNameStep.kt @@ -0,0 +1,66 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.demonwav.mcdev.creator.storeToData +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardBaseData +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.validation.AFTER_GRAPH_PROPAGATION +import com.intellij.openapi.ui.validation.CHECK_NON_EMPTY +import com.intellij.openapi.util.Key +import com.intellij.ui.dsl.builder.COLUMNS_MEDIUM +import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.bindText +import com.intellij.ui.dsl.builder.columns +import com.intellij.ui.dsl.builder.textValidation + +abstract class AbstractModNameStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { + private val baseData = data.getUserData(NewProjectWizardBaseData.KEY) + ?: throw IllegalStateException("Mod name step created without base step") + val nameProperty = propertyGraph.property(baseData.name) + var name by nameProperty + init { + baseData.nameProperty.afterChange { name = it } + storeToData() + } + + abstract val label: String + + override fun setupUI(builder: Panel) { + with(builder) { + row(label) { + textField() + .bindText(nameProperty) + .columns(COLUMNS_MEDIUM) + .validationRequestor(AFTER_GRAPH_PROPAGATION(propertyGraph)) + .textValidation(CHECK_NON_EMPTY) + } + } + } + + override fun setupProject(project: Project) { + data.putUserData(KEY, name) + } + + companion object { + val KEY = Key.create("${AbstractModNameStep::class.java.name}.name") + } +} + +class ModNameStep(parent: NewProjectWizardStep) : AbstractModNameStep(parent) { + override val label = "Mod Name:" +} + +class PluginNameStep(parent: NewProjectWizardStep) : AbstractModNameStep(parent) { + override val label = "Plugin Name:" +} diff --git a/src/main/kotlin/creator/step/OptionalSteps.kt b/src/main/kotlin/creator/step/OptionalSteps.kt new file mode 100644 index 000000000..b9d75e9a8 --- /dev/null +++ b/src/main/kotlin/creator/step/OptionalSteps.kt @@ -0,0 +1,201 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.demonwav.mcdev.creator.updateWhenChanged +import com.intellij.ide.users.LocalUserSettings +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardBaseData.Companion.baseData +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.observable.util.bindStorage +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import com.intellij.ui.dsl.builder.COLUMNS_LARGE +import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.bindText +import com.intellij.ui.dsl.builder.columns + +abstract class AbstractOptionalStringStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { + protected abstract val label: String + protected open val bindToStorage = false + + val valueProperty = propertyGraph.property("").apply { + if (bindToStorage) { + bindStorage("${this@AbstractOptionalStringStep.javaClass.name}.value") + } + } + var value by valueProperty + + override fun setupUI(builder: Panel) { + with(builder) { + row(label) { + textField() + .bindText(valueProperty) + .columns(COLUMNS_LARGE) + } + } + } +} + +abstract class AbstractOptionalStringBasedOnProjectNameStep( + parent: NewProjectWizardStep, +) : AbstractOptionalStringStep(parent) { + private val formatProperty = propertyGraph.property("").bindStorage("${javaClass.name}.format") + var format by formatProperty + + init { + if (format.isNotEmpty()) { + value = suggestValue() + } + valueProperty.updateWhenChanged(formatProperty, ::suggestValue) + valueProperty.updateWhenChanged(baseData.nameProperty, ::suggestValue) + formatProperty.updateWhenChanged(valueProperty, ::suggestFormat) + } + + private fun suggestValue() = format.replace(PROJECT_NAME_PLACEHOLDER, baseData.name) + + private fun suggestFormat(): String { + val index = value.indexOf(baseData.name) + if (index == -1) { + return value + } + if (value.indexOf(baseData.name, startIndex = index + baseData.name.length) != -1) { + // don't change format if there are multiple instances of the project name + return format + } + return value.replace(baseData.name, PROJECT_NAME_PLACEHOLDER) + } + + companion object { + const val PROJECT_NAME_PLACEHOLDER = "{PROJECT_NAME}" + } +} + +class DescriptionStep(parent: NewProjectWizardStep) : AbstractOptionalStringStep(parent) { + override val label = "Description:" + + override fun setupProject(project: Project) { + data.putUserData(KEY, value) + } + + companion object { + val KEY = Key.create("${DescriptionStep::class.java.name}.description") + } +} + +class AuthorsStep(parent: NewProjectWizardStep) : AbstractOptionalStringStep(parent) { + override val label = "Authors:" + override val bindToStorage = true + + override fun setupProject(project: Project) { + data.putUserData(KEY, parseAuthors(value)) + } + + companion object { + val KEY = Key.create>("${AuthorsStep::class.java.name}.authors") + + private val bracketRegex = Regex("[\\[\\]]") + private val commaRegex = Regex("\\s*,\\s*") + + fun parseAuthors(string: String): List { + return if (string.isNotBlank()) { + string.trim().replace(bracketRegex, "").split(commaRegex).toList() + } else { + emptyList() + } + } + } +} + +class WebsiteStep(parent: NewProjectWizardStep) : AbstractOptionalStringStep(parent) { + override val label = "Website:" + override val bindToStorage = true + + override fun setupProject(project: Project) { + data.putUserData(KEY, value) + } + + companion object { + val KEY = Key.create("${WebsiteStep::class.java.name}.website") + } +} + +class RepositoryStep(parent: NewProjectWizardStep) : AbstractOptionalStringBasedOnProjectNameStep(parent) { + override val label = "Repository:" + + init { + if (format.isEmpty()) { + format = "https://github.com/${LocalUserSettings.userName}/$PROJECT_NAME_PLACEHOLDER" + } + } + + override fun setupProject(project: Project) { + data.putUserData(KEY, value) + } + + companion object { + val KEY = Key.create("${RepositoryStep::class.java.name}.repository") + } +} + +class IssueTrackerStep(parent: NewProjectWizardStep) : AbstractOptionalStringBasedOnProjectNameStep(parent) { + override val label = "Issue Tracker:" + + init { + if (format.isEmpty()) { + format = "https://${LocalUserSettings.userName}/$PROJECT_NAME_PLACEHOLDER/issues" + } + } + + override fun setupProject(project: Project) { + data.putUserData(KEY, value) + } + + companion object { + val KEY = Key.create("${IssueTrackerStep::class.java.name}.issueTracker") + } +} + +class UpdateUrlStep(parent: NewProjectWizardStep) : AbstractOptionalStringStep(parent) { + override val label = "Update URL:" + + override fun setupProject(project: Project) { + data.putUserData(KEY, value) + } + + companion object { + val KEY = Key.create("${UpdateUrlStep::class.java.name}.updateUrl") + } +} + +class DependStep(parent: NewProjectWizardStep) : AbstractOptionalStringStep(parent) { + override val label = "Depend:" + + override fun setupProject(project: Project) { + data.putUserData(KEY, AuthorsStep.parseAuthors(value)) + } + + companion object { + val KEY = Key.create>("${DependStep::class.java.name}.depend") + } +} + +class SoftDependStep(parent: NewProjectWizardStep) : AbstractOptionalStringStep(parent) { + override val label = "Soft Depend:" + + override fun setupProject(project: Project) { + data.putUserData(KEY, AuthorsStep.parseAuthors(value)) + } + + companion object { + val KEY = Key.create>("${SoftDependStep::class.java.name}.depend") + } +} diff --git a/src/main/kotlin/creator/step/TemplateOutdatedStep.kt b/src/main/kotlin/creator/step/TemplateOutdatedStep.kt new file mode 100644 index 000000000..6d055f6b5 --- /dev/null +++ b/src/main/kotlin/creator/step/TemplateOutdatedStep.kt @@ -0,0 +1,41 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.demonwav.mcdev.update.PluginUtil +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.application.ApplicationInfo +import com.intellij.openapi.util.SystemInfoRt +import com.intellij.ui.dsl.builder.Panel +import java.net.URLEncoder +import java.nio.charset.StandardCharsets + +class TemplateOutdatedStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { + override fun setupUI(builder: Panel) { + with(builder) { + separator() + row { + val issueUrl = "https://github.com/minecraft-dev/MinecraftDev/issues/new" + + "?template=project_wizard_outdated.yaml" + + "&plugin-version=${PluginUtil.pluginVersion.urlEncode()}" + + "&intellij-version=${ApplicationInfo.getInstance().build.asString().urlEncode()}" + + "&operating-system=${SystemInfoRt.OS_NAME.urlEncode()}" + text( + "Is the Minecraft project wizard outdated? " + + "Create an issue on the MinecraftDev issue tracker.", + ) + } + } + } + + private fun String.urlEncode() = URLEncoder.encode(this, StandardCharsets.UTF_8) +} diff --git a/src/main/kotlin/creator/step/UseMixinsStep.kt b/src/main/kotlin/creator/step/UseMixinsStep.kt new file mode 100644 index 000000000..88d919a46 --- /dev/null +++ b/src/main/kotlin/creator/step/UseMixinsStep.kt @@ -0,0 +1,42 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.observable.util.bindBooleanStorage +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.bindSelected + +class UseMixinsStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { + val useMixinsProperty = propertyGraph.property(false) + .bindBooleanStorage("${javaClass.name}.useMixins") + var useMixins by useMixinsProperty + + override fun setupUI(builder: Panel) { + with(builder) { + row("Use Mixins:") { + checkBox("") + .bindSelected(useMixinsProperty) + } + } + } + + override fun setupProject(project: Project) { + data.putUserData(KEY, useMixins) + } + + companion object { + val KEY = Key.create("${UseMixinsStep::class.java.name}.useMixins") + } +} diff --git a/src/main/kotlin/creator/step/WaitForSmartModeStep.kt b/src/main/kotlin/creator/step/WaitForSmartModeStep.kt new file mode 100644 index 000000000..a838ee488 --- /dev/null +++ b/src/main/kotlin/creator/step/WaitForSmartModeStep.kt @@ -0,0 +1,28 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.creator.step + +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.project.DumbService +import com.intellij.openapi.project.Project + +/** + * This step shows to the user that we're waiting for smart mode as opposed to taking a while doing something else. + * Note that dumb mode may occur immediately after this step, and subsequent steps must not assume smart mode is active. + * Thus, this step is for UX purposes only. + */ +class WaitForSmartModeStep(parent: NewProjectWizardStep) : AbstractLongRunningStep(parent) { + override val description = "Indexing" + + override fun perform(project: Project) { + DumbService.getInstance(project).waitForSmartMode() + } +} diff --git a/src/main/kotlin/errorreporter/AnonymousFeedback.kt b/src/main/kotlin/errorreporter/AnonymousFeedback.kt index 92c12301b..da7af609e 100644 --- a/src/main/kotlin/errorreporter/AnonymousFeedback.kt +++ b/src/main/kotlin/errorreporter/AnonymousFeedback.kt @@ -35,7 +35,7 @@ object AnonymousFeedback { fun sendFeedback( factory: HttpConnectionFactory, envDetails: LinkedHashMap, - attachments: List + attachments: List, ): FeedbackData { val duplicateId = findDuplicateIssue(envDetails, factory) if (duplicateId != null) { @@ -51,7 +51,7 @@ object AnonymousFeedback { private fun convertToGitHubIssueFormat( envDetails: LinkedHashMap, - attachments: List + attachments: List, ): ByteArray { val result = LinkedHashMap(5) result["title"] = "[auto-generated] Exception in plugin" diff --git a/src/main/kotlin/errorreporter/AnonymousFeedbackTask.kt b/src/main/kotlin/errorreporter/AnonymousFeedbackTask.kt index 30ef3a1ae..1d1b17c98 100644 --- a/src/main/kotlin/errorreporter/AnonymousFeedbackTask.kt +++ b/src/main/kotlin/errorreporter/AnonymousFeedbackTask.kt @@ -23,7 +23,7 @@ class AnonymousFeedbackTask( private val params: LinkedHashMap, private val attachments: List, private val callback: (String, Int, Boolean) -> Unit, - private val errorCallback: (Exception) -> Unit + private val errorCallback: (Exception) -> Unit, ) : Task.Backgroundable(project, title, canBeCancelled) { override fun run(indicator: ProgressIndicator) { diff --git a/src/main/kotlin/errorreporter/ErrorReporter.kt b/src/main/kotlin/errorreporter/ErrorReporter.kt index 6bb8b0647..05bf443dd 100644 --- a/src/main/kotlin/errorreporter/ErrorReporter.kt +++ b/src/main/kotlin/errorreporter/ErrorReporter.kt @@ -33,7 +33,7 @@ import java.awt.Component class ErrorReporter : ErrorReportSubmitter() { private val ignoredErrorMessages = listOf( "Key com.demonwav.mcdev.translations.TranslationFoldingSettings duplicated", - "Inspection #EntityConstructor has no description" + "Inspection #EntityConstructor has no description", ) override fun getReportActionText() = "Report to Minecraft Dev GitHub Issue Tracker" @@ -41,7 +41,7 @@ class ErrorReporter : ErrorReportSubmitter() { events: Array, additionalInfo: String?, parentComponent: Component, - consumer: Consumer + consumer: Consumer, ): Boolean { val dataContext = DataManager.getInstance().getDataContext(parentComponent) val project = CommonDataKeys.PROJECT.getData(dataContext) @@ -108,7 +108,7 @@ class ErrorReporter : ErrorReportSubmitter() { NotificationGroupManager.getInstance().getNotificationGroup("Error Report").createNotification( DiagnosticBundle.message("error.report.title"), message, - NotificationType.INFORMATION + NotificationType.INFORMATION, ).addAction(BrowseNotificationAction(actionText, htmlUrl)).setImportant(false).notify(project) val reportInfo = SubmittedReportInfo(htmlUrl, "Issue #$token", type) @@ -125,7 +125,7 @@ class ErrorReporter : ErrorReportSubmitter() { ).addAction(BrowseNotificationAction(actionText, userUrl)).setImportant(false).notify(project) consumer.consume(SubmittedReportInfo(null, null, SubmittedReportInfo.SubmissionStatus.FAILED)) - } + }, ) if (project == null) { diff --git a/src/main/kotlin/facet/LibraryPresentationProviders.kt b/src/main/kotlin/facet/LibraryPresentationProviders.kt index a30ad063c..229d889bf 100644 --- a/src/main/kotlin/facet/LibraryPresentationProviders.kt +++ b/src/main/kotlin/facet/LibraryPresentationProviders.kt @@ -24,7 +24,7 @@ import java.util.jar.Attributes.Name.IMPLEMENTATION_VERSION abstract class ManifestLibraryPresentationProvider( kind: LibraryKind, private val title: String, - private val startsWith: Boolean = false + private val startsWith: Boolean = false, ) : LibraryPresentationProvider(kind) { @@ -55,7 +55,7 @@ abstract class MavenLibraryPresentationProvider( kind: LibraryKind, private val groupId: String, private val artifactId: String, - private val strict: Boolean = true + private val strict: Boolean = true, ) : LibraryPresentationProvider(kind) { diff --git a/src/main/kotlin/facet/MinecraftFacet.kt b/src/main/kotlin/facet/MinecraftFacet.kt index 827ef2b34..df706a6ab 100644 --- a/src/main/kotlin/facet/MinecraftFacet.kt +++ b/src/main/kotlin/facet/MinecraftFacet.kt @@ -35,7 +35,6 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod import java.util.concurrent.ConcurrentHashMap import javax.swing.Icon -import kotlin.jvm.Throws import org.jetbrains.jps.model.java.JavaResourceRootType import org.jetbrains.jps.model.java.JavaSourceRootType @@ -43,7 +42,7 @@ class MinecraftFacet( module: Module, name: String, configuration: MinecraftFacetConfiguration, - underlyingFacet: Facet<*>? + underlyingFacet: Facet<*>?, ) : Facet(facetType, module, name, configuration, underlyingFacet) { private val moduleMap = ConcurrentHashMap, AbstractModule>() diff --git a/src/main/kotlin/facet/MinecraftFacetConfiguration.kt b/src/main/kotlin/facet/MinecraftFacetConfiguration.kt index d62e13abc..085fb8f40 100644 --- a/src/main/kotlin/facet/MinecraftFacetConfiguration.kt +++ b/src/main/kotlin/facet/MinecraftFacetConfiguration.kt @@ -39,5 +39,5 @@ data class MinecraftFacetConfigurationData( @XCollection(elementName = "platformType", valueAttributeName = "", style = XCollection.Style.v2) var autoDetectTypes: MutableSet = mutableSetOf(), @Tag("forgePatcher") - var forgePatcher: Boolean = false + var forgePatcher: Boolean = false, ) diff --git a/src/main/kotlin/facet/MinecraftFacetDetector.kt b/src/main/kotlin/facet/MinecraftFacetDetector.kt index 21326b755..ae8855e43 100644 --- a/src/main/kotlin/facet/MinecraftFacetDetector.kt +++ b/src/main/kotlin/facet/MinecraftFacetDetector.kt @@ -138,7 +138,7 @@ class MinecraftFacetDetector : StartupActivity { object : LibraryDetectionManager.LibraryPropertiesProcessor { override fun

> processProperties( kind: LibraryKind, - properties: P + properties: P, ): Boolean { return if (properties is LibraryVersionProperties) { libraryVersions[kind] = properties.versionString ?: return true @@ -147,7 +147,7 @@ class MinecraftFacetDetector : StartupActivity { true } } - } + }, ) platformKinds.add(kind) } diff --git a/src/main/kotlin/facet/MinecraftFacetEditorTab.kt b/src/main/kotlin/facet/MinecraftFacetEditorTab.kt index 33cd778cb..a2f5956ed 100644 --- a/src/main/kotlin/facet/MinecraftFacetEditorTab.kt +++ b/src/main/kotlin/facet/MinecraftFacetEditorTab.kt @@ -71,7 +71,7 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura bungeecordEnabledCheckBox, waterfallEnabledCheckBox, velocityEnabledCheckBox, - adventureEnabledCheckBox + adventureEnabledCheckBox, ) } @@ -90,7 +90,7 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura bungeecordAutoCheckBox, waterfallAutoCheckBox, velocityAutoCheckBox, - adventureAutoCheckBox + adventureAutoCheckBox, ) } @@ -109,40 +109,40 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura unique( bukkitEnabledCheckBox, spigotEnabledCheckBox, - paperEnabledCheckBox + paperEnabledCheckBox, ) } spigotEnabledCheckBox.addActionListener { unique( spigotEnabledCheckBox, bukkitEnabledCheckBox, - paperEnabledCheckBox + paperEnabledCheckBox, ) } paperEnabledCheckBox.addActionListener { unique( paperEnabledCheckBox, bukkitEnabledCheckBox, - spigotEnabledCheckBox + spigotEnabledCheckBox, ) } bukkitAutoCheckBox.addActionListener { all(bukkitAutoCheckBox, spigotAutoCheckBox, paperAutoCheckBox)( SPIGOT, - PAPER + PAPER, ) } spigotAutoCheckBox.addActionListener { all(spigotAutoCheckBox, bukkitAutoCheckBox, paperAutoCheckBox)( BUKKIT, - PAPER + PAPER, ) } paperAutoCheckBox.addActionListener { all(paperAutoCheckBox, bukkitAutoCheckBox, spigotAutoCheckBox)( BUKKIT, - SPIGOT + SPIGOT, ) } @@ -158,28 +158,28 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura unique( architecturyEnabledCheckBox, fabricEnabledCheckBox, - forgeEnabledCheckBox + forgeEnabledCheckBox, ) } forgeAutoCheckBox.addActionListener { all(forgeAutoCheckBox, fabricAutoCheckBox, architecturyAutoCheckBox)( FABRIC, - ARCHITECTURY + ARCHITECTURY, ) } fabricAutoCheckBox.addActionListener { all(fabricAutoCheckBox, forgeAutoCheckBox, architecturyAutoCheckBox)( FORGE, - ARCHITECTURY + ARCHITECTURY, ) } architecturyAutoCheckBox.addActionListener { all(architecturyAutoCheckBox, forgeAutoCheckBox, fabricAutoCheckBox)( FORGE, - FABRIC + FABRIC, ) } @@ -226,7 +226,7 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura } private inline fun runOnAll( - run: (JCheckBox, JCheckBox, PlatformType, MutableMap, Set) -> Unit + run: (JCheckBox, JCheckBox, PlatformType, MutableMap, Set) -> Unit, ) { val state = configuration.state for (i in indexes) { @@ -235,7 +235,7 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura autoCheckBoxArray[i], platformTypes[i], state.userChosenTypes, - state.autoDetectTypes + state.autoDetectTypes, ) } } @@ -306,8 +306,7 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura private const val FORGE = SPONGE + 1 private const val FABRIC = FORGE + 1 private const val ARCHITECTURY = FABRIC + 1 - private const val LITELOADER = ARCHITECTURY + 1 - private const val MCP = LITELOADER + 1 + private const val MCP = ARCHITECTURY + 1 private const val MIXIN = MCP + 1 private const val BUNGEECORD = MIXIN + 1 private const val WATERFALL = BUNGEECORD + 1 @@ -322,13 +321,12 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura PlatformType.FORGE, PlatformType.FABRIC, PlatformType.ARCHITECTURY, - PlatformType.LITELOADER, PlatformType.MCP, PlatformType.MIXIN, PlatformType.BUNGEECORD, PlatformType.WATERFALL, PlatformType.VELOCITY, - PlatformType.ADVENTURE + PlatformType.ADVENTURE, ) private val indexes = intArrayOf( @@ -339,13 +337,12 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura FORGE, FABRIC, ARCHITECTURY, - LITELOADER, MCP, MIXIN, BUNGEECORD, WATERFALL, VELOCITY, - ADVENTURE + ADVENTURE, ) } } diff --git a/src/main/kotlin/facet/MinecraftFacetType.kt b/src/main/kotlin/facet/MinecraftFacetType.kt index f9771c583..ed8731470 100644 --- a/src/main/kotlin/facet/MinecraftFacetType.kt +++ b/src/main/kotlin/facet/MinecraftFacetType.kt @@ -24,7 +24,7 @@ class MinecraftFacetType : module: Module, name: String, configuration: MinecraftFacetConfiguration, - underlyingFacet: Facet<*>? + underlyingFacet: Facet<*>?, ) = MinecraftFacet(module, name, configuration, underlyingFacet) override fun createDefaultConfiguration() = MinecraftFacetConfiguration() diff --git a/src/main/kotlin/facet/MinecraftLibraryKinds.kt b/src/main/kotlin/facet/MinecraftLibraryKinds.kt index 85a9b40a8..74e4687e5 100644 --- a/src/main/kotlin/facet/MinecraftLibraryKinds.kt +++ b/src/main/kotlin/facet/MinecraftLibraryKinds.kt @@ -19,7 +19,6 @@ import com.demonwav.mcdev.platform.bungeecord.framework.BUNGEECORD_LIBRARY_KIND import com.demonwav.mcdev.platform.bungeecord.framework.WATERFALL_LIBRARY_KIND import com.demonwav.mcdev.platform.fabric.framework.FABRIC_LIBRARY_KIND import com.demonwav.mcdev.platform.forge.framework.FORGE_LIBRARY_KIND -import com.demonwav.mcdev.platform.liteloader.framework.LITELOADER_LIBRARY_KIND import com.demonwav.mcdev.platform.mcp.framework.MCP_LIBRARY_KIND import com.demonwav.mcdev.platform.mixin.framework.MIXIN_LIBRARY_KIND import com.demonwav.mcdev.platform.sponge.framework.SPONGE_LIBRARY_KIND @@ -33,11 +32,10 @@ val MINECRAFT_LIBRARY_KINDS = setOf( FORGE_LIBRARY_KIND, FABRIC_LIBRARY_KIND, ARCHITECTURY_LIBRARY_KIND, - LITELOADER_LIBRARY_KIND, MCP_LIBRARY_KIND, MIXIN_LIBRARY_KIND, BUNGEECORD_LIBRARY_KIND, WATERFALL_LIBRARY_KIND, VELOCITY_LIBRARY_KIND, - ADVENTURE_LIBRARY_KIND + ADVENTURE_LIBRARY_KIND, ) diff --git a/src/main/kotlin/insight/ColorLineMarkerProvider.kt b/src/main/kotlin/insight/ColorLineMarkerProvider.kt index 08371e138..5ce0cd55d 100644 --- a/src/main/kotlin/insight/ColorLineMarkerProvider.kt +++ b/src/main/kotlin/insight/ColorLineMarkerProvider.kt @@ -58,7 +58,7 @@ class ColorLineMarkerProvider : LineMarkerProvider { color: Color, map: Map, colorName: String, - workElement: UElement + workElement: UElement, ) : super( element, element.textRange, @@ -78,7 +78,7 @@ class ColorLineMarkerProvider : LineMarkerProvider { } }, GutterIconRenderer.Alignment.RIGHT, - { "$colorName color indicator" } + { "$colorName color indicator" }, ) { this.color = color } @@ -90,7 +90,7 @@ class ColorLineMarkerProvider : LineMarkerProvider { FunctionUtil.nullConstant(), handler, GutterIconRenderer.Alignment.RIGHT, - { "color indicator" } + { "color indicator" }, ) { this.color = color } @@ -113,8 +113,8 @@ class ColorLineMarkerProvider : LineMarkerProvider { class CommonColorInfo( element: PsiElement, color: Color, - workElement: UElement - ) : ColorLineMarkerProvider.ColorInfo( + workElement: UElement, + ) : ColorInfo( element, color, GutterIconNavigationHandler handler@{ _, psiElement -> @@ -140,7 +140,7 @@ class ColorLineMarkerProvider : LineMarkerProvider { is ULiteralExpression -> workElement.setColor(c.rgb and 0xFFFFFF) is UCallExpression -> workElement.setColor(c.red, c.green, c.blue) } - } + }, ) abstract class CommonLineMarkerProvider : LineMarkerProvider { diff --git a/src/main/kotlin/insight/ColorPicker.kt b/src/main/kotlin/insight/ColorPicker.kt index a3bca4268..ec1f968fd 100644 --- a/src/main/kotlin/insight/ColorPicker.kt +++ b/src/main/kotlin/insight/ColorPicker.kt @@ -63,7 +63,7 @@ class ColorPicker(private val colorMap: Map, parent: JComponent) chosenColor = entry.key dialog.close(0) } - } + }, ) val constraints = GridBagConstraints() @@ -75,17 +75,17 @@ class ColorPicker(private val colorMap: Map, parent: JComponent) } } - private class ColorPickerDialog constructor(parent: JComponent, private val component: JComponent) : + private class ColorPickerDialog(parent: JComponent, private val component: JComponent) : DialogWrapper(parent, false) { init { title = "Choose Color" - setResizable(true) + isResizable = true init() } - override fun createCenterPanel(): JComponent? { + override fun createCenterPanel(): JComponent { return component } } diff --git a/src/main/kotlin/insight/ColorUtil.kt b/src/main/kotlin/insight/ColorUtil.kt index cb9b4900b..f598d6e84 100644 --- a/src/main/kotlin/insight/ColorUtil.kt +++ b/src/main/kotlin/insight/ColorUtil.kt @@ -85,7 +85,7 @@ fun UIdentifier.findColor( className: String, vectorClasses: Array?, maxDepth: Int = 10, - depth: Int = 0 + depth: Int = 0, ): Pair? { if (depth >= maxDepth) { return null @@ -133,7 +133,7 @@ fun UIdentifier.findColor( private fun findColorFromCallExpression( methodExpression: UCallExpression, - vectorClasses: Array? + vectorClasses: Array?, ): Pair? { val project = methodExpression.sourcePsi?.project ?: return null diff --git a/src/main/kotlin/insight/ListenerLineMarkerProvider.kt b/src/main/kotlin/insight/ListenerLineMarkerProvider.kt index 1fb68f6fc..f669812c7 100644 --- a/src/main/kotlin/insight/ListenerLineMarkerProvider.kt +++ b/src/main/kotlin/insight/ListenerLineMarkerProvider.kt @@ -63,7 +63,7 @@ class ListenerLineMarkerProvider : LineMarkerProviderDescriptor() { element, element.textRange, icon, - createHandler() + createHandler(), ) } @@ -80,11 +80,11 @@ class ListenerLineMarkerProvider : LineMarkerProviderDescriptor() { override fun getName() = "Event Listener line marker" override fun getIcon() = GeneralAssets.LISTENER - private class EventLineMarkerInfo constructor( + private class EventLineMarkerInfo( element: PsiElement, range: TextRange, icon: Icon, - handler: GutterIconNavigationHandler + handler: GutterIconNavigationHandler, ) : MergeableLineMarkerInfo( element, range, @@ -92,7 +92,7 @@ class ListenerLineMarkerProvider : LineMarkerProviderDescriptor() { Function { "Go to Event declaration" }, handler, GutterIconRenderer.Alignment.RIGHT, - { "event listener indicator" } + { "event listener indicator" }, ) { override fun canMergeWith(info: MergeableLineMarkerInfo<*>): Boolean { diff --git a/src/main/kotlin/insight/PluginLineMarkerProvider.kt b/src/main/kotlin/insight/PluginLineMarkerProvider.kt index 19837be85..2d007e83d 100644 --- a/src/main/kotlin/insight/PluginLineMarkerProvider.kt +++ b/src/main/kotlin/insight/PluginLineMarkerProvider.kt @@ -36,6 +36,7 @@ class PluginLineMarkerProvider : LineMarkerProviderDescriptor() { return null } + @Suppress("MoveLambdaOutsideParentheses") return LineMarkerInfo( element, element.textRange, @@ -43,7 +44,7 @@ class PluginLineMarkerProvider : LineMarkerProviderDescriptor() { FunctionUtil.nullConstant(), null, GutterIconRenderer.Alignment.RIGHT, - { "minecraft plugin entry point indicator" } + { "minecraft plugin entry point indicator" }, ) } } diff --git a/src/main/kotlin/insight/generation/GenerateEventListenerHandler.kt b/src/main/kotlin/insight/generation/GenerateEventListenerHandler.kt index 0949e5164..a8439080a 100644 --- a/src/main/kotlin/insight/generation/GenerateEventListenerHandler.kt +++ b/src/main/kotlin/insight/generation/GenerateEventListenerHandler.kt @@ -48,7 +48,7 @@ class GenerateEventListenerHandler : GenerateMembersHandlerBase(MCDevBundle.mess var data: GenerationData?, var chosenClass: PsiClass, var chosenName: String, - var relevantModule: AbstractModule + var relevantModule: AbstractModule, ) private var data: GenerateData? = null @@ -65,7 +65,7 @@ class GenerateEventListenerHandler : GenerateMembersHandlerBase(MCDevBundle.mess RefactoringBundle.message("choose.destination.class"), GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(moduleForPsiElement, false), { aClass1 -> isSuperEventListenerAllowed(aClass1, facet) }, - null + null, ) chooser.showDialog() @@ -81,7 +81,7 @@ class GenerateEventListenerHandler : GenerateMembersHandlerBase(MCDevBundle.mess editor, relevantModule.moduleType.getEventGenerationPanel(chosenClass), chosenClassName, - relevantModule.moduleType.getDefaultListenerName(chosenClass) + relevantModule.moduleType.getDefaultListenerName(chosenClass), ) val okay = generationDialog.showAndGet() @@ -97,7 +97,7 @@ class GenerateEventListenerHandler : GenerateMembersHandlerBase(MCDevBundle.mess val method = PsiTreeUtil.getParentOfType( aClass.containingFile.findElementAt(editor.caretModel.offset), - PsiMethod::class.java + PsiMethod::class.java, ) this.data = GenerateData( @@ -108,7 +108,7 @@ class GenerateEventListenerHandler : GenerateMembersHandlerBase(MCDevBundle.mess dialogDAta, chosenClass, chosenName, - relevantModule + relevantModule, ) return DUMMY_RESULT diff --git a/src/main/kotlin/insight/generation/MinecraftClassCreateAction.kt b/src/main/kotlin/insight/generation/MinecraftClassCreateAction.kt index 39b4c01e8..742776530 100644 --- a/src/main/kotlin/insight/generation/MinecraftClassCreateAction.kt +++ b/src/main/kotlin/insight/generation/MinecraftClassCreateAction.kt @@ -43,7 +43,7 @@ class MinecraftClassCreateAction : CAPTION, "Class generation for modders", GeneralAssets.MC_TEMPLATE, - JavaModuleSourceRootTypes.SOURCES + JavaModuleSourceRootTypes.SOURCES, ), DumbAware { @@ -117,7 +117,7 @@ class MinecraftClassCreateAction : private class ClassInputValidator( private val project: Project, - private val directory: PsiDirectory + private val directory: PsiDirectory, ) : InputValidatorEx { override fun getErrorText(inputString: String): String? { if (inputString.isNotEmpty() && !PsiNameHelper.getInstance(project).isQualifiedName(inputString)) { diff --git a/src/main/kotlin/insight/generation/ui/EventGenerationDialog.kt b/src/main/kotlin/insight/generation/ui/EventGenerationDialog.kt index f96b946f4..1cd9fb8b2 100644 --- a/src/main/kotlin/insight/generation/ui/EventGenerationDialog.kt +++ b/src/main/kotlin/insight/generation/ui/EventGenerationDialog.kt @@ -20,7 +20,7 @@ class EventGenerationDialog( editor: Editor, private val panel: EventGenerationPanel, className: String, - defaultListenerName: String + defaultListenerName: String, ) : DialogWrapper(editor.component, false) { private val wizard: EventListenerWizard = EventListenerWizard(panel.panel, className, defaultListenerName) diff --git a/src/main/kotlin/inspection/IsCancelled.kt b/src/main/kotlin/inspection/IsCancelled.kt index 8b511359b..b1515564a 100644 --- a/src/main/kotlin/inspection/IsCancelled.kt +++ b/src/main/kotlin/inspection/IsCancelled.kt @@ -16,7 +16,7 @@ import com.siyeh.ig.InspectionGadgetsFix class IsCancelled( fix: (ProblemDescriptor) -> Unit, - val errorString: String + val errorString: String, ) { val buildFix: InspectionGadgetsFix diff --git a/src/main/kotlin/inspection/WrongEntityDataParameterClassInspection.kt b/src/main/kotlin/inspection/WrongEntityDataParameterClassInspection.kt index b3e55d8be..67ef40919 100644 --- a/src/main/kotlin/inspection/WrongEntityDataParameterClassInspection.kt +++ b/src/main/kotlin/inspection/WrongEntityDataParameterClassInspection.kt @@ -57,7 +57,7 @@ class WrongEntityDataParameterClassInspection : AbstractBaseJavaLocalInspectionT holder.registerProblem( expression, "Entity class does not match this entity class", - QuickFix(firstParameter) + QuickFix(firstParameter), ) } } @@ -74,8 +74,8 @@ class WrongEntityDataParameterClassInspection : AbstractBaseJavaLocalInspectionT firstParameter.replace( factory.createExpressionFromText( "${containingClass.name}.class", - firstParameter - ) + firstParameter, + ), ) } @@ -90,12 +90,12 @@ class WrongEntityDataParameterClassInspection : AbstractBaseJavaLocalInspectionT private val ENTITY_DATA_MANAGER_CLASSES = setOf( "net.minecraft.network.datasync.EntityDataManager", "net.minecraft.network.syncher.SynchedEntityData", - "net.minecraft.entity.data.DataTracker" + "net.minecraft.entity.data.DataTracker", ) private val DEFINE_ID_METHODS = setOf( "defineId", "createKey", - "registerData" + "registerData", ) private fun isEntitySubclass(clazz: PsiClass): Boolean = diff --git a/src/main/kotlin/nbt/NbtVirtualFile.kt b/src/main/kotlin/nbt/NbtVirtualFile.kt index 329f8502e..c83c2e61c 100644 --- a/src/main/kotlin/nbt/NbtVirtualFile.kt +++ b/src/main/kotlin/nbt/NbtVirtualFile.kt @@ -85,7 +85,7 @@ class NbtVirtualFile(private val backingFile: VirtualFile, private val project: "Error saving NBT file", "The file is not recognised as a NBTT file. This might be caused by wrong file type associations," + " or the file could be too large.", - NotificationType.WARNING + NotificationType.WARNING, ).notify(project) return@runReadActionAsync } @@ -97,7 +97,7 @@ class NbtVirtualFile(private val backingFile: VirtualFile, private val project: "NBT Save Error", "Error saving NBT file", "Due to errors in the text representation, ${backingFile.name} could not be saved.", - NotificationType.WARNING + NotificationType.WARNING, ).notify(project) return@runReadActionAsync } @@ -118,7 +118,7 @@ class NbtVirtualFile(private val backingFile: VirtualFile, private val project: "NBT Save Success", "Saved NBT file successfully", "${backingFile.name} was saved successfully.", - NotificationType.INFORMATION + NotificationType.INFORMATION, ).notify(project) } } diff --git a/src/main/kotlin/nbt/editor/CompressionSelection.kt b/src/main/kotlin/nbt/editor/CompressionSelection.kt index b02075173..1babfb7ad 100644 --- a/src/main/kotlin/nbt/editor/CompressionSelection.kt +++ b/src/main/kotlin/nbt/editor/CompressionSelection.kt @@ -12,7 +12,8 @@ package com.demonwav.mcdev.nbt.editor enum class CompressionSelection(private val selectionName: String) { GZIP("GZipped"), - UNCOMPRESSED("Uncompressed"); + UNCOMPRESSED("Uncompressed"), + ; override fun toString() = selectionName } diff --git a/src/main/kotlin/nbt/editor/NbtFileEditorProvider.kt b/src/main/kotlin/nbt/editor/NbtFileEditorProvider.kt index 539f05c6f..364451ce2 100644 --- a/src/main/kotlin/nbt/editor/NbtFileEditorProvider.kt +++ b/src/main/kotlin/nbt/editor/NbtFileEditorProvider.kt @@ -76,7 +76,7 @@ class NbtFileEditorProvider : PsiAwareTextEditorProvider(), DumbAware { private class NbtFileEditor( private val file: VirtualFile, - private val editorProvider: (NbtVirtualFile) -> FileEditor + private val editorProvider: (NbtVirtualFile) -> FileEditor, ) : FileEditor { private var editor: FileEditor? = null @@ -147,7 +147,7 @@ private class NbtFileEditor( nbtFile.writeFile(this) } - } + }, ) } diff --git a/src/main/kotlin/nbt/lang/NbttBraceMatcher.kt b/src/main/kotlin/nbt/lang/NbttBraceMatcher.kt index 3ce7ee3ca..2be2e58b7 100644 --- a/src/main/kotlin/nbt/lang/NbttBraceMatcher.kt +++ b/src/main/kotlin/nbt/lang/NbttBraceMatcher.kt @@ -38,7 +38,7 @@ class NbttBraceMatcher : PairedBraceMatcher { override fun getPairs() = arrayOf( BracePair(NbttTypes.LPAREN, NbttTypes.RPAREN, true), BracePair(NbttTypes.LBRACE, NbttTypes.RBRACE, true), - BracePair(NbttTypes.LBRACKET, NbttTypes.RBRACKET, true) + BracePair(NbttTypes.LBRACKET, NbttTypes.RBRACKET, true), ) override fun isPairedBracesAllowedBeforeType(lbraceType: IElementType, contextType: IElementType?) = true diff --git a/src/main/kotlin/nbt/lang/NbttParserDefinition.kt b/src/main/kotlin/nbt/lang/NbttParserDefinition.kt index ea1fe3146..4e17c9fce 100644 --- a/src/main/kotlin/nbt/lang/NbttParserDefinition.kt +++ b/src/main/kotlin/nbt/lang/NbttParserDefinition.kt @@ -47,19 +47,19 @@ class NbttParserDefinition : ParserDefinition { NbttTypes.INT_ARRAY, NbttTypes.LONG_ARRAY, NbttTypes.COMPOUND, - NbttTypes.LIST + NbttTypes.LIST, ) val NBTT_OPEN_BRACES = TokenSet.create( NbttTypes.LPAREN, NbttTypes.LBRACE, - NbttTypes.LBRACKET + NbttTypes.LBRACKET, ) val NBTT_CLOSE_BRACES = TokenSet.create( NbttTypes.RPAREN, NbttTypes.RBRACE, - NbttTypes.RBRACKET + NbttTypes.RBRACKET, ) val NBTT_BRACES = TokenSet.orSet(NBTT_OPEN_BRACES, NBTT_CLOSE_BRACES) diff --git a/src/main/kotlin/nbt/lang/colors/NbttColorSettingsPage.kt b/src/main/kotlin/nbt/lang/colors/NbttColorSettingsPage.kt index af51dc27a..6b6e2ff4d 100644 --- a/src/main/kotlin/nbt/lang/colors/NbttColorSettingsPage.kt +++ b/src/main/kotlin/nbt/lang/colors/NbttColorSettingsPage.kt @@ -76,13 +76,13 @@ class NbttColorSettingsPage : ColorSettingsPage { AttributesDescriptor("Long", NbttSyntaxHighlighter.LONG), AttributesDescriptor("Float", NbttSyntaxHighlighter.FLOAT), AttributesDescriptor("Double", NbttSyntaxHighlighter.DOUBLE), - AttributesDescriptor("Material", NbttSyntaxHighlighter.MATERIAL) + AttributesDescriptor("Material", NbttSyntaxHighlighter.MATERIAL), ) private val map = mapOf( "name" to NbttSyntaxHighlighter.STRING_NAME, "uname" to NbttSyntaxHighlighter.UNQUOTED_STRING_NAME, - "material" to NbttSyntaxHighlighter.MATERIAL + "material" to NbttSyntaxHighlighter.MATERIAL, ) } } diff --git a/src/main/kotlin/nbt/lang/format/NbttBlock.kt b/src/main/kotlin/nbt/lang/format/NbttBlock.kt index a31df2fa6..655cd9a4c 100644 --- a/src/main/kotlin/nbt/lang/format/NbttBlock.kt +++ b/src/main/kotlin/nbt/lang/format/NbttBlock.kt @@ -34,7 +34,7 @@ class NbttBlock( private val node: ASTNode, private val settings: CodeStyleSettings, private val indent: Indent, - private val wrap: Wrap? + private val wrap: Wrap?, ) : ASTBlock { private val psiElement = node.psi diff --git a/src/main/kotlin/nbt/lang/format/NbttFoldingBuilder.kt b/src/main/kotlin/nbt/lang/format/NbttFoldingBuilder.kt index e1a167272..a08c80df9 100644 --- a/src/main/kotlin/nbt/lang/format/NbttFoldingBuilder.kt +++ b/src/main/kotlin/nbt/lang/format/NbttFoldingBuilder.kt @@ -60,8 +60,8 @@ class NbttFoldingBuilder : FoldingBuilder { list.add( FoldingDescriptor( node, - TextRange(lbrace.textRange.endOffset, rbrace.textRange.startOffset) - ) + TextRange(lbrace.textRange.endOffset, rbrace.textRange.startOffset), + ), ) } } @@ -74,8 +74,8 @@ class NbttFoldingBuilder : FoldingBuilder { list.add( FoldingDescriptor( node, - TextRange(lbracket.textRange.endOffset, rbracket.textRange.startOffset) - ) + TextRange(lbracket.textRange.endOffset, rbracket.textRange.startOffset), + ), ) } } @@ -88,8 +88,8 @@ class NbttFoldingBuilder : FoldingBuilder { list.add( FoldingDescriptor( node, - TextRange(lparen.textRange.endOffset, rparen.textRange.startOffset) - ) + TextRange(lparen.textRange.endOffset, rparen.textRange.startOffset), + ), ) } } @@ -100,9 +100,7 @@ class NbttFoldingBuilder : FoldingBuilder { } override fun isCollapsedByDefault(node: ASTNode): Boolean { - val psi = node.psi - - val size = when (psi) { + val size = when (val psi = node.psi) { is NbttByteArray -> psi.getByteList().size is NbttIntArray -> psi.getIntList().size is NbttLongArray -> psi.getLongList().size diff --git a/src/main/kotlin/nbt/lang/format/NbttFormattingModelBuilder.kt b/src/main/kotlin/nbt/lang/format/NbttFormattingModelBuilder.kt index 239c7203b..567d24262 100644 --- a/src/main/kotlin/nbt/lang/format/NbttFormattingModelBuilder.kt +++ b/src/main/kotlin/nbt/lang/format/NbttFormattingModelBuilder.kt @@ -26,7 +26,7 @@ class NbttFormattingModelBuilder : FormattingModelBuilder { return FormattingModelProvider.createFormattingModelForPsiFile( formattingContext.containingFile, block, - formattingContext.codeStyleSettings + formattingContext.codeStyleSettings, ) } diff --git a/src/main/kotlin/nbt/lang/format/NbttLanguageCodeStyleSettingsProvider.kt b/src/main/kotlin/nbt/lang/format/NbttLanguageCodeStyleSettingsProvider.kt index f88ef0845..476e5b425 100644 --- a/src/main/kotlin/nbt/lang/format/NbttLanguageCodeStyleSettingsProvider.kt +++ b/src/main/kotlin/nbt/lang/format/NbttLanguageCodeStyleSettingsProvider.kt @@ -40,7 +40,7 @@ class NbttLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvider( CommonCodeStyleSettings.DO_NOT_WRAP, CommonCodeStyleSettings.WRAP_AS_NEEDED, CommonCodeStyleSettings.WRAP_ALWAYS, - ) + ), ) consumer.showCustomOption( NbttCodeStyleSettings::class.java, @@ -56,7 +56,7 @@ class NbttLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvider( CommonCodeStyleSettings.DO_NOT_WRAP, CommonCodeStyleSettings.WRAP_AS_NEEDED, CommonCodeStyleSettings.WRAP_ALWAYS, - ) + ), ) } @@ -65,19 +65,19 @@ class NbttLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvider( "SPACE_WITHIN_BRACKETS", "SPACE_WITHIN_PARENTHESES", "SPACE_BEFORE_COMMA", - "SPACE_AFTER_COMMA" + "SPACE_AFTER_COMMA", ) consumer.showCustomOption( NbttCodeStyleSettings::class.java, "SPACE_BEFORE_COLON", "Space before colon", - CodeStyleSettingsCustomizableOptions.getInstance().SPACES_AROUND_OPERATORS + CodeStyleSettingsCustomizableOptions.getInstance().SPACES_AROUND_OPERATORS, ) consumer.showCustomOption( NbttCodeStyleSettings::class.java, "SPACE_AFTER_COLON", "Space after colon", - CodeStyleSettingsCustomizableOptions.getInstance().SPACES_AROUND_OPERATORS + CodeStyleSettingsCustomizableOptions.getInstance().SPACES_AROUND_OPERATORS, ) consumer.renameStandardOption("SPACE_WITHIN_BRACKETS", "List brackets") @@ -95,7 +95,7 @@ class NbttLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvider( override fun customizeDefaults( commonSettings: CommonCodeStyleSettings, - indentOptions: CommonCodeStyleSettings.IndentOptions + indentOptions: CommonCodeStyleSettings.IndentOptions, ) { commonSettings.RIGHT_MARGIN = 150 indentOptions.USE_TAB_CHARACTER = true diff --git a/src/main/kotlin/nbt/lang/format/NbttParameterNameHints.kt b/src/main/kotlin/nbt/lang/format/NbttParameterNameHints.kt index 6481501d5..cbf421f6e 100644 --- a/src/main/kotlin/nbt/lang/format/NbttParameterNameHints.kt +++ b/src/main/kotlin/nbt/lang/format/NbttParameterNameHints.kt @@ -30,8 +30,8 @@ class NbttParameterNameHints : InlayParameterHintsProvider { list.add( InlayInfo( "$size ${if (size == 1) "child" else "children"}", - element.textRange.startOffset + 1 - ) + element.textRange.startOffset + 1, + ), ) } is NbttList -> { @@ -40,8 +40,8 @@ class NbttParameterNameHints : InlayParameterHintsProvider { list.add( InlayInfo( "$size ${if (size == 1) "child" else "children"}", - element.textRange.startOffset + 1 - ) + element.textRange.startOffset + 1, + ), ) if (size > 5) { @@ -56,8 +56,8 @@ class NbttParameterNameHints : InlayParameterHintsProvider { list.add( InlayInfo( "$size ${if (size == 1) "child" else "children"}", - element.node.getChildren(null)[1].textRange.startOffset + 1 - ) + element.node.getChildren(null)[1].textRange.startOffset + 1, + ), ) if (size > 5) { @@ -72,8 +72,8 @@ class NbttParameterNameHints : InlayParameterHintsProvider { list.add( InlayInfo( "$size ${if (size == 1) "child" else "children"}", - element.node.getChildren(null)[1].textRange.startOffset + 1 - ) + element.node.getChildren(null)[1].textRange.startOffset + 1, + ), ) if (size > 5) { @@ -88,8 +88,8 @@ class NbttParameterNameHints : InlayParameterHintsProvider { list.add( InlayInfo( "$size ${if (size == 1) "child" else "children"}", - element.node.getChildren(null)[1].textRange.startOffset + 1 - ) + element.node.getChildren(null)[1].textRange.startOffset + 1, + ), ) // Index hints diff --git a/src/main/kotlin/nbt/tags/NbtTypeId.kt b/src/main/kotlin/nbt/tags/NbtTypeId.kt index c63eee538..c6d466c54 100644 --- a/src/main/kotlin/nbt/tags/NbtTypeId.kt +++ b/src/main/kotlin/nbt/tags/NbtTypeId.kt @@ -25,7 +25,8 @@ enum class NbtTypeId(val typeIdByte: Byte, val tagName: String, val tagClass: KC LIST(9, "TAG_List", TagList::class), COMPOUND(10, "TAG_Compound", TagCompound::class), INT_ARRAY(11, "TAG_Int_Array", TagIntArray::class), - LONG_ARRAY(12, "TAG_Long_Array", TagLongArray::class); + LONG_ARRAY(12, "TAG_Long_Array", TagLongArray::class), + ; companion object { fun getById(id: Byte) = values().firstOrNull { it.typeIdByte == id } diff --git a/src/main/kotlin/platform/AbstractModule.kt b/src/main/kotlin/platform/AbstractModule.kt index 2855e7e90..9f966e17a 100644 --- a/src/main/kotlin/platform/AbstractModule.kt +++ b/src/main/kotlin/platform/AbstractModule.kt @@ -59,7 +59,7 @@ abstract class AbstractModule(protected val facet: MinecraftFacet) { containingClass: PsiClass, chosenClass: PsiClass, chosenName: String, - data: GenerationData? + data: GenerationData?, ): PsiMethod? = null open fun shouldShowPluginIcon(element: PsiElement?) = false diff --git a/src/main/kotlin/platform/BaseTemplate.kt b/src/main/kotlin/platform/BaseTemplate.kt index d671ab45a..621256d02 100644 --- a/src/main/kotlin/platform/BaseTemplate.kt +++ b/src/main/kotlin/platform/BaseTemplate.kt @@ -17,7 +17,7 @@ abstract class BaseTemplate { protected fun Project.applyTemplate( templateName: String, - properties: Map? = null + properties: Map? = null, ): String { val manager = FileTemplateManager.getInstance(this) val template = manager.getJ2eeTemplate(templateName) diff --git a/src/main/kotlin/platform/CommonTemplate.kt b/src/main/kotlin/platform/CommonTemplate.kt deleted file mode 100644 index 4ff7e36ec..000000000 --- a/src/main/kotlin/platform/CommonTemplate.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform - -import com.demonwav.mcdev.util.License -import com.intellij.openapi.project.Project -import java.time.ZonedDateTime - -object CommonTemplate : BaseTemplate() { - - fun applyLicenseTemplate( - project: Project, - license: License, - author: String - ): String { - val props = mapOf( - "YEAR" to ZonedDateTime.now().year.toString(), - "AUTHOR" to author - ) - return project.applyTemplate("${license.id}.txt", props) - } -} diff --git a/src/main/kotlin/platform/MinecraftModuleType.kt b/src/main/kotlin/platform/MinecraftModuleType.kt index ba61d77b2..4d984340d 100644 --- a/src/main/kotlin/platform/MinecraftModuleType.kt +++ b/src/main/kotlin/platform/MinecraftModuleType.kt @@ -11,13 +11,11 @@ package com.demonwav.mcdev.platform import com.demonwav.mcdev.asset.PlatformAssets -import com.demonwav.mcdev.creator.MinecraftModuleBuilder import com.intellij.openapi.module.JavaModuleType import com.intellij.openapi.module.ModuleTypeManager class MinecraftModuleType : JavaModuleType() { - override fun createModuleBuilder() = MinecraftModuleBuilder() override fun getIcon() = PlatformAssets.MINECRAFT_ICON override fun getNodeIcon(isOpened: Boolean) = PlatformAssets.MINECRAFT_ICON override fun getName() = NAME diff --git a/src/main/kotlin/platform/PlatformType.kt b/src/main/kotlin/platform/PlatformType.kt index 48c79d2e9..6cc753a50 100644 --- a/src/main/kotlin/platform/PlatformType.kt +++ b/src/main/kotlin/platform/PlatformType.kt @@ -28,8 +28,6 @@ import com.demonwav.mcdev.platform.fabric.FabricModuleType import com.demonwav.mcdev.platform.fabric.framework.FABRIC_LIBRARY_KIND import com.demonwav.mcdev.platform.forge.ForgeModuleType import com.demonwav.mcdev.platform.forge.framework.FORGE_LIBRARY_KIND -import com.demonwav.mcdev.platform.liteloader.LiteLoaderModuleType -import com.demonwav.mcdev.platform.liteloader.framework.LITELOADER_LIBRARY_KIND import com.demonwav.mcdev.platform.mcp.McpModuleType import com.demonwav.mcdev.platform.mcp.framework.MCP_LIBRARY_KIND import com.demonwav.mcdev.platform.mixin.MixinModuleType @@ -42,25 +40,24 @@ import com.intellij.openapi.roots.libraries.LibraryKind enum class PlatformType( val type: AbstractModuleType<*>, - val normalName: String, val versionJson: String? = null, - private val parent: PlatformType? = null + private val parent: PlatformType? = null, ) { - BUKKIT(BukkitModuleType, "Bukkit", "bukkit.json"), - SPIGOT(SpigotModuleType, "Spigot", "spigot.json", BUKKIT), - PAPER(PaperModuleType, "Paper", "paper.json", SPIGOT), - ARCHITECTURY(ArchitecturyModuleType, "Architectury"), - FORGE(ForgeModuleType, "Forge"), - FABRIC(FabricModuleType, "Fabric"), - SPONGE(SpongeModuleType, "Sponge"), - BUNGEECORD(BungeeCordModuleType, "BungeeCord", "bungeecord_v2.json"), - WATERFALL(WaterfallModuleType, "Waterfall", "waterfall.json", BUNGEECORD), - VELOCITY(VelocityModuleType, "Velocity", "velocity.json"), - LITELOADER(LiteLoaderModuleType, "LiteLoader"), - MIXIN(MixinModuleType, "Mixin"), - MCP(McpModuleType, "MCP"), - ADVENTURE(AdventureModuleType, "Adventure"); + BUKKIT(BukkitModuleType, "bukkit.json"), + SPIGOT(SpigotModuleType, "spigot.json", BUKKIT), + PAPER(PaperModuleType, "paper.json", SPIGOT), + ARCHITECTURY(ArchitecturyModuleType), + FORGE(ForgeModuleType), + FABRIC(FabricModuleType), + SPONGE(SpongeModuleType), + BUNGEECORD(BungeeCordModuleType, "bungeecord_v2.json"), + WATERFALL(WaterfallModuleType, "waterfall.json", BUNGEECORD), + VELOCITY(VelocityModuleType, "velocity.json"), + MIXIN(MixinModuleType), + MCP(McpModuleType), + ADVENTURE(AdventureModuleType), + ; private val children = mutableListOf() @@ -85,7 +82,6 @@ enum class PlatformType( ARCHITECTURY_LIBRARY_KIND -> ARCHITECTURY FORGE_LIBRARY_KIND -> FORGE FABRIC_LIBRARY_KIND -> FABRIC - LITELOADER_LIBRARY_KIND -> LITELOADER MCP_LIBRARY_KIND -> MCP MIXIN_LIBRARY_KIND -> MIXIN BUNGEECORD_LIBRARY_KIND -> BUNGEECORD diff --git a/src/main/kotlin/platform/adventure/AdventureModuleType.kt b/src/main/kotlin/platform/adventure/AdventureModuleType.kt index ce3446c12..c5ceeda91 100644 --- a/src/main/kotlin/platform/adventure/AdventureModuleType.kt +++ b/src/main/kotlin/platform/adventure/AdventureModuleType.kt @@ -19,7 +19,7 @@ import javax.swing.Icon object AdventureModuleType : AbstractModuleType( AdventureConstants.GROUP_ID, - AdventureConstants.API_ARTIFACT_ID + AdventureConstants.API_ARTIFACT_ID, ) { const val ID = "ADVENTURE_MODULE_TYPE" diff --git a/src/main/kotlin/platform/architectury/version/ArchitecturyVersion.kt b/src/main/kotlin/platform/architectury/ArchitecturyVersion.kt similarity index 87% rename from src/main/kotlin/platform/architectury/version/ArchitecturyVersion.kt rename to src/main/kotlin/platform/architectury/ArchitecturyVersion.kt index 797bcae14..0f4c05300 100644 --- a/src/main/kotlin/platform/architectury/version/ArchitecturyVersion.kt +++ b/src/main/kotlin/platform/architectury/ArchitecturyVersion.kt @@ -8,7 +8,7 @@ * MIT License */ -package com.demonwav.mcdev.platform.architectury.version +package com.demonwav.mcdev.platform.architectury import com.demonwav.mcdev.creator.selectProxy import com.demonwav.mcdev.update.PluginUtil @@ -19,7 +19,6 @@ import com.github.kittinunf.fuel.core.requests.suspendable import com.github.kittinunf.fuel.coroutines.awaitString import com.google.gson.Gson import com.google.gson.annotations.SerializedName -import com.intellij.openapi.diagnostic.logger import java.io.IOException class ArchitecturyVersion private constructor( @@ -45,7 +44,6 @@ class ArchitecturyVersion private constructor( ) companion object { - private val LOGGER = logger() suspend fun downloadData(): ArchitecturyVersion? { try { @@ -66,7 +64,7 @@ class ArchitecturyVersion private constructor( val apiVersion = SemanticVersion.parse(version.versionNumber.substringBeforeLast('+')) for (gameVersion in version.gameVersions) { - val parsed = SemanticVersion.parse(gameVersion) + val parsed = SemanticVersion.tryParse(gameVersion) ?: continue val set = apiVersionMap.computeIfAbsent(parsed) { HashSet() } set += apiVersion } @@ -78,10 +76,10 @@ class ArchitecturyVersion private constructor( } return ArchitecturyVersion(apiVersionMapList) - } catch (e: IOException) { - LOGGER.error("Failed to retrieve Architectury version data", e) + } catch (e: Exception) { + e.printStackTrace() + return null } - return null } } } diff --git a/src/main/kotlin/platform/architectury/creator/ArchitecturyProjectConfig.kt b/src/main/kotlin/platform/architectury/creator/ArchitecturyProjectConfig.kt deleted file mode 100644 index 8dc41f4cc..000000000 --- a/src/main/kotlin/platform/architectury/creator/ArchitecturyProjectConfig.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.architectury.creator - -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.ProjectCreator -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleCreator -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.util.License -import com.demonwav.mcdev.util.MinecraftVersions -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.VersionRange -import com.intellij.openapi.module.Module -import com.intellij.util.lang.JavaVersion -import java.nio.file.Path - -class ArchitecturyProjectConfig : ProjectConfig(), GradleCreator { - - var mcVersion: SemanticVersion = SemanticVersion.release() - var forgeVersion: SemanticVersion = SemanticVersion.release() - var forgeVersionText: String = "" - var fabricLoaderVersion = SemanticVersion.release() - var fabricApiVersion: SemanticVersion = SemanticVersion.release() - var architecturyApiVersion: SemanticVersion = SemanticVersion.release() - var loomVersion = SemanticVersion.release() - private var gradleVersion = SemanticVersion.release() - val architecturyGroup: String - get() = when { - architecturyApiVersion >= SemanticVersion.release(2, 0, 10) -> "dev.architectury" - else -> "me.shedaniel" - } - val architecturyPackage: String - get() = when { - architecturyApiVersion >= SemanticVersion.release(2, 0, 10) -> "dev.architectury" - else -> "me.shedaniel.architectury" - } - var modRepo: String? = null - fun hasRepo() = !modRepo.isNullOrBlank() - var modIssue: String? = null - fun hasIssue() = !modIssue.isNullOrBlank() - var fabricApi = true - var architecturyApi = true - var mixins = false - var license: License? = null - - override var type = PlatformType.ARCHITECTURY - - override val preferredBuildSystem = BuildSystemType.GRADLE - - override val javaVersion: JavaVersion - get() = MinecraftVersions.requiredJavaVersion(mcVersion) - - override val compatibleGradleVersions: VersionRange - get() = VersionRange.fixed(gradleVersion) - - override fun buildGradleCreator( - rootDirectory: Path, - module: Module, - buildSystem: GradleBuildSystem - ): ProjectCreator { - return ArchitecturyProjectCreator( - rootDirectory, - module, - buildSystem, - this - ) - } -} diff --git a/src/main/kotlin/platform/architectury/creator/ArchitecturyProjectCreator.kt b/src/main/kotlin/platform/architectury/creator/ArchitecturyProjectCreator.kt deleted file mode 100644 index ad8ded5ba..000000000 --- a/src/main/kotlin/platform/architectury/creator/ArchitecturyProjectCreator.kt +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.architectury.creator - -import com.demonwav.mcdev.creator.BaseProjectCreator -import com.demonwav.mcdev.creator.BasicJavaClassStep -import com.demonwav.mcdev.creator.CreateDirectoriesStep -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.BasicGradleFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleFiles -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleGitignoreStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleWrapperStep -import com.demonwav.mcdev.creator.buildsystem.gradle.SimpleGradleSetupStep -import com.demonwav.mcdev.platform.fabric.EntryPoint -import com.demonwav.mcdev.platform.fabric.util.FabricConstants -import com.demonwav.mcdev.platform.forge.util.ForgeConstants -import com.demonwav.mcdev.platform.forge.util.ForgePackAdditionalData -import com.demonwav.mcdev.platform.forge.util.ForgePackDescriptor -import com.demonwav.mcdev.util.runGradleTaskAndWait -import com.demonwav.mcdev.util.runWriteAction -import com.demonwav.mcdev.util.runWriteTask -import com.demonwav.mcdev.util.runWriteTaskInSmartMode -import com.intellij.json.JsonLanguage -import com.intellij.json.psi.JsonArray -import com.intellij.json.psi.JsonElementGenerator -import com.intellij.json.psi.JsonFile -import com.intellij.json.psi.JsonObject -import com.intellij.openapi.module.Module -import com.intellij.openapi.module.ModuleManager -import com.intellij.openapi.module.ModuleType -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.text.StringUtil -import com.intellij.psi.PsiFileFactory -import java.nio.file.Files -import java.nio.file.Path -import org.gradle.internal.impldep.org.apache.commons.io.FileUtils - -class ArchitecturyProjectCreator( - private val rootDirectory: Path, - private val rootModule: Module, - private val buildSystem: GradleBuildSystem, - private val config: ArchitecturyProjectConfig -) : BaseProjectCreator(rootModule, buildSystem) { - - private val commonModule: Module = project.runWriteTaskInSmartMode { - ModuleManager.getInstance(rootModule.project) - .newModule(rootDirectory.resolve("common"), ModuleType.get(rootModule).id) - } - private val forgeModule: Module = project.runWriteTaskInSmartMode { - ModuleManager.getInstance(rootModule.project) - .newModule(rootDirectory.resolve("forge"), ModuleType.get(rootModule).id) - } - private val fabricModule: Module = project.runWriteTaskInSmartMode { - ModuleManager.getInstance(rootModule.project) - .newModule(rootDirectory.resolve("fabric"), ModuleType.get(rootModule).id) - } - - override fun getSteps(): Iterable { - val steps = mutableListOf() - steps += ArchitecturyCommonProjectCreator( - rootDirectory.resolve("common"), - commonModule, - buildSystem, - config - ).getSteps() - steps += ArchitecturyForgeProjectCreator( - rootDirectory.resolve("forge"), - forgeModule, - buildSystem, - config - ).getSteps() - steps += ArchitecturyFabricProjectCreator( - rootDirectory.resolve("fabric"), - fabricModule, - buildSystem, - config - ).getSteps() - steps += listOf( - SimpleGradleSetupStep( - project, - rootDirectory, - buildSystem, - GradleFiles( - ArchitecturyTemplate.applyBuildGradle(project, buildSystem, config), - ArchitecturyTemplate.applyGradleProp(project, buildSystem, config), - ArchitecturyTemplate.applySettingsGradle(project, buildSystem, config) - ) - ), - GradleWrapperStep(project, rootDirectory, buildSystem), - GenRunsStep(project, rootDirectory), - GradleGitignoreStep(project, rootDirectory), - CleanUpStep(rootDirectory), - BasicGradleFinalizerStep(rootModule, rootDirectory, buildSystem) - ) - return steps - } - - class GenRunsStep( - private val project: Project, - private val rootDirectory: Path - ) : CreatorStep { - - override fun runStep(indicator: ProgressIndicator) { - indicator.text = "Setting up project" - indicator.text2 = "Running Gradle task: 'genIntellijRuns'" - runGradleTaskAndWait(project, rootDirectory) { settings -> - settings.taskNames = listOf("genIntellijRuns") - settings.vmOptions = "-Xmx1G" - } - indicator.text2 = null - } - } - - class CleanUpStep( - private val rootDirectory: Path - ) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - FileUtils.deleteDirectory(rootDirectory.resolve("src").toFile()) - } - } -} - -class ArchitecturyCommonProjectCreator( - private val rootDirectory: Path, - rootModule: Module, - private val buildSystem: GradleBuildSystem, - private val config: ArchitecturyProjectConfig -) : BaseProjectCreator(rootModule, buildSystem) { - override fun getSteps(): Iterable { - return listOf( - CreateDirectoriesStep(buildSystem, rootDirectory), - ArchitecturyCommonMixinStep(project, buildSystem, config), - SimpleGradleSetupStep( - project, - rootDirectory, - buildSystem, - GradleFiles(ArchitecturyTemplate.applyCommonBuildGradle(project, buildSystem, config), null, null) - ), - setupMainClassStep() - ) - } - - private fun setupMainClassStep(): BasicJavaClassStep { - return BasicJavaClassStep( - project, - buildSystem, - buildSystem.groupId + "." + buildSystem.artifactId + "." + config.pluginName.replace(" ", ""), - ArchitecturyTemplate.applyCommonMainClass( - project, - buildSystem, - config, - buildSystem.groupId + "." + buildSystem.artifactId, - config.pluginName.replace(" ", "") - ) - ) - } - - class ArchitecturyCommonMixinStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val config: ArchitecturyProjectConfig - ) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - if (config.mixins) { - val text = ArchitecturyTemplate.applyCommonMixinConfigTemplate(project, buildSystem, config) - val dir = buildSystem.dirsOrError.resourceDirectory - runWriteTask { - CreatorStep.writeTextToFile(project, dir, "${buildSystem.artifactId}-common.mixins.json", text) - } - } - } - } -} - -class ArchitecturyForgeProjectCreator( - private val rootDirectory: Path, - rootModule: Module, - private val buildSystem: GradleBuildSystem, - private val config: ArchitecturyProjectConfig -) : BaseProjectCreator(rootModule, buildSystem) { - override fun getSteps(): Iterable { - return listOf( - CreateDirectoriesStep(buildSystem, rootDirectory), - ArchitecturyForgeMixinStep(project, buildSystem, config), - ArchitecturyForgeResourcesStep(project, buildSystem, config), - SimpleGradleSetupStep( - project, - rootDirectory, - buildSystem, - GradleFiles( - ArchitecturyTemplate.applyForgeBuildGradle(project, buildSystem, config), - ArchitecturyTemplate.applyForgeGradleProp(project, buildSystem, config), - null - ) - ), - setupMainClassStep() - ) - } - - private fun setupMainClassStep(): BasicJavaClassStep { - return BasicJavaClassStep( - project, - buildSystem, - buildString { - append(buildSystem.groupId) - append(".") - append(buildSystem.artifactId) - append(".forge.") - append(config.pluginName.replace(" ", "")) - append("Forge") - }, - ArchitecturyTemplate.applyForgeMainClass( - project, - buildSystem, - config, - buildSystem.groupId + "." + buildSystem.artifactId, - config.pluginName.replace(" ", "") - ) - ) - } - - class ArchitecturyForgeMixinStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val config: ArchitecturyProjectConfig - ) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - if (config.mixins) { - val text = ArchitecturyTemplate.applyForgeMixinConfigTemplate(project, buildSystem, config) - val dir = buildSystem.dirsOrError.resourceDirectory - runWriteTask { - CreatorStep.writeTextToFile(project, dir, "${buildSystem.artifactId}.mixins.json", text) - } - } - } - } - - class ArchitecturyForgeResourcesStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val config: ArchitecturyProjectConfig - ) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val modsTomlText = ArchitecturyTemplate.applyModsToml(project, buildSystem, config) - val packDescriptor = ForgePackDescriptor.forMcVersion(config.mcVersion) ?: ForgePackDescriptor.FORMAT_3 - val additionalData = ForgePackAdditionalData.forMcVersion(config.mcVersion) - val packMcmetaText = - ArchitecturyTemplate.applyPackMcmeta(project, buildSystem.artifactId, packDescriptor, additionalData) - val dir = buildSystem.dirsOrError.resourceDirectory - runWriteTask { - CreatorStep.writeTextToFile(project, dir, ForgeConstants.PACK_MCMETA, packMcmetaText) - val meta = dir.resolve("META-INF") - Files.createDirectories(meta) - CreatorStep.writeTextToFile(project, meta, ForgeConstants.MODS_TOML, modsTomlText) - } - } - } -} - -class ArchitecturyFabricProjectCreator( - private val rootDirectory: Path, - rootModule: Module, - private val buildSystem: GradleBuildSystem, - private val config: ArchitecturyProjectConfig -) : BaseProjectCreator(rootModule, buildSystem) { - override fun getSteps(): Iterable { - return listOf( - CreateDirectoriesStep(buildSystem, rootDirectory), - ArchitecturyFabricMixinStep(project, buildSystem, config), - ArchitecturyFabricResourcesStep(project, buildSystem, config), - SimpleGradleSetupStep( - project, - rootDirectory, - buildSystem, - GradleFiles( - ArchitecturyTemplate.applyFabricBuildGradle(project, buildSystem, config), - null, - null - ) - ), - setupMainClassStep() - ) - } - - private fun setupMainClassStep(): BasicJavaClassStep { - return BasicJavaClassStep( - project, - buildSystem, - buildString { - append(buildSystem.groupId) - append(".") - append(buildSystem.artifactId) - append(".fabric.") - append(config.pluginName.replace(" ", "")) - append("Fabric") - }, - ArchitecturyTemplate.applyFabricMainClass( - project, - buildSystem, - config, - buildSystem.groupId + "." + buildSystem.artifactId, - config.pluginName.replace(" ", "") - ) - ) - } - - class ArchitecturyFabricMixinStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val config: ArchitecturyProjectConfig - ) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - if (config.mixins) { - val text = ArchitecturyTemplate.applyFabricMixinConfigTemplate(project, buildSystem, config) - val dir = buildSystem.dirsOrError.resourceDirectory - runWriteTask { - CreatorStep.writeTextToFile(project, dir, "${buildSystem.artifactId}.mixins.json", text) - } - } - } - } - - class ArchitecturyFabricResourcesStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val config: ArchitecturyProjectConfig - ) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val text = ArchitecturyTemplate.applyFabricModJsonTemplate(project, buildSystem, config) - val dir = buildSystem.dirsOrError.resourceDirectory - - indicator.text = "Indexing" - - project.runWriteTaskInSmartMode { - indicator.text = "Creating 'fabric.mod.json'" - - val file = PsiFileFactory.getInstance(project).createFileFromText(JsonLanguage.INSTANCE, text) - file.runWriteAction { - val jsonFile = file as JsonFile - val json = jsonFile.topLevelValue as? JsonObject ?: return@runWriteAction - val generator = JsonElementGenerator(project) - - (json.findProperty("authors")?.value as? JsonArray)?.let { authorsArray -> - for (i in config.authors.indices) { - if (i != 0) { - authorsArray.addBefore(generator.createComma(), authorsArray.lastChild) - } - authorsArray.addBefore( - generator.createStringLiteral(config.authors[i]), - authorsArray.lastChild - ) - } - } - - (json.findProperty("contact")?.value as? JsonObject)?.let { contactObject -> - val properties = mutableListOf>() - val website = config.website - if (!website.isNullOrBlank()) { - properties += "website" to website - } - val repo = config.modRepo - if (!repo.isNullOrBlank()) { - properties += "repo" to repo - } - val issues = config.modIssue - if (!issues.isNullOrBlank()) { - properties += "issues" to issues - } - for (i in properties.indices) { - if (i != 0) { - contactObject.addBefore(generator.createComma(), contactObject.lastChild) - } - val key = StringUtil.escapeStringCharacters(properties[i].first) - val value = "\"" + StringUtil.escapeStringCharacters(properties[i].second) + "\"" - contactObject.addBefore(generator.createProperty(key, value), contactObject.lastChild) - } - } - - (json.findProperty("entrypoints")?.value as? JsonObject)?.let { entryPointsObject -> - val entryPointsByCategory = listOf( - EntryPoint( - "main", - EntryPoint.Type.CLASS, - buildString { - append(buildSystem.groupId) - append(".") - append(buildSystem.artifactId) - append(".fabric.") - append(config.pluginName.replace(" ", "")) - append("Fabric") - }, - FabricConstants.MOD_INITIALIZER - ) - ) - .groupBy { it.category } - .asSequence() - .sortedBy { it.key } - .toList() - for (i in entryPointsByCategory.indices) { - val entryPointCategory = entryPointsByCategory[i] - if (i != 0) { - entryPointsObject.addBefore(generator.createComma(), entryPointsObject.lastChild) - } - val values = generator.createValue("[]") - for (j in entryPointCategory.value.indices) { - if (j != 0) { - values.addBefore(generator.createComma(), values.lastChild) - } - val entryPointReference = entryPointCategory.value[j].computeReference(project) - val value = generator.createStringLiteral(entryPointReference) - values.addBefore(value, values.lastChild) - } - val key = StringUtil.escapeStringCharacters(entryPointCategory.key) - val prop = generator.createProperty(key, "[]") - prop.value?.replace(values) - entryPointsObject.addBefore(prop, entryPointsObject.lastChild) - } - } - } - CreatorStep.writeTextToFile(project, dir, FabricConstants.FABRIC_MOD_JSON, file.text) - } - } - } -} diff --git a/src/main/kotlin/platform/architectury/creator/ArchitecturyProjectSettingsWizard.form b/src/main/kotlin/platform/architectury/creator/ArchitecturyProjectSettingsWizard.form deleted file mode 100644 index 12fb5d91d..000000000 --- a/src/main/kotlin/platform/architectury/creator/ArchitecturyProjectSettingsWizard.form +++ /dev/null @@ -1,402 +0,0 @@ - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/main/kotlin/platform/architectury/creator/ArchitecturyProjectSettingsWizard.kt b/src/main/kotlin/platform/architectury/creator/ArchitecturyProjectSettingsWizard.kt deleted file mode 100644 index f0d89d187..000000000 --- a/src/main/kotlin/platform/architectury/creator/ArchitecturyProjectSettingsWizard.kt +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.architectury.creator - -import com.demonwav.mcdev.asset.PlatformAssets -import com.demonwav.mcdev.creator.MinecraftModuleWizardStep -import com.demonwav.mcdev.creator.MinecraftProjectCreator -import com.demonwav.mcdev.creator.ValidatedField -import com.demonwav.mcdev.creator.ValidatedFieldType.CLASS_NAME -import com.demonwav.mcdev.creator.ValidatedFieldType.LIST -import com.demonwav.mcdev.creator.ValidatedFieldType.NON_BLANK -import com.demonwav.mcdev.platform.architectury.version.ArchitecturyVersion -import com.demonwav.mcdev.platform.architectury.version.FabricVersion -import com.demonwav.mcdev.platform.forge.version.ForgeVersion -import com.demonwav.mcdev.util.License -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.asyncIO -import com.demonwav.mcdev.util.modUpdateStep -import com.intellij.openapi.diagnostic.logger -import com.intellij.ui.CollectionComboBoxModel -import com.intellij.ui.EnumComboBoxModel -import java.awt.event.ActionListener -import javax.swing.JCheckBox -import javax.swing.JComboBox -import javax.swing.JComponent -import javax.swing.JLabel -import javax.swing.JPanel -import javax.swing.JProgressBar -import javax.swing.JTextField -import kotlin.math.min -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import kotlinx.coroutines.swing.Swing - -class ArchitecturyProjectSettingsWizard(private val creator: MinecraftProjectCreator) : MinecraftModuleWizardStep() { - - @ValidatedField(NON_BLANK) - private lateinit var modNameField: JTextField - - @ValidatedField(NON_BLANK, CLASS_NAME) - private lateinit var panel: JPanel - private lateinit var title: JLabel - private lateinit var descriptionField: JTextField - - @ValidatedField(LIST) - private lateinit var authorsField: JTextField - private lateinit var websiteField: JTextField - private lateinit var repositoryField: JTextField - private lateinit var issueField: JTextField - private lateinit var licenseBox: JComboBox - private lateinit var mixinsCheckbox: JCheckBox - private lateinit var architecturyCheckbox: JCheckBox - private lateinit var fabricCheckbox: JCheckBox - private lateinit var minecraftVersionBox: JComboBox - private lateinit var forgeVersionBox: JComboBox - private lateinit var fabricVersionBox: JComboBox - private lateinit var fabricApiVersionBox: JComboBox - private lateinit var architecturyApiVersionBox: JComboBox - private lateinit var loadingBar: JProgressBar - private lateinit var minecraftVersionLabel: JLabel - private lateinit var errorLabel: JLabel - - private var config: ArchitecturyProjectConfig? = null - - private data class ArchitecturyVersions( - var fabricVersion: FabricVersion, - var forgeVersion: ForgeVersion, - var architecturyVersion: ArchitecturyVersion - ) - - private var versions: ArchitecturyVersions? = null - - private var currentJob: Job? = null - - private val forgeVersionBoxListener = ActionListener { - val selectedVersion = forgeVersionBox.selectedItem as? SemanticVersion ?: return@ActionListener - val supportedMixinVersion = selectedVersion >= SemanticVersion.release(31, 2, 45) - - mixinsCheckbox.isEnabled = supportedMixinVersion - if (!supportedMixinVersion) { - mixinsCheckbox.isSelected = false - } - } - - private val minecraftBoxActionListener: ActionListener = ActionListener { - CoroutineScope(Dispatchers.Swing).launch { - loadingBar.isIndeterminate = true - loadingBar.isVisible = true - - updateForm() - - loadingBar.isIndeterminate = false - loadingBar.isVisible = false - } - } - - override fun getComponent(): JComponent { - return panel - } - - override fun updateStep() { - val (conf) = modUpdateStep(creator, modNameField) ?: return - config = conf - - title.icon = PlatformAssets.ARCHITECTURY_ICON_2X - title.text = "Architectury Settings" - - minecraftVersionLabel.text = "Minecraft Version" - - licenseBox.model = EnumComboBoxModel(License::class.java) - licenseBox.selectedItem = License.ALL_RIGHTS_RESERVED - - if (versions != null || currentJob?.isActive == true) { - return - } - currentJob = updateVersions() - } - - private fun setForgeVersion(data: Data) { - forgeVersionBox.model = CollectionComboBoxModel(data.forgeVersions.subList(0, min(50, data.forgeVersions.size))) - forgeVersionBox.selectedIndex = data.forgeSelectedIndex - } - - private fun setFabricVersion(data: Data) { - fabricVersionBox.model = CollectionComboBoxModel( - data.fabricVersions.subList(0, min(50, data.fabricVersions.size)) - ) - fabricVersionBox.selectedIndex = data.fabricSelectedIndex - } - - private fun setFabricApiVersion(data: Data) { - fabricApiVersionBox.model = CollectionComboBoxModel( - data.fabricApiVersions.subList(0, min(50, data.fabricApiVersions.size)) - ) - fabricApiVersionBox.selectedIndex = data.fabricApiSelectedIndex - } - - private fun setArchitecturyApiVersion(data: Data) { - architecturyApiVersionBox.model = CollectionComboBoxModel( - data.architecturyApiVersions.subList(0, min(50, data.architecturyApiVersions.size)) - ) - architecturyApiVersionBox.selectedIndex = data.architecturyApiSelectedIndex - } - - private val version: SemanticVersion? - get() = minecraftVersionBox.selectedItem as? SemanticVersion - - override fun validate(): Boolean { - return super.validate() && !loadingBar.isVisible - } - - override fun isStepVisible(): Boolean { - return creator.config is ArchitecturyProjectConfig - } - - override fun onStepLeaving() { - currentJob?.cancel() - } - - override fun updateDataModel() { - val conf = this.config ?: return - - conf.pluginName = this.modNameField.text - conf.description = this.descriptionField.text - conf.website = this.websiteField.text - - conf.modRepo = this.repositoryField.text - conf.modIssue = this.issueField.text - - conf.setAuthors(this.authorsField.text) - - conf.mcVersion = this.version ?: SemanticVersion.release() - - (this.forgeVersionBox.selectedItem as SemanticVersion).let { version -> - val versionString = version.toString() - val forgeVersion = this.versions?.forgeVersion ?: return@let - conf.forgeVersionText = forgeVersion.versions.first { it.endsWith(versionString) } - conf.forgeVersion = version - } - (this.fabricVersionBox.selectedItem as SemanticVersion).let { version -> - conf.fabricLoaderVersion = version - } - (this.fabricApiVersionBox.selectedItem as SemanticVersion).let { version -> - conf.fabricApiVersion = version - } - (this.architecturyApiVersionBox.selectedItem as SemanticVersion).let { version -> - conf.architecturyApiVersion = version - } - - conf.fabricApi = fabricCheckbox.isSelected - conf.architecturyApi = architecturyCheckbox.isSelected - conf.mixins = mixinsCheckbox.isSelected - conf.license = licenseBox.selectedItem as? License ?: License.ALL_RIGHTS_RESERVED - } - - private fun mcVersionUpdate(data: Data) { - forgeVersionBox.removeActionListener(forgeVersionBoxListener) - setForgeVersion(data) - forgeVersionBox.addActionListener(forgeVersionBoxListener) - forgeVersionBoxListener.actionPerformed(null) - - fabricCheckbox.addActionListener { - if (fabricCheckbox.isSelected) { - architecturyCheckbox.isEnabled = true - } else { - architecturyCheckbox.isEnabled = false - architecturyCheckbox.isSelected = false - } - } - - setFabricVersion(data) - setFabricApiVersion(data) - setArchitecturyApiVersion(data) - } - - private fun updateVersions() = CoroutineScope(Dispatchers.Swing).launch { - loadingBar.isIndeterminate = true - loadingBar.isVisible = true - - try { - downloadVersions() - val data = updateForm() - if (data != null) { - updateMcForm(data) - } - } catch (e: Exception) { - LOGGER.error("Failed to update versions form", e) - error() - } - - loadingBar.isIndeterminate = false - loadingBar.isVisible = false - - currentJob = null - } - - fun error() { - errorLabel.isVisible = true - loadingBar.isIndeterminate = false - loadingBar.isVisible = false - } - - private suspend fun downloadVersions() = coroutineScope { - val fabricVersionJob = asyncIO { FabricVersion.downloadData() } - val forgeVersionJob = asyncIO { ForgeVersion.downloadData() } - val architecturyApiVersionJob = asyncIO { ArchitecturyVersion.downloadData() } - - versions = ArchitecturyVersions( - fabricVersionJob.await() ?: return@coroutineScope, - forgeVersionJob.await() ?: return@coroutineScope, - architecturyApiVersionJob.await() ?: return@coroutineScope, - ) - } - - private suspend fun updateForm(): Data? = coroutineScope { - try { - val vers = versions ?: return@coroutineScope null - - val selectedVersion = version ?: vers.forgeVersion.sortedMcVersions.firstOrNull() - ?: return@coroutineScope null - - val fabricVersionsJob = asyncIO { vers.fabricVersion.getFabricVersions(selectedVersion) } - val forgeVersionsJob = asyncIO { vers.forgeVersion.getForgeVersions(selectedVersion) } - val fabricApiVersionsJob = asyncIO { vers.fabricVersion.getFabricApiVersions(selectedVersion) } - val architecturyApiVersionsJob = asyncIO { - vers.architecturyVersion.getArchitecturyVersions(selectedVersion) - } - - // awaitAll is better than calling .await() individually - val ( - fabricVersions, - forgeVersions, - fabricApiVersions, - architecturyApiVersions, - ) = listOf( - fabricVersionsJob, - forgeVersionsJob, - fabricApiVersionsJob, - architecturyApiVersionsJob - ).awaitAll() - - val data = Data(0, fabricVersions, 0, forgeVersions, 0, fabricApiVersions, 0, architecturyApiVersions, 0) - - mcVersionUpdate(data) - - return@coroutineScope data - } catch (e: Exception) { - // log error manually - something is weird about intellij & coroutine exception handling - LOGGER.error("Error while updating Architectury form version fields", e) - return@coroutineScope null - } - } - - private fun updateMcForm(data: Data) { - val vers = versions ?: return - - minecraftVersionBox.removeActionListener(minecraftBoxActionListener) - minecraftVersionBox.removeAllItems() - - // make copy, so the next 2 operations don't mess up the map - val mcVersions = vers.architecturyVersion.versions.keys.toCollection(LinkedHashSet()) - mcVersions.retainAll(vers.forgeVersion.sortedMcVersions.toSet()) - // Fabric also targets preview versions which aren't semver - // The other option would be to try to parse all of them and catching any exceptions - // But exceptions are slow, so this should be more efficient - val fabricMcVersions = vers.fabricVersion.versions.minecraftVersions.mapTo(HashSet()) { it.name } - mcVersions.retainAll { fabricMcVersions.contains(it.toString()) } - - minecraftVersionBox.model = CollectionComboBoxModel(mcVersions.sortedDescending()) - minecraftVersionBox.selectedIndex = data.mcSelectedIndex - minecraftVersionBox.addActionListener(minecraftBoxActionListener) - } - - private data class Data( - val mcSelectedIndex: Int, - val fabricVersions: List, - val fabricSelectedIndex: Int, - val forgeVersions: List, - val forgeSelectedIndex: Int, - val fabricApiVersions: List, - val fabricApiSelectedIndex: Int, - val architecturyApiVersions: List, - val architecturyApiSelectedIndex: Int - ) - - companion object { - private val LOGGER = logger() - } -} diff --git a/src/main/kotlin/platform/architectury/creator/ArchitecturyTemplate.kt b/src/main/kotlin/platform/architectury/creator/ArchitecturyTemplate.kt deleted file mode 100644 index cf91555d8..000000000 --- a/src/main/kotlin/platform/architectury/creator/ArchitecturyTemplate.kt +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.architectury.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.platform.BaseTemplate -import com.demonwav.mcdev.platform.forge.util.ForgeConstants -import com.demonwav.mcdev.platform.forge.util.ForgePackAdditionalData -import com.demonwav.mcdev.platform.forge.util.ForgePackDescriptor -import com.demonwav.mcdev.util.License -import com.demonwav.mcdev.util.MinecraftTemplates -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.toPackageName -import com.intellij.openapi.project.Project - -object ArchitecturyTemplate : BaseTemplate() { - private fun Project.applyGradleTemplate( - templateName: String, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - val props = mutableMapOf( - "GROUP_ID" to buildSystem.groupId, - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "VERSION" to buildSystem.version, - "MC_VERSION" to config.mcVersion.toString(), - "FORGE_VERSION" to config.forgeVersionText, - "FABRIC_LOADER_VERSION" to config.fabricLoaderVersion.toString(), - "FABRIC_API_VERSION" to config.fabricApiVersion.toString(), - "ARCHITECTURY_API_VERSION" to config.architecturyApiVersion.toString(), - "ARCHITECTURY_GROUP" to config.architecturyGroup, - "LOOM_VERSION" to config.loomVersion.toString(), - "JAVA_VERSION" to config.javaVersion.feature - ) - if (config.fabricApi) { - props["FABRIC_API"] = "true" - } - if (config.architecturyApi) { - props["ARCHITECTURY_API"] = "true" - } - return applyTemplate(templateName, props) - } - - fun applyBuildGradle( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - return project.applyGradleTemplate(MinecraftTemplates.ARCHITECTURY_BUILD_GRADLE_TEMPLATE, buildSystem, config) - } - - fun applyGradleProp( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - return project.applyGradleTemplate( - MinecraftTemplates.ARCHITECTURY_GRADLE_PROPERTIES_TEMPLATE, - buildSystem, - config - ) - } - - fun applyMultiModuleBuildGradle( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - return project.applyGradleTemplate( - MinecraftTemplates.ARCHITECTURY_SUBMODULE_BUILD_GRADLE_TEMPLATE, - buildSystem, - config - ) - } - - fun applyMultiModuleGradleProp( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - return project.applyGradleTemplate( - MinecraftTemplates.ARCHITECTURY_SUBMODULE_GRADLE_PROPERTIES_TEMPLATE, - buildSystem, - config - ) - } - - fun applySettingsGradle( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - return project.applyGradleTemplate( - MinecraftTemplates.ARCHITECTURY_SETTINGS_GRADLE_TEMPLATE, - buildSystem, - config - ) - } - - fun applyCommonBuildGradle( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - return project.applyGradleTemplate( - MinecraftTemplates.ARCHITECTURY_COMMON_BUILD_GRADLE_TEMPLATE, - buildSystem, - config - ) - } - - fun applyForgeBuildGradle( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - return project.applyGradleTemplate( - MinecraftTemplates.ARCHITECTURY_FORGE_BUILD_GRADLE_TEMPLATE, - buildSystem, - config - ) - } - - fun applyForgeGradleProp( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - return project.applyGradleTemplate( - MinecraftTemplates.ARCHITECTURY_FORGE_GRADLE_PROPERTIES_TEMPLATE, - buildSystem, - config - ) - } - - fun applyFabricBuildGradle( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - return project.applyGradleTemplate( - MinecraftTemplates.ARCHITECTURY_FABRIC_BUILD_GRADLE_TEMPLATE, - buildSystem, - config - ) - } - - fun applyFabricModJsonTemplate( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - val props = mutableMapOf( - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "MOD_DESCRIPTION" to (config.description ?: ""), - "MOD_ENVIRONMENT" to "*", - "FABRIC_LOADER_VERSION" to config.fabricLoaderVersion.toString(), - "FABRIC_API_VERSION" to config.fabricApiVersion.toString(), - "ARCHITECTURY_API_VERSION" to config.architecturyApiVersion.toString(), - "MC_VERSION" to config.mcVersion.toString(), - "JAVA_VERSION" to config.javaVersion.feature, - "LICENSE" to ((config.license ?: License.ALL_RIGHTS_RESERVED).id) - ) - if (config.mixins) { - props["MIXINS"] = "true" - } - - return project.applyTemplate(MinecraftTemplates.ARCHITECTURY_FABRIC_MOD_JSON_TEMPLATE, props) - } - - fun applyModsToml(project: Project, buildSystem: BuildSystem, config: ArchitecturyProjectConfig): String { - val hasDisplayTestInManifest = config.forgeVersion >= ForgeConstants.DISPLAY_TEST_MANIFEST_VERSION - val nextMcVersion = when (val part = config.mcVersion.parts.getOrNull(1)) { - // Mimics the code used to get the next Minecraft version in Forge's MDK - // https://github.com/MinecraftForge/MinecraftForge/blob/0ff8a596fc1ef33d4070be89dd5cb4851f93f731/build.gradle#L884 - is SemanticVersion.Companion.VersionPart.ReleasePart -> (part.version + 1).toString() - null -> "?" - else -> part.versionString - } - val props = mutableMapOf( - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "DISPLAY_TEST" to hasDisplayTestInManifest, - "FORGE_SPEC_VERSION" to config.forgeVersion.parts[0].versionString, - "ARCHITECTURY_API_VERSION" to config.architecturyApiVersion.toString(), - "MC_VERSION" to config.mcVersion.toString(), - "MC_NEXT_VERSION" to "1.$nextMcVersion", - "LICENSE" to config.license.toString() - ) - props["DESCRIPTION"] = config.description ?: "" - if (config.hasAuthors()) { - props["AUTHOR_LIST"] = config.authors.joinToString(", ") - } - if (config.hasWebsite()) { - props["WEBSITE"] = config.website.toString() - } - if (config.hasIssue()) { - props["ISSUE"] = config.modIssue.toString() - } - - return project.applyTemplate(MinecraftTemplates.ARCHITECTURY_FORGE_MODS_TOML_TEMPLATE, props) - } - - fun applyPackMcmeta( - project: Project, - artifactId: String, - pack: ForgePackDescriptor, - additionalData: ForgePackAdditionalData? - ): String { - val props = mapOf( - "ARTIFACT_ID" to artifactId, - "PACK_FORMAT" to pack.format.toString(), - "PACK_COMMENT" to pack.comment, - "FORGE_DATA" to additionalData, - ) - - return project.applyTemplate(MinecraftTemplates.ARCHITECTURY_FORGE_PACK_MCMETA_TEMPLATE, props) - } - - fun applyCommonMixinConfigTemplate( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - val packageName = buildSystem.groupId.toPackageName() + "." + buildSystem.artifactId - val props = mapOf( - "PACKAGE_NAME" to packageName, - "JAVA_VERSION" to config.javaVersion.feature - ) - return project.applyTemplate(MinecraftTemplates.ARCHITECTURY_COMMON_MIXINS_JSON_TEMPLATE, props) - } - - fun applyForgeMixinConfigTemplate( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - val packageName = buildSystem.groupId.toPackageName() + "." + buildSystem.artifactId - val props = mapOf( - "PACKAGE_NAME" to packageName, - "JAVA_VERSION" to config.javaVersion.feature - ) - return project.applyTemplate(MinecraftTemplates.ARCHITECTURY_FORGE_MIXINS_JSON_TEMPLATE, props) - } - - fun applyFabricMixinConfigTemplate( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig - ): String { - val packageName = buildSystem.groupId.toPackageName() + "." + buildSystem.artifactId - val props = mapOf( - "PACKAGE_NAME" to packageName, - "JAVA_VERSION" to config.javaVersion.feature - ) - return project.applyTemplate(MinecraftTemplates.ARCHITECTURY_FABRIC_MIXINS_JSON_TEMPLATE, props) - } - - fun applyCommonMainClass( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig, - packageName: String, - className: String - ): String { - val props = mapOf( - "PACKAGE_NAME" to packageName, - "CLASS_NAME" to className, - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "MOD_VERSION" to buildSystem.version - ) - - return project.applyTemplate(MinecraftTemplates.ARCHITECTURY_COMMON_MAIN_CLASS_TEMPLATE, props) - } - - fun applyForgeMainClass( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig, - packageName: String, - className: String - ): String { - val props = mutableMapOf( - "PACKAGE_NAME" to packageName, - "CLASS_NAME" to className, - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "MOD_VERSION" to buildSystem.version, - "ARCHITECTURY_PACKAGE" to config.architecturyPackage - ) - - if (config.architecturyApi) { - props["ARCHITECTURY_API"] = "true" - } - - return project.applyTemplate(MinecraftTemplates.ARCHITECTURY_FORGE_MAIN_CLASS_TEMPLATE, props) - } - - fun applyFabricMainClass( - project: Project, - buildSystem: BuildSystem, - config: ArchitecturyProjectConfig, - packageName: String, - className: String - ): String { - val props = mapOf( - "PACKAGE_NAME" to packageName, - "CLASS_NAME" to className, - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "MOD_VERSION" to buildSystem.version - ) - - return project.applyTemplate(MinecraftTemplates.ARCHITECTURY_FABRIC_MAIN_CLASS_TEMPLATE, props) - } -} diff --git a/src/main/kotlin/platform/architectury/creator/asset-steps.kt b/src/main/kotlin/platform/architectury/creator/asset-steps.kt new file mode 100644 index 000000000..702efa4db --- /dev/null +++ b/src/main/kotlin/platform/architectury/creator/asset-steps.kt @@ -0,0 +1,237 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.architectury.creator + +import com.demonwav.mcdev.creator.JdkProjectSetupFinalizer +import com.demonwav.mcdev.creator.addLicense +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.AbstractRunBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModNameStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.IssueTrackerStep +import com.demonwav.mcdev.creator.step.LicenseStep +import com.demonwav.mcdev.creator.step.UseMixinsStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.platform.architectury.ArchitecturyVersion +import com.demonwav.mcdev.platform.fabric.util.FabricApiVersions +import com.demonwav.mcdev.platform.fabric.util.FabricVersions +import com.demonwav.mcdev.platform.forge.util.ForgeConstants +import com.demonwav.mcdev.platform.forge.util.ForgePackAdditionalData +import com.demonwav.mcdev.platform.forge.util.ForgePackDescriptor +import com.demonwav.mcdev.platform.forge.version.ForgeVersion +import com.demonwav.mcdev.util.MinecraftTemplates +import com.demonwav.mcdev.util.SemanticVersion +import com.demonwav.mcdev.util.toJavaClassName +import com.demonwav.mcdev.util.toPackageName +import com.intellij.ide.starters.local.GeneratorEmptyDirectory +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.project.Project + +class ArchitecturyVersionData( + val forgeVersions: ForgeVersion, + val fabricVersions: FabricVersions, + val fabricApiVersions: FabricApiVersions, + val architecturyVersions: ArchitecturyVersion, +) + +private val NewProjectWizardStep.architecturyPackage: String get() { + val apiVersion = data.getUserData(ArchitecturyVersionChainStep.ARCHITECTURY_API_VERSION_KEY) + return when { + apiVersion == null || apiVersion >= SemanticVersion.release(2, 0, 10) -> "dev.architectury" + else -> "me.shedaniel.architectury" + } +} + +class ArchitecturyProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Adding Architectury project files (phase 1)" + + override fun setupAssets(project: Project) { + val buildSystemProps = findStep>() + val useMixins = data.getUserData(UseMixinsStep.KEY) ?: false + val javaVersion = findStep().preferredJdk.ordinal + val packageName = "${buildSystemProps.groupId.toPackageName()}.${buildSystemProps.artifactId.toPackageName()}" + val mcVersion = data.getUserData(ArchitecturyVersionChainStep.MC_VERSION_KEY) ?: return + val modName = data.getUserData(AbstractModNameStep.KEY) ?: return + val forgeVersion = data.getUserData(ArchitecturyVersionChainStep.FORGE_VERSION_KEY) ?: return + val fabricLoaderVersion = data.getUserData(ArchitecturyVersionChainStep.FABRIC_LOADER_VERSION_KEY) ?: return + val fabricApiVersion = data.getUserData(ArchitecturyVersionChainStep.FABRIC_API_VERSION_KEY) + val archApiVersion = data.getUserData(ArchitecturyVersionChainStep.ARCHITECTURY_API_VERSION_KEY) + val license = data.getUserData(LicenseStep.KEY) ?: return + val authors = data.getUserData(AuthorsStep.KEY) ?: emptyList() + val website = data.getUserData(WebsiteStep.KEY) ?: "" + val issueTracker = data.getUserData(IssueTrackerStep.KEY) ?: "" + val description = data.getUserData(DescriptionStep.KEY) ?: "" + + val hasDisplayTestInManifest = forgeVersion >= ForgeConstants.DISPLAY_TEST_MANIFEST_VERSION + val nextMcVersion = when (val part = mcVersion.parts.getOrNull(1)) { + // Mimics the code used to get the next Minecraft version in Forge's MDK + // https://github.com/MinecraftForge/MinecraftForge/blob/0ff8a596fc1ef33d4070be89dd5cb4851f93f731/build.gradle#L884 + is SemanticVersion.Companion.VersionPart.ReleasePart -> (part.version + 1).toString() + null -> "?" + else -> part.versionString + } + + assets.addAssets( + GeneratorEmptyDirectory("common/src/main/java"), + GeneratorEmptyDirectory("common/src/main/resources"), + GeneratorEmptyDirectory("forge/src/main/java"), + GeneratorEmptyDirectory("forge/src/main/resources"), + GeneratorEmptyDirectory("fabric/src/main/java"), + GeneratorEmptyDirectory("fabric/src/main/resources"), + ) + + val packDescriptor = ForgePackDescriptor.forMcVersion(mcVersion) ?: ForgePackDescriptor.FORMAT_3 + val packAdditionalData = ForgePackAdditionalData.forMcVersion(mcVersion) + + assets.addTemplateProperties( + "ARTIFACT_ID" to buildSystemProps.artifactId, + "PACK_FORMAT" to packDescriptor.format, + "PACK_COMMENT" to packDescriptor.comment, + "PACKAGE_NAME" to packageName, + "JAVA_VERSION" to javaVersion, + "MOD_NAME" to modName, + "DISPLAY_TEST" to hasDisplayTestInManifest, + "FORGE_SPEC_VERSION" to forgeVersion.parts[0].versionString, + "MC_VERSION" to mcVersion, + "MC_NEXT_VERSION" to "1.$nextMcVersion", + "LICENSE" to license, + "DESCRIPTION" to description, + "MOD_DESCRIPTION" to description, + "MOD_ENVIRONMENT" to "*", + "FABRIC_LOADER_VERSION" to fabricLoaderVersion, + ) + + if (fabricApiVersion != null) { + assets.addTemplateProperties( + "FABRIC_API_VERSION" to fabricApiVersion, + ) + } + + if (archApiVersion != null) { + assets.addTemplateProperties( + "ARCHITECTURY_API_VERSION" to archApiVersion, + ) + } + + if (authors.isNotEmpty()) { + assets.addTemplateProperties("AUTHOR_LIST" to authors.joinToString(", ")) + } + + if (website.isNotBlank()) { + assets.addTemplateProperties("WEBSITE" to website) + } + + if (issueTracker.isNotBlank()) { + assets.addTemplateProperties("ISSUE" to issueTracker) + } + + if (packAdditionalData != null) { + assets.addTemplateProperties( + "FORGE_DATA" to packAdditionalData, + ) + } + + if (useMixins) { + assets.addTemplateProperties( + "MIXINS" to "true", + ) + val commonMixinsFile = "common/src/main/resources/${buildSystemProps.artifactId}-common.mixins.json" + val forgeMixinsFile = "forge/src/main/resources/${buildSystemProps.artifactId}.mixins.json" + val fabricMixinsFile = "fabric/src/main/resources/${buildSystemProps.artifactId}.mixins.json" + assets.addTemplates( + project, + commonMixinsFile to MinecraftTemplates.ARCHITECTURY_COMMON_MIXINS_JSON_TEMPLATE, + forgeMixinsFile to MinecraftTemplates.ARCHITECTURY_FORGE_MIXINS_JSON_TEMPLATE, + fabricMixinsFile to MinecraftTemplates.ARCHITECTURY_FABRIC_MIXINS_JSON_TEMPLATE, + ) + } + + assets.addTemplates( + project, + "forge/src/main/resources/pack.mcmeta" to MinecraftTemplates.ARCHITECTURY_FORGE_PACK_MCMETA_TEMPLATE, + "forge/src/main/resources/META-INF/mods.toml" to MinecraftTemplates.ARCHITECTURY_FORGE_MODS_TOML_TEMPLATE, + "fabric/src/main/resources/fabric.mod.json" to MinecraftTemplates.ARCHITECTURY_FABRIC_MOD_JSON_TEMPLATE, + ) + + assets.addLicense(project) + } +} + +abstract class ArchitecturyMainClassStep( + parent: NewProjectWizardStep, + phase: Int, +) : AbstractLongRunningAssetsStep(parent) { + abstract val projectDir: String + abstract val template: String + abstract fun getClassName(packageName: String, className: String): String + + override val description = "Adding Architectury project files (phase $phase)" + + override fun setupAssets(project: Project) { + val buildSystemProps = findStep>() + val modName = data.getUserData(AbstractModNameStep.KEY) ?: return + val useArchApi = data.getUserData(ArchitecturyVersionChainStep.ARCHITECTURY_API_VERSION_KEY) != null + + val packageName = "${buildSystemProps.groupId.toPackageName()}.${buildSystemProps.artifactId.toPackageName()}" + val className = modName.toJavaClassName() + assets.addTemplateProperties( + "PACKAGE_NAME" to packageName, + "CLASS_NAME" to className, + "ARTIFACT_ID" to buildSystemProps.artifactId, + "MOD_NAME" to modName, + "MOD_VERSION" to buildSystemProps.version, + "ARCHITECTURY_PACKAGE" to architecturyPackage, + ) + if (useArchApi) { + assets.addTemplateProperties("ARCHITECTURY_API" to "true") + } + + val mainClass = getClassName(packageName, className) + assets.addTemplates(project, "$projectDir/src/main/java/${mainClass.replace('.', '/')}.java" to template) + } +} + +class ArchitecturyCommonMainClassStep(parent: NewProjectWizardStep) : ArchitecturyMainClassStep(parent, 2) { + override val projectDir = "common" + override val template = MinecraftTemplates.ARCHITECTURY_COMMON_MAIN_CLASS_TEMPLATE + + override fun getClassName(packageName: String, className: String) = "$packageName.$className" +} + +class ArchitecturyForgeMainClassStep(parent: NewProjectWizardStep) : ArchitecturyMainClassStep(parent, 3) { + override val projectDir = "forge" + override val template = MinecraftTemplates.ARCHITECTURY_FORGE_MAIN_CLASS_TEMPLATE + + override fun getClassName(packageName: String, className: String) = "$packageName.forge.${className}Forge" +} + +class ArchitecturyFabricMainClassStep(parent: NewProjectWizardStep) : ArchitecturyMainClassStep(parent, 4) { + override val projectDir = "fabric" + override val template = MinecraftTemplates.ARCHITECTURY_FABRIC_MAIN_CLASS_TEMPLATE + + override fun getClassName(packageName: String, className: String) = "$packageName.fabric.${className}Fabric" +} + +class ArchitecturyBuildSystemStep(parent: NewProjectWizardStep) : AbstractBuildSystemStep(parent) { + override val platformName = "Architectury" +} + +class ArchitecturyPostBuildSystemStep( + parent: NewProjectWizardStep, +) : AbstractRunBuildSystemStep(parent, ArchitecturyBuildSystemStep::class.java) { + override val step = BuildSystemSupport.POST_STEP +} diff --git a/src/main/kotlin/platform/architectury/creator/gradle-steps.kt b/src/main/kotlin/platform/architectury/creator/gradle-steps.kt new file mode 100644 index 000000000..af0e0465e --- /dev/null +++ b/src/main/kotlin/platform/architectury/creator/gradle-steps.kt @@ -0,0 +1,108 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.architectury.creator + +import com.demonwav.mcdev.creator.EmptyStep +import com.demonwav.mcdev.creator.JdkProjectSetupFinalizer +import com.demonwav.mcdev.creator.addGradleGitignore +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.buildsystem.GradleImportStep +import com.demonwav.mcdev.creator.buildsystem.GradleWrapperStep +import com.demonwav.mcdev.creator.buildsystem.addGradleWrapperProperties +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.gitEnabled +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModNameStep +import com.demonwav.mcdev.util.MinecraftTemplates +import com.demonwav.mcdev.util.SemanticVersion +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.project.Project + +private val NewProjectWizardStep.architecturyGroup: String get() { + val apiVersion = data.getUserData(ArchitecturyVersionChainStep.ARCHITECTURY_API_VERSION_KEY) + return when { + apiVersion == null || apiVersion >= SemanticVersion.release(2, 0, 10) -> "dev.architectury" + else -> "me.shedaniel" + } +} + +class ArchitecturyGradleSupport : BuildSystemSupport { + override val preferred = true + + override fun createStep(step: String, parent: NewProjectWizardStep): NewProjectWizardStep { + return when (step) { + BuildSystemSupport.PRE_STEP -> ArchitecturyGradleFilesStep(parent).chain(::GradleWrapperStep) + BuildSystemSupport.POST_STEP -> GradleImportStep(parent) + else -> EmptyStep(parent) + } + } +} + +class ArchitecturyGradleFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating Gradle files" + + override fun setupAssets(project: Project) { + val buildSystemProps = findStep>() + val modName = data.getUserData(AbstractModNameStep.KEY) ?: return + val mcVersion = data.getUserData(ArchitecturyVersionChainStep.MC_VERSION_KEY) ?: return + val forgeVersion = data.getUserData(ArchitecturyVersionChainStep.FORGE_VERSION_KEY) ?: return + val fabricLoaderVersion = data.getUserData(ArchitecturyVersionChainStep.FABRIC_LOADER_VERSION_KEY) ?: return + val fabricApiVersion = data.getUserData(ArchitecturyVersionChainStep.FABRIC_API_VERSION_KEY) + val archApiVersion = data.getUserData(ArchitecturyVersionChainStep.ARCHITECTURY_API_VERSION_KEY) + val javaVersion = findStep().preferredJdk.ordinal + + assets.addTemplateProperties( + "GROUP_ID" to buildSystemProps.groupId, + "ARTIFACT_ID" to buildSystemProps.artifactId, + "MOD_NAME" to modName, + "VERSION" to buildSystemProps.version, + "MC_VERSION" to mcVersion, + "FORGE_VERSION" to "$mcVersion-$forgeVersion", + "FABRIC_LOADER_VERSION" to fabricLoaderVersion, + "ARCHITECTURY_GROUP" to architecturyGroup, + "JAVA_VERSION" to javaVersion, + ) + + if (fabricApiVersion != null) { + assets.addTemplateProperties( + "FABRIC_API_VERSION" to fabricApiVersion, + "FABRIC_API" to "true", + ) + } + + if (archApiVersion != null) { + assets.addTemplateProperties( + "ARCHITECTURY_API_VERSION" to archApiVersion, + "ARCHITECTURY_API" to "true", + ) + } + + assets.addTemplates( + project, + "build.gradle" to MinecraftTemplates.ARCHITECTURY_BUILD_GRADLE_TEMPLATE, + "gradle.properties" to MinecraftTemplates.ARCHITECTURY_GRADLE_PROPERTIES_TEMPLATE, + "settings.gradle" to MinecraftTemplates.ARCHITECTURY_SETTINGS_GRADLE_TEMPLATE, + "common/build.gradle" to MinecraftTemplates.ARCHITECTURY_COMMON_BUILD_GRADLE_TEMPLATE, + "forge/build.gradle" to MinecraftTemplates.ARCHITECTURY_FORGE_BUILD_GRADLE_TEMPLATE, + "forge/gradle.properties" to MinecraftTemplates.ARCHITECTURY_FORGE_GRADLE_PROPERTIES_TEMPLATE, + "fabric/build.gradle" to MinecraftTemplates.ARCHITECTURY_FABRIC_BUILD_GRADLE_TEMPLATE, + ) + + assets.addGradleWrapperProperties(project) + + if (gitEnabled) { + assets.addGradleGitignore(project) + } + } +} diff --git a/src/main/kotlin/platform/architectury/creator/ui-steps.kt b/src/main/kotlin/platform/architectury/creator/ui-steps.kt new file mode 100644 index 000000000..9ff419b2c --- /dev/null +++ b/src/main/kotlin/platform/architectury/creator/ui-steps.kt @@ -0,0 +1,202 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.architectury.creator + +import com.demonwav.mcdev.creator.chain +import com.demonwav.mcdev.creator.platformtype.ModPlatformStep +import com.demonwav.mcdev.creator.step.AbstractCollapsibleStep +import com.demonwav.mcdev.creator.step.AbstractLatentStep +import com.demonwav.mcdev.creator.step.AbstractMcVersionChainStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.IssueTrackerStep +import com.demonwav.mcdev.creator.step.LicenseStep +import com.demonwav.mcdev.creator.step.ModNameStep +import com.demonwav.mcdev.creator.step.RepositoryStep +import com.demonwav.mcdev.creator.step.UseMixinsStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.platform.architectury.ArchitecturyVersion +import com.demonwav.mcdev.platform.fabric.util.FabricApiVersions +import com.demonwav.mcdev.platform.fabric.util.FabricVersions +import com.demonwav.mcdev.platform.forge.version.ForgeVersion +import com.demonwav.mcdev.util.SemanticVersion +import com.demonwav.mcdev.util.asyncIO +import com.demonwav.mcdev.util.bindEnabled +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.observable.util.bindBooleanStorage +import com.intellij.openapi.observable.util.transform +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.ComboBox +import com.intellij.openapi.util.Key +import com.intellij.ui.JBColor +import com.intellij.ui.dsl.builder.Cell +import com.intellij.ui.dsl.builder.Row +import com.intellij.ui.dsl.builder.bindSelected +import com.intellij.ui.dsl.builder.bindText +import com.intellij.util.IncorrectOperationException +import kotlinx.coroutines.coroutineScope + +class ArchitecturyPlatformStep(parent: ModPlatformStep) : AbstractLatentStep(parent) { + override val description = "download Forge, Fabric and Architectury versions" + + override suspend fun computeData() = coroutineScope { + val forgeJob = asyncIO { ForgeVersion.downloadData() } + val fabricJob = asyncIO { FabricVersions.downloadData() } + val fabricApiJob = asyncIO { FabricApiVersions.downloadData() } + val archJob = asyncIO { ArchitecturyVersion.downloadData() } + + val forge = forgeJob.await() ?: return@coroutineScope null + val fabric = fabricJob.await() ?: return@coroutineScope null + val fabricApi = fabricApiJob.await() ?: return@coroutineScope null + val arch = archJob.await() ?: return@coroutineScope null + + ArchitecturyVersionData(forge, fabric, fabricApi, arch) + } + + override fun createStep(data: ArchitecturyVersionData): NewProjectWizardStep { + return ArchitecturyVersionChainStep(this, data).chain( + ::UseMixinsStep, + ::ModNameStep, + ::LicenseStep, + ::ArchitecturyOptionalSettingsStep, + ::ArchitecturyBuildSystemStep, + ::ArchitecturyProjectFilesStep, + ::ArchitecturyCommonMainClassStep, + ::ArchitecturyForgeMainClassStep, + ::ArchitecturyFabricMainClassStep, + ::ArchitecturyPostBuildSystemStep, + ) + } + + class Factory : ModPlatformStep.Factory { + override val name = "Architectury" + override fun createStep(parent: ModPlatformStep) = ArchitecturyPlatformStep(parent) + } +} + +class ArchitecturyVersionChainStep( + parent: NewProjectWizardStep, + private val versionData: ArchitecturyVersionData, +) : AbstractMcVersionChainStep( + parent, + "Forge Version:", + "Fabric Loader Version:", + "Fabric API Version:", + "Architectury API Version:", +) { + companion object { + private const val FORGE_VERSION = 1 + private const val FABRIC_LOADER_VERSION = 2 + private const val FABRIC_API_VERSION = 3 + private const val ARCHITECTURY_API_VERSION = 4 + + val MC_VERSION_KEY = + Key.create("${ArchitecturyVersionChainStep::class.java.name}.mcVersion") + val FORGE_VERSION_KEY = + Key.create("${ArchitecturyVersionChainStep::class.java.name}.forgeVersion") + val FABRIC_LOADER_VERSION_KEY = + Key.create("${ArchitecturyVersionChainStep::class.java.name}.fabricLoaderVersion") + val FABRIC_API_VERSION_KEY = + Key.create("${ArchitecturyVersionChainStep::class.java.name}.fabricApiVersion") + val ARCHITECTURY_API_VERSION_KEY = + Key.create("${ArchitecturyVersionChainStep::class.java.name}.architecturyApiVersion") + } + + private val mcVersions by lazy { + versionData.architecturyVersions.versions.keys + .intersect(versionData.forgeVersions.sortedMcVersions.toSet()) + .intersect( + versionData.fabricVersions.game.mapNotNullTo(mutableSetOf()) { + SemanticVersion.tryParse(it.version) + }, + ) + .toList() + } + + private val useFabricApiProperty = propertyGraph.property(true) + .bindBooleanStorage("${javaClass.name}.useFabricApi") + private var useFabricApi by useFabricApiProperty + + private val useArchApiProperty = propertyGraph.property(true) + .bindBooleanStorage("${javaClass.name}.useArchApi") + private var useArchApi by useArchApiProperty + + override fun createComboBox(row: Row, index: Int, items: List>): Cell>> { + return when (index) { + FABRIC_API_VERSION -> { + val comboBox = super.createComboBox(row, index, items).bindEnabled(useFabricApiProperty) + row.checkBox("Use Fabric API").bindSelected(useFabricApiProperty) + row.label("").bindText( + getVersionProperty(MINECRAFT_VERSION).transform { mcVersion -> + val versionStr = mcVersion.toString() + val matched = versionData.fabricApiVersions.versions.any { versionStr in it.gameVersions } + if (matched) { + "" + } else { + "Unable to match API versions to Minecraft version" + } + }, + ).bindEnabled(useFabricApiProperty).component.foreground = JBColor.YELLOW + comboBox + } + ARCHITECTURY_API_VERSION -> { + val comboBox = super.createComboBox(row, index, items).bindEnabled(useArchApiProperty) + row.checkBox("Use Architectury API").bindSelected(useArchApiProperty) + comboBox + } + else -> super.createComboBox(row, index, items) + } + } + + override fun getAvailableVersions(versionsAbove: List>): List> { + val mcVersion by lazy { versionsAbove[MINECRAFT_VERSION] as SemanticVersion } + + return when (versionsAbove.size) { + MINECRAFT_VERSION -> mcVersions + FORGE_VERSION -> versionData.forgeVersions.getForgeVersions(mcVersion) + FABRIC_LOADER_VERSION -> versionData.fabricVersions.loader + FABRIC_API_VERSION -> { + val versionStr = mcVersion.toString() + val apiVersions = versionData.fabricApiVersions.versions + .filter { versionStr in it.gameVersions } + .map { it.version } + apiVersions.ifEmpty { versionData.fabricApiVersions.versions.map { it.version } } + } + ARCHITECTURY_API_VERSION -> versionData.architecturyVersions.getArchitecturyVersions(mcVersion) + else -> throw IncorrectOperationException() + } + } + + override fun setupProject(project: Project) { + super.setupProject(project) + data.putUserData(MC_VERSION_KEY, getVersion(MINECRAFT_VERSION) as SemanticVersion) + data.putUserData(FORGE_VERSION_KEY, getVersion(FORGE_VERSION) as SemanticVersion) + data.putUserData(FABRIC_LOADER_VERSION_KEY, getVersion(FABRIC_LOADER_VERSION) as SemanticVersion) + if (useFabricApi) { + data.putUserData(FABRIC_API_VERSION_KEY, getVersion(FABRIC_API_VERSION) as SemanticVersion) + } + if (useArchApi) { + data.putUserData(ARCHITECTURY_API_VERSION_KEY, getVersion(ARCHITECTURY_API_VERSION) as SemanticVersion) + } + } +} + +class ArchitecturyOptionalSettingsStep(parent: NewProjectWizardStep) : AbstractCollapsibleStep(parent) { + override val title = "Optional Settings" + + override fun createStep() = DescriptionStep(this).chain( + ::AuthorsStep, + ::WebsiteStep, + ::RepositoryStep, + ::IssueTrackerStep, + ) +} diff --git a/src/main/kotlin/platform/architectury/framework/ArchitecturyGradleData.kt b/src/main/kotlin/platform/architectury/framework/ArchitecturyGradleData.kt index b81a66e8e..fb5c299cb 100644 --- a/src/main/kotlin/platform/architectury/framework/ArchitecturyGradleData.kt +++ b/src/main/kotlin/platform/architectury/framework/ArchitecturyGradleData.kt @@ -18,7 +18,7 @@ import com.intellij.openapi.externalSystem.model.project.ModuleData data class ArchitecturyGradleData( val module: ModuleData, - val moduleType: ArchitecturyModel.ModuleType + val moduleType: ArchitecturyModel.ModuleType, ) : AbstractExternalEntityData(module.owner) { companion object { val KEY = Key.create(ArchitecturyGradleData::class.java, ProjectKeys.TASK.processingWeight + 1) diff --git a/src/main/kotlin/platform/architectury/framework/ArchitecturyPresentationProvider.kt b/src/main/kotlin/platform/architectury/framework/ArchitecturyPresentationProvider.kt index 9c3957d80..978503b0b 100644 --- a/src/main/kotlin/platform/architectury/framework/ArchitecturyPresentationProvider.kt +++ b/src/main/kotlin/platform/architectury/framework/ArchitecturyPresentationProvider.kt @@ -18,7 +18,7 @@ import com.intellij.openapi.vfs.VirtualFile import java.util.jar.JarFile class ArchitecturyPresentationProvider : LibraryPresentationProvider( - ARCHITECTURY_LIBRARY_KIND + ARCHITECTURY_LIBRARY_KIND, ) { override fun getIcon(properties: LibraryVersionProperties?) = PlatformAssets.ARCHITECTURY_ICON diff --git a/src/main/kotlin/platform/architectury/version/FabricVersion.kt b/src/main/kotlin/platform/architectury/version/FabricVersion.kt deleted file mode 100644 index 7cc8eb90c..000000000 --- a/src/main/kotlin/platform/architectury/version/FabricVersion.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.architectury.version - -import com.demonwav.mcdev.util.SemanticVersion -import com.extracraftx.minecraft.templatemakerfabric.data.DataProvider -import com.extracraftx.minecraft.templatemakerfabric.data.holders.LoaderVersion -import com.intellij.openapi.diagnostic.logger -import java.io.IOException - -class FabricVersion private constructor(val versions: DataProvider) { - - fun getFabricVersions(mcVersion: SemanticVersion): List { - val versionText = mcVersion.toString() - return versions.getFilteredLoaderVersions( - versions.getDefaultLoomVersion( - versions.getFilteredYarnVersions( - versions.getNormalizedMinecraftVersion(versionText) - ).firstOrNull() - ) - ) - .map { loaderVersion: LoaderVersion -> - SemanticVersion.parse(loaderVersion.toString()) - } - .sortedDescending() - .take(50) - .toList() - } - - fun getFabricApiVersions(mcVersion: SemanticVersion): List { - val versionText = mcVersion.toString() - return versions.sortedFabricApiVersions.filter { indexedFabricApiVersion -> - indexedFabricApiVersion.mcVersion.equals( - versionText - ) - }.map { indexedFabricApiVersion -> SemanticVersion.parse(indexedFabricApiVersion.mavenVersion) } - .sortedDescending().take(50) - } - - companion object { - private val LOGGER = logger() - private val dataProvider: DataProvider = DataProvider() - - fun downloadData(): FabricVersion? { - try { - dataProvider.loaderVersions - dataProvider.loomVersions - dataProvider.yarnVersions - dataProvider.fabricApiVersions - return FabricVersion(dataProvider) - } catch (e: IOException) { - LOGGER.error("Failed to retrieve Fabric version data", e) - } - return null - } - } -} diff --git a/src/main/kotlin/platform/bukkit/BukkitModule.kt b/src/main/kotlin/platform/bukkit/BukkitModule.kt index f5f33677b..49cc425c7 100644 --- a/src/main/kotlin/platform/bukkit/BukkitModule.kt +++ b/src/main/kotlin/platform/bukkit/BukkitModule.kt @@ -20,6 +20,7 @@ import com.demonwav.mcdev.platform.bukkit.generation.BukkitGenerationData import com.demonwav.mcdev.platform.bukkit.util.BukkitConstants import com.demonwav.mcdev.util.SourceType import com.demonwav.mcdev.util.addImplements +import com.demonwav.mcdev.util.createVoidMethodWithParameterType import com.demonwav.mcdev.util.extendsOrImplements import com.demonwav.mcdev.util.findContainingMethod import com.demonwav.mcdev.util.nullable @@ -27,18 +28,15 @@ import com.intellij.lang.jvm.JvmModifier import com.intellij.openapi.project.Project import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiClass -import com.intellij.psi.PsiClassType import com.intellij.psi.PsiElement import com.intellij.psi.PsiLiteralExpression import com.intellij.psi.PsiMethod import com.intellij.psi.PsiMethodCallExpression -import com.intellij.psi.PsiType -import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.uast.UClass import org.jetbrains.uast.UIdentifier import org.jetbrains.uast.toUElementOfType -class BukkitModule> constructor(facet: MinecraftFacet, type: T) : AbstractModule(facet) { +class BukkitModule>(facet: MinecraftFacet, type: T) : AbstractModule(facet) { var pluginYml by nullable { facet.findFile("plugin.yml", SourceType.RESOURCE) } private set @@ -66,7 +64,7 @@ class BukkitModule> constructor(facet: MinecraftFa containingClass: PsiClass, chosenClass: PsiClass, chosenName: String, - data: GenerationData? + data: GenerationData?, ): PsiMethod? { val bukkitData = data as BukkitGenerationData @@ -75,7 +73,7 @@ class BukkitModule> constructor(facet: MinecraftFa chosenName, project, BukkitConstants.HANDLER_ANNOTATION, - bukkitData.isIgnoreCanceled + bukkitData.isIgnoreCanceled, ) ?: return null if (bukkitData.eventPriority != "NORMAL") { @@ -85,7 +83,7 @@ class BukkitModule> constructor(facet: MinecraftFa val value = JavaPsiFacade.getElementFactory(project) .createExpressionFromText( BukkitConstants.EVENT_PRIORITY_CLASS + "." + bukkitData.eventPriority, - annotation + annotation, ) annotation.setDeclaredAttributeValue("priority", value) @@ -147,10 +145,10 @@ class BukkitModule> constructor(facet: MinecraftFa expression.replace( JavaPsiFacade.getElementFactory(project).createExpressionFromText( "false", - expression - ) + expression, + ), ) - } + }, ) } @@ -180,19 +178,9 @@ class BukkitModule> constructor(facet: MinecraftFa chosenName: String, project: Project, annotationName: String, - setIgnoreCancelled: Boolean + setIgnoreCancelled: Boolean, ): PsiMethod? { - val newMethod = JavaPsiFacade.getElementFactory(project).createMethod(chosenName, PsiType.VOID) - - val list = newMethod.parameterList - val qName = chosenClass.qualifiedName ?: return null - val parameter = JavaPsiFacade.getElementFactory(project) - .createParameter( - "event", - PsiClassType.getTypeByName(qName, project, GlobalSearchScope.allScope(project)) - ) - list.add(parameter) - + val newMethod = createVoidMethodWithParameterType(project, chosenName, chosenClass) ?: return null val modifierList = newMethod.modifierList val annotation = modifierList.addAnnotation(annotationName) diff --git a/src/main/kotlin/platform/bukkit/creator/BukkitProjectConfig.kt b/src/main/kotlin/platform/bukkit/creator/BukkitProjectConfig.kt deleted file mode 100644 index af7395fe1..000000000 --- a/src/main/kotlin/platform/bukkit/creator/BukkitProjectConfig.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.bukkit.creator - -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.ProjectCreator -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleCreator -import com.demonwav.mcdev.creator.buildsystem.maven.MavenBuildSystem -import com.demonwav.mcdev.creator.buildsystem.maven.MavenCreator -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.platform.bukkit.BukkitLikeConfiguration -import com.demonwav.mcdev.platform.bukkit.data.LoadOrder -import com.demonwav.mcdev.util.MinecraftVersions -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.VersionRange -import com.intellij.openapi.module.Module -import com.intellij.util.lang.JavaVersion -import java.nio.file.Path - -class BukkitProjectConfig(override var type: PlatformType) : - ProjectConfig(), BukkitLikeConfiguration, MavenCreator, GradleCreator { - - override lateinit var mainClass: String - - var loadOrder: LoadOrder = LoadOrder.POSTWORLD - var minecraftVersion: String = "" - val semanticMinecraftVersion: SemanticVersion - get() = if (minecraftVersion.isBlank()) SemanticVersion.release() else SemanticVersion.parse(minecraftVersion) - - var prefix: String? = null - fun hasPrefix() = prefix?.isNotBlank() == true - - var loadBefore: MutableList = mutableListOf() - fun hasLoadBefore() = listContainsAtLeastOne(loadBefore) - fun setLoadBefore(string: String) { - loadBefore.clear() - loadBefore.addAll(commaSplit(string)) - } - - override val dependencies = mutableListOf() - override fun hasDependencies() = listContainsAtLeastOne(dependencies) - override fun setDependencies(string: String) { - dependencies.clear() - dependencies.addAll(commaSplit(string)) - } - - override val softDependencies = mutableListOf() - override fun hasSoftDependencies() = listContainsAtLeastOne(softDependencies) - override fun setSoftDependencies(string: String) { - softDependencies.clear() - softDependencies.addAll(commaSplit(string)) - } - - override val preferredBuildSystem = BuildSystemType.MAVEN - - override val javaVersion: JavaVersion - get() = MinecraftVersions.requiredJavaVersion(semanticMinecraftVersion) - - override val compatibleGradleVersions: VersionRange? = null - - override fun buildMavenCreator( - rootDirectory: Path, - module: Module, - buildSystem: MavenBuildSystem - ): ProjectCreator { - return BukkitMavenCreator(rootDirectory, module, buildSystem, this) - } - - override fun buildGradleCreator( - rootDirectory: Path, - module: Module, - buildSystem: GradleBuildSystem - ): ProjectCreator { - return BukkitGradleCreator(rootDirectory, module, buildSystem, this) - } -} diff --git a/src/main/kotlin/platform/bukkit/creator/BukkitProjectCreator.kt b/src/main/kotlin/platform/bukkit/creator/BukkitProjectCreator.kt deleted file mode 100644 index d3bdcd888..000000000 --- a/src/main/kotlin/platform/bukkit/creator/BukkitProjectCreator.kt +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.bukkit.creator - -import com.demonwav.mcdev.creator.BaseProjectCreator -import com.demonwav.mcdev.creator.BasicJavaClassStep -import com.demonwav.mcdev.creator.CreateDirectoriesStep -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.buildsystem.BuildDependency -import com.demonwav.mcdev.creator.buildsystem.BuildRepository -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.BasicGradleFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleFiles -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleGitignoreStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleSetupStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleWrapperStep -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenStep -import com.demonwav.mcdev.creator.buildsystem.maven.MavenBuildSystem -import com.demonwav.mcdev.creator.buildsystem.maven.MavenGitignoreStep -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.util.MinecraftVersions -import com.demonwav.mcdev.util.SemanticVersion -import com.intellij.openapi.module.Module -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.project.Project -import java.nio.file.Path - -sealed class BukkitProjectCreator( - protected val rootDirectory: Path, - protected val rootModule: Module, - protected val buildSystem: T, - protected val config: BukkitProjectConfig -) : BaseProjectCreator(rootModule, buildSystem) { - - protected fun setupMainClassStep(): BasicJavaClassStep { - return createJavaClassStep(config.mainClass) { packageName, className -> - BukkitTemplate.applyMainClass(project, packageName, className) - } - } - - protected fun setupDependencyStep(): BukkitDependenciesStep { - val mcVersion = config.minecraftVersion - return BukkitDependenciesStep(buildSystem, config.type, mcVersion) - } - - protected fun setupYmlStep(): PluginYmlStep { - return PluginYmlStep(project, buildSystem, config) - } -} - -class BukkitMavenCreator( - rootDirectory: Path, - rootModule: Module, - buildSystem: MavenBuildSystem, - config: BukkitProjectConfig -) : BukkitProjectCreator(rootDirectory, rootModule, buildSystem, config) { - - override fun getSteps(): Iterable { - val pomText = BukkitTemplate.applyPom(project) - return listOf( - setupDependencyStep(), - BasicMavenStep(project, rootDirectory, buildSystem, config, pomText), - setupMainClassStep(), - setupYmlStep(), - MavenGitignoreStep(project, rootDirectory), - BasicMavenFinalizerStep(rootModule, rootDirectory) - ) - } -} - -class BukkitGradleCreator( - rootDirectory: Path, - rootModule: Module, - buildSystem: GradleBuildSystem, - config: BukkitProjectConfig -) : BukkitProjectCreator(rootDirectory, rootModule, buildSystem, config) { - - override fun getSteps(): Iterable { - val buildText = BukkitTemplate.applyBuildGradle(project, buildSystem, config) - val propText = BukkitTemplate.applyGradleProp(project) - val settingsText = BukkitTemplate.applySettingsGradle(project, buildSystem.artifactId) - val files = GradleFiles(buildText, propText, settingsText) - - return listOf( - setupDependencyStep(), - CreateDirectoriesStep(buildSystem, rootDirectory), - GradleSetupStep(project, rootDirectory, buildSystem, files), - setupMainClassStep(), - setupYmlStep(), - GradleWrapperStep(project, rootDirectory, buildSystem), - GradleGitignoreStep(project, rootDirectory), - BasicGradleFinalizerStep(rootModule, rootDirectory, buildSystem) - ) - } -} - -open class BukkitDependenciesStep( - protected val buildSystem: BuildSystem, - protected val type: PlatformType, - protected val mcVersion: String -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - when (type) { - PlatformType.PAPER -> { - buildSystem.repositories.add( - BuildRepository( - "papermc-repo", - "https://repo.papermc.io/repository/maven-public/" - ) - ) - val paperGroupId = when { - SemanticVersion.parse(mcVersion) >= MinecraftVersions.MC1_17 -> "io.papermc.paper" - else -> "com.destroystokyo.paper" - } - buildSystem.dependencies.add( - BuildDependency( - paperGroupId, - "paper-api", - "$mcVersion-R0.1-SNAPSHOT", - mavenScope = "provided", - gradleConfiguration = "compileOnly" - ) - ) - addSonatype(buildSystem.repositories) - } - PlatformType.SPIGOT -> { - spigotRepo(buildSystem.repositories) - buildSystem.dependencies.add( - BuildDependency( - "org.spigotmc", - "spigot-api", - "$mcVersion-R0.1-SNAPSHOT", - mavenScope = "provided", - gradleConfiguration = "compileOnly" - ) - ) - addSonatype(buildSystem.repositories) - } - PlatformType.BUKKIT -> { - spigotRepo(buildSystem.repositories) - buildSystem.dependencies.add( - BuildDependency( - "org.bukkit", - "bukkit", - "$mcVersion-R0.1-SNAPSHOT", - mavenScope = "provided", - gradleConfiguration = "compileOnly" - ) - ) - } - else -> {} - } - } - - protected fun addSonatype(buildRepositories: MutableList) { - buildRepositories.add(BuildRepository("sonatype", "https://oss.sonatype.org/content/groups/public/")) - } - - private fun spigotRepo(list: MutableList) { - list.add( - BuildRepository( - "spigotmc-repo", - "https://hub.spigotmc.org/nexus/content/repositories/snapshots/" - ) - ) - } -} - -class PluginYmlStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val config: BukkitProjectConfig -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val text = BukkitTemplate.applyPluginYml(project, config, buildSystem) - CreatorStep.writeTextToFile(project, buildSystem.dirsOrError.resourceDirectory, "plugin.yml", text) - } -} diff --git a/src/main/kotlin/platform/bukkit/creator/BukkitProjectSettingsWizard.form b/src/main/kotlin/platform/bukkit/creator/BukkitProjectSettingsWizard.form deleted file mode 100644 index 366497877..000000000 --- a/src/main/kotlin/platform/bukkit/creator/BukkitProjectSettingsWizard.form +++ /dev/null @@ -1,299 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/main/kotlin/platform/bukkit/creator/BukkitProjectSettingsWizard.kt b/src/main/kotlin/platform/bukkit/creator/BukkitProjectSettingsWizard.kt deleted file mode 100644 index 544ca2823..000000000 --- a/src/main/kotlin/platform/bukkit/creator/BukkitProjectSettingsWizard.kt +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.bukkit.creator - -import com.demonwav.mcdev.asset.PlatformAssets -import com.demonwav.mcdev.creator.MinecraftModuleWizardStep -import com.demonwav.mcdev.creator.MinecraftProjectCreator -import com.demonwav.mcdev.creator.ValidatedField -import com.demonwav.mcdev.creator.ValidatedFieldType.CLASS_NAME -import com.demonwav.mcdev.creator.ValidatedFieldType.LIST -import com.demonwav.mcdev.creator.ValidatedFieldType.NON_BLANK -import com.demonwav.mcdev.creator.getVersionSelector -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.platform.bukkit.data.LoadOrder -import javax.swing.JComboBox -import javax.swing.JComponent -import javax.swing.JLabel -import javax.swing.JPanel -import javax.swing.JTextField -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.swing.Swing -import kotlinx.coroutines.withContext - -class BukkitProjectSettingsWizard(private val creator: MinecraftProjectCreator) : MinecraftModuleWizardStep() { - - @ValidatedField(NON_BLANK) - private lateinit var pluginNameField: JTextField - - @ValidatedField(NON_BLANK, CLASS_NAME) - private lateinit var mainClassField: JTextField - private lateinit var panel: JPanel - private lateinit var descriptionField: JTextField - - @ValidatedField(LIST) - private lateinit var authorsField: JTextField - private lateinit var websiteField: JTextField - private lateinit var prefixField: JTextField - private lateinit var loadOrderBox: JComboBox<*> - private lateinit var loadBeforeField: JTextField - - @ValidatedField(LIST) - private lateinit var dependField: JTextField - private lateinit var softDependField: JTextField - private lateinit var title: JLabel - private lateinit var minecraftVersionBox: JComboBox - private lateinit var errorLabel: JLabel - - private var config: BukkitProjectConfig? = null - - private var versionsLoaded: Boolean = false - - override fun getComponent(): JComponent { - return panel - } - - override fun isStepVisible(): Boolean { - return creator.config is BukkitProjectConfig - } - - override fun updateStep() { - config = creator.config as? BukkitProjectConfig - if (config == null) { - return - } - val conf = config ?: return - - basicUpdateStep(creator, pluginNameField, mainClassField) - - when (conf.type) { - PlatformType.BUKKIT -> { - title.icon = PlatformAssets.BUKKIT_ICON_2X - title.text = "Bukkit Settings" - } - PlatformType.SPIGOT -> { - title.icon = PlatformAssets.SPIGOT_ICON_2X - title.text = "Spigot Settings" - } - PlatformType.PAPER -> { - title.icon = PlatformAssets.PAPER_ICON_2X - title.text = "Paper Settings" - } - else -> { - } - } - - if (versionsLoaded) { - return - } - - versionsLoaded = true - CoroutineScope(Dispatchers.Swing).launch { - try { - withContext(Dispatchers.IO) { getVersionSelector(conf.type) }.set(minecraftVersionBox) - } catch (e: Exception) { - errorLabel.isVisible = true - } - } - } - - override fun validate(): Boolean { - return super.validate() && minecraftVersionBox.selectedItem != null - } - - override fun updateDataModel() { - val conf = this.config ?: return - - conf.pluginName = this.pluginNameField.text - conf.mainClass = this.mainClassField.text - conf.description = this.descriptionField.text - conf.website = this.websiteField.text - - conf.loadOrder = if (this.loadOrderBox.selectedIndex == 0) LoadOrder.POSTWORLD else LoadOrder.STARTUP - conf.prefix = this.prefixField.text - conf.minecraftVersion = this.minecraftVersionBox.selectedItem as String - - conf.setLoadBefore(this.loadBeforeField.text) - conf.setAuthors(this.authorsField.text) - conf.setDependencies(this.dependField.text) - conf.setSoftDependencies(this.softDependField.text) - } -} diff --git a/src/main/kotlin/platform/bukkit/creator/BukkitTemplate.kt b/src/main/kotlin/platform/bukkit/creator/BukkitTemplate.kt deleted file mode 100644 index 54246a387..000000000 --- a/src/main/kotlin/platform/bukkit/creator/BukkitTemplate.kt +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.bukkit.creator - -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenStep -import com.demonwav.mcdev.platform.BaseTemplate -import com.demonwav.mcdev.platform.bukkit.BukkitLikeConfiguration -import com.demonwav.mcdev.platform.bukkit.BukkitModuleType -import com.demonwav.mcdev.platform.bukkit.data.LoadOrder -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUKKIT_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUKKIT_GRADLE_PROPERTIES_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUKKIT_MAIN_CLASS_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUKKIT_PLUGIN_YML_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUKKIT_POM_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUKKIT_SETTINGS_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUKKIT_SUBMODULE_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUKKIT_SUBMODULE_POM_TEMPLATE -import com.intellij.openapi.project.Project - -object BukkitTemplate : BaseTemplate() { - - fun applyMainClass( - project: Project, - packageName: String, - className: String - ): String { - val props = mapOf( - "PACKAGE" to packageName, - "CLASS_NAME" to className - ) - - return project.applyTemplate(BUKKIT_MAIN_CLASS_TEMPLATE, props) - } - - fun applyPom(project: Project): String { - return project.applyTemplate(BUKKIT_POM_TEMPLATE, BasicMavenStep.pluginVersions) - } - - fun applySubPom(project: Project): String { - return project.applyTemplate(BUKKIT_SUBMODULE_POM_TEMPLATE, BasicMavenStep.pluginVersions) - } - - fun applyBuildGradle(project: Project, buildSystem: BuildSystem, config: BukkitProjectConfig): String { - val props = mapOf( - "GROUP_ID" to buildSystem.groupId, - "PLUGIN_VERSION" to buildSystem.version, - "JAVA_VERSION" to config.javaVersion.feature - ) - - return project.applyTemplate(BUKKIT_BUILD_GRADLE_TEMPLATE, props) - } - - fun applyGradleProp(project: Project): String { - return project.applyTemplate(BUKKIT_GRADLE_PROPERTIES_TEMPLATE) - } - - fun applySettingsGradle(project: Project, artifactId: String): String { - val props = mapOf( - "ARTIFACT_ID" to artifactId - ) - - return project.applyTemplate(BUKKIT_SETTINGS_GRADLE_TEMPLATE, props) - } - - fun applySubBuildGradle(project: Project, buildSystem: BuildSystem): String { - val props = mapOf( - "COMMON_PROJECT_NAME" to buildSystem.commonModuleName - ) - - return project.applyTemplate(BUKKIT_SUBMODULE_BUILD_GRADLE_TEMPLATE, props) - } - - fun applyPluginYml( - project: Project, - config: BukkitProjectConfig, - buildSystem: BuildSystem - ): String { - fun bukkitDeps(props: MutableMap, configuration: BukkitLikeConfiguration) { - if (configuration.hasDependencies()) { - props["DEPEND"] = configuration.dependencies.toString() - } - if (configuration.hasSoftDependencies()) { - props["SOFT_DEPEND"] = configuration.softDependencies.toString() - } - } - - val props = bukkitMain(buildSystem.type, config) - - if (config.hasPrefix()) { - props["PREFIX"] = config.prefix ?: throw IllegalStateException("prefix is null when not blank") - } - - if (config.loadOrder != LoadOrder.POSTWORLD) { - props["LOAD"] = LoadOrder.STARTUP.name - } - - if (config.hasLoadBefore()) { - props["LOAD_BEFORE"] = config.loadBefore.toString() - } - - bukkitDeps(props, config) - - if (config.hasAuthors()) { - props["AUTHOR_LIST"] = config.authors.toString() - } - - if (config.hasDescription()) { - props["DESCRIPTION"] = config.description - ?: throw IllegalStateException("description is null when not blank") - } - - if (config.hasWebsite()) { - props["WEBSITE"] = config.website ?: throw IllegalStateException("website is null when not blank") - } - - // Plugins targeting 1.13 or newer need an explicit api declaration flag - // This is the major and minor version separated by a dot without the patch version. ex: 1.15 even for 1.15.2 - val mcVersion = config.semanticMinecraftVersion - if (mcVersion >= BukkitModuleType.API_TAG_VERSION) { - props["API_VERSION"] = mcVersion.take(2).toString() - } - - return project.applyTemplate(BUKKIT_PLUGIN_YML_TEMPLATE, props) - } - - fun bukkitMain(type: BuildSystemType, config: C): MutableMap - where C : ProjectConfig, - C : BukkitLikeConfiguration { - val version = when (type) { - BuildSystemType.GRADLE -> "\${version}" - BuildSystemType.MAVEN -> "\${project.version}" - } - - return mutableMapOf( - "MAIN" to config.mainClass, - "VERSION" to version, - "NAME" to config.pluginName - ) - } -} diff --git a/src/main/kotlin/platform/bukkit/creator/LoadOrder.kt b/src/main/kotlin/platform/bukkit/creator/LoadOrder.kt new file mode 100644 index 000000000..d7245d4d9 --- /dev/null +++ b/src/main/kotlin/platform/bukkit/creator/LoadOrder.kt @@ -0,0 +1,19 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.bukkit.creator + +enum class LoadOrder(private val myName: String) { + STARTUP("Startup"), + POSTWORLD("Post World"), + ; + + override fun toString() = myName +} diff --git a/src/main/kotlin/platform/bukkit/creator/asset-steps.kt b/src/main/kotlin/platform/bukkit/creator/asset-steps.kt new file mode 100644 index 000000000..af5e7e561 --- /dev/null +++ b/src/main/kotlin/platform/bukkit/creator/asset-steps.kt @@ -0,0 +1,116 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.bukkit.creator + +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.AbstractRunBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.splitPackage +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModNameStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DependStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.MainClassStep +import com.demonwav.mcdev.creator.step.SimpleMcVersionStep +import com.demonwav.mcdev.creator.step.SoftDependStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.platform.bukkit.BukkitModuleType +import com.demonwav.mcdev.util.MinecraftTemplates +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key + +class BukkitProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating project files" + + override fun setupAssets(project: Project) { + val pluginName = data.getUserData(AbstractModNameStep.KEY) ?: return + val mainClass = data.getUserData(MainClassStep.KEY) ?: return + val versionRef = data.getUserData(VERSION_REF_KEY) ?: "\${version}" + val prefix = data.getUserData(BukkitLogPrefixStep.KEY) ?: "" + val loadOrder = data.getUserData(BukkitLoadOrderStep.KEY) ?: return + val loadBefore = data.getUserData(BukkitLoadBeforeStep.KEY) ?: emptyList() + val deps = data.getUserData(DependStep.KEY) ?: emptyList() + val softDeps = data.getUserData(SoftDependStep.KEY) ?: emptyList() + val authors = data.getUserData(AuthorsStep.KEY) ?: emptyList() + val description = data.getUserData(DescriptionStep.KEY) ?: "" + val website = data.getUserData(WebsiteStep.KEY) ?: "" + val mcVersion = data.getUserData(SimpleMcVersionStep.KEY) ?: return + + val (packageName, className) = splitPackage(mainClass) + + assets.addTemplateProperties( + "MAIN" to mainClass, + "VERSION" to versionRef, + "NAME" to pluginName, + "PACKAGE" to packageName, + "CLASS_NAME" to className, + ) + + if (prefix.isNotBlank()) { + assets.addTemplateProperties("PREFIX" to prefix) + } + + if (loadOrder != LoadOrder.POSTWORLD) { + assets.addTemplateProperties("LOAD" to loadOrder.name) + } + + if (loadBefore.isNotEmpty()) { + assets.addTemplateProperties("LOAD_BEFORE" to loadBefore) + } + + if (deps.isNotEmpty()) { + assets.addTemplateProperties("DEPEND" to deps) + } + + if (softDeps.isNotEmpty()) { + assets.addTemplateProperties("SOFT_DEPEND" to softDeps) + } + + if (authors.isNotEmpty()) { + assets.addTemplateProperties("AUTHOR_LIST" to authors) + } + + if (description.isNotBlank()) { + assets.addTemplateProperties("DESCRIPTION" to description) + } + + if (website.isNotEmpty()) { + assets.addTemplateProperties("WEBSITE" to website) + } + + if (mcVersion >= BukkitModuleType.API_TAG_VERSION) { + assets.addTemplateProperties("API_VERSION" to mcVersion.take(2)) + } + + assets.addTemplates( + project, + "src/main/resources/plugin.yml" to MinecraftTemplates.BUKKIT_PLUGIN_YML_TEMPLATE, + "src/main/java/${mainClass.replace('.', '/')}.java" to MinecraftTemplates.BUKKIT_MAIN_CLASS_TEMPLATE, + ) + } + + companion object { + val VERSION_REF_KEY = Key.create("${BukkitProjectFilesStep::class.java.name}.versionRef") + } +} + +class BukkitBuildSystemStep(parent: NewProjectWizardStep) : AbstractBuildSystemStep(parent) { + override val platformName = "Bukkit" +} + +class BukkitPostBuildSystemStep( + parent: NewProjectWizardStep, +) : AbstractRunBuildSystemStep(parent, BukkitBuildSystemStep::class.java) { + override val step = BuildSystemSupport.POST_STEP +} diff --git a/src/main/kotlin/platform/bukkit/creator/bukkit-platforms.kt b/src/main/kotlin/platform/bukkit/creator/bukkit-platforms.kt new file mode 100644 index 000000000..5df762ef0 --- /dev/null +++ b/src/main/kotlin/platform/bukkit/creator/bukkit-platforms.kt @@ -0,0 +1,81 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.bukkit.creator + +import com.demonwav.mcdev.creator.buildsystem.BuildDependency +import com.demonwav.mcdev.creator.buildsystem.BuildRepository +import com.demonwav.mcdev.platform.PlatformType +import com.demonwav.mcdev.util.MinecraftVersions +import com.demonwav.mcdev.util.SemanticVersion + +class SpigotPlatformStep(parent: BukkitPlatformStep) : AbstractBukkitPlatformStep(parent, PlatformType.SPIGOT) { + override fun getRepositories(mcVersion: SemanticVersion) = listOf( + BuildRepository( + "spigotmc-repo", + "https://hub.spigotmc.org/nexus/content/repositories/snapshots/", + ), + BuildRepository( + "sonatype", + "https://oss.sonatype.org/content/groups/public/", + ), + ) + + override fun getDependencies(mcVersion: SemanticVersion) = listOf( + BuildDependency( + "org.spigotmc", + "spigot-api", + "$mcVersion-R0.1-SNAPSHOT", + mavenScope = "provided", + gradleConfiguration = "compileOnly", + ), + ) + + class Factory : BukkitPlatformStep.Factory { + override val name = "Spigot" + + override fun createStep(parent: BukkitPlatformStep) = SpigotPlatformStep(parent) + } +} + +class PaperPlatformStep(parent: BukkitPlatformStep) : AbstractBukkitPlatformStep(parent, PlatformType.PAPER) { + override fun getRepositories(mcVersion: SemanticVersion) = listOf( + BuildRepository( + "papermc-repo", + "https://repo.papermc.io/repository/maven-public/", + ), + BuildRepository( + "sonatype", + "https://oss.sonatype.org/content/groups/public/", + ), + ) + + override fun getDependencies(mcVersion: SemanticVersion): List { + val paperGroupId = when { + mcVersion >= MinecraftVersions.MC1_17 -> "io.papermc.paper" + else -> "com.destroystokyo.paper" + } + return listOf( + BuildDependency( + paperGroupId, + "paper-api", + "$mcVersion-R0.1-SNAPSHOT", + mavenScope = "provided", + gradleConfiguration = "compileOnly", + ), + ) + } + + class Factory : BukkitPlatformStep.Factory { + override val name = "Paper" + + override fun createStep(parent: BukkitPlatformStep) = PaperPlatformStep(parent) + } +} diff --git a/src/main/kotlin/platform/bukkit/creator/gradle-steps.kt b/src/main/kotlin/platform/bukkit/creator/gradle-steps.kt new file mode 100644 index 000000000..9c7c2eb2f --- /dev/null +++ b/src/main/kotlin/platform/bukkit/creator/gradle-steps.kt @@ -0,0 +1,81 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.bukkit.creator + +import com.demonwav.mcdev.creator.EmptyStep +import com.demonwav.mcdev.creator.JdkProjectSetupFinalizer +import com.demonwav.mcdev.creator.addGradleGitignore +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractPatchGradleFilesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.buildsystem.GradleImportStep +import com.demonwav.mcdev.creator.buildsystem.GradleWrapperStep +import com.demonwav.mcdev.creator.buildsystem.ReformatBuildGradleStep +import com.demonwav.mcdev.creator.buildsystem.addGradleWrapperProperties +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.gitEnabled +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.SimpleMcVersionStep +import com.demonwav.mcdev.util.MinecraftTemplates +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.project.Project + +class BukkitGradleSupport : BuildSystemSupport { + override fun createStep(step: String, parent: NewProjectWizardStep): NewProjectWizardStep { + return when (step) { + BuildSystemSupport.PRE_STEP -> BukkitGradleFilesStep(parent).chain( + ::BukkitPatchBuildGradleStep, + ::GradleWrapperStep, + ) + BuildSystemSupport.POST_STEP -> GradleImportStep(parent).chain(::ReformatBuildGradleStep) + else -> EmptyStep(parent) + } + } +} + +class BukkitGradleFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating Gradle files" + + override fun setupAssets(project: Project) { + val buildSystemProps = findStep>() + val javaVersion = findStep().preferredJdk.ordinal + assets.addTemplateProperties( + "GROUP_ID" to buildSystemProps.groupId, + "ARTIFACT_ID" to buildSystemProps.artifactId, + "PLUGIN_VERSION" to buildSystemProps.version, + "JAVA_VERSION" to javaVersion, + ) + assets.addTemplates( + project, + "build.gradle" to MinecraftTemplates.BUKKIT_BUILD_GRADLE_TEMPLATE, + "gradle.properties" to MinecraftTemplates.BUKKIT_GRADLE_PROPERTIES_TEMPLATE, + "settings.gradle" to MinecraftTemplates.BUKKIT_SETTINGS_GRADLE_TEMPLATE, + ) + assets.addGradleWrapperProperties(project) + + if (gitEnabled) { + assets.addGradleGitignore(project) + } + } +} + +class BukkitPatchBuildGradleStep(parent: NewProjectWizardStep) : AbstractPatchGradleFilesStep(parent) { + override fun patch(project: Project, gradleFiles: GradleFiles) { + val platform = data.getUserData(AbstractBukkitPlatformStep.KEY) ?: return + val mcVersion = data.getUserData(SimpleMcVersionStep.KEY) ?: return + val repositories = platform.getRepositories(mcVersion) + val dependencies = platform.getDependencies(mcVersion) + addRepositories(project, gradleFiles.buildGradle, repositories) + addDependencies(project, gradleFiles.buildGradle, dependencies) + } +} diff --git a/src/main/kotlin/platform/bukkit/creator/maven-steps.kt b/src/main/kotlin/platform/bukkit/creator/maven-steps.kt new file mode 100644 index 000000000..20b8ca53d --- /dev/null +++ b/src/main/kotlin/platform/bukkit/creator/maven-steps.kt @@ -0,0 +1,65 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.bukkit.creator + +import com.demonwav.mcdev.creator.EmptyStep +import com.demonwav.mcdev.creator.addMavenGitignore +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractPatchPomStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.buildsystem.MavenImportStep +import com.demonwav.mcdev.creator.buildsystem.ReformatPomStep +import com.demonwav.mcdev.creator.buildsystem.addDefaultMavenProperties +import com.demonwav.mcdev.creator.gitEnabled +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.SimpleMcVersionStep +import com.demonwav.mcdev.util.MinecraftTemplates +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.project.Project +import com.intellij.psi.xml.XmlTag +import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel + +class BukkitMavenSupport : BuildSystemSupport { + override val preferred = true + + override fun createStep(step: String, parent: NewProjectWizardStep): NewProjectWizardStep { + return when (step) { + BuildSystemSupport.PRE_STEP -> BukkitMavenFilesStep(parent).chain(::BukkitPatchPomStep) + BuildSystemSupport.POST_STEP -> MavenImportStep(parent).chain(::ReformatPomStep) + else -> EmptyStep(parent) + } + } +} + +class BukkitMavenFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating Maven files" + + override fun setupAssets(project: Project) { + data.putUserData(BukkitProjectFilesStep.VERSION_REF_KEY, "\${project.version}") + assets.addDefaultMavenProperties() + assets.addTemplates(project, "pom.xml" to MinecraftTemplates.BUKKIT_POM_TEMPLATE) + if (gitEnabled) { + assets.addMavenGitignore(project) + } + } +} + +class BukkitPatchPomStep(parent: NewProjectWizardStep) : AbstractPatchPomStep(parent) { + override fun patchPom(model: MavenDomProjectModel, root: XmlTag) { + super.patchPom(model, root) + val platform = data.getUserData(AbstractBukkitPlatformStep.KEY) ?: return + val mcVersion = data.getUserData(SimpleMcVersionStep.KEY) ?: return + val repositories = platform.getRepositories(mcVersion) + val dependencies = platform.getDependencies(mcVersion) + setupDependencies(model, repositories, dependencies) + } +} diff --git a/src/main/kotlin/platform/bukkit/creator/ui-steps.kt b/src/main/kotlin/platform/bukkit/creator/ui-steps.kt new file mode 100644 index 000000000..393921c26 --- /dev/null +++ b/src/main/kotlin/platform/bukkit/creator/ui-steps.kt @@ -0,0 +1,165 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.bukkit.creator + +import com.demonwav.mcdev.creator.PlatformVersion +import com.demonwav.mcdev.creator.buildsystem.BuildDependency +import com.demonwav.mcdev.creator.buildsystem.BuildRepository +import com.demonwav.mcdev.creator.chain +import com.demonwav.mcdev.creator.getVersionSelector +import com.demonwav.mcdev.creator.platformtype.PluginPlatformStep +import com.demonwav.mcdev.creator.step.AbstractCollapsibleStep +import com.demonwav.mcdev.creator.step.AbstractLatentStep +import com.demonwav.mcdev.creator.step.AbstractOptionalStringStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DependStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.MainClassStep +import com.demonwav.mcdev.creator.step.PluginNameStep +import com.demonwav.mcdev.creator.step.SimpleMcVersionStep +import com.demonwav.mcdev.creator.step.SoftDependStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.platform.PlatformType +import com.demonwav.mcdev.util.SemanticVersion +import com.demonwav.mcdev.util.asyncIO +import com.intellij.ide.wizard.AbstractNewProjectWizardMultiStep +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardMultiStepFactory +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.extensions.ExtensionPointName +import com.intellij.openapi.observable.util.bindStorage +import com.intellij.openapi.observable.util.transform +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import com.intellij.ui.dsl.builder.Panel +import kotlinx.coroutines.coroutineScope + +class BukkitPlatformStep( + parent: PluginPlatformStep, +) : AbstractNewProjectWizardMultiStep(parent, EP_NAME) { + companion object { + val EP_NAME = ExtensionPointName("com.demonwav.minecraft-dev.bukkitPlatformWizard") + } + + override val self = this + override val label = "Bukkit Platform:" + + class PlatformFactory : PluginPlatformStep.Factory { + override val name = "Bukkit" + + override fun createStep(parent: PluginPlatformStep) = BukkitPlatformStep(parent) + } + + interface Factory : NewProjectWizardMultiStepFactory +} + +abstract class AbstractBukkitPlatformStep( + parent: BukkitPlatformStep, + private val platform: PlatformType, +) : AbstractLatentStep(parent) { + override val description = "download versions" + + override suspend fun computeData() = coroutineScope { + try { + asyncIO { getVersionSelector(platform) }.await() + } catch (e: Throwable) { + null + } + } + + override fun createStep(data: PlatformVersion) = + SimpleMcVersionStep(this, data.versions.mapNotNull(SemanticVersion::tryParse)).chain( + ::PluginNameStep, + ::MainClassStep, + ::BukkitOptionalSettingsStep, + ::BukkitBuildSystemStep, + ::BukkitProjectFilesStep, + ::BukkitPostBuildSystemStep, + ) + + override fun setupProject(project: Project) { + data.putUserData(KEY, this) + super.setupProject(project) + } + + abstract fun getRepositories(mcVersion: SemanticVersion): List + + abstract fun getDependencies(mcVersion: SemanticVersion): List + + companion object { + val KEY = Key.create("${AbstractBukkitPlatformStep::class.java.name}.platform") + } +} + +class BukkitOptionalSettingsStep(parent: NewProjectWizardStep) : AbstractCollapsibleStep(parent) { + override val title = "Optional Settings" + + override fun createStep() = DescriptionStep(this).chain( + ::AuthorsStep, + ::WebsiteStep, + ::BukkitLogPrefixStep, + ::BukkitLoadOrderStep, + ::BukkitLoadBeforeStep, + ::DependStep, + ::SoftDependStep, + ) +} + +class BukkitLogPrefixStep(parent: NewProjectWizardStep) : AbstractOptionalStringStep(parent) { + override val label = "Log Prefix:" + + override fun setupProject(project: Project) { + data.putUserData(KEY, value) + } + + companion object { + val KEY = Key.create("${BukkitLogPrefixStep::class.java.name}.logPrefix") + } +} + +class BukkitLoadOrderStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { + private val loadOrderProperty = propertyGraph.property(LoadOrder.POSTWORLD) + private var loadOrder by loadOrderProperty + + init { + loadOrderProperty.transform(LoadOrder::name, LoadOrder::valueOf) + .bindStorage("${javaClass.name}.loadOrder") + } + + override fun setupUI(builder: Panel) { + with(builder) { + row("Load at:") { + segmentedButton(LoadOrder.values().toList(), LoadOrder::toString) + .bind(loadOrderProperty) + } + } + } + + override fun setupProject(project: Project) { + data.putUserData(KEY, loadOrder) + } + + companion object { + val KEY = Key.create("${BukkitLoadOrderStep::class.java.name}.loadOrder") + } +} + +class BukkitLoadBeforeStep(parent: NewProjectWizardStep) : AbstractOptionalStringStep(parent) { + override val label = "Load Before:" + + override fun setupProject(project: Project) { + data.putUserData(KEY, AuthorsStep.parseAuthors(value)) + } + + companion object { + val KEY = Key.create>("${BukkitLoadBeforeStep::class.java.name}.loadBefore") + } +} diff --git a/src/main/kotlin/platform/bukkit/data/LoadOrder.kt b/src/main/kotlin/platform/bukkit/data/LoadOrder.kt deleted file mode 100644 index 2a50c0836..000000000 --- a/src/main/kotlin/platform/bukkit/data/LoadOrder.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.bukkit.data - -enum class LoadOrder { - STARTUP, - POSTWORLD -} diff --git a/src/main/kotlin/platform/bukkit/generation/BukkitEventGenerationPanel.kt b/src/main/kotlin/platform/bukkit/generation/BukkitEventGenerationPanel.kt index 3ec7f06c8..871a6e01a 100644 --- a/src/main/kotlin/platform/bukkit/generation/BukkitEventGenerationPanel.kt +++ b/src/main/kotlin/platform/bukkit/generation/BukkitEventGenerationPanel.kt @@ -23,7 +23,7 @@ class BukkitEventGenerationPanel(chosenClass: PsiClass) : EventGenerationPanel(c private lateinit var parentPanel: JPanel private lateinit var eventPriorityComboBox: JComboBox - override val panel: JPanel? + override val panel: JPanel get() { ignoreCanceledCheckBox.isSelected = true @@ -40,7 +40,10 @@ class BukkitEventGenerationPanel(chosenClass: PsiClass) : EventGenerationPanel(c return parentPanel } - override fun gatherData(): GenerationData? { - return BukkitGenerationData(ignoreCanceledCheckBox.isSelected, eventPriorityComboBox.selectedItem.toString()) + override fun gatherData(): GenerationData { + return BukkitGenerationData( + ignoreCanceledCheckBox.isSelected, + eventPriorityComboBox.selectedItem?.toString() ?: error("No selected item") + ) } } diff --git a/src/main/kotlin/platform/bukkit/inspection/BukkitListenerImplementedInspection.kt b/src/main/kotlin/platform/bukkit/inspection/BukkitListenerImplementedInspection.kt index 668877b1c..321f2e6a3 100644 --- a/src/main/kotlin/platform/bukkit/inspection/BukkitListenerImplementedInspection.kt +++ b/src/main/kotlin/platform/bukkit/inspection/BukkitListenerImplementedInspection.kt @@ -33,7 +33,7 @@ class BukkitListenerImplementedInspection : BaseInspection() { override fun getStaticDescription() = "All Bukkit @EventHandler methods must reside in a class that implements Listener." - override fun buildFix(vararg infos: Any): InspectionGadgetsFix? { + override fun buildFix(vararg infos: Any): InspectionGadgetsFix { return object : InspectionGadgetsFix() { override fun doFix(project: Project, descriptor: ProblemDescriptor) { val psiClass = infos[0] as PsiClass diff --git a/src/main/kotlin/platform/bungeecord/BungeeCordModule.kt b/src/main/kotlin/platform/bungeecord/BungeeCordModule.kt index 6efc00349..359bbd43f 100644 --- a/src/main/kotlin/platform/bungeecord/BungeeCordModule.kt +++ b/src/main/kotlin/platform/bungeecord/BungeeCordModule.kt @@ -73,14 +73,14 @@ class BungeeCordModule>(facet: MinecraftFacet, typ containingClass: PsiClass, chosenClass: PsiClass, chosenName: String, - data: GenerationData? + data: GenerationData?, ): PsiMethod? { val method = BukkitModule.generateBukkitStyleEventListenerMethod( chosenClass, chosenName, project, BungeeCordConstants.HANDLER_ANNOTATION, - false + false, ) ?: return null val generationData = data as BungeeCordGenerationData? ?: return method @@ -95,7 +95,7 @@ class BungeeCordModule>(facet: MinecraftFacet, typ val value = JavaPsiFacade.getElementFactory(project) .createExpressionFromText( BungeeCordConstants.EVENT_PRIORITY_CLASS + "." + generationData.eventPriority, - annotation + annotation, ) annotation.setDeclaredAttributeValue("priority", value) diff --git a/src/main/kotlin/platform/bungeecord/creator/BungeeCordProjectConfig.kt b/src/main/kotlin/platform/bungeecord/creator/BungeeCordProjectConfig.kt deleted file mode 100644 index c7450f3ed..000000000 --- a/src/main/kotlin/platform/bungeecord/creator/BungeeCordProjectConfig.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.bungeecord.creator - -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.ProjectCreator -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleCreator -import com.demonwav.mcdev.creator.buildsystem.maven.MavenBuildSystem -import com.demonwav.mcdev.creator.buildsystem.maven.MavenCreator -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.platform.bukkit.BukkitLikeConfiguration -import com.demonwav.mcdev.util.MinecraftVersions -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.VersionRange -import com.intellij.openapi.module.Module -import com.intellij.util.lang.JavaVersion -import java.nio.file.Path - -class BungeeCordProjectConfig(override var type: PlatformType) : - ProjectConfig(), MavenCreator, GradleCreator, BukkitLikeConfiguration { - - override lateinit var mainClass: String - - var minecraftVersion = "" - val semanticMinecraftVersion: SemanticVersion - get() = if (minecraftVersion.isBlank()) SemanticVersion.release() else SemanticVersion.parse(minecraftVersion) - - override val dependencies = mutableListOf() - override fun hasDependencies() = listContainsAtLeastOne(dependencies) - override fun setDependencies(string: String) { - dependencies.clear() - dependencies.addAll(commaSplit(string)) - } - - override val softDependencies = mutableListOf() - override fun hasSoftDependencies() = listContainsAtLeastOne(softDependencies) - override fun setSoftDependencies(string: String) { - softDependencies.clear() - softDependencies.addAll(commaSplit(string)) - } - - override val preferredBuildSystem = BuildSystemType.MAVEN - - override val javaVersion: JavaVersion - get() = MinecraftVersions.requiredJavaVersion(semanticMinecraftVersion) - - override val compatibleGradleVersions: VersionRange? = null - - override fun buildMavenCreator( - rootDirectory: Path, - module: Module, - buildSystem: MavenBuildSystem - ): ProjectCreator { - return BungeeCordMavenCreator(rootDirectory, module, buildSystem, this) - } - - override fun buildGradleCreator( - rootDirectory: Path, - module: Module, - buildSystem: GradleBuildSystem - ): ProjectCreator { - return BungeeCordGradleCreator(rootDirectory, module, buildSystem, this) - } -} diff --git a/src/main/kotlin/platform/bungeecord/creator/BungeeCordProjectCreator.kt b/src/main/kotlin/platform/bungeecord/creator/BungeeCordProjectCreator.kt deleted file mode 100644 index 017b4f857..000000000 --- a/src/main/kotlin/platform/bungeecord/creator/BungeeCordProjectCreator.kt +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.bungeecord.creator - -import com.demonwav.mcdev.creator.BaseProjectCreator -import com.demonwav.mcdev.creator.BasicJavaClassStep -import com.demonwav.mcdev.creator.CreateDirectoriesStep -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.buildsystem.BuildDependency -import com.demonwav.mcdev.creator.buildsystem.BuildRepository -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.BasicGradleFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleFiles -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleGitignoreStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleSetupStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleWrapperStep -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenStep -import com.demonwav.mcdev.creator.buildsystem.maven.MavenBuildSystem -import com.demonwav.mcdev.creator.buildsystem.maven.MavenGitignoreStep -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.platform.bukkit.creator.BukkitDependenciesStep -import com.intellij.openapi.module.Module -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.project.Project -import java.nio.file.Path - -sealed class BungeeCordProjectCreator( - protected val rootDirectory: Path, - protected val rootModule: Module, - protected val buildSystem: T, - protected val config: BungeeCordProjectConfig -) : BaseProjectCreator(rootModule, buildSystem) { - - protected fun setupMainClassStep(): BasicJavaClassStep { - return createJavaClassStep(config.mainClass) { packageName, className -> - BungeeCordTemplate.applyMainClass(project, packageName, className) - } - } - - protected fun setupDependencyStep(): BungeeCordDependenciesStep { - val mcVersion = config.minecraftVersion - return BungeeCordDependenciesStep(buildSystem, config.type, mcVersion) - } - - protected fun setupYmlStep(): BungeeYmlStep { - return BungeeYmlStep(project, buildSystem, config) - } -} - -class BungeeCordMavenCreator( - rootDirectory: Path, - rootModule: Module, - buildSystem: MavenBuildSystem, - config: BungeeCordProjectConfig -) : BungeeCordProjectCreator(rootDirectory, rootModule, buildSystem, config) { - - override fun getSteps(): Iterable { - val pomText = BungeeCordTemplate.applyPom(project) - return listOf( - setupDependencyStep(), - BasicMavenStep(project, rootDirectory, buildSystem, config, pomText), - setupMainClassStep(), - setupYmlStep(), - MavenGitignoreStep(project, rootDirectory), - BasicMavenFinalizerStep(rootModule, rootDirectory) - ) - } -} - -class BungeeCordGradleCreator( - rootDirectory: Path, - rootModule: Module, - buildSystem: GradleBuildSystem, - config: BungeeCordProjectConfig -) : BungeeCordProjectCreator(rootDirectory, rootModule, buildSystem, config) { - - override fun getSteps(): Iterable { - val buildText = BungeeCordTemplate.applyBuildGradle(project, buildSystem) - val projectText = BungeeCordTemplate.applyGradleProp(project) - val settingsText = BungeeCordTemplate.applySettingsGradle(project, buildSystem.artifactId) - val files = GradleFiles(buildText, projectText, settingsText) - - return listOf( - setupDependencyStep(), - CreateDirectoriesStep(buildSystem, rootDirectory), - GradleSetupStep(project, rootDirectory, buildSystem, files), - setupMainClassStep(), - setupYmlStep(), - GradleWrapperStep(project, rootDirectory, buildSystem), - GradleGitignoreStep(project, rootDirectory), - BasicGradleFinalizerStep(rootModule, rootDirectory, buildSystem) - ) - } -} - -class BungeeCordDependenciesStep( - buildSystem: BuildSystem, - type: PlatformType, - mcVersion: String -) : BukkitDependenciesStep(buildSystem, type, mcVersion) { - override fun runStep(indicator: ProgressIndicator) { - addSonatype(buildSystem.repositories) - when (type) { - PlatformType.WATERFALL -> { - buildSystem.repositories.add( - BuildRepository( - "papermc-repo", - "https://repo.papermc.io/repository/maven-public/" - ) - ) - buildSystem.dependencies.add( - BuildDependency( - "io.github.waterfallmc", - "waterfall-api", - "$mcVersion-SNAPSHOT", - mavenScope = "provided", - gradleConfiguration = "compileOnly" - ) - ) - } - PlatformType.BUNGEECORD -> { - buildSystem.dependencies.add( - BuildDependency( - "net.md-5", - "bungeecord-api", - mcVersion, - mavenScope = "provided", - gradleConfiguration = "compileOnly" - ) - ) - } - else -> { - } - } - } -} - -class BungeeYmlStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val config: BungeeCordProjectConfig -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val text = BungeeCordTemplate.applyBungeeYml(project, config, buildSystem) - CreatorStep.writeTextToFile(project, buildSystem.dirsOrError.resourceDirectory, "bungee.yml", text) - } -} diff --git a/src/main/kotlin/platform/bungeecord/creator/BungeeCordProjectSettingsWizard.form b/src/main/kotlin/platform/bungeecord/creator/BungeeCordProjectSettingsWizard.form deleted file mode 100644 index 95d0a3b5a..000000000 --- a/src/main/kotlin/platform/bungeecord/creator/BungeeCordProjectSettingsWizard.form +++ /dev/null @@ -1,234 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/main/kotlin/platform/bungeecord/creator/BungeeCordProjectSettingsWizard.kt b/src/main/kotlin/platform/bungeecord/creator/BungeeCordProjectSettingsWizard.kt deleted file mode 100644 index e5cc0ee5a..000000000 --- a/src/main/kotlin/platform/bungeecord/creator/BungeeCordProjectSettingsWizard.kt +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.bungeecord.creator - -import com.demonwav.mcdev.asset.PlatformAssets -import com.demonwav.mcdev.creator.MinecraftModuleWizardStep -import com.demonwav.mcdev.creator.MinecraftProjectCreator -import com.demonwav.mcdev.creator.ValidatedField -import com.demonwav.mcdev.creator.ValidatedFieldType.CLASS_NAME -import com.demonwav.mcdev.creator.ValidatedFieldType.LIST -import com.demonwav.mcdev.creator.ValidatedFieldType.NON_BLANK -import com.demonwav.mcdev.creator.getVersionSelector -import com.demonwav.mcdev.platform.PlatformType -import javax.swing.JComboBox -import javax.swing.JComponent -import javax.swing.JLabel -import javax.swing.JPanel -import javax.swing.JTextField -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.swing.Swing -import kotlinx.coroutines.withContext - -class BungeeCordProjectSettingsWizard( - private val creator: MinecraftProjectCreator -) : MinecraftModuleWizardStep() { - - private lateinit var panel: JPanel - - @ValidatedField(NON_BLANK) - private lateinit var pluginNameField: JTextField - - @ValidatedField(NON_BLANK, CLASS_NAME) - private lateinit var mainClassField: JTextField - private lateinit var descriptionField: JTextField - - @ValidatedField(LIST) - private lateinit var authorField: JTextField - - @ValidatedField(LIST) - private lateinit var dependField: JTextField - private lateinit var softDependField: JTextField - private lateinit var title: JLabel - private lateinit var minecraftVersionBox: JComboBox - private lateinit var errorLabel: JLabel - - private var config: BungeeCordProjectConfig? = null - - private var versionsLoaded: Boolean = false - - override fun getComponent(): JComponent { - return panel - } - - override fun validate(): Boolean { - return super.validate() && minecraftVersionBox.selectedItem != null - } - - override fun updateStep() { - config = creator.config as? BungeeCordProjectConfig - if (config == null) { - return - } - val conf = config ?: return - - basicUpdateStep(creator, pluginNameField, mainClassField) - - when (conf.type) { - PlatformType.BUNGEECORD -> { - title.icon = PlatformAssets.BUNGEECORD_ICON_2X - title.text = "BungeeCord Settings" - } - PlatformType.WATERFALL -> { - title.icon = PlatformAssets.WATERFALL_ICON_2X - title.text = "Waterfall Settings" - } - else -> {} - } - - if (versionsLoaded) { - return - } - - versionsLoaded = true - CoroutineScope(Dispatchers.Swing).launch { - try { - withContext(Dispatchers.IO) { getVersionSelector(conf.type) }.set(minecraftVersionBox) - } catch (e: Exception) { - errorLabel.isVisible = true - } - } - } - - override fun isStepVisible(): Boolean { - return creator.config is BungeeCordProjectConfig - } - - override fun updateDataModel() { - val conf = this.config ?: return - - conf.pluginName = this.pluginNameField.text - conf.mainClass = this.mainClassField.text - conf.description = this.descriptionField.text - conf.minecraftVersion = this.minecraftVersionBox.selectedItem as String - - conf.setAuthors(this.authorField.text) - conf.setDependencies(this.dependField.text) - conf.setSoftDependencies(this.softDependField.text) - } -} diff --git a/src/main/kotlin/platform/bungeecord/creator/BungeeCordTemplate.kt b/src/main/kotlin/platform/bungeecord/creator/BungeeCordTemplate.kt deleted file mode 100644 index 76abb8fa4..000000000 --- a/src/main/kotlin/platform/bungeecord/creator/BungeeCordTemplate.kt +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.bungeecord.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenStep -import com.demonwav.mcdev.platform.BaseTemplate -import com.demonwav.mcdev.platform.bukkit.creator.BukkitTemplate -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUKKIT_PLUGIN_YML_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUNGEECORD_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUNGEECORD_GRADLE_PROPERTIES_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUNGEECORD_MAIN_CLASS_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUNGEECORD_POM_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUNGEECORD_SETTINGS_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUNGEECORD_SUBMODULE_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.BUNGEECORD_SUBMODULE_POM_TEMPLATE -import com.intellij.openapi.project.Project - -object BungeeCordTemplate : BaseTemplate() { - - fun applyMainClass( - project: Project, - packageName: String, - className: String - ): String { - val props = mapOf( - "PACKAGE" to packageName, - "CLASS_NAME" to className - ) - - return project.applyTemplate(BUNGEECORD_MAIN_CLASS_TEMPLATE, props) - } - - fun applyPom(project: Project): String { - return project.applyTemplate(BUNGEECORD_POM_TEMPLATE, BasicMavenStep.pluginVersions) - } - - fun applySubPom(project: Project): String { - return project.applyTemplate(BUNGEECORD_SUBMODULE_POM_TEMPLATE, BasicMavenStep.pluginVersions) - } - - fun applyBuildGradle(project: Project, buildSystem: BuildSystem): String { - val props = mapOf( - "GROUP_ID" to buildSystem.groupId, - "PLUGIN_VERSION" to buildSystem.version - ) - - return project.applyTemplate(BUNGEECORD_BUILD_GRADLE_TEMPLATE, props) - } - - fun applyGradleProp(project: Project): String { - return project.applyTemplate(BUNGEECORD_GRADLE_PROPERTIES_TEMPLATE) - } - - fun applySettingsGradle(project: Project, artifactId: String): String { - val props = mapOf( - "ARTIFACT_ID" to artifactId - ) - - return project.applyTemplate(BUNGEECORD_SETTINGS_GRADLE_TEMPLATE, props) - } - - fun applySubBuildGradle(project: Project, buildSystem: BuildSystem): String { - val props = mapOf( - "COMMON_PROJECT_NAME" to buildSystem.commonModuleName - ) - - return project.applyTemplate(BUNGEECORD_SUBMODULE_BUILD_GRADLE_TEMPLATE, props) - } - - fun applyBungeeYml( - project: Project, - config: BungeeCordProjectConfig, - buildSystem: BuildSystem - ): String { - val props = BukkitTemplate.bukkitMain(buildSystem.type, config) - - if (config.hasAuthors()) { - // BungeeCord only supports one author - props["AUTHOR"] = config.authors[0] - } - - if (config.hasDescription()) { - props["DESCRIPTION"] = config.description - ?: throw IllegalStateException("description is null when not blank") - } - - return project.applyTemplate(BUKKIT_PLUGIN_YML_TEMPLATE, props) - } -} diff --git a/src/main/kotlin/platform/bungeecord/creator/asset-steps.kt b/src/main/kotlin/platform/bungeecord/creator/asset-steps.kt new file mode 100644 index 000000000..982fc8b9e --- /dev/null +++ b/src/main/kotlin/platform/bungeecord/creator/asset-steps.kt @@ -0,0 +1,92 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.bungeecord.creator + +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.AbstractRunBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.splitPackage +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModNameStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DependStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.MainClassStep +import com.demonwav.mcdev.creator.step.SoftDependStep +import com.demonwav.mcdev.util.MinecraftTemplates +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key + +class BungeeProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating project files" + + override fun setupAssets(project: Project) { + val mainClass = data.getUserData(MainClassStep.KEY) ?: return + val (packageName, className) = splitPackage(mainClass) + val versionRef = data.getUserData(VERSION_REF_KEY) ?: "\${version}" + val pluginName = data.getUserData(AbstractModNameStep.KEY) ?: return + val authors = data.getUserData(AuthorsStep.KEY) ?: emptyList() + val description = data.getUserData(DescriptionStep.KEY) ?: "" + val depend = data.getUserData(DependStep.KEY) ?: emptyList() + val softDepend = data.getUserData(SoftDependStep.KEY) ?: emptyList() + + assets.addTemplateProperties( + "PACKAGE" to packageName, + "CLASS_NAME" to className, + "MAIN" to mainClass, + "VERSION" to versionRef, + "NAME" to pluginName, + ) + + if (authors.isNotEmpty()) { + assets.addTemplateProperties( + "AUTHOR" to authors.joinToString(", "), + ) + } + if (description.isNotBlank()) { + assets.addTemplateProperties( + "DESCRIPTION" to description, + ) + } + if (depend.isNotEmpty()) { + assets.addTemplateProperties( + "DEPEND" to depend, + ) + } + if (softDepend.isNotEmpty()) { + assets.addTemplateProperties( + "SOFT_DEPEND" to softDepend, + ) + } + + assets.addTemplates( + project, + "src/main/resources/bungee.yml" to MinecraftTemplates.BUNGEECORD_PLUGIN_YML_TEMPLATE, + "src/main/java/${mainClass.replace('.', '/')}.java" to MinecraftTemplates.BUNGEECORD_MAIN_CLASS_TEMPLATE, + ) + } + + companion object { + val VERSION_REF_KEY = Key.create("${BungeeProjectFilesStep::class.java.name}.versionRef") + } +} + +class BungeeBuildSystemStep(parent: NewProjectWizardStep) : AbstractBuildSystemStep(parent) { + override val platformName = "BungeeCord" +} + +class BungeePostBuildSystemStep( + parent: NewProjectWizardStep, +) : AbstractRunBuildSystemStep(parent, BungeeBuildSystemStep::class.java) { + override val step = BuildSystemSupport.POST_STEP +} diff --git a/src/main/kotlin/platform/bungeecord/creator/bungee-platforms.kt b/src/main/kotlin/platform/bungeecord/creator/bungee-platforms.kt new file mode 100644 index 000000000..cb54080ce --- /dev/null +++ b/src/main/kotlin/platform/bungeecord/creator/bungee-platforms.kt @@ -0,0 +1,64 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.bungeecord.creator + +import com.demonwav.mcdev.creator.buildsystem.BuildDependency +import com.demonwav.mcdev.creator.buildsystem.BuildRepository +import com.demonwav.mcdev.platform.PlatformType +import com.demonwav.mcdev.util.SemanticVersion + +class BungeeMainPlatformStep(parent: BungeePlatformStep) : AbstractBungeePlatformStep(parent, PlatformType.BUNGEECORD) { + override fun getRepositories(mcVersion: SemanticVersion) = listOf( + BuildRepository("sonatype", "https://oss.sonatype.org/content/groups/public/"), + ) + + override fun getDependencies(mcVersion: SemanticVersion) = listOf( + BuildDependency( + "net.md-5", + "bungeecord-api", + mcVersion.toString(), + mavenScope = "provided", + gradleConfiguration = "compileOnly", + ), + ) + + class Factory : BungeePlatformStep.Factory { + override val name = "BungeeCord" + + override fun createStep(parent: BungeePlatformStep) = BungeeMainPlatformStep(parent) + } +} + +class WaterfallPlatformStep(parent: BungeePlatformStep) : AbstractBungeePlatformStep(parent, PlatformType.WATERFALL) { + override fun getRepositories(mcVersion: SemanticVersion) = listOf( + BuildRepository("sonatype", "https://oss.sonatype.org/content/groups/public/"), + BuildRepository( + "papermc-repo", + "https://repo.papermc.io/repository/maven-public/", + ), + ) + + override fun getDependencies(mcVersion: SemanticVersion) = listOf( + BuildDependency( + "io.github.waterfallmc", + "waterfall-api", + "$mcVersion-SNAPSHOT", + mavenScope = "provided", + gradleConfiguration = "compileOnly", + ), + ) + + class Factory : BungeePlatformStep.Factory { + override val name = "Waterfall" + + override fun createStep(parent: BungeePlatformStep) = WaterfallPlatformStep(parent) + } +} diff --git a/src/main/kotlin/platform/bungeecord/creator/gradle-steps.kt b/src/main/kotlin/platform/bungeecord/creator/gradle-steps.kt new file mode 100644 index 000000000..37e238014 --- /dev/null +++ b/src/main/kotlin/platform/bungeecord/creator/gradle-steps.kt @@ -0,0 +1,81 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.bungeecord.creator + +import com.demonwav.mcdev.creator.EmptyStep +import com.demonwav.mcdev.creator.addGradleGitignore +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractPatchGradleFilesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.buildsystem.GradleImportStep +import com.demonwav.mcdev.creator.buildsystem.GradleWrapperStep +import com.demonwav.mcdev.creator.buildsystem.ReformatBuildGradleStep +import com.demonwav.mcdev.creator.buildsystem.addGradleWrapperProperties +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.gitEnabled +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.SimpleMcVersionStep +import com.demonwav.mcdev.util.MinecraftTemplates +import com.intellij.ide.wizard.NewProjectWizardBaseData.Companion.baseData +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.project.Project + +class BungeeGradleSupport : BuildSystemSupport { + override fun createStep(step: String, parent: NewProjectWizardStep): NewProjectWizardStep { + return when (step) { + BuildSystemSupport.PRE_STEP -> BungeeGradleFilesStep(parent).chain( + ::BungeePatchBuildGradleStep, + ::GradleWrapperStep, + ) + BuildSystemSupport.POST_STEP -> GradleImportStep(parent).chain(::ReformatBuildGradleStep) + else -> EmptyStep(parent) + } + } +} + +class BungeeGradleFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating Gradle files" + + override fun setupAssets(project: Project) { + val projectName = baseData.name + val buildSystemProps = findStep>() + assets.addTemplateProperties( + "PROJECT_NAME" to projectName, + "GROUP_ID" to buildSystemProps.groupId, + "ARTIFACT_ID" to buildSystemProps.artifactId, + "PLUGIN_VERSION" to buildSystemProps.version, + ) + assets.addTemplates( + project, + "build.gradle" to MinecraftTemplates.BUNGEECORD_BUILD_GRADLE_TEMPLATE, + "gradle.properties" to MinecraftTemplates.BUNGEECORD_GRADLE_PROPERTIES_TEMPLATE, + "settings.gradle" to MinecraftTemplates.BUNGEECORD_SETTINGS_GRADLE_TEMPLATE, + ) + assets.addGradleWrapperProperties(project) + + if (gitEnabled) { + assets.addGradleGitignore(project) + } + } +} + +class BungeePatchBuildGradleStep(parent: NewProjectWizardStep) : AbstractPatchGradleFilesStep(parent) { + override fun patch(project: Project, gradleFiles: GradleFiles) { + val platform = data.getUserData(AbstractBungeePlatformStep.KEY) ?: return + val mcVersion = data.getUserData(SimpleMcVersionStep.KEY) ?: return + val repositories = platform.getRepositories(mcVersion) + val dependencies = platform.getDependencies(mcVersion) + addRepositories(project, gradleFiles.buildGradle, repositories) + addDependencies(project, gradleFiles.buildGradle, dependencies) + } +} diff --git a/src/main/kotlin/platform/bungeecord/creator/maven-steps.kt b/src/main/kotlin/platform/bungeecord/creator/maven-steps.kt new file mode 100644 index 000000000..b20bbc2c9 --- /dev/null +++ b/src/main/kotlin/platform/bungeecord/creator/maven-steps.kt @@ -0,0 +1,65 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.bungeecord.creator + +import com.demonwav.mcdev.creator.EmptyStep +import com.demonwav.mcdev.creator.addMavenGitignore +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractPatchPomStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.buildsystem.MavenImportStep +import com.demonwav.mcdev.creator.buildsystem.ReformatPomStep +import com.demonwav.mcdev.creator.buildsystem.addDefaultMavenProperties +import com.demonwav.mcdev.creator.gitEnabled +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.SimpleMcVersionStep +import com.demonwav.mcdev.util.MinecraftTemplates +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.project.Project +import com.intellij.psi.xml.XmlTag +import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel + +class BungeeMavenSupport : BuildSystemSupport { + override val preferred = true + + override fun createStep(step: String, parent: NewProjectWizardStep): NewProjectWizardStep { + return when (step) { + BuildSystemSupport.PRE_STEP -> BungeeMavenFilesStep(parent).chain(::BungeePatchPomStep) + BuildSystemSupport.POST_STEP -> MavenImportStep(parent).chain(::ReformatPomStep) + else -> EmptyStep(parent) + } + } +} + +class BungeeMavenFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating Maven files" + + override fun setupAssets(project: Project) { + data.putUserData(BungeeProjectFilesStep.VERSION_REF_KEY, "\${project.version}") + assets.addDefaultMavenProperties() + assets.addTemplates(project, "pom.xml" to MinecraftTemplates.BUNGEECORD_POM_TEMPLATE) + if (gitEnabled) { + assets.addMavenGitignore(project) + } + } +} + +class BungeePatchPomStep(parent: NewProjectWizardStep) : AbstractPatchPomStep(parent) { + override fun patchPom(model: MavenDomProjectModel, root: XmlTag) { + super.patchPom(model, root) + val platform = data.getUserData(AbstractBungeePlatformStep.KEY) ?: return + val mcVersion = data.getUserData(SimpleMcVersionStep.KEY) ?: return + val repositories = platform.getRepositories(mcVersion) + val dependencies = platform.getDependencies(mcVersion) + setupDependencies(model, repositories, dependencies) + } +} diff --git a/src/main/kotlin/platform/bungeecord/creator/ui-steps.kt b/src/main/kotlin/platform/bungeecord/creator/ui-steps.kt new file mode 100644 index 000000000..bd9f7566a --- /dev/null +++ b/src/main/kotlin/platform/bungeecord/creator/ui-steps.kt @@ -0,0 +1,105 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.bungeecord.creator + +import com.demonwav.mcdev.creator.PlatformVersion +import com.demonwav.mcdev.creator.buildsystem.BuildDependency +import com.demonwav.mcdev.creator.buildsystem.BuildRepository +import com.demonwav.mcdev.creator.chain +import com.demonwav.mcdev.creator.getVersionSelector +import com.demonwav.mcdev.creator.platformtype.PluginPlatformStep +import com.demonwav.mcdev.creator.step.AbstractCollapsibleStep +import com.demonwav.mcdev.creator.step.AbstractLatentStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DependStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.MainClassStep +import com.demonwav.mcdev.creator.step.PluginNameStep +import com.demonwav.mcdev.creator.step.SimpleMcVersionStep +import com.demonwav.mcdev.creator.step.SoftDependStep +import com.demonwav.mcdev.platform.PlatformType +import com.demonwav.mcdev.util.SemanticVersion +import com.demonwav.mcdev.util.asyncIO +import com.intellij.ide.wizard.AbstractNewProjectWizardMultiStep +import com.intellij.ide.wizard.NewProjectWizardMultiStepFactory +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.extensions.ExtensionPointName +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import kotlinx.coroutines.coroutineScope + +class BungeePlatformStep( + parent: PluginPlatformStep, +) : AbstractNewProjectWizardMultiStep(parent, EP_NAME) { + companion object { + val EP_NAME = ExtensionPointName("com.demonwav.minecraft-dev.bungeePlatformWizard") + } + + override val self = this + override val label = "Bungee Platform:" + + class PlatformFactory : PluginPlatformStep.Factory { + override val name = "BungeeCord" + + override fun createStep(parent: PluginPlatformStep) = BungeePlatformStep(parent) + } + + interface Factory : NewProjectWizardMultiStepFactory +} + +abstract class AbstractBungeePlatformStep( + parent: BungeePlatformStep, + private val platform: PlatformType, +) : AbstractLatentStep(parent) { + override val description = "download versions" + + override suspend fun computeData() = coroutineScope { + try { + asyncIO { getVersionSelector(platform) }.await() + } catch (e: Throwable) { + null + } + } + + override fun createStep(data: PlatformVersion) = + SimpleMcVersionStep(this, data.versions.mapNotNull(SemanticVersion::tryParse)).chain( + ::PluginNameStep, + ::MainClassStep, + ::BungeeOptionalSettingsStep, + ::BungeeBuildSystemStep, + ::BungeeProjectFilesStep, + ::BungeePostBuildSystemStep, + ) + + override fun setupProject(project: Project) { + data.putUserData(KEY, this) + super.setupProject(project) + } + + abstract fun getRepositories(mcVersion: SemanticVersion): List + + abstract fun getDependencies(mcVersion: SemanticVersion): List + + companion object { + val KEY = Key.create("${AbstractBungeePlatformStep::class.java.name}.platform") + } +} + +class BungeeOptionalSettingsStep(parent: NewProjectWizardStep) : AbstractCollapsibleStep(parent) { + override val title = "Optional Settings" + + override fun createStep() = DescriptionStep(this).chain( + ::AuthorsStep, + ::DependStep, + ::SoftDependStep, + ) +} diff --git a/src/main/kotlin/platform/bungeecord/generation/BungeeCordEventGenerationPanel.kt b/src/main/kotlin/platform/bungeecord/generation/BungeeCordEventGenerationPanel.kt index cd9dc9f9c..cc3c27ac0 100644 --- a/src/main/kotlin/platform/bungeecord/generation/BungeeCordEventGenerationPanel.kt +++ b/src/main/kotlin/platform/bungeecord/generation/BungeeCordEventGenerationPanel.kt @@ -20,7 +20,7 @@ class BungeeCordEventGenerationPanel(chosenClass: PsiClass) : EventGenerationPan private lateinit var eventPriorityComboBox: JComboBox private lateinit var parentPanel: JPanel - override val panel: JPanel? + override val panel: JPanel get() { // Not static because the form builder is not reliable eventPriorityComboBox.addItem("HIGHEST") diff --git a/src/main/kotlin/platform/bungeecord/inspection/BungeeCordListenerImplementedInspection.kt b/src/main/kotlin/platform/bungeecord/inspection/BungeeCordListenerImplementedInspection.kt index b5d9de789..d095423b9 100644 --- a/src/main/kotlin/platform/bungeecord/inspection/BungeeCordListenerImplementedInspection.kt +++ b/src/main/kotlin/platform/bungeecord/inspection/BungeeCordListenerImplementedInspection.kt @@ -32,7 +32,7 @@ class BungeeCordListenerImplementedInspection : BaseInspection() { override fun getStaticDescription() = "All BungeeCord @EventHandler methods must reside in a class that implements Listener." - override fun buildFix(vararg infos: Any): InspectionGadgetsFix? { + override fun buildFix(vararg infos: Any): InspectionGadgetsFix { return object : InspectionGadgetsFix() { override fun doFix(project: Project, descriptor: ProblemDescriptor) { val psiClass = infos[0] as PsiClass diff --git a/src/main/kotlin/platform/fabric/EntryPoint.kt b/src/main/kotlin/platform/fabric/EntryPoint.kt index ae2a63211..5c7551012 100644 --- a/src/main/kotlin/platform/fabric/EntryPoint.kt +++ b/src/main/kotlin/platform/fabric/EntryPoint.kt @@ -23,7 +23,7 @@ data class EntryPoint( val type: Type, val className: String, val interfaceName: String, - val methodName: String? = null + val methodName: String? = null, ) { private val dumbReference = when (type) { Type.CLASS -> className diff --git a/src/main/kotlin/platform/fabric/creator/FabricMcVersion.kt b/src/main/kotlin/platform/fabric/creator/FabricMcVersion.kt new file mode 100644 index 000000000..66e603af0 --- /dev/null +++ b/src/main/kotlin/platform/fabric/creator/FabricMcVersion.kt @@ -0,0 +1,20 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.fabric.creator + +class FabricMcVersion( + private val ordinal: Int, + val version: String, + val stable: Boolean, +) : Comparable { + override fun toString() = version + override fun compareTo(other: FabricMcVersion) = ordinal.compareTo(other.ordinal) +} diff --git a/src/main/kotlin/platform/fabric/creator/FabricProjectConfig.kt b/src/main/kotlin/platform/fabric/creator/FabricProjectConfig.kt deleted file mode 100644 index dfd77e85f..000000000 --- a/src/main/kotlin/platform/fabric/creator/FabricProjectConfig.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.fabric.creator - -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.ProjectCreator -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleCreator -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.platform.fabric.EntryPoint -import com.demonwav.mcdev.platform.forge.inspections.sideonly.Side -import com.demonwav.mcdev.util.License -import com.demonwav.mcdev.util.MinecraftVersions -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.VersionRange -import com.intellij.openapi.module.Module -import com.intellij.util.lang.JavaVersion -import java.nio.file.Path - -class FabricProjectConfig : ProjectConfig(), GradleCreator { - - var yarnVersion = "" - var yarnClassifier: String? = "v2" - - // Minecraft does not follow semver in the snapshots - var mcVersion = "" - var semanticMcVersion = SemanticVersion.release() - var loaderVersion = SemanticVersion.release() - var apiVersion: SemanticVersion? = null - var apiMavenLocation: String? = null - var loomVersion = SemanticVersion.release() - var gradleVersion = SemanticVersion.release() - var environment = Side.NONE - var entryPoints: List = arrayListOf() - var modRepo: String? = null - var mixins = false - var genSources = true - var license: License? = null - - override var type = PlatformType.FABRIC - - override val preferredBuildSystem = BuildSystemType.GRADLE - - override val javaVersion: JavaVersion - get() = MinecraftVersions.requiredJavaVersion(semanticMcVersion) - - override val compatibleGradleVersions: VersionRange - get() = VersionRange.fixed(gradleVersion) - - override fun buildGradleCreator( - rootDirectory: Path, - module: Module, - buildSystem: GradleBuildSystem - ): ProjectCreator { - return FabricProjectCreator( - rootDirectory, - module, - buildSystem, - this - ) - } - - override fun configureRootGradle(rootDirectory: Path, buildSystem: GradleBuildSystem) { - buildSystem.gradleVersion = - if (semanticMcVersion >= MinecraftVersions.MC1_17) SemanticVersion.release(7, 4, 2) else gradleVersion - } -} diff --git a/src/main/kotlin/platform/fabric/creator/FabricProjectCreator.kt b/src/main/kotlin/platform/fabric/creator/FabricProjectCreator.kt deleted file mode 100644 index 470997184..000000000 --- a/src/main/kotlin/platform/fabric/creator/FabricProjectCreator.kt +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.fabric.creator - -import com.demonwav.mcdev.asset.MCDevBundle -import com.demonwav.mcdev.creator.BaseProjectCreator -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.LicenseStep -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.BasicGradleFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleFiles -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleGitignoreStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleWrapperStep -import com.demonwav.mcdev.creator.buildsystem.gradle.SimpleGradleSetupStep -import com.demonwav.mcdev.platform.fabric.EntryPoint -import com.demonwav.mcdev.platform.fabric.util.FabricConstants -import com.demonwav.mcdev.util.addAnnotation -import com.demonwav.mcdev.util.addImplements -import com.demonwav.mcdev.util.addMethod -import com.demonwav.mcdev.util.invokeLater -import com.demonwav.mcdev.util.runGradleTaskAndWait -import com.demonwav.mcdev.util.runWriteAction -import com.demonwav.mcdev.util.runWriteTask -import com.demonwav.mcdev.util.runWriteTaskInSmartMode -import com.demonwav.mcdev.util.virtualFile -import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils -import com.intellij.codeInsight.generation.OverrideImplementUtil -import com.intellij.codeInsight.generation.PsiMethodMember -import com.intellij.ide.util.EditorHelper -import com.intellij.json.JsonLanguage -import com.intellij.json.psi.JsonArray -import com.intellij.json.psi.JsonElementGenerator -import com.intellij.json.psi.JsonFile -import com.intellij.json.psi.JsonObject -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.module.Module -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.project.Project -import com.intellij.openapi.ui.Messages -import com.intellij.openapi.util.text.StringUtil -import com.intellij.psi.JavaDirectoryService -import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiFileFactory -import com.intellij.psi.PsiManager -import com.intellij.psi.PsiModifier -import com.intellij.psi.PsiModifierListOwner -import com.intellij.util.IncorrectOperationException -import java.nio.file.Files -import java.nio.file.Path -import java.util.Locale - -class FabricProjectCreator( - private val rootDirectory: Path, - private val rootModule: Module, - private val buildSystem: GradleBuildSystem, - private val config: FabricProjectConfig -) : BaseProjectCreator(rootModule, buildSystem) { - - override fun getSteps(): Iterable { - val buildText = FabricTemplate.applyBuildGradle(project, buildSystem, config) - val propText = FabricTemplate.applyGradleProp(project, buildSystem, config) - val settingsText = FabricTemplate.applySettingsGradle(project, buildSystem, config) - val files = GradleFiles(buildText, propText, settingsText) - - val steps = mutableListOf( - SimpleGradleSetupStep(project, rootDirectory, buildSystem, files), - GradleWrapperStep(project, rootDirectory, buildSystem) - ) - if (config.genSources) { - steps += GenSourcesStep(project, rootDirectory) - } - steps += GradleGitignoreStep(project, rootDirectory) - config.license?.let { - steps += LicenseStep(project, rootDirectory, it, config.authors.joinToString(", ")) - } - steps += BasicGradleFinalizerStep(rootModule, rootDirectory, buildSystem) - if (config.mixins) { - steps += MixinConfigStep(project, buildSystem, config) - } - createPostSteps(steps) - steps += FabricModJsonStep(project, buildSystem, config) - return steps - } - - private fun createPostSteps(steps: MutableList) { - for (entry in config.entryPoints.groupBy { it.className }.entries.sortedBy { it.key }) { - steps += CreateEntryPointStep(project, buildSystem, entry.key, entry.value) - } - } -} - -class GenSourcesStep( - private val project: Project, - private val rootDirectory: Path -) : CreatorStep { - - override fun runStep(indicator: ProgressIndicator) { - indicator.text = "Setting up project" - indicator.text2 = "Running Gradle task: 'genSources'" - runGradleTaskAndWait(project, rootDirectory) { settings -> - settings.taskNames = listOf("genSources") - settings.vmOptions = "-Xmx1G" - } - indicator.text2 = null - } -} - -class FabricModJsonStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val config: FabricProjectConfig -) : CreatorStep { - - override fun runStep(indicator: ProgressIndicator) { - val text = FabricTemplate.applyFabricModJsonTemplate(project, buildSystem, config) - val dir = buildSystem.dirsOrError.resourceDirectory - - indicator.text = "Indexing" - - project.runWriteTaskInSmartMode { - indicator.text = "Creating 'fabric.mod.json'" - - val file = PsiFileFactory.getInstance(project).createFileFromText(JsonLanguage.INSTANCE, text) - file.runWriteAction { - val jsonFile = file as JsonFile - val json = jsonFile.topLevelValue as? JsonObject ?: return@runWriteAction - val generator = JsonElementGenerator(project) - - (json.findProperty("authors")?.value as? JsonArray)?.let { authorsArray -> - for (i in config.authors.indices) { - if (i != 0) { - authorsArray.addBefore(generator.createComma(), authorsArray.lastChild) - } - authorsArray.addBefore(generator.createStringLiteral(config.authors[i]), authorsArray.lastChild) - } - } - - (json.findProperty("contact")?.value as? JsonObject)?.let { contactObject -> - val properties = mutableListOf>() - val website = config.website - if (!website.isNullOrBlank()) { - properties += "website" to website - } - val repo = config.modRepo - if (!repo.isNullOrBlank()) { - properties += "repo" to repo - } - for (i in properties.indices) { - if (i != 0) { - contactObject.addBefore(generator.createComma(), contactObject.lastChild) - } - val key = StringUtil.escapeStringCharacters(properties[i].first) - val value = "\"" + StringUtil.escapeStringCharacters(properties[i].second) + "\"" - contactObject.addBefore(generator.createProperty(key, value), contactObject.lastChild) - } - } - - (json.findProperty("entrypoints")?.value as? JsonObject)?.let { entryPointsObject -> - val entryPointsByCategory = config.entryPoints - .groupBy { it.category } - .asSequence() - .sortedBy { it.key } - .toList() - for (i in entryPointsByCategory.indices) { - val entryPointCategory = entryPointsByCategory[i] - if (i != 0) { - entryPointsObject.addBefore(generator.createComma(), entryPointsObject.lastChild) - } - val values = generator.createValue("[]") - for (j in entryPointCategory.value.indices) { - if (j != 0) { - values.addBefore(generator.createComma(), values.lastChild) - } - val entryPointReference = entryPointCategory.value[j].computeReference(project) - val value = generator.createStringLiteral(entryPointReference) - values.addBefore(value, values.lastChild) - } - val key = StringUtil.escapeStringCharacters(entryPointCategory.key) - val prop = generator.createProperty(key, "[]") - prop.value?.replace(values) - entryPointsObject.addBefore(prop, entryPointsObject.lastChild) - } - } - } - CreatorStep.writeTextToFile(project, dir, FabricConstants.FABRIC_MOD_JSON, file.text) - } - } -} - -class MixinConfigStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val config: FabricProjectConfig -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val text = FabricTemplate.applyMixinConfigTemplate(project, buildSystem, config) - val dir = buildSystem.dirsOrError.resourceDirectory - runWriteTask { - CreatorStep.writeTextToFile(project, dir, "${buildSystem.artifactId}.mixins.json", text) - } - } -} - -class CreateEntryPointStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val qualifiedClassName: String, - private val entryPoints: List -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val dirs = buildSystem.dirsOrError - - indicator.text = "Indexing" - - val dotIndex = qualifiedClassName.lastIndexOf('.') - val packageName = if (dotIndex == -1) { - "" - } else { - qualifiedClassName.substring(0, dotIndex) - } - val className = qualifiedClassName.substring(dotIndex + 1) - - var directory = dirs.sourceDirectory - for (part in packageName.split(".")) { - directory = directory.resolve(part) - } - if (Files.notExists(directory)) { - Files.createDirectories(directory) - } - - val virtualDir = directory.virtualFile ?: return - - project.runWriteTaskInSmartMode { - indicator.text = "Writing class: $className" - - val psiDir = PsiManager.getInstance(project).findDirectory(virtualDir) ?: return@runWriteTaskInSmartMode - val clazz = try { - JavaDirectoryService.getInstance().createClass(psiDir, className) - } catch (e: IncorrectOperationException) { - invokeLater { - val message = MCDevBundle.message( - "intention.error.cannot.create.class.message", - className, - e.localizedMessage - ) - Messages.showErrorDialog( - project, - message, - MCDevBundle.message("intention.error.cannot.create.class.title") - ) - } - return@runWriteTaskInSmartMode - } - - val editor = EditorHelper.openInEditor(clazz) - - clazz.containingFile.runWriteAction { - val clientEntryPoints = entryPoints.filter { it.category == "client" } - val serverEntryPoints = entryPoints.filter { it.category == "server" } - val otherEntryPoints = entryPoints.filter { it.category != "client" && it.category != "server" } - val entryPointsByInterface = entryPoints - .filter { it.type == EntryPoint.Type.CLASS } - .groupBy { it.interfaceName } - .entries - .sortedBy { it.key } - val entryPointsByMethodNameAndSig = entryPoints - .filter { it.type == EntryPoint.Type.METHOD } - .groupBy { entryPoint -> - val functionalMethod = entryPoint.findFunctionalMethod(project) ?: return@groupBy null - val paramTypes = functionalMethod.parameterList.parameters.map { it.type.canonicalText } - (entryPoint.methodName ?: functionalMethod.name) to paramTypes - } - .entries - .mapNotNull { it.key?.let { k -> k to it.value } } - .sortedBy { it.first.first } - - val elementFactory = JavaPsiFacade.getElementFactory(project) - - var isClientClass = false - var isServerClass = false - if (clientEntryPoints.isNotEmpty()) { - if (serverEntryPoints.isEmpty() && otherEntryPoints.isEmpty()) { - addEnvironmentAnnotation(clazz, "CLIENT") - isClientClass = true - } else { - addSidedInterfaceEntryPoints(entryPointsByInterface, clazz, editor, "client") - } - } else if (serverEntryPoints.isNotEmpty()) { - if (clientEntryPoints.isEmpty() && otherEntryPoints.isEmpty()) { - addEnvironmentAnnotation(clazz, "SERVER") - isServerClass = true - } else { - addSidedInterfaceEntryPoints(entryPointsByInterface, clazz, editor, "server") - } - } - - for (eps in entryPointsByInterface) { - clazz.addImplements(eps.key) - } - implementAll(clazz, editor) - - for (eps in entryPointsByMethodNameAndSig) { - val functionalMethod = eps.second.first().findFunctionalMethod(project) ?: continue - val newMethod = clazz.addMethod(functionalMethod) ?: continue - val methodName = eps.first.first - newMethod.nameIdentifier?.replace(elementFactory.createIdentifier(methodName)) - newMethod.modifierList.setModifierProperty(PsiModifier.PUBLIC, true) - newMethod.modifierList.setModifierProperty(PsiModifier.STATIC, true) - newMethod.modifierList.setModifierProperty(PsiModifier.ABSTRACT, false) - CreateFromUsageUtils.setupMethodBody(newMethod) - if (!isClientClass && eps.second.all { it.category == "client" }) { - addEnvironmentAnnotation(newMethod, "CLIENT") - } else if (!isServerClass && eps.second.all { it.category == "server" }) { - addEnvironmentAnnotation(newMethod, "SERVER") - } - } - } - } - } - - private fun addSidedInterfaceEntryPoints( - entryPointsByInterface: List>>, - clazz: PsiClass, - editor: Editor, - side: String - ) { - val capsSide = side.uppercase(Locale.ENGLISH) - var needsInterfaceFix = false - for (eps in entryPointsByInterface) { - if (eps.value.all { it.category == side }) { - addEnvironmentInterfaceAnnotation(clazz, capsSide, eps.key) - clazz.addImplements(eps.key) - needsInterfaceFix = true - } - } - if (needsInterfaceFix) { - implementAll(clazz, editor) - for (method in clazz.methods) { - if (!method.hasAnnotation(FabricConstants.ENVIRONMENT_ANNOTATION)) { - addEnvironmentAnnotation(method, capsSide) - } - } - } - } - - private fun addEnvironmentAnnotation(owner: PsiModifierListOwner, envType: String) { - owner.addAnnotation("@${FabricConstants.ENVIRONMENT_ANNOTATION}(${FabricConstants.ENV_TYPE}.$envType)") - } - - private fun addEnvironmentInterfaceAnnotation( - owner: PsiModifierListOwner, - envType: String, - interfaceQualifiedName: String - ) { - val annotationText = "@${FabricConstants.ENVIRONMENT_INTERFACE_ANNOTATION}(" + - "value=${FabricConstants.ENV_TYPE}.$envType," + - "itf=$interfaceQualifiedName.class" + - ")" - owner.addAnnotation(annotationText) - } - - private fun implementAll(clazz: PsiClass, editor: Editor) { - val methodsToImplement = OverrideImplementUtil.getMethodsToOverrideImplement(clazz, true) - .map { PsiMethodMember(it) } - OverrideImplementUtil.overrideOrImplementMethodsInRightPlace( - editor, - clazz, - methodsToImplement, - false, - true - ) - } -} diff --git a/src/main/kotlin/platform/fabric/creator/FabricProjectSettingsWizard.form b/src/main/kotlin/platform/fabric/creator/FabricProjectSettingsWizard.form deleted file mode 100644 index d60abb347..000000000 --- a/src/main/kotlin/platform/fabric/creator/FabricProjectSettingsWizard.form +++ /dev/null @@ -1,408 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/main/kotlin/platform/fabric/creator/FabricProjectSettingsWizard.kt b/src/main/kotlin/platform/fabric/creator/FabricProjectSettingsWizard.kt deleted file mode 100644 index faff532d3..000000000 --- a/src/main/kotlin/platform/fabric/creator/FabricProjectSettingsWizard.kt +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.fabric.creator - -import com.demonwav.mcdev.asset.PlatformAssets -import com.demonwav.mcdev.creator.MinecraftModuleWizardStep -import com.demonwav.mcdev.creator.MinecraftProjectCreator -import com.demonwav.mcdev.creator.ValidatedField -import com.demonwav.mcdev.creator.ValidatedFieldType.LIST -import com.demonwav.mcdev.creator.ValidatedFieldType.NON_BLANK -import com.demonwav.mcdev.platform.fabric.EntryPoint -import com.demonwav.mcdev.platform.fabric.util.FabricConstants -import com.demonwav.mcdev.platform.forge.inspections.sideonly.Side -import com.demonwav.mcdev.util.License -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.asyncIO -import com.demonwav.mcdev.util.modUpdateStep -import com.demonwav.mcdev.util.toPackageName -import com.extracraftx.minecraft.templatemakerfabric.data.DataProvider -import com.intellij.openapi.ui.ComboBox -import com.intellij.ui.CollectionComboBoxModel -import com.intellij.ui.ToolbarDecorator -import com.intellij.ui.table.JBTable -import com.intellij.util.ui.EditableModel -import com.intellij.util.ui.table.ComboBoxTableCellEditor -import java.awt.event.ActionListener -import java.awt.event.ComponentAdapter -import java.awt.event.ComponentEvent -import java.util.Collections -import java.util.Locale -import javax.swing.JCheckBox -import javax.swing.JComboBox -import javax.swing.JComponent -import javax.swing.JLabel -import javax.swing.JPanel -import javax.swing.JProgressBar -import javax.swing.JTextField -import javax.swing.table.AbstractTableModel -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import kotlinx.coroutines.swing.Swing -import org.apache.commons.lang.WordUtils - -class FabricProjectSettingsWizard(private val creator: MinecraftProjectCreator) : MinecraftModuleWizardStep() { - - // Initialize ALL custom fields in createUIComponents, otherwise they are null until after that point! - @ValidatedField(NON_BLANK) - private lateinit var modNameField: JTextField - private lateinit var panel: JPanel - private lateinit var title: JLabel - private lateinit var descriptionField: JTextField - - @ValidatedField(LIST) - private lateinit var authorsField: JTextField - private lateinit var websiteField: JTextField - private lateinit var repositoryField: JTextField - private lateinit var minecraftVersionBox: JComboBox - private lateinit var loaderVersionBox: JComboBox - private lateinit var yarnVersionBox: JComboBox - private lateinit var loomVersionBox: JComboBox - private lateinit var licenseBox: JComboBox - private lateinit var useFabricApiCheckbox: JCheckBox - private lateinit var fabricApiBox: JComboBox - private lateinit var environmentBox: JComboBox - private lateinit var mixinsCheckbox: JCheckBox - private lateinit var decompileMcCheckbox: JCheckBox - private lateinit var loadingBar: JProgressBar - private lateinit var minecraftVersionLabel: JLabel - private lateinit var entryPointsTable: JPanel - private lateinit var entryPoints: ArrayList - private lateinit var tableModel: EntryPointTableModel - private lateinit var yarnWarning: JLabel - private lateinit var errorLabel: JLabel - - private var config: FabricProjectConfig? = null - - private var dataProvider: DataProvider? = null - - private var currentJob: Job? = null - - private var initializedEntryPointsTable = false - - private val minecraftBoxActionListener: ActionListener = ActionListener { - yarnVersionBox.selectedItem = null - loaderVersionBox.selectedItem = null - loomVersionBox.selectedItem = null - fabricApiBox.selectedItem = null - updateForm() - } - - init { - yarnWarning.isVisible = false - errorLabel.isVisible = false - } - - fun createUIComponents() { - entryPoints = arrayListOf() - - tableModel = EntryPointTableModel(entryPoints) - val entryPointsTable = JBTable(tableModel) - entryPointsTable.setDefaultEditor(EntryPoint.Type::class.java, ComboBoxTableCellEditor.INSTANCE) - fun resizeColumns() { - val model = entryPointsTable.columnModel - val totalWidth = model.totalColumnWidth - model.getColumn(0).preferredWidth = (totalWidth * 0.1).toInt() - model.getColumn(1).preferredWidth = (totalWidth * 0.1).toInt() - model.getColumn(2).preferredWidth = (totalWidth * 0.3).toInt() - model.getColumn(3).preferredWidth = (totalWidth * 0.3).toInt() - model.getColumn(4).preferredWidth = (totalWidth * 0.2).toInt() - } - resizeColumns() - entryPointsTable.addComponentListener( - object : ComponentAdapter() { - override fun componentResized(e: ComponentEvent?) { - resizeColumns() - } - } - ) - this.entryPointsTable = ToolbarDecorator.createDecorator(entryPointsTable).createPanel() - - licenseBox = ComboBox(CollectionComboBoxModel(enumValues().toList())) - licenseBox.selectedItem = License.MIT - } - - override fun getComponent(): JComponent { - return panel - } - - override fun updateStep() { - val (conf, buildSystem) = modUpdateStep(creator, modNameField) ?: return - config = conf - - if (!initializedEntryPointsTable) { - val packageName = "${buildSystem.groupId.toPackageName()}.${buildSystem.artifactId.toPackageName()}" - val className = buildSystem.artifactId.replace('-', ' ').let { WordUtils.capitalize(it) }.replace(" ", "") - entryPoints.add( - EntryPoint( - "main", - EntryPoint.Type.CLASS, - "$packageName.$className", - FabricConstants.MOD_INITIALIZER - ) - ) - entryPoints.add( - EntryPoint( - "client", - EntryPoint.Type.CLASS, - "$packageName.client.${className}Client", - FabricConstants.CLIENT_MOD_INITIALIZER - ) - ) - tableModel.fireTableDataChanged() - entryPointsTable.revalidate() - initializedEntryPointsTable = true - } - - title.icon = PlatformAssets.FABRIC_ICON_2X - title.text = "Fabric Settings" - - minecraftVersionLabel.text = "Minecraft Version" - - if (dataProvider != null || currentJob?.isActive == true) { - return - } - currentJob = updateVersions() - } - - private val mcVersion: String? - get() = minecraftVersionBox.selectedItem as? String - - private val yarnVersion: String? - get() = yarnVersionBox.selectedItem as? String - - private val loomVersion: String? - get() = loomVersionBox.selectedItem as? String - - private val loaderVersion: String? - get() = loaderVersionBox.selectedItem as? String - - private val fabricApiVersion: String? - get() = fabricApiBox.selectedItem as? String - - override fun validate(): Boolean { - return super.validate() && !loadingBar.isVisible - } - - override fun isStepVisible(): Boolean { - return creator.config is FabricProjectConfig - } - - override fun onStepLeaving() { - currentJob?.cancel() - } - - fun error() { - errorLabel.isVisible = true - loadingBar.isIndeterminate = false - loadingBar.isVisible = false - } - - override fun updateDataModel() { - val conf = config ?: return - conf.pluginName = modNameField.text - conf.description = descriptionField.text - conf.website = websiteField.text - - conf.setAuthors(authorsField.text) - conf.modRepo = repositoryField.text - - conf.yarnVersion = yarnVersion ?: "$mcVersion+build.1" - val yarnVersionObj = dataProvider?.yarnVersions?.firstOrNull { it.name == yarnVersion } - conf.yarnClassifier = if (yarnVersionObj?.hasV2Mappings == false) { - null - } else { - "v2" - } - conf.mcVersion = mcVersion ?: "" - val normalizedMcVersion = dataProvider?.getNormalizedMinecraftVersion(mcVersion)?.normalized - conf.semanticMcVersion = normalizedMcVersion?.let { SemanticVersion.parse(it) } ?: SemanticVersion.release() - val loaderVer = loaderVersion - if (loaderVer != null) { - conf.loaderVersion = SemanticVersion.parse(loaderVer) - } - val api = if (useFabricApiCheckbox.isSelected) { - dataProvider?.fabricApiVersions?.firstOrNull { it.name == fabricApiVersion } - } else { - null - } - conf.apiVersion = api?.mavenVersion?.let { SemanticVersion.parse(it) } - conf.apiMavenLocation = api?.mavenLocation - conf.gradleVersion = when (dataProvider?.loomVersions?.firstOrNull { it.name == loomVersion }?.gradle) { - 4 -> SemanticVersion.release(4, 10, 3) - 5 -> SemanticVersion.release(5, 6, 4) - else -> SemanticVersion.release(6, 9) - } - val loomVer = loomVersion - if (loomVer != null) { - conf.loomVersion = SemanticVersion.parse(loomVer) - } - if (conf.loomVersion >= SemanticVersion.release(0, 7)) { - // TemplateMakerFabric incorrectly indicates loom 0.8 requires Gradle 6... - conf.gradleVersion = SemanticVersion.release(7, 3) - } - conf.environment = when ((environmentBox.selectedItem as? String)?.lowercase(Locale.ENGLISH)) { - "client" -> Side.CLIENT - "server" -> Side.SERVER - else -> Side.NONE - } - conf.license = licenseBox.selectedItem as? License - conf.entryPoints = entryPoints.filter { it.valid } - conf.mixins = mixinsCheckbox.isSelected - conf.genSources = decompileMcCheckbox.isSelected - } - - private fun updateVersions() = CoroutineScope(Dispatchers.Swing).launch { - loadingBar.isIndeterminate = true - loadingBar.isVisible = true - - try { - dataProvider = downloadVersions() - updateForm() - } catch (e: Exception) { - e.printStackTrace() - error() - } - - loadingBar.isIndeterminate = false - loadingBar.isVisible = false - - currentJob = null - } - - private suspend fun downloadVersions(): DataProvider? = coroutineScope { - // prefetch the data - val dataProvider = DataProvider() - val minecraftVersionJob = asyncIO { runCatching { dataProvider.minecraftVersions }.getOrNull() } - val fabricApiVersionJob = asyncIO { runCatching { dataProvider.fabricApiVersions }.getOrNull() } - val yarnVersionJob = asyncIO { runCatching { dataProvider.yarnVersions }.getOrNull() } - val loomVersionJob = asyncIO { runCatching { dataProvider.loomVersions }.getOrNull() } - val loaderVersionJob = asyncIO { runCatching { dataProvider.loaderVersions }.getOrNull() } - - val results = listOf( - minecraftVersionJob, - fabricApiVersionJob, - yarnVersionJob, - loomVersionJob, - loaderVersionJob, - ).awaitAll() - - if (results.any { it == null }) { - return@coroutineScope null - } - - return@coroutineScope dataProvider - } - - private fun updateForm() { - val dp = dataProvider ?: return - - val mcVer = mcVersion ?: dp.minecraftVersions.firstOrNull { it.stable }?.name - val mcVerObj = dp.minecraftVersions.firstOrNull { it.name == mcVer } - - val yarnVer = yarnVersion ?: mcVerObj?.let { mvo -> - dp.getFilteredYarnVersions(mvo).firstOrNull()?.name - } - val yarnVerObj = dp.yarnVersions.firstOrNull { it.name == yarnVer } - - val loomVer = loomVersion ?: yarnVerObj?.let { dp.getDefaultLoomVersion(it) }?.name - val loomVerObj = dp.loomVersions.firstOrNull { it.name == loomVer } - - val loaderVer = loaderVersion ?: loomVerObj?.let { lvo -> - dp.getFilteredLoaderVersions(lvo).firstOrNull()?.name - } - - val fabricVer = fabricApiVersion ?: mcVerObj?.let { mvo -> - dp.getDefaultFabricApiVersion(mvo) - }?.let { dp.sortedFabricApiVersions[it] }?.name - - minecraftVersionBox.removeActionListener(minecraftBoxActionListener) - minecraftVersionBox.model = CollectionComboBoxModel(dp.minecraftVersions.map { it.name }) - minecraftVersionBox.selectedItem = mcVer - minecraftVersionBox.addActionListener(minecraftBoxActionListener) - yarnVersionBox.model = CollectionComboBoxModel(dp.yarnVersions.map { it.name }) - yarnVersionBox.selectedItem = yarnVer - loomVersionBox.model = CollectionComboBoxModel(dp.loomVersions.map { it.name }) - loomVersionBox.selectedItem = loomVer - loaderVersionBox.model = CollectionComboBoxModel(dp.loaderVersions.map { it.name }) - loaderVersionBox.selectedItem = loaderVer - fabricApiBox.model = CollectionComboBoxModel(dp.fabricApiVersions.map { it.name }) - fabricApiBox.selectedItem = fabricVer - useFabricApiCheckbox.isSelected = fabricVer != null - } - - class EntryPointTableModel(private val entryPoints: ArrayList) : AbstractTableModel(), EditableModel { - - override fun getColumnName(col: Int) = when (col) { - 0 -> "Category" - 1 -> "Type" - 2 -> "Class" - 3 -> "Interface" - else -> "Method Name" - } - - override fun getRowCount() = entryPoints.size - - override fun getColumnCount() = 5 - - override fun getValueAt(row: Int, col: Int): Any? = when (col) { - 0 -> entryPoints[row].category - 1 -> entryPoints[row].type - 2 -> entryPoints[row].className - 3 -> entryPoints[row].interfaceName - else -> entryPoints[row].methodName - } - - override fun isCellEditable(row: Int, col: Int): Boolean { - return col != 4 || entryPoints.getOrNull(row)?.type == EntryPoint.Type.METHOD - } - - override fun setValueAt(value: Any?, row: Int, col: Int) { - when (col) { - 0 -> entryPoints[row] = entryPoints[row].copy(category = value.toString()) - 1 -> entryPoints[row] = entryPoints[row].copy(type = parseEntryPointType(value)) - 2 -> entryPoints[row] = entryPoints[row].copy(className = value.toString()) - 3 -> entryPoints[row] = entryPoints[row].copy(interfaceName = value.toString()) - 4 -> entryPoints[row] = entryPoints[row].copy(methodName = value.toString()) - } - fireTableCellUpdated(row, col) - } - - private fun parseEntryPointType(value: Any?): EntryPoint.Type { - return when (value) { - is EntryPoint.Type -> value - else -> enumValues().firstOrNull { - it.name.equals(value.toString(), ignoreCase = true) - } ?: EntryPoint.Type.CLASS - } - } - - override fun removeRow(idx: Int) { - entryPoints.removeAt(idx) - } - - override fun exchangeRows(oldIndex: Int, newIndex: Int) { - Collections.swap(entryPoints, oldIndex, newIndex) - } - - override fun canExchangeRows(oldIndex: Int, newIndex: Int) = true - - override fun addRow() { - entryPoints.add(EntryPoint("", EntryPoint.Type.CLASS, "", "", "")) - } - - override fun getColumnClass(col: Int): Class<*> { - return if (col == 1) { - EntryPoint.Type::class.java - } else { - String::class.java - } - } - } -} diff --git a/src/main/kotlin/platform/fabric/creator/FabricTemplate.kt b/src/main/kotlin/platform/fabric/creator/FabricTemplate.kt deleted file mode 100644 index a633deb91..000000000 --- a/src/main/kotlin/platform/fabric/creator/FabricTemplate.kt +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.fabric.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.platform.BaseTemplate -import com.demonwav.mcdev.platform.forge.inspections.sideonly.Side -import com.demonwav.mcdev.util.License -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FABRIC_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FABRIC_GRADLE_PROPERTIES_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FABRIC_MIXINS_JSON_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FABRIC_MOD_JSON_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FABRIC_SETTINGS_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FABRIC_SUBMODULE_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FABRIC_SUBMODULE_GRADLE_PROPERTIES_TEMPLATE -import com.demonwav.mcdev.util.toPackageName -import com.intellij.openapi.project.Project - -object FabricTemplate : BaseTemplate() { - - private fun Project.applyGradleTemplate( - templateName: String, - buildSystem: BuildSystem, - config: FabricProjectConfig - ): String { - val props = mutableMapOf( - "GROUP_ID" to buildSystem.groupId, - "ARTIFACT_ID" to buildSystem.artifactId, - "VERSION" to buildSystem.version, - "MC_VERSION" to config.mcVersion, - "YARN_MAPPINGS" to config.yarnVersion, - "LOADER_VERSION" to config.loaderVersion.toString(), - "LOOM_VERSION" to config.loomVersion.toString(), - "JAVA_VERSION" to config.javaVersion.feature - ) - config.yarnClassifier?.let { - props["YARN_CLASSIFIER"] = it - } - config.apiVersion?.let { - props["API_VERSION"] = it.toString() - } - config.apiMavenLocation?.let { - props["API_MAVEN_LOCATION"] = it - } - - return applyTemplate(templateName, props) - } - - fun applyBuildGradle( - project: Project, - buildSystem: BuildSystem, - config: FabricProjectConfig - ): String { - return project.applyGradleTemplate(FABRIC_BUILD_GRADLE_TEMPLATE, buildSystem, config) - } - - fun applyMultiModuleBuildGradle( - project: Project, - buildSystem: BuildSystem, - config: FabricProjectConfig - ): String { - return project.applyGradleTemplate(FABRIC_SUBMODULE_BUILD_GRADLE_TEMPLATE, buildSystem, config) - } - - fun applySettingsGradle( - project: Project, - buildSystem: BuildSystem, - config: FabricProjectConfig - ): String { - return project.applyGradleTemplate(FABRIC_SETTINGS_GRADLE_TEMPLATE, buildSystem, config) - } - - fun applyGradleProp( - project: Project, - buildSystem: BuildSystem, - config: FabricProjectConfig - ): String { - return project.applyGradleTemplate(FABRIC_GRADLE_PROPERTIES_TEMPLATE, buildSystem, config) - } - - fun applyMultiModuleGradleProp( - project: Project, - buildSystem: BuildSystem, - config: FabricProjectConfig - ): String { - return project.applyGradleTemplate(FABRIC_SUBMODULE_GRADLE_PROPERTIES_TEMPLATE, buildSystem, config) - } - - fun applyFabricModJsonTemplate( - project: Project, - buildSystem: BuildSystem, - config: FabricProjectConfig - ): String { - val props = mutableMapOf( - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "MOD_DESCRIPTION" to (config.description ?: ""), - "MOD_ENVIRONMENT" to when (config.environment) { - Side.CLIENT -> "client" - Side.SERVER -> "server" - else -> "*" - }, - "LOADER_VERSION" to config.loaderVersion.toString(), - "MC_VERSION" to config.semanticMcVersion.toString(), - "JAVA_VERSION" to config.javaVersion.feature, - "LICENSE" to ((config.license ?: License.ALL_RIGHTS_RESERVED).id) - ) - config.apiVersion?.let { - props["API_VERSION"] = it.toString() - } - if (config.mixins) { - props["MIXINS"] = "true" - } - - return project.applyTemplate(FABRIC_MOD_JSON_TEMPLATE, props) - } - - fun applyMixinConfigTemplate( - project: Project, - buildSystem: BuildSystem, - config: FabricProjectConfig - ): String { - val packageName = "${buildSystem.groupId.toPackageName()}.${buildSystem.artifactId.toPackageName()}.mixin" - val props = mapOf( - "PACKAGE_NAME" to packageName, - "JAVA_VERSION" to config.javaVersion.feature - ) - return project.applyTemplate(FABRIC_MIXINS_JSON_TEMPLATE, props) - } -} diff --git a/src/main/kotlin/platform/fabric/creator/asset-steps.kt b/src/main/kotlin/platform/fabric/creator/asset-steps.kt new file mode 100644 index 000000000..9ca458171 --- /dev/null +++ b/src/main/kotlin/platform/fabric/creator/asset-steps.kt @@ -0,0 +1,294 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.fabric.creator + +import com.demonwav.mcdev.asset.MCDevBundle +import com.demonwav.mcdev.creator.JdkProjectSetupFinalizer +import com.demonwav.mcdev.creator.addLicense +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.AbstractRunBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModNameStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.LicenseStep +import com.demonwav.mcdev.creator.step.RepositoryStep +import com.demonwav.mcdev.creator.step.UseMixinsStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.platform.fabric.EntryPoint +import com.demonwav.mcdev.platform.fabric.util.FabricConstants +import com.demonwav.mcdev.platform.forge.inspections.sideonly.Side +import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FABRIC_MIXINS_JSON_TEMPLATE +import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FABRIC_MOD_JSON_TEMPLATE +import com.demonwav.mcdev.util.addImplements +import com.demonwav.mcdev.util.addMethod +import com.demonwav.mcdev.util.invokeLater +import com.demonwav.mcdev.util.runWriteAction +import com.demonwav.mcdev.util.runWriteTaskInSmartMode +import com.demonwav.mcdev.util.toJavaClassName +import com.demonwav.mcdev.util.toPackageName +import com.intellij.codeInsight.actions.ReformatCodeProcessor +import com.intellij.codeInsight.generation.OverrideImplementUtil +import com.intellij.ide.starters.local.GeneratorEmptyDirectory +import com.intellij.ide.util.EditorHelper +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.json.psi.JsonArray +import com.intellij.json.psi.JsonElementGenerator +import com.intellij.json.psi.JsonFile +import com.intellij.json.psi.JsonObject +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.Messages +import com.intellij.openapi.util.text.StringUtil +import com.intellij.openapi.vfs.VfsUtil +import com.intellij.psi.JavaDirectoryService +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiManager +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.util.IncorrectOperationException +import java.nio.file.Path +import java.util.concurrent.CountDownLatch + +class FabricDumbModeFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Adding Fabric project files (phase 1)" + + override fun setupAssets(project: Project) { + val buildSystemProps = findStep>() + val useMixins = data.getUserData(UseMixinsStep.KEY) ?: false + val javaVersion = findStep().preferredJdk.ordinal + + if (useMixins) { + val packageName = + "${buildSystemProps.groupId.toPackageName()}.${buildSystemProps.artifactId.toPackageName()}.mixin" + assets.addTemplateProperties( + "PACKAGE_NAME" to packageName, + "JAVA_VERSION" to javaVersion, + ) + val mixinsJsonFile = "src/main/resources/${buildSystemProps.artifactId}.mixins.json" + assets.addTemplates(project, mixinsJsonFile to FABRIC_MIXINS_JSON_TEMPLATE) + } + + assets.addLicense(project) + + assets.addAssets( + GeneratorEmptyDirectory("src/main/java"), + GeneratorEmptyDirectory("src/main/resources"), + ) + } +} + +class FabricSmartModeFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Adding Fabric project files (phase 2)" + + private lateinit var entryPoints: List + + override fun setupAssets(project: Project) { + val buildSystemProps = findStep>() + val modName = data.getUserData(AbstractModNameStep.KEY) ?: return + val description = data.getUserData(DescriptionStep.KEY) ?: "" + val envName = when (data.getUserData(FabricEnvironmentStep.KEY) ?: Side.NONE) { + Side.CLIENT -> "client" + Side.SERVER -> "server" + else -> "*" + } + val loaderVersion = data.getUserData(FabricVersionChainStep.LOADER_VERSION_KEY) ?: return + val mcVersion = data.getUserData(FabricVersionChainStep.MC_VERSION_KEY) ?: return + val javaVersion = findStep().preferredJdk.ordinal + val license = data.getUserData(LicenseStep.KEY) ?: return + val apiVersion = data.getUserData(FabricVersionChainStep.API_VERSION_KEY) + val useMixins = data.getUserData(UseMixinsStep.KEY) ?: false + + val packageName = "${buildSystemProps.groupId.toPackageName()}.${buildSystemProps.artifactId.toPackageName()}" + val mainClassName = "$packageName.${modName.toJavaClassName()}" + val clientClassName = "$packageName.client.${modName.toJavaClassName()}Client" + entryPoints = listOf( + EntryPoint("main", EntryPoint.Type.CLASS, mainClassName, FabricConstants.MOD_INITIALIZER), + EntryPoint("client", EntryPoint.Type.CLASS, clientClassName, FabricConstants.CLIENT_MOD_INITIALIZER), + ) // TODO: un-hardcode? + + assets.addTemplateProperties( + "ARTIFACT_ID" to buildSystemProps.artifactId, + "MOD_NAME" to StringUtil.escapeStringCharacters(modName), + "MOD_DESCRIPTION" to StringUtil.escapeStringCharacters(description), + "MOD_ENVIRONMENT" to envName, + "LOADER_VERSION" to loaderVersion, + "MC_VERSION" to mcVersion, + "JAVA_VERSION" to javaVersion, + "LICENSE" to license.id, + ) + + if (apiVersion != null) { + assets.addTemplateProperties("API_VERSION" to apiVersion) + } + + if (useMixins) { + assets.addTemplateProperties("MIXINS" to "true") + } + + assets.addTemplates(project, "src/main/resources/fabric.mod.json" to FABRIC_MOD_JSON_TEMPLATE) + } + + private fun fixupFabricModJson(project: Project) { + val authors = data.getUserData(AuthorsStep.KEY) ?: emptyList() + val website = data.getUserData(WebsiteStep.KEY) + val repo = data.getUserData(RepositoryStep.KEY) + + val fabricModJsonFile = + VfsUtil.findFile(Path.of(context.projectFileDirectory, "src", "main", "resources", "fabric.mod.json"), true) + ?: return + val jsonFile = PsiManager.getInstance(project).findFile(fabricModJsonFile) as? JsonFile ?: return + val json = jsonFile.topLevelValue as? JsonObject ?: return + val generator = JsonElementGenerator(project) + + jsonFile.runWriteAction { + (json.findProperty("authors")?.value as? JsonArray)?.let { authorsArray -> + for (i in authors.indices) { + if (i != 0) { + authorsArray.addBefore(generator.createComma(), authorsArray.lastChild) + } + authorsArray.addBefore(generator.createStringLiteral(authors[i]), authorsArray.lastChild) + } + } + + (json.findProperty("contact")?.value as? JsonObject)?.let { contactObject -> + val properties = mutableListOf>() + if (!website.isNullOrBlank()) { + properties += "website" to website + } + if (!repo.isNullOrBlank()) { + properties += "repo" to repo + } + for (i in properties.indices) { + if (i != 0) { + contactObject.addBefore(generator.createComma(), contactObject.lastChild) + } + val key = StringUtil.escapeStringCharacters(properties[i].first) + val value = "\"" + StringUtil.escapeStringCharacters(properties[i].second) + "\"" + contactObject.addBefore(generator.createProperty(key, value), contactObject.lastChild) + } + } + + (json.findProperty("entrypoints")?.value as? JsonObject)?.let { entryPointsObject -> + val entryPointsByCategory = entryPoints + .groupBy { it.category } + .asSequence() + .sortedBy { it.key } + .toList() + for (i in entryPointsByCategory.indices) { + val entryPointCategory = entryPointsByCategory[i] + if (i != 0) { + entryPointsObject.addBefore(generator.createComma(), entryPointsObject.lastChild) + } + val values = generator.createValue("[]") + for (j in entryPointCategory.value.indices) { + if (j != 0) { + values.addBefore(generator.createComma(), values.lastChild) + } + val entryPointReference = entryPointCategory.value[j].computeReference(project) + val value = generator.createStringLiteral(entryPointReference) + values.addBefore(value, values.lastChild) + } + val key = StringUtil.escapeStringCharacters(entryPointCategory.key) + val prop = generator.createProperty(key, "[]") + prop.value?.replace(values) + entryPointsObject.addBefore(prop, entryPointsObject.lastChild) + } + } + + ReformatCodeProcessor(project, jsonFile, null, false).run() + } + } + + private fun createEntryPoints(project: Project) { + val root = VfsUtil.findFile(Path.of(context.projectFileDirectory), true) ?: return + val psiManager = PsiManager.getInstance(project) + + val generatedClasses = mutableSetOf() + + for (entryPoint in entryPoints) { + // find the class, and create it if it doesn't exist + val clazz = JavaPsiFacade.getInstance(project).findClass( + entryPoint.className, + GlobalSearchScope.projectScope(project), + ) ?: run { + val packageName = entryPoint.className.substringBeforeLast('.', missingDelimiterValue = "") + val className = entryPoint.className.substringAfterLast('.') + + val dir = VfsUtil.createDirectoryIfMissing(root, "src/main/java/${packageName.replace('.', '/')}") + val psiDir = psiManager.findDirectory(dir) ?: return@run null + try { + JavaDirectoryService.getInstance().createClass(psiDir, className) + } catch (e: IncorrectOperationException) { + invokeLater { + val message = MCDevBundle.message( + "intention.error.cannot.create.class.message", + className, + e.localizedMessage, + ) + Messages.showErrorDialog( + project, + message, + MCDevBundle.message("intention.error.cannot.create.class.title"), + ) + } + return + } + } ?: continue + + clazz.containingFile.runWriteAction { + clazz.addImplements(entryPoint.interfaceName) + + val methodsToImplement = OverrideImplementUtil.getMethodsToOverrideImplement(clazz, true) + val methods = OverrideImplementUtil.overrideOrImplementMethodCandidates(clazz, methodsToImplement, true) + for (method in methods) { + clazz.addMethod(method) + } + } + + generatedClasses += clazz + } + + for (clazz in generatedClasses) { + ReformatCodeProcessor(project, clazz.containingFile, null, false).run() + EditorHelper.openInEditor(clazz) + } + } + + override fun perform(project: Project) { + super.perform(project) + val latch = CountDownLatch(1) + assets.runWhenCreated(project) { + project.runWriteTaskInSmartMode { + try { + fixupFabricModJson(project) + createEntryPoints(project) + } finally { + latch.countDown() + } + } + } + latch.await() + } +} + +class FabricBuildSystemStep(parent: NewProjectWizardStep) : AbstractBuildSystemStep(parent) { + override val platformName = "Fabric" +} + +class FabricPostBuildSystemStep( + parent: NewProjectWizardStep, +) : AbstractRunBuildSystemStep(parent, FabricBuildSystemStep::class.java) { + override val step = BuildSystemSupport.POST_STEP +} diff --git a/src/main/kotlin/platform/fabric/creator/gradle-steps.kt b/src/main/kotlin/platform/fabric/creator/gradle-steps.kt new file mode 100644 index 000000000..d40ddd7d6 --- /dev/null +++ b/src/main/kotlin/platform/fabric/creator/gradle-steps.kt @@ -0,0 +1,82 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.fabric.creator + +import com.demonwav.mcdev.creator.EmptyStep +import com.demonwav.mcdev.creator.JdkProjectSetupFinalizer +import com.demonwav.mcdev.creator.addGradleGitignore +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.buildsystem.GradleImportStep +import com.demonwav.mcdev.creator.buildsystem.GradleWrapperStep +import com.demonwav.mcdev.creator.buildsystem.addGradleWrapperProperties +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.gitEnabled +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.util.MinecraftTemplates +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.project.Project + +class FabricGradleSupport : BuildSystemSupport { + override val preferred = true + + override fun createStep(step: String, parent: NewProjectWizardStep): NewProjectWizardStep { + return when (step) { + BuildSystemSupport.PRE_STEP -> FabricGradleFilesStep(parent).chain(::GradleWrapperStep) + BuildSystemSupport.POST_STEP -> GradleImportStep(parent) + else -> EmptyStep(parent) + } + } +} + +class FabricGradleFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating Gradle files" + + override fun setupAssets(project: Project) { + val buildSystemProps = findStep>() + val mcVersion = data.getUserData(FabricVersionChainStep.MC_VERSION_KEY) ?: return + val yarnVersion = data.getUserData(FabricVersionChainStep.YARN_VERSION_KEY) ?: return + val loaderVersion = data.getUserData(FabricVersionChainStep.LOADER_VERSION_KEY) ?: return + val loomVersion = "1.0-SNAPSHOT" // TODO + val javaVersion = findStep().preferredJdk.ordinal + val apiVersion = data.getUserData(FabricVersionChainStep.API_VERSION_KEY) + + assets.addTemplateProperties( + "GROUP_ID" to buildSystemProps.groupId, + "ARTIFACT_ID" to buildSystemProps.artifactId, + "VERSION" to buildSystemProps.version, + "MC_VERSION" to mcVersion, + "YARN_MAPPINGS" to yarnVersion, + "LOADER_VERSION" to loaderVersion, + "LOOM_VERSION" to loomVersion, + "JAVA_VERSION" to javaVersion, + ) + + if (apiVersion != null) { + assets.addTemplateProperties("API_VERSION" to apiVersion) + } + + assets.addTemplates( + project, + "build.gradle" to MinecraftTemplates.FABRIC_BUILD_GRADLE_TEMPLATE, + "gradle.properties" to MinecraftTemplates.FABRIC_GRADLE_PROPERTIES_TEMPLATE, + "settings.gradle" to MinecraftTemplates.FABRIC_SETTINGS_GRADLE_TEMPLATE, + ) + + assets.addGradleWrapperProperties(project) + + if (gitEnabled) { + assets.addGradleGitignore(project) + } + } +} diff --git a/src/main/kotlin/platform/fabric/creator/ui-steps.kt b/src/main/kotlin/platform/fabric/creator/ui-steps.kt new file mode 100644 index 000000000..60ab008f4 --- /dev/null +++ b/src/main/kotlin/platform/fabric/creator/ui-steps.kt @@ -0,0 +1,260 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.fabric.creator + +import com.demonwav.mcdev.creator.chain +import com.demonwav.mcdev.creator.platformtype.ModPlatformStep +import com.demonwav.mcdev.creator.step.AbstractCollapsibleStep +import com.demonwav.mcdev.creator.step.AbstractLatentStep +import com.demonwav.mcdev.creator.step.AbstractMcVersionChainStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.LicenseStep +import com.demonwav.mcdev.creator.step.ModNameStep +import com.demonwav.mcdev.creator.step.RepositoryStep +import com.demonwav.mcdev.creator.step.UseMixinsStep +import com.demonwav.mcdev.creator.step.WaitForSmartModeStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.platform.fabric.util.FabricApiVersions +import com.demonwav.mcdev.platform.fabric.util.FabricVersions +import com.demonwav.mcdev.platform.forge.inspections.sideonly.Side +import com.demonwav.mcdev.util.SemanticVersion +import com.demonwav.mcdev.util.asyncIO +import com.demonwav.mcdev.util.bindEnabled +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.observable.util.bindBooleanStorage +import com.intellij.openapi.observable.util.bindStorage +import com.intellij.openapi.observable.util.transform +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.ComboBox +import com.intellij.openapi.util.Key +import com.intellij.ui.JBColor +import com.intellij.ui.dsl.builder.Cell +import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.Row +import com.intellij.ui.dsl.builder.bindItem +import com.intellij.ui.dsl.builder.bindSelected +import com.intellij.ui.dsl.builder.bindText +import com.intellij.util.IncorrectOperationException +import kotlinx.coroutines.coroutineScope + +class FabricPlatformStep( + parent: ModPlatformStep, +) : AbstractLatentStep>(parent) { + override val description = "download Fabric versions" + + override suspend fun computeData() = coroutineScope { + val fabricVersions = asyncIO { FabricVersions.downloadData() } + val fabricApiVersions = asyncIO { FabricApiVersions.downloadData() } + fabricVersions.await()?.let { a -> fabricApiVersions.await()?.let { b -> a to b } } + } + + override fun createStep(data: Pair): NewProjectWizardStep { + val (fabricVersions, apiVersions) = data + return FabricVersionChainStep(this, fabricVersions, apiVersions) + .chain( + ::FabricEnvironmentStep, + ::UseMixinsStep, + ::ModNameStep, + ::LicenseStep, + ::FabricOptionalSettingsStep, + ::FabricBuildSystemStep, + ::FabricDumbModeFilesStep, + ::FabricPostBuildSystemStep, + ::WaitForSmartModeStep, + ::FabricSmartModeFilesStep, + ) + } + + class Factory : ModPlatformStep.Factory { + override val name = "Fabric" + override fun createStep(parent: ModPlatformStep) = FabricPlatformStep(parent) + } +} + +class FabricVersionChainStep( + parent: NewProjectWizardStep, + private val fabricVersions: FabricVersions, + private val apiVersions: FabricApiVersions, +) : AbstractMcVersionChainStep(parent, "Loader Version:", "Yarn Version:", "API Version:") { + companion object { + private const val LOADER_VERSION = 1 + private const val YARN_VERSION = 2 + private const val API_VERSION = 3 + + val MC_VERSION_KEY = Key.create("${FabricVersionChainStep::class.java.name}.mcVersion") + val LOADER_VERSION_KEY = Key.create("${FabricVersionChainStep::class.java.name}.loaderVersion") + val YARN_VERSION_KEY = Key.create("${FabricVersionChainStep::class.java.name}.yarnVersion") + val API_VERSION_KEY = Key.create("${FabricVersionChainStep::class.java.name}.apiVersion") + } + + private val showSnapshotsProperty = propertyGraph.property(false) + .bindBooleanStorage("${javaClass.name}.showSnapshots") + private var showSnapshots by showSnapshotsProperty + + private val useApiProperty = propertyGraph.property(true) + .bindBooleanStorage("${javaClass.name}.useApi") + private var useApi by useApiProperty + + init { + showSnapshotsProperty.afterChange { updateVersionBox() } + } + + private val mcVersions by lazy { + fabricVersions.game.mapIndexed { index, version -> + FabricMcVersion(fabricVersions.game.size - 1 - index, version.version, version.stable) + } + } + + override fun createComboBox(row: Row, index: Int, items: List>): Cell>> { + return when (index) { + MINECRAFT_VERSION -> { + val comboBox = super.createComboBox(row, index, items) + row.checkBox("Show snapshots").bindSelected(showSnapshotsProperty) + comboBox + } + YARN_VERSION -> { + val comboBox = super.createComboBox(row, index, items) + row.label("").bindText( + getVersionProperty(MINECRAFT_VERSION).transform { mcVersion -> + mcVersion as FabricMcVersion + val matched = fabricVersions.mappings.any { it.gameVersion == mcVersion.version } + if (matched) { + "" + } else { + "Unable to match Yarn versions to Minecraft version" + } + }, + ).component.foreground = JBColor.YELLOW + comboBox + } + API_VERSION -> { + val comboBox = super.createComboBox(row, index, items).bindEnabled(useApiProperty) + row.checkBox("Use Fabric API").bindSelected(useApiProperty) + row.label("").bindText( + getVersionProperty(MINECRAFT_VERSION).transform { mcVersion -> + mcVersion as FabricMcVersion + val matched = apiVersions.versions.any { mcVersion.version in it.gameVersions } + if (matched) { + "" + } else { + "Unable to match API versions to Minecraft version" + } + }, + ).bindEnabled(useApiProperty).component.foreground = JBColor.YELLOW + comboBox + } + else -> super.createComboBox(row, index, items) + } + } + + override fun getAvailableVersions(versionsAbove: List>): List> { + return when (versionsAbove.size) { + MINECRAFT_VERSION -> mcVersions + LOADER_VERSION -> fabricVersions.loader + YARN_VERSION -> { + val mcVersion = versionsAbove[MINECRAFT_VERSION] as FabricMcVersion + val filteredVersions = fabricVersions.mappings.mapNotNull { mapping -> + mapping.version.takeIf { mapping.gameVersion == mcVersion.version } + } + filteredVersions.ifEmpty { fabricVersions.mappings.map { it.version } } + } + API_VERSION -> { + val mcVersion = versionsAbove[MINECRAFT_VERSION] as FabricMcVersion + val filteredVersions = apiVersions.versions.mapNotNull { api -> + api.version.takeIf { mcVersion.version in api.gameVersions } + } + filteredVersions.ifEmpty { apiVersions.versions.map { it.version } } + } + else -> throw IncorrectOperationException() + } + } + + override fun setupUI(builder: Panel) { + super.setupUI(builder) + if (!showSnapshots) { + updateVersionBox() + } + } + + private fun updateVersionBox() { + val versionBox = getVersionBox(MINECRAFT_VERSION) ?: return + val selectedItem = versionBox.selectedItem + versionBox.removeAllItems() + for (gameVer in mcVersions) { + if (showSnapshots || gameVer.stable) { + versionBox.addItem(gameVer) + } + } + versionBox.selectedItem = selectedItem + } + + override fun setupProject(project: Project) { + super.setupProject(project) + data.putUserData(MC_VERSION_KEY, (getVersion(MINECRAFT_VERSION) as FabricMcVersion).version) + data.putUserData(LOADER_VERSION_KEY, getVersion(LOADER_VERSION) as SemanticVersion) + data.putUserData(YARN_VERSION_KEY, (getVersion(YARN_VERSION) as FabricVersions.YarnVersion).name) + if (useApi) { + data.putUserData(API_VERSION_KEY, getVersion(API_VERSION) as SemanticVersion) + } + } +} + +class FabricEnvironmentStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { + private val environmentProperty = propertyGraph.property(Side.NONE) + init { + environmentProperty.transform(Side::name, Side::valueOf).bindStorage("${javaClass.name}.side") + } + private var environment by environmentProperty + + override fun setupUI(builder: Panel) { + with(builder) { + row("Environment:") { + comboBox(listOf("Both", "Client", "Server")) + .bindItem( + environmentProperty.transform({ + when (it) { + Side.CLIENT -> "Client" + Side.SERVER -> "Server" + else -> "Both" + } + }, { + when (it) { + "Client" -> Side.CLIENT + "Server" -> Side.SERVER + else -> Side.NONE + } + },), + ) + } + } + } + + override fun setupProject(project: Project) { + data.putUserData(KEY, environment) + } + + companion object { + val KEY = Key.create("${FabricEnvironmentStep::class.java.name}.environment") + } +} + +class FabricOptionalSettingsStep(parent: NewProjectWizardStep) : AbstractCollapsibleStep(parent) { + override val title = "Optional Settings" + + override fun createStep() = DescriptionStep(this).chain( + ::AuthorsStep, + ::WebsiteStep, + ::RepositoryStep, + ) +} diff --git a/src/main/kotlin/platform/fabric/inspection/UnresolvedReferenceInspection.kt b/src/main/kotlin/platform/fabric/inspection/UnresolvedReferenceInspection.kt index 97d47b897..3f163bf45 100644 --- a/src/main/kotlin/platform/fabric/inspection/UnresolvedReferenceInspection.kt +++ b/src/main/kotlin/platform/fabric/inspection/UnresolvedReferenceInspection.kt @@ -53,7 +53,7 @@ class UnresolvedReferenceInspection : LocalInspectionTool() { literal, "Cannot resolve ${reference.description}".format(reference.canonicalText), ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, - reference.rangeInElement + reference.rangeInElement, ) } } diff --git a/src/main/kotlin/platform/fabric/reference/EntryPointReference.kt b/src/main/kotlin/platform/fabric/reference/EntryPointReference.kt index b7f696c97..a5c128da1 100644 --- a/src/main/kotlin/platform/fabric/reference/EntryPointReference.kt +++ b/src/main/kotlin/platform/fabric/reference/EntryPointReference.kt @@ -49,8 +49,8 @@ object EntryPointReference : PsiReferenceProvider() { element, range.cutOut(TextRange.from(cursor, clazzPart.length)), innerClassDepth, - false - ) + false, + ), ) cursor += clazzPart.length } @@ -61,8 +61,8 @@ object EntryPointReference : PsiReferenceProvider() { element, range.cutOut(TextRange.from(cursor, methodParts[1].length)), innerClassDepth, - true - ) + true, + ), ) } return references.toTypedArray() @@ -71,7 +71,7 @@ object EntryPointReference : PsiReferenceProvider() { private fun resolveReference( element: JsonStringLiteral, innerClassDepth: Int, - isMethodReference: Boolean + isMethodReference: Boolean, ): Array { val strReference = element.value val methodParts = strReference.split("::", limit = 2) @@ -81,7 +81,9 @@ object EntryPointReference : PsiReferenceProvider() { if (innerClassDepth >= clazzParts.size || innerClassDepth + 1 < clazzParts.size && isMethodReference - ) throw IncorrectOperationException("Invalid reference") + ) { + throw IncorrectOperationException("Invalid reference") + } var clazz = JavaPsiFacade.getInstance(element.project).findClass(clazzParts[0], element.resolveScope) ?: return PsiElement.EMPTY_ARRAY // if class is inner class, then a dot "." was used as separator instead of a dollar sign "$", this does not work to reference an inner class @@ -112,7 +114,7 @@ object EntryPointReference : PsiReferenceProvider() { element: JsonStringLiteral, range: TextRange, private val innerClassDepth: Int, - private val isMethodReference: Boolean + private val isMethodReference: Boolean, ) : PsiReferenceBase(element, range), PsiPolyVariantReference, diff --git a/src/main/kotlin/platform/fabric/reference/FabricReferenceContributor.kt b/src/main/kotlin/platform/fabric/reference/FabricReferenceContributor.kt index 32172e3d1..aae248699 100644 --- a/src/main/kotlin/platform/fabric/reference/FabricReferenceContributor.kt +++ b/src/main/kotlin/platform/fabric/reference/FabricReferenceContributor.kt @@ -28,24 +28,24 @@ class FabricReferenceContributor : PsiReferenceContributor() { PlatformPatterns.psiElement(JsonArray::class.java) .withSuperParent( 2, - PlatformPatterns.psiElement(JsonObject::class.java).isPropertyValue("entrypoints") - ) + PlatformPatterns.psiElement(JsonObject::class.java).isPropertyValue("entrypoints"), + ), ) registrar.registerReferenceProvider(entryPointPattern, EntryPointReference) val mixinConfigPattern = stringInModJson.withParent( - PlatformPatterns.psiElement(JsonArray::class.java).isPropertyValue("mixins") + PlatformPatterns.psiElement(JsonArray::class.java).isPropertyValue("mixins"), ) registrar.registerReferenceProvider(mixinConfigPattern, ResourceFileReference("mixin config '%s'")) registrar.registerReferenceProvider( stringInModJson.isPropertyValue("accessWidener"), - ResourceFileReference("access widener '%s'") + ResourceFileReference("access widener '%s'"), ) registrar.registerReferenceProvider( stringInModJson.isPropertyValue("icon"), - ResourceFileReference("icon '%s'") + ResourceFileReference("icon '%s'"), ) registrar.registerReferenceProvider(stringInModJson.isPropertyValue("license"), LicenseReference) diff --git a/src/main/kotlin/platform/fabric/util/FabricApiVersions.kt b/src/main/kotlin/platform/fabric/util/FabricApiVersions.kt new file mode 100644 index 000000000..90fa49534 --- /dev/null +++ b/src/main/kotlin/platform/fabric/util/FabricApiVersions.kt @@ -0,0 +1,78 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.fabric.util + +import com.demonwav.mcdev.creator.selectProxy +import com.demonwav.mcdev.update.PluginUtil +import com.demonwav.mcdev.util.SemanticVersion +import com.github.kittinunf.fuel.core.FuelManager +import com.github.kittinunf.fuel.core.requests.suspendable +import com.google.gson.JsonParser +import com.google.gson.JsonSyntaxException +import com.intellij.openapi.diagnostic.logger +import java.io.IOException + +private val LOGGER = logger() + +class FabricApiVersions(val versions: List) { + class Version(val gameVersions: List, val version: SemanticVersion) + + companion object { + suspend fun downloadData(): FabricApiVersions? { + try { + val url = "https://api.modrinth.com/v2/project/P7dR8mSH/version" + val manager = FuelManager() + manager.proxy = selectProxy(url) + + val response = manager.get(url) + .header("User-Agent", PluginUtil.useragent) + .suspendable() + .await() + + val versions = mutableListOf() + response.body().toStream().use { stream -> + val json = JsonParser.parseReader(stream.reader())?.asJsonArray ?: return null + versionLoop@ + for (ver in json) { + val version = ver?.asJsonObject ?: return null + val files = version["files"]?.asJsonArray ?: return null + for (file in files) { + val fileObj = file?.asJsonObject ?: return null + val filename = fileObj["filename"]?.asString ?: return null + if (!filename.startsWith("fabric-api-")) { + continue@versionLoop + } + } + val versionNumber = version["version_number"]?.asString?.let(SemanticVersion::tryParse) + ?: return null + val gameVersions = version["game_versions"]?.asJsonArray ?: return null + val gameVersionsList = mutableListOf() + for (gameVer in gameVersions) { + val gameVersion = gameVer?.asString ?: return null + gameVersionsList += gameVersion + } + versions += Version(gameVersionsList, versionNumber) + } + } + return FabricApiVersions(versions) + } catch (e: IOException) { + LOGGER.error(e) + } catch (e: JsonSyntaxException) { + LOGGER.error(e) + } catch (e: IllegalStateException) { + LOGGER.error(e) + } catch (e: UnsupportedOperationException) { + LOGGER.error(e) + } + return null + } + } +} diff --git a/src/main/kotlin/platform/fabric/util/FabricVersions.kt b/src/main/kotlin/platform/fabric/util/FabricVersions.kt new file mode 100644 index 000000000..8c8c2f8fb --- /dev/null +++ b/src/main/kotlin/platform/fabric/util/FabricVersions.kt @@ -0,0 +1,89 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.fabric.util + +import com.demonwav.mcdev.creator.selectProxy +import com.demonwav.mcdev.update.PluginUtil +import com.demonwav.mcdev.util.SemanticVersion +import com.github.kittinunf.fuel.core.FuelManager +import com.github.kittinunf.fuel.core.requests.suspendable +import com.google.gson.JsonParser +import com.google.gson.JsonSyntaxException +import com.intellij.openapi.diagnostic.logger +import java.io.IOException + +private val LOGGER = logger() + +class FabricVersions(val game: List, val mappings: List, val loader: List) { + class Game(val version: String, val stable: Boolean) + class Mappings(val gameVersion: String, val version: YarnVersion) + + class YarnVersion(val name: String, val build: Int) : Comparable { + override fun toString() = name + override fun compareTo(other: YarnVersion) = build.compareTo(other.build) + } + + companion object { + suspend fun downloadData(): FabricVersions? { + try { + val url = "https://meta.fabricmc.net/v2/versions" + val manager = FuelManager() + manager.proxy = selectProxy(url) + + val response = manager.get(url) + .header("User-Agent", PluginUtil.useragent) + .suspendable() + .await() + + val gameList = mutableListOf() + val mappingsList = mutableListOf() + val loaderList = mutableListOf() + response.body().toStream().use { stream -> + val json = JsonParser.parseReader(stream.reader())?.asJsonObject ?: return null + + val game = json["game"]?.asJsonArray ?: return null + for (version in game) { + val versionObj = version?.asJsonObject ?: return null + val gameVer = versionObj["version"]?.asString ?: return null + val stable = versionObj["stable"]?.asBoolean ?: return null + gameList += Game(gameVer, stable) + } + + val mappings = json["mappings"]?.asJsonArray ?: return null + for (mapping in mappings) { + val mappingObj = mapping?.asJsonObject ?: return null + val gameVersion = mappingObj["gameVersion"]?.asString ?: return null + val version = mappingObj["version"]?.asString ?: return null + val build = mappingObj["build"]?.asInt ?: return null + mappingsList += Mappings(gameVersion, YarnVersion(version, build)) + } + + val loaders = json["loader"]?.asJsonArray ?: return null + for (loader in loaders) { + val loaderObj = loader?.asJsonObject ?: return null + val version = loaderObj["version"]?.asString?.let(SemanticVersion::tryParse) ?: return null + loaderList += version + } + } + return FabricVersions(gameList, mappingsList, loaderList) + } catch (e: IOException) { + LOGGER.error(e) + } catch (e: JsonSyntaxException) { + LOGGER.error(e) + } catch (e: IllegalStateException) { + LOGGER.error(e) + } catch (e: UnsupportedOperationException) { + LOGGER.error(e) + } + return null + } + } +} diff --git a/src/main/kotlin/platform/forge/ForgeModule.kt b/src/main/kotlin/platform/forge/ForgeModule.kt index 22ba2ec2e..fd1613298 100644 --- a/src/main/kotlin/platform/forge/ForgeModule.kt +++ b/src/main/kotlin/platform/forge/ForgeModule.kt @@ -21,6 +21,7 @@ import com.demonwav.mcdev.platform.forge.util.ForgeConstants import com.demonwav.mcdev.platform.mcp.McpModuleSettings import com.demonwav.mcdev.util.SemanticVersion import com.demonwav.mcdev.util.SourceType +import com.demonwav.mcdev.util.createVoidMethodWithParameterType import com.demonwav.mcdev.util.extendsOrImplements import com.demonwav.mcdev.util.nullable import com.demonwav.mcdev.util.runWriteTaskLater @@ -32,11 +33,9 @@ import com.intellij.openapi.fileTypes.FileTypeManager import com.intellij.openapi.project.DumbService import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiClass -import com.intellij.psi.PsiClassType import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod import com.intellij.psi.PsiMethodCallExpression -import com.intellij.psi.PsiType import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.searches.AnnotatedElementsSearch import org.jetbrains.uast.UClass @@ -117,7 +116,7 @@ class ForgeModule internal constructor(facet: MinecraftFacet) : AbstractModule(f return formatWrongEventMessage( ForgeConstants.EVENTBUS_EVENT, ForgeConstants.EVENTBUS_SUBSCRIBE_EVENT_ANNOTATION, - ForgeConstants.EVENTBUS_EVENT == eventClass.qualifiedName + ForgeConstants.EVENTBUS_EVENT == eventClass.qualifiedName, ) } @@ -127,14 +126,14 @@ class ForgeModule internal constructor(facet: MinecraftFacet) : AbstractModule(f return formatWrongEventMessage( ForgeConstants.FML_EVENT, ForgeConstants.SUBSCRIBE_EVENT_ANNOTATION, - ForgeConstants.EVENT == eventClass.qualifiedName + ForgeConstants.EVENT == eventClass.qualifiedName, ) } return formatWrongEventMessage( ForgeConstants.EVENT, ForgeConstants.EVENT_HANDLER_ANNOTATION, - ForgeConstants.FML_EVENT == eventClass.qualifiedName + ForgeConstants.FML_EVENT == eventClass.qualifiedName, ) } @@ -152,21 +151,11 @@ class ForgeModule internal constructor(facet: MinecraftFacet) : AbstractModule(f containingClass: PsiClass, chosenClass: PsiClass, chosenName: String, - data: GenerationData? + data: GenerationData?, ): PsiMethod? { val isFmlEvent = chosenClass.extendsOrImplements(ForgeConstants.FML_EVENT) - val method = JavaPsiFacade.getElementFactory(project).createMethod(chosenName, PsiType.VOID) - val parameterList = method.parameterList - - val qName = chosenClass.qualifiedName ?: return null - val parameter = JavaPsiFacade.getElementFactory(project) - .createParameter( - "event", - PsiClassType.getTypeByName(qName, project, GlobalSearchScope.allScope(project)) - ) - - parameterList.add(parameter) + val method = createVoidMethodWithParameterType(project, chosenName, chosenClass) ?: return null val modifierList = method.modifierList if (isFmlEvent) { diff --git a/src/main/kotlin/platform/forge/ForgeModuleType.kt b/src/main/kotlin/platform/forge/ForgeModuleType.kt index 6294eedc1..2c75567fa 100644 --- a/src/main/kotlin/platform/forge/ForgeModuleType.kt +++ b/src/main/kotlin/platform/forge/ForgeModuleType.kt @@ -26,12 +26,12 @@ object ForgeModuleType : AbstractModuleType("", "") { ForgeConstants.MOD_ANNOTATION, ForgeConstants.EVENT_HANDLER_ANNOTATION, ForgeConstants.SUBSCRIBE_EVENT_ANNOTATION, - ForgeConstants.EVENTBUS_SUBSCRIBE_EVENT_ANNOTATION + ForgeConstants.EVENTBUS_SUBSCRIBE_EVENT_ANNOTATION, ) private val LISTENER_ANNOTATIONS = listOf( ForgeConstants.EVENT_HANDLER_ANNOTATION, ForgeConstants.SUBSCRIBE_EVENT_ANNOTATION, - ForgeConstants.EVENTBUS_SUBSCRIBE_EVENT_ANNOTATION + ForgeConstants.EVENTBUS_SUBSCRIBE_EVENT_ANNOTATION, ) override val platformType = PlatformType.FORGE diff --git a/src/main/kotlin/platform/forge/creator/Fg2Template.kt b/src/main/kotlin/platform/forge/creator/Fg2Template.kt deleted file mode 100644 index 7f67a94b1..000000000 --- a/src/main/kotlin/platform/forge/creator/Fg2Template.kt +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.forge.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.platform.BaseTemplate -import com.demonwav.mcdev.platform.forge.ForgeModuleType -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FORGE_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FORGE_GRADLE_PROPERTIES_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FORGE_MAIN_CLASS_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FORGE_SETTINGS_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FORGE_SUBMODULE_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.MCMOD_INFO_TEMPLATE -import com.demonwav.mcdev.util.SemanticVersion -import com.intellij.openapi.project.Project - -object Fg2Template : BaseTemplate() { - - fun applyMainClass( - project: Project, - buildSystem: BuildSystem, - config: ForgeProjectConfig, - packageName: String, - className: String - ): String { - val props = mapOf( - "PACKAGE_NAME" to packageName, - "CLASS_NAME" to className, - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "MOD_VERSION" to buildSystem.version - ) - - return project.applyTemplate(FORGE_MAIN_CLASS_TEMPLATE, props) - } - - fun applyBuildGradle(project: Project, buildSystem: BuildSystem, mcVersion: SemanticVersion): String { - val props = mapOf( - "FORGEGRADLE_VERSION" to fgVersion(mcVersion), - "GROUP_ID" to buildSystem.groupId, - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_VERSION" to buildSystem.version - ) - - return project.applyTemplate(FORGE_BUILD_GRADLE_TEMPLATE, props) - } - - fun applyGradleProp( - project: Project, - config: ForgeProjectConfig - ): String { - val props = mapOf( - "FORGE_VERSION" to config.forgeVersionText, - "MCP_VERSION" to config.mcpVersion.mcpVersion - ) - - return project.applyTemplate(FORGE_GRADLE_PROPERTIES_TEMPLATE, props) - } - - fun applySettingsGradle(project: Project, artifactId: String): String { - val props = mapOf( - "ARTIFACT_ID" to artifactId - ) - - return project.applyTemplate(FORGE_SETTINGS_GRADLE_TEMPLATE, props) - } - - fun applySubBuildGradle(project: Project, buildSystem: BuildSystem, mcVersion: SemanticVersion): String { - val props = mapOf( - "FORGEGRADLE_VERSION" to fgVersion(mcVersion), - "ARTIFACT_ID" to buildSystem.artifactId, - "COMMON_PROJECT_NAME" to buildSystem.commonModuleName - ) - - return project.applyTemplate(FORGE_SUBMODULE_BUILD_GRADLE_TEMPLATE, props) - } - - fun applyMcmodInfo(project: Project, buildSystem: BuildSystem, config: ForgeProjectConfig): String { - val props = mutableMapOf( - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName - ) - props["DESCRIPTION"] = config.description ?: "" - config.website?.let { url -> - if (url.isNotBlank()) { - props["URL"] = url - } - } - config.updateUrl?.let { url -> - if (url.isNotBlank()) { - props["UPDATE_URL"] = url - } - } - if (config.hasAuthors()) { - props["AUTHOR_LIST"] = config.authors.joinToString(", ") { "\"$it\"" } - } - - return project.applyTemplate(MCMOD_INFO_TEMPLATE, props) - } - - private fun fgVersion(mcVersion: SemanticVersion): String { - return if (mcVersion >= ForgeModuleType.FG23_MC_VERSION) { - "2.3" - } else { - "2.2" - } - } -} diff --git a/src/main/kotlin/platform/forge/creator/Fg3Template.kt b/src/main/kotlin/platform/forge/creator/Fg3Template.kt deleted file mode 100644 index b0ea6d658..000000000 --- a/src/main/kotlin/platform/forge/creator/Fg3Template.kt +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.forge.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.platform.BaseTemplate -import com.demonwav.mcdev.platform.forge.util.ForgeConstants -import com.demonwav.mcdev.platform.forge.util.ForgePackAdditionalData -import com.demonwav.mcdev.platform.forge.util.ForgePackDescriptor -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FG3_1_17_MAIN_CLASS_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FG3_1_18_MAIN_CLASS_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FG3_1_19_3_MAIN_CLASS_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FG3_1_19_MAIN_CLASS_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FG3_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FG3_GRADLE_PROPERTIES_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FG3_MAIN_CLASS_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FG3_SETTINGS_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FG3_SUBMODULE_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.FORGE_MIXINS_JSON_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.MODS_TOML_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.PACK_MCMETA_TEMPLATE -import com.demonwav.mcdev.util.MinecraftVersions -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.toPackageName -import com.intellij.openapi.project.Project - -object Fg3Template : BaseTemplate() { - - fun applyMainClass( - project: Project, - buildSystem: BuildSystem, - config: ForgeProjectConfig, - packageName: String, - className: String - ): String { - val props = mapOf( - "PACKAGE_NAME" to packageName, - "CLASS_NAME" to className, - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "MOD_VERSION" to buildSystem.version - ) - - return project.applyTemplate(FG3_MAIN_CLASS_TEMPLATE, props) - } - - fun apply1_17MainClass( - project: Project, - buildSystem: BuildSystem, - config: ForgeProjectConfig, - packageName: String, - className: String - ): String { - val props = mapOf( - "PACKAGE_NAME" to packageName, - "CLASS_NAME" to className, - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "MOD_VERSION" to buildSystem.version - ) - - return project.applyTemplate(FG3_1_17_MAIN_CLASS_TEMPLATE, props) - } - - fun apply1_18MainClass( - project: Project, - buildSystem: BuildSystem, - config: ForgeProjectConfig, - packageName: String, - className: String - ): String { - val props = mapOf( - "PACKAGE_NAME" to packageName, - "CLASS_NAME" to className, - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "MOD_VERSION" to buildSystem.version - ) - - return project.applyTemplate(FG3_1_18_MAIN_CLASS_TEMPLATE, props) - } - - fun apply1_19MainClass( - project: Project, - buildSystem: BuildSystem, - config: ForgeProjectConfig, - packageName: String, - className: String - ): String { - val props = mapOf( - "PACKAGE_NAME" to packageName, - "CLASS_NAME" to className, - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "MOD_VERSION" to buildSystem.version - ) - - return project.applyTemplate(FG3_1_19_MAIN_CLASS_TEMPLATE, props) - } - - fun apply1_19_3MainClass( - project: Project, - buildSystem: BuildSystem, - config: ForgeProjectConfig, - packageName: String, - className: String - ): String { - val props = mapOf( - "PACKAGE_NAME" to packageName, - "CLASS_NAME" to className, - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "MOD_VERSION" to buildSystem.version - ) - - return project.applyTemplate(FG3_1_19_3_MAIN_CLASS_TEMPLATE, props) - } - - fun applyBuildGradle( - project: Project, - buildSystem: BuildSystem, - config: ForgeProjectConfig, - modName: String, - hasData: Boolean - ): String { - val (channel, version) = config.mcpVersion.mcpVersion.split('_', limit = 2) - val props = mutableMapOf( - "MOD_NAME" to modName, - "MCP_CHANNEL" to channel, - "MCP_VERSION" to version, - "MCP_MC_VERSION" to config.mcpVersion.mcVersion.toString(), - "FORGE_VERSION" to config.forgeVersionText, - "GROUP_ID" to buildSystem.groupId, - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_VERSION" to buildSystem.version, - "JAVA_VERSION" to config.javaVersion.feature - ) - if (hasData) { - props["HAS_DATA"] = "true" - } - if (config.hasAuthors()) { - props["AUTHOR_LIST"] = config.authors.joinToString(", ") - } - if (config.mixins) { - props["MIXINS"] = "true" - } - if (config.forgeVersion >= SemanticVersion.release(39, 0, 88)) { - props["GAME_TEST_FRAMEWORK"] = "true" - } - - return project.applyTemplate(FG3_BUILD_GRADLE_TEMPLATE, props) - } - - fun applyGradleProp(project: Project): String { - return project.applyTemplate(FG3_GRADLE_PROPERTIES_TEMPLATE) - } - - fun applySettingsGradle(project: Project, artifactId: String): String { - val props = mapOf( - "ARTIFACT_ID" to artifactId - ) - - return project.applyTemplate(FG3_SETTINGS_GRADLE_TEMPLATE, props) - } - - fun applySubBuildGradle( - project: Project, - buildSystem: BuildSystem, - config: ForgeProjectConfig, - modName: String, - hasData: Boolean - ): String { - val (channel, version) = config.mcpVersion.mcpVersion.split('_', limit = 2) - val props = mutableMapOf( - "MOD_NAME" to modName, - "MCP_CHANNEL" to channel, - "MCP_VERSION" to version, - "MCP_MC_VERSION" to config.mcpVersion.mcVersion.toString(), - "FORGE_VERSION" to config.forgeVersionText, - "ARTIFACT_ID" to buildSystem.artifactId, - "JAVA_VERSION" to if (config.mcVersion < MinecraftVersions.MC1_17) 8 else 16, - "COMMON_PROJECT_NAME" to buildSystem.commonModuleName - ) - if (hasData) { - props["HAS_DATA"] = "true" - } - if (config.hasAuthors()) { - props["AUTHOR_LIST"] = config.authors.joinToString(", ") - } - if (config.mixins) { - props["MIXINS"] = "true" - } - - return project.applyTemplate(FG3_SUBMODULE_BUILD_GRADLE_TEMPLATE, props) - } - - fun applyModsToml(project: Project, buildSystem: BuildSystem, config: ForgeProjectConfig): String { - val hasDisplayTestInManifest = config.forgeVersion >= ForgeConstants.DISPLAY_TEST_MANIFEST_VERSION - val nextMcVersion = when (val part = config.mcVersion.parts.getOrNull(1)) { - // Mimics the code used to get the next Minecraft version in Forge's MDK - // https://github.com/MinecraftForge/MinecraftForge/blob/0ff8a596fc1ef33d4070be89dd5cb4851f93f731/build.gradle#L884 - is SemanticVersion.Companion.VersionPart.ReleasePart -> (part.version + 1).toString() - null -> "?" - else -> part.versionString - } - val props = mutableMapOf( - "ARTIFACT_ID" to buildSystem.artifactId, - "MOD_NAME" to config.pluginName, - "DISPLAY_TEST" to hasDisplayTestInManifest, - "FORGE_SPEC_VERSION" to config.forgeVersion.parts[0].versionString, - "MC_VERSION" to config.mcVersion.toString(), - "MC_NEXT_VERSION" to "1.$nextMcVersion", - "LICENSE" to config.license.toString() - ) - props["DESCRIPTION"] = config.description ?: "" - config.updateUrl?.let { url -> - if (url.isNotBlank()) { - props["UPDATE_URL"] = url - } - } - config.website?.let { url -> - if (url.isNotBlank()) { - props["WEBSITE"] = url - } - } - if (config.hasAuthors()) { - props["AUTHOR_LIST"] = config.authors.joinToString(", ") - } - - return project.applyTemplate(MODS_TOML_TEMPLATE, props) - } - - fun applyPackMcmeta( - project: Project, - artifactId: String, - pack: ForgePackDescriptor, - additionalData: ForgePackAdditionalData? - ): String { - val props = mapOf( - "ARTIFACT_ID" to artifactId, - "PACK_FORMAT" to pack.format.toString(), - "PACK_COMMENT" to pack.comment, - "FORGE_DATA" to additionalData, - ) - - return project.applyTemplate(PACK_MCMETA_TEMPLATE, props) - } - - fun applyMixinConfigTemplate( - project: Project, - buildSystem: BuildSystem - ): String { - val groupId = buildSystem.groupId.toPackageName() - val artifactId = buildSystem.artifactId.toPackageName() - val packageName = "$groupId.$artifactId.mixin" - val props = mapOf( - "PACKAGE_NAME" to packageName, - "ARTIFACT_ID" to artifactId - ) - return project.applyTemplate(FORGE_MIXINS_JSON_TEMPLATE, props) - } -} diff --git a/src/main/kotlin/platform/forge/creator/ForgeProjectConfig.kt b/src/main/kotlin/platform/forge/creator/ForgeProjectConfig.kt deleted file mode 100644 index b51a6b603..000000000 --- a/src/main/kotlin/platform/forge/creator/ForgeProjectConfig.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.forge.creator - -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.ProjectCreator -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleCreator -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.platform.forge.ForgeModuleType -import com.demonwav.mcdev.platform.mcp.McpVersionPair -import com.demonwav.mcdev.util.License -import com.demonwav.mcdev.util.MinecraftVersions -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.VersionRange -import com.demonwav.mcdev.util.until -import com.intellij.openapi.module.Module -import com.intellij.util.lang.JavaVersion -import java.nio.file.Path - -class ForgeProjectConfig : ProjectConfig(), GradleCreator { - - lateinit var mainClass: String - - var updateUrl: String? = null - - override var type: PlatformType = PlatformType.FORGE - - var mcpVersion = McpVersionPair("", SemanticVersion.release()) - var forgeVersionText: String = "" - var forgeVersion: SemanticVersion = SemanticVersion.release() - var mcVersion: SemanticVersion = SemanticVersion.release() - var mixins = false - var license = License.ALL_RIGHTS_RESERVED - - override val preferredBuildSystem = BuildSystemType.GRADLE - - override val javaVersion: JavaVersion - get() = MinecraftVersions.requiredJavaVersion(mcVersion) - - override val compatibleGradleVersions: VersionRange - get() = when { - isFg3(mcVersion, forgeVersion) -> Fg3ProjectCreator.FG5_WRAPPER_VERSION until null - else -> VersionRange.fixed(Fg2ProjectCreator.FG_WRAPPER_VERSION) - } - - override fun buildGradleCreator( - rootDirectory: Path, - module: Module, - buildSystem: GradleBuildSystem - ): ProjectCreator { - return if (isFg3(mcVersion, forgeVersion)) { - if (mcVersion >= ForgeModuleType.FG3_MC_VERSION) { - Fg3ProjectCreator(rootDirectory, module, buildSystem, this) - } else { - Fg3Mc112ProjectCreator(rootDirectory, module, buildSystem, this) - } - } else { - Fg2ProjectCreator(rootDirectory, module, buildSystem, this, mcVersion) - } - } - - override fun configureRootGradle( - rootDirectory: Path, - buildSystem: GradleBuildSystem - ) { - buildSystem.gradleVersion = if (isFg3(mcVersion, forgeVersion)) { - Fg3ProjectCreator.FG5_WRAPPER_VERSION - } else { - Fg2ProjectCreator.FG_WRAPPER_VERSION - } - } - - private fun isFg3(mcVersion: SemanticVersion, forgeVersion: SemanticVersion): Boolean { - return mcVersion >= ForgeModuleType.FG3_MC_VERSION || forgeVersion >= ForgeModuleType.FG3_FORGE_VERSION - } -} diff --git a/src/main/kotlin/platform/forge/creator/ForgeProjectCreator.kt b/src/main/kotlin/platform/forge/creator/ForgeProjectCreator.kt deleted file mode 100644 index d5b3afdf8..000000000 --- a/src/main/kotlin/platform/forge/creator/ForgeProjectCreator.kt +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.forge.creator - -import com.demonwav.mcdev.creator.BaseProjectCreator -import com.demonwav.mcdev.creator.BasicJavaClassStep -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.LicenseStep -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.BasicGradleFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleFiles -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleGitignoreStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleWrapperStep -import com.demonwav.mcdev.creator.buildsystem.gradle.SimpleGradleSetupStep -import com.demonwav.mcdev.platform.forge.util.ForgeConstants -import com.demonwav.mcdev.platform.forge.util.ForgePackAdditionalData -import com.demonwav.mcdev.platform.forge.util.ForgePackDescriptor -import com.demonwav.mcdev.util.MinecraftVersions -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.runGradleTaskAndWait -import com.demonwav.mcdev.util.runWriteTask -import com.intellij.openapi.module.Module -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.project.Project -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.StandardOpenOption.CREATE -import java.nio.file.StandardOpenOption.TRUNCATE_EXISTING -import java.nio.file.StandardOpenOption.WRITE -import java.util.Locale - -class Fg2ProjectCreator( - private val rootDirectory: Path, - private val rootModule: Module, - private val buildSystem: GradleBuildSystem, - private val config: ForgeProjectConfig, - private val mcVersion: SemanticVersion -) : BaseProjectCreator(rootModule, buildSystem) { - - private fun setupMainClassStep(): BasicJavaClassStep { - return createJavaClassStep(config.mainClass) { packageName, className -> - Fg2Template.applyMainClass(project, buildSystem, config, packageName, className) - } - } - - override fun getSteps(): Iterable { - val buildText = Fg2Template.applyBuildGradle(project, buildSystem, mcVersion) - val propText = Fg2Template.applyGradleProp(project, config) - val settingsText = Fg2Template.applySettingsGradle(project, buildSystem.artifactId) - val files = GradleFiles(buildText, propText, settingsText) - - return listOf( - SimpleGradleSetupStep( - project, - rootDirectory, - buildSystem, - files - ), - setupMainClassStep(), - GradleWrapperStep(project, rootDirectory, buildSystem), - McmodInfoStep(project, buildSystem, config), - SetupDecompWorkspaceStep(project, rootDirectory), - GradleGitignoreStep(project, rootDirectory), - BasicGradleFinalizerStep(rootModule, rootDirectory, buildSystem), - ForgeRunConfigsStep(buildSystem, rootDirectory, config, CreatedModuleType.SINGLE) - ) - } - - companion object { - val FG_WRAPPER_VERSION = SemanticVersion.release(4, 10, 3) - } -} - -open class Fg3ProjectCreator( - protected val rootDirectory: Path, - protected val rootModule: Module, - protected val buildSystem: GradleBuildSystem, - protected val config: ForgeProjectConfig -) : BaseProjectCreator(rootModule, buildSystem) { - - private fun setupMainClassStep(): BasicJavaClassStep { - return createJavaClassStep(config.mainClass) { packageName, className -> - if (config.mcVersion >= MinecraftVersions.MC1_19_3) { - Fg3Template.apply1_19_3MainClass(project, buildSystem, config, packageName, className) - } else if (config.mcVersion >= MinecraftVersions.MC1_19) { - Fg3Template.apply1_19MainClass(project, buildSystem, config, packageName, className) - } else if (config.mcVersion >= MinecraftVersions.MC1_18) { - Fg3Template.apply1_18MainClass(project, buildSystem, config, packageName, className) - } else if (config.mcVersion >= MinecraftVersions.MC1_17) { - Fg3Template.apply1_17MainClass(project, buildSystem, config, packageName, className) - } else { - Fg3Template.applyMainClass(project, buildSystem, config, packageName, className) - } - } - } - - protected fun transformModName(modName: String?): String { - modName ?: return "examplemod" - return modName.lowercase(Locale.ENGLISH).replace(" ", "") - } - - protected fun createGradleFiles(hasData: Boolean): GradleFiles { - val modName = transformModName(config.pluginName) - val buildText = Fg3Template.applyBuildGradle(project, buildSystem, config, modName, hasData) - val propText = Fg3Template.applyGradleProp(project) - val settingsText = Fg3Template.applySettingsGradle(project, buildSystem.artifactId) - return GradleFiles(buildText, propText, settingsText) - } - - override fun getSteps(): Iterable { - val files = createGradleFiles(hasData = true) - val steps = mutableListOf( - SimpleGradleSetupStep( - project, - rootDirectory, - buildSystem, - files - ), - setupMainClassStep(), - GradleWrapperStep(project, rootDirectory, buildSystem), - Fg3ProjectFilesStep(project, buildSystem, config), - Fg3CompileJavaStep(project, rootDirectory), - GradleGitignoreStep(project, rootDirectory), - LicenseStep(project, rootDirectory, config.license, config.authors.joinToString(", ")), - BasicGradleFinalizerStep(rootModule, rootDirectory, buildSystem), - ForgeRunConfigsStep(buildSystem, rootDirectory, config, CreatedModuleType.SINGLE) - ) - - if (config.mixins) { - steps += MixinConfigStep(project, buildSystem) - } - - return steps - } - - companion object { - val FG5_WRAPPER_VERSION = SemanticVersion.release(7, 5, 1) - } -} - -class Fg3Mc112ProjectCreator( - rootDirectory: Path, - rootModule: Module, - buildSystem: GradleBuildSystem, - config: ForgeProjectConfig -) : Fg3ProjectCreator(rootDirectory, rootModule, buildSystem, config) { - - private fun setupMainClassStep(): BasicJavaClassStep { - return createJavaClassStep(config.mainClass) { packageName, className -> - Fg2Template.applyMainClass(project, buildSystem, config, packageName, className) - } - } - - override fun getSteps(): Iterable { - val files = createGradleFiles(hasData = false) - - return listOf( - SimpleGradleSetupStep( - project, - rootDirectory, - buildSystem, - files - ), - setupMainClassStep(), - GradleWrapperStep(project, rootDirectory, buildSystem), - McmodInfoStep(project, buildSystem, config), - Fg3CompileJavaStep(project, rootDirectory), - GradleGitignoreStep(project, rootDirectory), - BasicGradleFinalizerStep(rootModule, rootDirectory, buildSystem), - ForgeRunConfigsStep(buildSystem, rootDirectory, config, CreatedModuleType.SINGLE) - ) - } -} - -class SetupDecompWorkspaceStep( - private val project: Project, - private val rootDirectory: Path -) : CreatorStep { - - override fun runStep(indicator: ProgressIndicator) { - indicator.text = "Setting up project" - indicator.text2 = "Running Gradle task: 'setupDecompWorkspace'" - runGradleTaskAndWait(project, rootDirectory) { settings -> - settings.taskNames = listOf("setupDecompWorkspace") - settings.vmOptions = "-Xmx2G" - } - indicator.text2 = null - } -} - -class McmodInfoStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val config: ForgeProjectConfig -) : CreatorStep { - - override fun runStep(indicator: ProgressIndicator) { - val text = Fg2Template.applyMcmodInfo(project, buildSystem, config) - val dir = buildSystem.dirsOrError.resourceDirectory - runWriteTask { - CreatorStep.writeTextToFile(project, dir, ForgeConstants.MCMOD_INFO, text) - } - } -} - -class Fg3ProjectFilesStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val config: ForgeProjectConfig -) : CreatorStep { - - override fun runStep(indicator: ProgressIndicator) { - val modsTomlText = Fg3Template.applyModsToml(project, buildSystem, config) - val packDescriptor = ForgePackDescriptor.forMcVersion(config.mcVersion) ?: ForgePackDescriptor.FORMAT_3 - val additionalData = ForgePackAdditionalData.forMcVersion(config.mcVersion) - val packMcmetaText = - Fg3Template.applyPackMcmeta(project, buildSystem.artifactId, packDescriptor, additionalData) - val dir = buildSystem.dirsOrError.resourceDirectory - runWriteTask { - CreatorStep.writeTextToFile(project, dir, ForgeConstants.PACK_MCMETA, packMcmetaText) - val meta = dir.resolve("META-INF") - Files.createDirectories(meta) - CreatorStep.writeTextToFile(project, meta, ForgeConstants.MODS_TOML, modsTomlText) - } - } -} - -class Fg3CompileJavaStep( - private val project: Project, - private val rootDirectory: Path -) : CreatorStep { - - override fun runStep(indicator: ProgressIndicator) { - indicator.text = "Setting up classpath" - indicator.text2 = "Running Gradle task: 'compileJava'" - runGradleTaskAndWait(project, rootDirectory) { settings -> - settings.taskNames = listOf("compileJava") - } - indicator.text2 = null - } -} - -class MixinConfigStep( - private val project: Project, - private val buildSystem: BuildSystem -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val text = Fg3Template.applyMixinConfigTemplate(project, buildSystem) - val dir = buildSystem.dirsOrError.resourceDirectory - runWriteTask { - CreatorStep.writeTextToFile(project, dir, "${buildSystem.artifactId}.mixins.json", text) - } - } -} - -enum class CreatedModuleType { - SINGLE, MULTI -} - -class ForgeRunConfigsStep( - private val buildSystem: BuildSystem, - private val rootDirectory: Path, - private val config: ForgeProjectConfig, - private val createdModuleType: CreatedModuleType -) : CreatorStep { - - override fun runStep(indicator: ProgressIndicator) { - val gradleDir = rootDirectory.resolve(".gradle") - Files.createDirectories(gradleDir) - val hello = gradleDir.resolve(HELLO) - - val task = if (createdModuleType == CreatedModuleType.MULTI) { - ":${buildSystem.artifactId}:genIntellijRuns" - } else { - "genIntellijRuns" - } - - // We don't use `rootModule.name` here because Gradle will change the name of the module to match - // what was set as the artifactId once it imports the project - val moduleName = if (createdModuleType == CreatedModuleType.MULTI) { - "${buildSystem.parentOrError.artifactId}.${buildSystem.artifactId}" - } else { - buildSystem.artifactId - } - - val fileContents = moduleName + "\n" + - config.mcVersion + "\n" + - config.forgeVersion + "\n" + - task - - Files.write(hello, fileContents.toByteArray(Charsets.UTF_8), CREATE, TRUNCATE_EXISTING, WRITE) - } - - companion object { - const val HELLO = ".hello_from_mcdev" - } -} diff --git a/src/main/kotlin/platform/forge/creator/ForgeProjectSettingsWizard.form b/src/main/kotlin/platform/forge/creator/ForgeProjectSettingsWizard.form deleted file mode 100644 index 72c8f7e3f..000000000 --- a/src/main/kotlin/platform/forge/creator/ForgeProjectSettingsWizard.form +++ /dev/null @@ -1,320 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/main/kotlin/platform/forge/creator/ForgeProjectSettingsWizard.kt b/src/main/kotlin/platform/forge/creator/ForgeProjectSettingsWizard.kt deleted file mode 100644 index 91aba3adc..000000000 --- a/src/main/kotlin/platform/forge/creator/ForgeProjectSettingsWizard.kt +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.forge.creator - -import com.demonwav.mcdev.asset.PlatformAssets -import com.demonwav.mcdev.creator.MinecraftModuleWizardStep -import com.demonwav.mcdev.creator.MinecraftProjectCreator -import com.demonwav.mcdev.creator.ValidatedField -import com.demonwav.mcdev.creator.ValidatedFieldType.CLASS_NAME -import com.demonwav.mcdev.creator.ValidatedFieldType.LIST -import com.demonwav.mcdev.creator.ValidatedFieldType.NON_BLANK -import com.demonwav.mcdev.platform.forge.version.ForgeVersion -import com.demonwav.mcdev.platform.mcp.McpVersionPair -import com.demonwav.mcdev.platform.mcp.version.McpVersion -import com.demonwav.mcdev.platform.mcp.version.McpVersionEntry -import com.demonwav.mcdev.util.License -import com.demonwav.mcdev.util.MinecraftVersions -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.asyncIO -import com.demonwav.mcdev.util.modUpdateStep -import com.intellij.ui.CollectionComboBoxModel -import com.intellij.ui.EnumComboBoxModel -import java.awt.event.ActionListener -import javax.swing.JCheckBox -import javax.swing.JComboBox -import javax.swing.JComponent -import javax.swing.JLabel -import javax.swing.JPanel -import javax.swing.JProgressBar -import javax.swing.JTextField -import kotlin.math.min -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import kotlinx.coroutines.swing.Swing - -class ForgeProjectSettingsWizard(private val creator: MinecraftProjectCreator) : MinecraftModuleWizardStep() { - - @ValidatedField(NON_BLANK) - private lateinit var modNameField: JTextField - - @ValidatedField(NON_BLANK, CLASS_NAME) - private lateinit var mainClassField: JTextField - private lateinit var panel: JPanel - private lateinit var title: JLabel - private lateinit var descriptionField: JTextField - - @ValidatedField(LIST) - private lateinit var authorsField: JTextField - private lateinit var websiteField: JTextField - private lateinit var updateUrlField: JTextField - private lateinit var licenseBox: JComboBox - private lateinit var mixinsCheckbox: JCheckBox - private lateinit var minecraftVersionBox: JComboBox - private lateinit var forgeVersionBox: JComboBox - private lateinit var mcpVersionBox: JComboBox - private lateinit var loadingBar: JProgressBar - private lateinit var minecraftVersionLabel: JLabel - private lateinit var mcpWarning: JLabel - private lateinit var errorLabel: JLabel - - private var config: ForgeProjectConfig? = null - - private data class ForgeVersions( - var mcpVersion: McpVersion, - var forgeVersion: ForgeVersion - ) - - private var versions: ForgeVersions? = null - - private var currentJob: Job? = null - - private val mcpBoxActionListener = ActionListener { - mcpWarning.isVisible = (mcpVersionBox.selectedItem as? McpVersionEntry)?.isRed == true - } - - private val forgeVersionBoxListener = ActionListener { - val selectedVersion = forgeVersionBox.selectedItem as? SemanticVersion ?: return@ActionListener - val supportedMixinVersion = selectedVersion >= SemanticVersion.release(31, 2, 45) - val mcpMappingsVersion = selectedVersion <= SemanticVersion.release(37, 0, 0) - - mixinsCheckbox.isEnabled = supportedMixinVersion - if (!supportedMixinVersion) { - mixinsCheckbox.isSelected = false - } - - mcpVersionBox.isEnabled = mcpMappingsVersion - mcpWarning.isVisible = mcpMappingsVersion - if (mcpMappingsVersion) { - mcpBoxActionListener.actionPerformed(null) - } - } - - private val minecraftBoxActionListener: ActionListener = ActionListener { - CoroutineScope(Dispatchers.Swing).launch { - loadingBar.isIndeterminate = true - loadingBar.isVisible = true - - updateForm() - - loadingBar.isIndeterminate = false - loadingBar.isVisible = false - } - } - - init { - mcpWarning.isVisible = false - } - - override fun getComponent(): JComponent { - return panel - } - - override fun updateStep() { - val (conf, buildSystem) = modUpdateStep(creator, modNameField) ?: return - config = conf - - mainClassField.text = generateClassName(buildSystem, modNameField.text) - - title.icon = PlatformAssets.FORGE_ICON_2X - title.text = "Forge Settings" - - minecraftVersionLabel.text = "Minecraft Version" - - licenseBox.model = EnumComboBoxModel(License::class.java) - licenseBox.selectedItem = License.ALL_RIGHTS_RESERVED - - if (versions != null || currentJob?.isActive == true) { - return - } - currentJob = updateVersions() - } - - private fun setForgeVersion(data: Data) { - forgeVersionBox.model = CollectionComboBoxModel(data.forgeVersions.subList(0, min(50, data.forgeVersions.size))) - forgeVersionBox.selectedIndex = data.forgeSelectedIndex - } - - private val version: SemanticVersion? - get() = minecraftVersionBox.selectedItem as? SemanticVersion - - override fun validate(): Boolean { - return super.validate() && !loadingBar.isVisible - } - - override fun isStepVisible(): Boolean { - return creator.config is ForgeProjectConfig - } - - override fun onStepLeaving() { - currentJob?.cancel() - } - - override fun updateDataModel() { - val conf = this.config ?: return - - conf.pluginName = this.modNameField.text - conf.mainClass = this.mainClassField.text - conf.description = this.descriptionField.text - conf.website = this.websiteField.text - - conf.setAuthors(this.authorsField.text) - conf.updateUrl = this.updateUrlField.text - - conf.mcVersion = this.version ?: SemanticVersion.release() - conf.mcpVersion = if (conf.mcVersion >= MinecraftVersions.MC1_17) { - McpVersionPair("official_" + conf.mcVersion, conf.mcVersion) - } else { - (this.mcpVersionBox.selectedItem as McpVersionEntry).versionPair - } - - (this.forgeVersionBox.selectedItem as SemanticVersion).let { version -> - val versionString = version.toString() - val forgeVersion = this.versions?.forgeVersion ?: return@let - conf.forgeVersionText = forgeVersion.versions.first { it.endsWith(versionString) } - conf.forgeVersion = version - } - - conf.mixins = mixinsCheckbox.isSelected - conf.license = licenseBox.selectedItem as? License ?: License.ALL_RIGHTS_RESERVED - } - - private fun mcVersionUpdate(data: Data) { - mcpVersionBox.removeActionListener(mcpBoxActionListener) - mcpVersionBox.model = CollectionComboBoxModel(data.mcpVersions.subList(0, min(50, data.mcpVersions.size))) - mcpVersionBox.selectedIndex = 0 - mcpVersionBox.addActionListener(mcpBoxActionListener) - mcpBoxActionListener.actionPerformed(null) - - forgeVersionBox.removeActionListener(forgeVersionBoxListener) - setForgeVersion(data) - forgeVersionBox.addActionListener(forgeVersionBoxListener) - forgeVersionBoxListener.actionPerformed(null) - } - - private fun updateVersions() = CoroutineScope(Dispatchers.Swing).launch { - loadingBar.isIndeterminate = true - loadingBar.isVisible = true - - try { - downloadVersions() - val data = updateForm() - if (data != null) { - updateMcForm(data) - } - } catch (e: Exception) { - error() - } - - loadingBar.isIndeterminate = false - loadingBar.isVisible = false - - currentJob = null - } - - fun error() { - errorLabel.isVisible = true - loadingBar.isIndeterminate = false - loadingBar.isVisible = false - } - - private suspend fun downloadVersions() = coroutineScope { - val mcpVersionJob = asyncIO { McpVersion.downloadData() } - val forgeVersionJob = asyncIO { ForgeVersion.downloadData() } - - versions = ForgeVersions( - mcpVersionJob.await() ?: return@coroutineScope, - forgeVersionJob.await() ?: return@coroutineScope - ) - } - - private suspend fun updateForm(): Data? = coroutineScope { - val vers = versions ?: return@coroutineScope null - - val selectedVersion = version ?: vers.forgeVersion.sortedMcVersions.firstOrNull() ?: return@coroutineScope null - - val mcpVersionListJob = asyncIO { vers.mcpVersion.getMcpVersionList(selectedVersion) } - val forgeVersionsJob = asyncIO { vers.forgeVersion.getForgeVersions(selectedVersion) } - - val mcpVersionList = mcpVersionListJob.await() - val forgeVersions = forgeVersionsJob.await() - - val data = Data(0, mcpVersionList, forgeVersions, 0) - - mcVersionUpdate(data) - - return@coroutineScope data - } - - private fun updateMcForm(data: Data) { - val vers = versions ?: return - - minecraftVersionBox.removeActionListener(minecraftBoxActionListener) - minecraftVersionBox.removeAllItems() - - minecraftVersionBox.model = CollectionComboBoxModel(vers.forgeVersion.sortedMcVersions) - minecraftVersionBox.selectedIndex = data.mcSelectedIndex - minecraftVersionBox.addActionListener(minecraftBoxActionListener) - } - - private data class Data( - val mcSelectedIndex: Int, - val mcpVersions: List, - val forgeVersions: List, - val forgeSelectedIndex: Int - ) -} diff --git a/src/main/kotlin/platform/forge/creator/asset-steps.kt b/src/main/kotlin/platform/forge/creator/asset-steps.kt new file mode 100644 index 000000000..e72968181 --- /dev/null +++ b/src/main/kotlin/platform/forge/creator/asset-steps.kt @@ -0,0 +1,139 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.forge.creator + +import com.demonwav.mcdev.creator.addLicense +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.AbstractRunBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.splitPackage +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModNameStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.LicenseStep +import com.demonwav.mcdev.creator.step.MainClassStep +import com.demonwav.mcdev.creator.step.UpdateUrlStep +import com.demonwav.mcdev.creator.step.UseMixinsStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.platform.forge.util.ForgeConstants +import com.demonwav.mcdev.platform.forge.util.ForgePackAdditionalData +import com.demonwav.mcdev.platform.forge.util.ForgePackDescriptor +import com.demonwav.mcdev.util.MinecraftTemplates +import com.demonwav.mcdev.util.MinecraftVersions +import com.demonwav.mcdev.util.SemanticVersion +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.project.Project + +class ForgeProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating Forge project files" + + override fun setupAssets(project: Project) { + val mcVersion = data.getUserData(ForgeVersionChainStep.MC_VERSION_KEY) ?: return + val forgeVersion = data.getUserData(ForgeVersionChainStep.FORGE_VERSION_KEY) ?: return + val (mainPackageName, mainClassName) = splitPackage(data.getUserData(MainClassStep.KEY) ?: return) + val buildSystemProps = findStep>() + val modName = data.getUserData(AbstractModNameStep.KEY) ?: return + val license = data.getUserData(LicenseStep.KEY) ?: return + val description = data.getUserData(DescriptionStep.KEY) ?: "" + val updateUrl = data.getUserData(UpdateUrlStep.KEY) ?: "" + val authors = data.getUserData(AuthorsStep.KEY) ?: emptyList() + val website = data.getUserData(WebsiteStep.KEY) ?: "" + + val nextMcVersion = when (val part = mcVersion.parts.getOrNull(1)) { + // Mimics the code used to get the next Minecraft version in Forge's MDK + // https://github.com/MinecraftForge/MinecraftForge/blob/0ff8a596fc1ef33d4070be89dd5cb4851f93f731/build.gradle#L884 + is SemanticVersion.Companion.VersionPart.ReleasePart -> (part.version + 1).toString() + null -> "?" + else -> part.versionString + } + + val packDescriptor = ForgePackDescriptor.forMcVersion(mcVersion) ?: ForgePackDescriptor.FORMAT_3 + val additionalPackData = ForgePackAdditionalData.forMcVersion(mcVersion) + + assets.addTemplateProperties( + "PACKAGE_NAME" to mainPackageName, + "CLASS_NAME" to mainClassName, + "ARTIFACT_ID" to buildSystemProps.artifactId, + "MOD_NAME" to modName, + "MOD_VERSION" to buildSystemProps.version, + "DISPLAY_TEST" to (forgeVersion >= ForgeConstants.DISPLAY_TEST_MANIFEST_VERSION), + "FORGE_SPEC_VERSION" to forgeVersion.parts[0].versionString, + "MC_VERSION" to mcVersion, + "MC_NEXT_VERSION" to "1.$nextMcVersion", + "LICENSE" to license, + "DESCRIPTION" to description, + "PACK_FORMAT" to packDescriptor.format, + "PACK_COMMENT" to packDescriptor.comment, + "FORGE_DATA" to (additionalPackData ?: ""), + ) + + if (updateUrl.isNotBlank()) { + assets.addTemplateProperties("UPDATE_URL" to updateUrl) + } + + if (authors.isNotEmpty()) { + assets.addTemplateProperties("AUTHOR_LIST" to authors.joinToString(", ")) + } + + if (website.isNotBlank()) { + assets.addTemplateProperties("WEBSITE" to website) + } + + val mainClassTemplate = when { + mcVersion >= MinecraftVersions.MC1_19_3 -> MinecraftTemplates.FG3_1_19_3_MAIN_CLASS_TEMPLATE + mcVersion >= MinecraftVersions.MC1_19 -> MinecraftTemplates.FG3_1_19_MAIN_CLASS_TEMPLATE + mcVersion >= MinecraftVersions.MC1_18 -> MinecraftTemplates.FG3_1_18_MAIN_CLASS_TEMPLATE + mcVersion >= MinecraftVersions.MC1_17 -> MinecraftTemplates.FG3_1_17_MAIN_CLASS_TEMPLATE + else -> MinecraftTemplates.FG3_MAIN_CLASS_TEMPLATE + } + + assets.addTemplates( + project, + "src/main/java/${mainPackageName.replace('.', '/')}/$mainClassName.java" to mainClassTemplate, + "src/main/resources/pack.mcmeta" to MinecraftTemplates.PACK_MCMETA_TEMPLATE, + "src/main/resources/META-INF/mods.toml" to MinecraftTemplates.MODS_TOML_TEMPLATE, + ) + + assets.addLicense(project) + } +} + +// Needs to be a separate step from above because of PACKAGE_NAME being different +class ForgeMixinsJsonStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating mixins json" + + override fun setupAssets(project: Project) { + val useMixins = data.getUserData(UseMixinsStep.KEY) ?: false + if (useMixins) { + val buildSystemProps = findStep>() + assets.addTemplateProperties( + "PACKAGE_NAME" to "${buildSystemProps.groupId}.${buildSystemProps.artifactId}.mixin", + "ARTIFACT_ID" to buildSystemProps.artifactId, + ) + val mixinsJsonFile = "src/main/resources/${buildSystemProps.artifactId}.mixins.json" + assets.addTemplates(project, mixinsJsonFile to MinecraftTemplates.FORGE_MIXINS_JSON_TEMPLATE) + } + } +} + +class ForgeBuildSystemStep(parent: NewProjectWizardStep) : AbstractBuildSystemStep(parent) { + override val platformName = "Forge" +} + +class ForgePostBuildSystemStep( + parent: NewProjectWizardStep, +) : AbstractRunBuildSystemStep(parent, ForgeBuildSystemStep::class.java) { + override val step = BuildSystemSupport.POST_STEP +} diff --git a/src/main/kotlin/platform/forge/creator/gradle-steps.kt b/src/main/kotlin/platform/forge/creator/gradle-steps.kt new file mode 100644 index 000000000..2b804da62 --- /dev/null +++ b/src/main/kotlin/platform/forge/creator/gradle-steps.kt @@ -0,0 +1,141 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.forge.creator + +import com.demonwav.mcdev.creator.EmptyStep +import com.demonwav.mcdev.creator.addGradleGitignore +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractRunGradleTaskStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.buildsystem.GRADLE_VERSION_KEY +import com.demonwav.mcdev.creator.buildsystem.GradleImportStep +import com.demonwav.mcdev.creator.buildsystem.GradleWrapperStep +import com.demonwav.mcdev.creator.buildsystem.addGradleWrapperProperties +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.gitEnabled +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModNameStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.UseMixinsStep +import com.demonwav.mcdev.util.MinecraftTemplates +import com.demonwav.mcdev.util.MinecraftVersions +import com.demonwav.mcdev.util.SemanticVersion +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.application.WriteAction +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.openapi.vfs.VfsUtil +import com.intellij.util.lang.JavaVersion +import java.util.Locale + +private val fg5WrapperVersion = SemanticVersion.release(7, 5, 1) + +const val MAGIC_RUN_CONFIGS_FILE = ".hello_from_mcdev" + +class ForgeGradleSupport : BuildSystemSupport { + override val preferred = true + + override fun createStep(step: String, parent: NewProjectWizardStep): NewProjectWizardStep { + return when (step) { + BuildSystemSupport.PRE_STEP -> ForgeGradleFilesStep(parent).chain(::GradleWrapperStep) + BuildSystemSupport.POST_STEP -> ForgeCompileJavaStep(parent).chain(::GradleImportStep) + else -> EmptyStep(parent) + } + } +} + +class ForgeGradleFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating Gradle files" + + private fun transformModName(modName: String): String { + return modName.lowercase(Locale.ENGLISH).replace(" ", "") + } + + override fun setupAssets(project: Project) { + val mcVersion = data.getUserData(ForgeVersionChainStep.MC_VERSION_KEY) ?: return + val forgeVersion = data.getUserData(ForgeVersionChainStep.FORGE_VERSION_KEY) ?: return + val modName = transformModName(data.getUserData(AbstractModNameStep.KEY) ?: return) + val buildSystemProps = findStep>() + val javaVersion = context.projectJdk.versionString?.let(JavaVersion::parse) + val authors = data.getUserData(AuthorsStep.KEY) ?: emptyList() + val useMixins = data.getUserData(UseMixinsStep.KEY) ?: false + + data.putUserData(GRADLE_VERSION_KEY, fg5WrapperVersion) + + assets.addTemplateProperties( + "MOD_NAME" to modName, + "MCP_CHANNEL" to "official", + "MCP_VERSION" to mcVersion, + "MCP_MC_VERSION" to mcVersion, + "FORGE_VERSION" to "$mcVersion-$forgeVersion", + "GROUP_ID" to buildSystemProps.groupId, + "ARTIFACT_ID" to buildSystemProps.artifactId, + "MOD_VERSION" to buildSystemProps.version, + "HAS_DATA" to "true", + ) + + if (javaVersion != null) { + assets.addTemplateProperties("JAVA_VERSION" to javaVersion.feature) + } + + if (authors.isNotEmpty()) { + assets.addTemplateProperties("AUTHOR_LIST" to authors.joinToString(", ")) + } + + if (useMixins) { + assets.addTemplateProperties("MIXINS" to "true") + } + + if (forgeVersion >= SemanticVersion.release(39, 0, 88)) { + assets.addTemplateProperties("GAME_TEST_FRAMEWORK" to "true") + } + + if (mcVersion <= MinecraftVersions.MC1_16_5) { + assets.addTemplateProperties( + "MCP_CHANNEL" to "snapshot", + "MCP_VERSION" to "20210309", + ) + } + + assets.addTemplates( + project, + "build.gradle" to MinecraftTemplates.FG3_BUILD_GRADLE_TEMPLATE, + "gradle.properties" to MinecraftTemplates.FG3_GRADLE_PROPERTIES_TEMPLATE, + "settings.gradle" to MinecraftTemplates.FG3_SETTINGS_GRADLE_TEMPLATE, + ) + + assets.addGradleWrapperProperties(project) + + if (gitEnabled) { + assets.addGradleGitignore(project) + } + + WriteAction.runAndWait { + val dir = VfsUtil.createDirectoryIfMissing( + LocalFileSystem.getInstance(), + "${assets.outputDirectory}/.gradle", + ) + ?: throw IllegalStateException("Unable to create .gradle directory") + val file = dir.findOrCreateChildData(this, MAGIC_RUN_CONFIGS_FILE) + val fileContents = buildSystemProps.artifactId + "\n" + + mcVersion + "\n" + + forgeVersion + "\n" + + "genIntellijRuns" + VfsUtil.saveText(file, fileContents) + } + } +} + +class ForgeCompileJavaStep(parent: NewProjectWizardStep) : AbstractRunGradleTaskStep(parent) { + override val task = "compileJava" +} diff --git a/src/main/kotlin/platform/forge/creator/ui-steps.kt b/src/main/kotlin/platform/forge/creator/ui-steps.kt new file mode 100644 index 000000000..ddb28ef5f --- /dev/null +++ b/src/main/kotlin/platform/forge/creator/ui-steps.kt @@ -0,0 +1,99 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.forge.creator + +import com.demonwav.mcdev.creator.chain +import com.demonwav.mcdev.creator.platformtype.ModPlatformStep +import com.demonwav.mcdev.creator.step.AbstractCollapsibleStep +import com.demonwav.mcdev.creator.step.AbstractLatentStep +import com.demonwav.mcdev.creator.step.AbstractMcVersionChainStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.LicenseStep +import com.demonwav.mcdev.creator.step.MainClassStep +import com.demonwav.mcdev.creator.step.ModNameStep +import com.demonwav.mcdev.creator.step.UpdateUrlStep +import com.demonwav.mcdev.creator.step.UseMixinsStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.platform.forge.version.ForgeVersion +import com.demonwav.mcdev.util.MinecraftVersions +import com.demonwav.mcdev.util.SemanticVersion +import com.demonwav.mcdev.util.asyncIO +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import com.intellij.util.IncorrectOperationException +import kotlinx.coroutines.coroutineScope + +private val minSupportedMcVersion = MinecraftVersions.MC1_16_5 + +class ForgePlatformStep(parent: ModPlatformStep) : AbstractLatentStep(parent) { + override val description = "fetch Forge versions" + + override suspend fun computeData() = coroutineScope { + asyncIO { ForgeVersion.downloadData() }.await() + } + + override fun createStep(data: ForgeVersion) = ForgeVersionChainStep(this, data) + .chain( + ::ModNameStep, + ::MainClassStep, + ::UseMixinsStep, + ::LicenseStep, + ::ForgeOptionalSettingsStep, + ::ForgeBuildSystemStep, + ::ForgeProjectFilesStep, + ::ForgeMixinsJsonStep, + ::ForgePostBuildSystemStep, + ) + + class Factory : ModPlatformStep.Factory { + override val name = "Forge" + override fun createStep(parent: ModPlatformStep) = ForgePlatformStep(parent) + } +} + +class ForgeVersionChainStep( + parent: NewProjectWizardStep, + private val forgeVersionData: ForgeVersion, +) : AbstractMcVersionChainStep(parent, "Forge Version:") { + companion object { + private const val FORGE_VERSION = 1 + + val MC_VERSION_KEY = Key.create("${ForgeVersionChainStep::class.java}.mcVersion") + val FORGE_VERSION_KEY = Key.create("${ForgeVersionChainStep::class.java}.forgeVersion") + } + + override fun getAvailableVersions(versionsAbove: List>): List> { + return when (versionsAbove.size) { + MINECRAFT_VERSION -> forgeVersionData.sortedMcVersions.filter { it >= minSupportedMcVersion } + FORGE_VERSION -> forgeVersionData.getForgeVersions(versionsAbove[MINECRAFT_VERSION] as SemanticVersion) + else -> throw IncorrectOperationException() + } + } + + override fun setupProject(project: Project) { + super.setupProject(project) + data.putUserData(MC_VERSION_KEY, getVersion(MINECRAFT_VERSION) as SemanticVersion) + data.putUserData(FORGE_VERSION_KEY, getVersion(FORGE_VERSION) as SemanticVersion) + } +} + +class ForgeOptionalSettingsStep(parent: NewProjectWizardStep) : AbstractCollapsibleStep(parent) { + override val title = "Optional Settings" + + override fun createStep() = DescriptionStep(this).chain( + ::AuthorsStep, + ::WebsiteStep, + ::UpdateUrlStep, + ) +} diff --git a/src/main/kotlin/platform/forge/gradle/ForgeRunConfigDataService.kt b/src/main/kotlin/platform/forge/gradle/ForgeRunConfigDataService.kt index a7e81e996..42a6b8b31 100644 --- a/src/main/kotlin/platform/forge/gradle/ForgeRunConfigDataService.kt +++ b/src/main/kotlin/platform/forge/gradle/ForgeRunConfigDataService.kt @@ -11,7 +11,7 @@ package com.demonwav.mcdev.platform.forge.gradle import com.demonwav.mcdev.platform.forge.ForgeModuleType -import com.demonwav.mcdev.platform.forge.creator.ForgeRunConfigsStep +import com.demonwav.mcdev.platform.forge.creator.MAGIC_RUN_CONFIGS_FILE import com.demonwav.mcdev.util.SemanticVersion import com.demonwav.mcdev.util.invokeAndWait import com.demonwav.mcdev.util.invokeLater @@ -49,7 +49,7 @@ class ForgeRunConfigDataService : AbstractProjectDataService>, projectData: ProjectData?, project: Project, - modelsProvider: IdeModifiableModelsProvider + modelsProvider: IdeModifiableModelsProvider, ) { if (projectData == null || projectData.owner != GradleConstants.SYSTEM_ID) { return @@ -57,7 +57,7 @@ class ForgeRunConfigDataService : AbstractProjectDataService, - module: Module + module: Module, ) { invokeLater { val mainModule = findMainModule(moduleMap, module) @@ -137,7 +137,7 @@ class ForgeRunConfigDataService : AbstractProjectDataService, module: Module, task: String, - hasData: Boolean + hasData: Boolean, ) { val mainModule = findMainModule(moduleMap, module) @@ -155,7 +155,7 @@ class ForgeRunConfigDataService : AbstractProjectDataService = element.createSmartPointer() +class RemoveAnnotationInspectionGadgetsFix( + private val annotationName: String, + private val name: String +) : InspectionGadgetsFix() { override fun doFix(project: Project, descriptor: ProblemDescriptor) { - pointer.element?.delete() + val decl = descriptor.psiElement.findParentOfType() ?: return + decl.findAnnotation(annotationName)?.delete() } @Nls diff --git a/src/main/kotlin/platform/forge/inspections/sideonly/Side.kt b/src/main/kotlin/platform/forge/inspections/sideonly/Side.kt index e4e8a9eda..7d17fb3d5 100644 --- a/src/main/kotlin/platform/forge/inspections/sideonly/Side.kt +++ b/src/main/kotlin/platform/forge/inspections/sideonly/Side.kt @@ -17,7 +17,8 @@ enum class Side { CLIENT, SERVER, NONE, - INVALID; + INVALID, + ; companion object { val KEY = Key("MC_DEV_SIDE") diff --git a/src/main/kotlin/platform/forge/inspections/sideonly/SideAnnotation.kt b/src/main/kotlin/platform/forge/inspections/sideonly/SideAnnotation.kt index 04df65cdf..9459c7fff 100644 --- a/src/main/kotlin/platform/forge/inspections/sideonly/SideAnnotation.kt +++ b/src/main/kotlin/platform/forge/inspections/sideonly/SideAnnotation.kt @@ -36,25 +36,25 @@ data class SideAnnotation( "net.minecraftforge.fml.relauncher.SideOnly", "net.minecraftforge.fml.relauncher.Side", "CLIENT", - "SERVER" + "SERVER", ), SideAnnotation( "cpw.mods.fml.relauncher.SideOnly", "cpw.mods.fml.relauncher.Side", "CLIENT", - "SERVER" + "SERVER", ), SideAnnotation( "net.minecraftforge.api.distmarker.OnlyIn", "net.minecraftforge.api.distmarker.Dist", "CLIENT", - "DEDICATED_SERVER" + "DEDICATED_SERVER", ), SideAnnotation( "net.fabricmc.api.Environment", "net.fabricmc.api.EnvType", "CLIENT", - "SERVER" + "SERVER", ), ) } diff --git a/src/main/kotlin/platform/forge/inspections/sideonly/SidedProxyAnnotator.kt b/src/main/kotlin/platform/forge/inspections/sideonly/SidedProxyAnnotator.kt index ff2c201a1..e0a028ad1 100644 --- a/src/main/kotlin/platform/forge/inspections/sideonly/SidedProxyAnnotator.kt +++ b/src/main/kotlin/platform/forge/inspections/sideonly/SidedProxyAnnotator.kt @@ -75,7 +75,7 @@ class SidedProxyAnnotator : Annotator { text = JavaConstantExpressionEvaluator.computeConstantExpression( resolve.initializer, null, - false + false, ) as? String ?: return } else { return diff --git a/src/main/kotlin/platform/forge/inspections/sideonly/VariableUseSideOnlyInspection.kt b/src/main/kotlin/platform/forge/inspections/sideonly/VariableUseSideOnlyInspection.kt index d73042759..30c2530d3 100644 --- a/src/main/kotlin/platform/forge/inspections/sideonly/VariableUseSideOnlyInspection.kt +++ b/src/main/kotlin/platform/forge/inspections/sideonly/VariableUseSideOnlyInspection.kt @@ -75,7 +75,7 @@ class VariableUseSideOnlyInspection : BaseInspection() { Error.ANNOTATED_CLASS_VAR_IN_CROSS_ANNOTATED_CLASS_METHOD, elementAnnotation.renderSide(elementSide), classAnnotation.renderSide(classSide), - declaration.getAnnotation(elementAnnotation.annotationName) + declaration.getAnnotation(elementAnnotation.annotationName), ) } else { registerError( @@ -83,7 +83,7 @@ class VariableUseSideOnlyInspection : BaseInspection() { Error.ANNOTATED_VAR_IN_CROSS_ANNOTATED_CLASS_METHOD, elementAnnotation.renderSide(elementSide), classAnnotation.renderSide(classSide), - declaration.getAnnotation(elementAnnotation.annotationName) + declaration.getAnnotation(elementAnnotation.annotationName), ) } } @@ -104,7 +104,7 @@ class VariableUseSideOnlyInspection : BaseInspection() { Error.ANNOTATED_CLASS_VAR_IN_UNANNOTATED_METHOD, elementAnnotation.renderSide(elementSide), null, - declaration.getAnnotation(elementAnnotation.annotationName) + declaration.getAnnotation(elementAnnotation.annotationName), ) } else { registerError( @@ -112,7 +112,7 @@ class VariableUseSideOnlyInspection : BaseInspection() { Error.ANNOTATED_VAR_IN_UNANNOTATED_METHOD, elementAnnotation.renderSide(elementSide), null, - declaration.getAnnotation(elementAnnotation.annotationName) + declaration.getAnnotation(elementAnnotation.annotationName), ) } } @@ -123,7 +123,7 @@ class VariableUseSideOnlyInspection : BaseInspection() { Error.ANNOTATED_CLASS_VAR_IN_CROSS_ANNOTATED_METHOD, elementAnnotation.renderSide(elementSide), methodAnnotation.renderSide(methodSide), - declaration.getAnnotation(elementAnnotation.annotationName) + declaration.getAnnotation(elementAnnotation.annotationName), ) } else { registerError( @@ -131,7 +131,7 @@ class VariableUseSideOnlyInspection : BaseInspection() { Error.ANNOTATED_VAR_IN_CROSS_ANNOTATED_METHOD, elementAnnotation.renderSide(elementSide), methodAnnotation.renderSide(methodSide), - declaration.getAnnotation(elementAnnotation.annotationName) + declaration.getAnnotation(elementAnnotation.annotationName), ) } } @@ -175,7 +175,7 @@ class VariableUseSideOnlyInspection : BaseInspection() { return "Variable declared in a class annotated with ${infos[0]}" + " cannot be referenced in a class annotated with ${infos[1]}." } - }; + }, ; abstract fun getErrorString(vararg infos: Any): String } diff --git a/src/main/kotlin/platform/forge/inspections/simpleimpl/AddEmptyConstructorInspectionGadgetsFix.kt b/src/main/kotlin/platform/forge/inspections/simpleimpl/AddEmptyConstructorInspectionGadgetsFix.kt index dc1a14d68..ed9fab4f5 100644 --- a/src/main/kotlin/platform/forge/inspections/simpleimpl/AddEmptyConstructorInspectionGadgetsFix.kt +++ b/src/main/kotlin/platform/forge/inspections/simpleimpl/AddEmptyConstructorInspectionGadgetsFix.kt @@ -10,24 +10,20 @@ package com.demonwav.mcdev.platform.forge.inspections.simpleimpl +import com.demonwav.mcdev.util.findContainingClass import com.intellij.codeInspection.ProblemDescriptor import com.intellij.openapi.project.Project import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiClass -import com.intellij.psi.SmartPsiElementPointer -import com.intellij.refactoring.suggested.createSmartPointer import com.siyeh.ig.InspectionGadgetsFix -class AddEmptyConstructorInspectionGadgetsFix(element: PsiClass, private val name: String) : InspectionGadgetsFix() { +object AddEmptyConstructorInspectionGadgetsFix : InspectionGadgetsFix() { - private val pointer: SmartPsiElementPointer = element.createSmartPointer() - - override fun doFix(project: Project, descriptor: ProblemDescriptor?) { - val clazz = pointer.element ?: return + override fun doFix(project: Project, descriptor: ProblemDescriptor) { + val clazz = descriptor.psiElement.findContainingClass() ?: return clazz.addBefore(JavaPsiFacade.getElementFactory(project).createConstructor(), clazz.methods[0]) } - override fun getName() = name + override fun getName() = "Add empty constructor" override fun getFamilyName() = name } diff --git a/src/main/kotlin/platform/forge/inspections/simpleimpl/MissingMessageConstructorInspection.kt b/src/main/kotlin/platform/forge/inspections/simpleimpl/MissingMessageConstructorInspection.kt index c032734f7..1fd2408bb 100644 --- a/src/main/kotlin/platform/forge/inspections/simpleimpl/MissingMessageConstructorInspection.kt +++ b/src/main/kotlin/platform/forge/inspections/simpleimpl/MissingMessageConstructorInspection.kt @@ -30,7 +30,7 @@ class MissingMessageConstructorInspection : BaseInspection() { val messageClass = infos[0] as PsiClass return if (messageClass.isWritable) { - AddEmptyConstructorInspectionGadgetsFix(messageClass, "Add empty constructor") + AddEmptyConstructorInspectionGadgetsFix } else { null } diff --git a/src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt b/src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt index d69e42d9c..d1f4b700b 100644 --- a/src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt +++ b/src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt @@ -21,17 +21,11 @@ import com.intellij.lang.jvm.JvmModifier import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.command.CommandProcessor import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiClassObjectAccessExpression -import com.intellij.psi.PsiClassType import com.intellij.psi.PsiElement -import com.intellij.psi.PsiElementResolveResult import com.intellij.psi.PsiExpressionList import com.intellij.psi.PsiLiteral import com.intellij.psi.PsiReference -import com.intellij.psi.PsiReferenceBase import com.intellij.psi.PsiReferenceProvider -import com.intellij.psi.ResolveResult import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.util.ProcessingContext @@ -44,10 +38,13 @@ object ReflectedFieldReference : PsiReferenceProvider() { return arrayOf(Reference(element as PsiLiteral)) } - class Reference(element: PsiLiteral) : PsiReferenceBase.Poly(element) { + class Reference(element: PsiLiteral) : ReflectedMemberReferenceBasePoly(element) { val fieldName get() = element.constantStringValue ?: "" + override val memberName: String + get() = fieldName + override fun getVariants(): Array { val typeClass = findReferencedClass() ?: return arrayOf() @@ -76,7 +73,7 @@ object ReflectedFieldReference : PsiReferenceProvider() { val elementFactory = JavaPsiFacade.getElementFactory(context.project) val srgLiteral = elementFactory.createExpressionFromText( "\"${srgField.name}\"", - literal.parent + literal.parent, ) literal.replace(srgLiteral) @@ -90,27 +87,5 @@ object ReflectedFieldReference : PsiReferenceProvider() { } .toTypedArray() } - - override fun multiResolve(incompleteCode: Boolean): Array { - val typeClass = findReferencedClass() ?: return arrayOf() - - val name = fieldName - val srgManager = element.findModule()?.let { MinecraftFacet.getInstance(it) } - ?.getModuleOfType(McpModuleType)?.srgManager - val srgMap = srgManager?.srgMapNow - val mcpName = srgMap?.mapMcpToSrgName(name) ?: name - - return typeClass.allFields.asSequence() - .filter { it.name == mcpName } - .map(::PsiElementResolveResult) - .toTypedArray() - } - - private fun findReferencedClass(): PsiClass? { - val callParams = element.parent as? PsiExpressionList - val classRef = callParams?.expressions?.first() as? PsiClassObjectAccessExpression - val type = classRef?.operand?.type as? PsiClassType - return type?.resolve() - } } } diff --git a/src/main/kotlin/platform/forge/reflection/reference/ReflectedMemberReferenceBasePoly.kt b/src/main/kotlin/platform/forge/reflection/reference/ReflectedMemberReferenceBasePoly.kt new file mode 100644 index 000000000..7fbd83232 --- /dev/null +++ b/src/main/kotlin/platform/forge/reflection/reference/ReflectedMemberReferenceBasePoly.kt @@ -0,0 +1,51 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.forge.reflection.reference + +import com.demonwav.mcdev.facet.MinecraftFacet +import com.demonwav.mcdev.platform.mcp.McpModuleType +import com.demonwav.mcdev.util.findModule +import com.demonwav.mcdev.util.toTypedArray +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiClassObjectAccessExpression +import com.intellij.psi.PsiClassType +import com.intellij.psi.PsiElementResolveResult +import com.intellij.psi.PsiExpressionList +import com.intellij.psi.PsiLiteral +import com.intellij.psi.PsiReferenceBase +import com.intellij.psi.ResolveResult + +abstract class ReflectedMemberReferenceBasePoly(element: PsiLiteral) : PsiReferenceBase.Poly(element) { + + abstract val memberName: String + + protected fun findReferencedClass(): PsiClass? { + val callParams = element.parent as? PsiExpressionList + val classRef = callParams?.expressions?.first() as? PsiClassObjectAccessExpression + val type = classRef?.operand?.type as? PsiClassType + return type?.resolve() + } + + override fun multiResolve(incompleteCode: Boolean): Array { + val typeClass = findReferencedClass() ?: return arrayOf() + + val name = memberName + val srgManager = element.findModule()?.let { MinecraftFacet.getInstance(it) } + ?.getModuleOfType(McpModuleType)?.srgManager + val srgMap = srgManager?.srgMapNow + val mcpName = srgMap?.mapMcpToSrgName(name) ?: name + + return typeClass.allFields.asSequence() + .filter { it.name == mcpName } + .map(::PsiElementResolveResult) + .toTypedArray() + } +} diff --git a/src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt b/src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt index 3b3b37ee5..780a4dccf 100644 --- a/src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt +++ b/src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt @@ -21,18 +21,12 @@ import com.intellij.lang.jvm.JvmModifier import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.command.CommandProcessor import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiClassObjectAccessExpression -import com.intellij.psi.PsiClassType import com.intellij.psi.PsiElement -import com.intellij.psi.PsiElementResolveResult import com.intellij.psi.PsiExpressionList import com.intellij.psi.PsiLiteral import com.intellij.psi.PsiReference -import com.intellij.psi.PsiReferenceBase import com.intellij.psi.PsiReferenceProvider import com.intellij.psi.PsiSubstitutor -import com.intellij.psi.ResolveResult import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.psi.codeStyle.JavaCodeStyleManager import com.intellij.psi.util.MethodSignatureUtil @@ -48,10 +42,13 @@ object ReflectedMethodReference : PsiReferenceProvider() { return arrayOf(Reference(element as PsiLiteral)) } - class Reference(element: PsiLiteral) : PsiReferenceBase.Poly(element) { + class Reference(element: PsiLiteral) : ReflectedMemberReferenceBasePoly(element) { val methodName get() = element.constantStringValue ?: "" + override val memberName: String + get() = methodName + val expressionList get() = element.parent as PsiExpressionList @@ -89,7 +86,7 @@ object ReflectedMethodReference : PsiReferenceProvider() { val elementFactory = JavaPsiFacade.getElementFactory(context.project) val srgLiteral = elementFactory.createExpressionFromText( "\"${srgMethod.name}\"", - params + params, ) if (params.expressionCount > 1) { @@ -103,14 +100,14 @@ object ReflectedMethodReference : PsiReferenceProvider() { } val returnTypeRef = elementFactory.createExpressionFromText( "$returnType.class", - params + params, ) params.add(returnTypeRef) for (paramType in paramTypes) { val paramTypeRef = elementFactory.createExpressionFromText( "$paramType.class", - params + params, ) params.add(paramTypeRef) } @@ -126,27 +123,5 @@ object ReflectedMethodReference : PsiReferenceProvider() { } .toTypedArray() } - - override fun multiResolve(incompleteCode: Boolean): Array { - val typeClass = findReferencedClass() ?: return arrayOf() - - val name = methodName - val srgManager = element.findModule()?.let { MinecraftFacet.getInstance(it) } - ?.getModuleOfType(McpModuleType)?.srgManager - val srgMap = srgManager?.srgMapNow - val mcpName = srgMap?.mapMcpToSrgName(name) ?: name - - return typeClass.allMethods.asSequence() - .filter { it.name == mcpName } - .map(::PsiElementResolveResult) - .toTypedArray() - } - - private fun findReferencedClass(): PsiClass? { - val callParams = element.parent as? PsiExpressionList - val classRef = callParams?.expressions?.first() as? PsiClassObjectAccessExpression - val type = classRef?.operand?.type as? PsiClassType - return type?.resolve() - } } } diff --git a/src/main/kotlin/platform/forge/reflection/reference/ReflectionReferenceContributor.kt b/src/main/kotlin/platform/forge/reflection/reference/ReflectionReferenceContributor.kt index abfe86429..8d1d6fe41 100644 --- a/src/main/kotlin/platform/forge/reflection/reference/ReflectionReferenceContributor.kt +++ b/src/main/kotlin/platform/forge/reflection/reference/ReflectionReferenceContributor.kt @@ -21,17 +21,17 @@ class ReflectionReferenceContributor : PsiReferenceContributor() { PsiJavaPatterns.psiLiteral(StandardPatterns.string()) .and( PsiJavaPatterns.psiElement() - .methodCallParameter(PsiJavaPatterns.psiMethod().withName("findField")) + .methodCallParameter(PsiJavaPatterns.psiMethod().withName("findField")), ), - ReflectedFieldReference + ReflectedFieldReference, ) registrar.registerReferenceProvider( PsiJavaPatterns.psiLiteral(StandardPatterns.string()) .and( PsiJavaPatterns.psiElement() - .methodCallParameter(PsiJavaPatterns.psiMethod().withName("findMethod")) + .methodCallParameter(PsiJavaPatterns.psiMethod().withName("findMethod")), ), - ReflectedMethodReference + ReflectedMethodReference, ) } } diff --git a/src/main/kotlin/platform/forge/util/ForgePackDescriptor.kt b/src/main/kotlin/platform/forge/util/ForgePackDescriptor.kt index 3100b3ac5..6b2f79425 100644 --- a/src/main/kotlin/platform/forge/util/ForgePackDescriptor.kt +++ b/src/main/kotlin/platform/forge/util/ForgePackDescriptor.kt @@ -21,21 +21,21 @@ data class ForgePackDescriptor(val format: Int, val comment: String) { "A pack_format of 3 should be used starting with Minecraft 1.11." + " All resources, including language files, should be lowercase (eg: en_us.lang)." + " A pack_format of 2 will load your mod resources with LegacyV2Adapter," + - " which requires language files to have uppercase letters (eg: en_US.lang)." + " which requires language files to have uppercase letters (eg: en_US.lang).", ) val FORMAT_4 = ForgePackDescriptor( 4, - "A pack_format of 4 requires json lang files. Note: we require v4 pack meta for all mods." + "A pack_format of 4 requires json lang files. Note: we require v4 pack meta for all mods.", ) val FORMAT_5 = ForgePackDescriptor( 5, "A pack_format of 5 requires json lang files and some texture changes from 1.15." + - " Note: we require v5 pack meta for all mods." + " Note: we require v5 pack meta for all mods.", ) val FORMAT_6 = ForgePackDescriptor( 6, "A pack_format of 6 requires json lang files and some texture changes from 1.16.2." + - " Note: we require v6 pack meta for all mods." + " Note: we require v6 pack meta for all mods.", ) val FORMAT_7 = ForgePackDescriptor(7, "") val FORMAT_8 = ForgePackDescriptor(8, "") diff --git a/src/main/kotlin/platform/forge/version/ForgeVersion.kt b/src/main/kotlin/platform/forge/version/ForgeVersion.kt index 79a3cabd2..2bf6e1653 100644 --- a/src/main/kotlin/platform/forge/version/ForgeVersion.kt +++ b/src/main/kotlin/platform/forge/version/ForgeVersion.kt @@ -32,7 +32,7 @@ class ForgeVersion private constructor(val versions: List) { return null } return version.substring(0, index) - } + }, ).distinct() .toList() return@lazy sortVersions(unsortedVersions) diff --git a/src/main/kotlin/platform/liteloader/LiteLoaderFileIconProvider.kt b/src/main/kotlin/platform/liteloader/LiteLoaderFileIconProvider.kt deleted file mode 100644 index 570bed6cf..000000000 --- a/src/main/kotlin/platform/liteloader/LiteLoaderFileIconProvider.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.liteloader - -import com.demonwav.mcdev.MinecraftSettings -import com.demonwav.mcdev.facet.MinecraftFacet -import com.intellij.ide.FileIconProvider -import com.intellij.openapi.module.ModuleUtilCore -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile -import javax.swing.Icon - -class LiteLoaderFileIconProvider : FileIconProvider { - override fun getIcon(file: VirtualFile, flags: Int, project: Project?): Icon? { - project ?: return null - - if (!MinecraftSettings.instance.isShowProjectPlatformIcons) { - return null - } - - val module = ModuleUtilCore.findModuleForFile(file, project) ?: return null - val liteloaderModule = MinecraftFacet.getInstance(module, LiteLoaderModuleType) ?: return null - - if (file == liteloaderModule.litemodJson) { - return liteloaderModule.icon - } - return null - } -} diff --git a/src/main/kotlin/platform/liteloader/LiteLoaderModule.kt b/src/main/kotlin/platform/liteloader/LiteLoaderModule.kt deleted file mode 100644 index 6531ddc05..000000000 --- a/src/main/kotlin/platform/liteloader/LiteLoaderModule.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.liteloader - -import com.demonwav.mcdev.asset.PlatformAssets -import com.demonwav.mcdev.facet.MinecraftFacet -import com.demonwav.mcdev.platform.AbstractModule -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.platform.liteloader.util.LiteLoaderConstants -import com.demonwav.mcdev.util.SourceType -import com.demonwav.mcdev.util.nullable -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import org.jetbrains.uast.UClass -import org.jetbrains.uast.UIdentifier -import org.jetbrains.uast.toUElementOfType - -class LiteLoaderModule internal constructor(facet: MinecraftFacet) : AbstractModule(facet) { - - var litemodJson by nullable { facet.findFile(LiteLoaderConstants.LITEMOD_JSON, SourceType.RESOURCE) } - private set - - override val moduleType = LiteLoaderModuleType - override val type = PlatformType.LITELOADER - override val icon = PlatformAssets.LITELOADER_ICON - - override fun isEventClassValid(eventClass: PsiClass, method: PsiMethod?) = true - - override fun writeErrorMessageForEventParameter(eventClass: PsiClass, method: PsiMethod) = "" - - override fun shouldShowPluginIcon(element: PsiElement?): Boolean { - val identifier = element?.toUElementOfType() - ?: return false - return identifier.uastParent is UClass && identifier.name.startsWith("LiteMod") - } - - override fun dispose() { - super.dispose() - litemodJson = null - } -} diff --git a/src/main/kotlin/platform/liteloader/LiteLoaderModuleType.kt b/src/main/kotlin/platform/liteloader/LiteLoaderModuleType.kt deleted file mode 100644 index 41a9ba839..000000000 --- a/src/main/kotlin/platform/liteloader/LiteLoaderModuleType.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.liteloader - -import com.demonwav.mcdev.asset.PlatformAssets -import com.demonwav.mcdev.facet.MinecraftFacet -import com.demonwav.mcdev.platform.AbstractModuleType -import com.demonwav.mcdev.platform.PlatformType - -object LiteLoaderModuleType : AbstractModuleType("", "") { - - private const val ID = "LITELOADER_MODULE_TYPE" - - val IGNORED_ANNOTATIONS = emptyList() - val LISTENER_ANNOTATIONS = emptyList() - - override val platformType = PlatformType.LITELOADER - override val icon = PlatformAssets.LITELOADER_ICON - override val id = ID - override val ignoredAnnotations = IGNORED_ANNOTATIONS - override val listenerAnnotations = LISTENER_ANNOTATIONS - - override fun generateModule(facet: MinecraftFacet) = LiteLoaderModule(facet) -} diff --git a/src/main/kotlin/platform/liteloader/creator/LiteLoaderProjectConfig.kt b/src/main/kotlin/platform/liteloader/creator/LiteLoaderProjectConfig.kt deleted file mode 100644 index 8d744ac02..000000000 --- a/src/main/kotlin/platform/liteloader/creator/LiteLoaderProjectConfig.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.liteloader.creator - -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.ProjectCreator -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleCreator -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.platform.forge.creator.Fg2ProjectCreator -import com.demonwav.mcdev.platform.mcp.McpVersionPair -import com.demonwav.mcdev.util.MinecraftVersions -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.VersionRange -import com.intellij.openapi.module.Module -import com.intellij.util.lang.JavaVersion -import java.nio.file.Path - -class LiteLoaderProjectConfig : ProjectConfig(), GradleCreator { - - lateinit var mainClass: String - - var mcpVersion = McpVersionPair("", SemanticVersion.release()) - var mcVersion: SemanticVersion = SemanticVersion.release() - - override var type = PlatformType.LITELOADER - - override val preferredBuildSystem = BuildSystemType.GRADLE - - override val javaVersion: JavaVersion - get() = MinecraftVersions.requiredJavaVersion(mcVersion) - - override val compatibleGradleVersions: VersionRange = VersionRange.fixed(Fg2ProjectCreator.FG_WRAPPER_VERSION) - - override fun buildGradleCreator( - rootDirectory: Path, - module: Module, - buildSystem: GradleBuildSystem - ): ProjectCreator { - return LiteLoaderProjectCreator(rootDirectory, module, buildSystem, this) - } - - override fun configureRootGradle( - rootDirectory: Path, - buildSystem: GradleBuildSystem - ) { - buildSystem.gradleVersion = Fg2ProjectCreator.FG_WRAPPER_VERSION - } -} diff --git a/src/main/kotlin/platform/liteloader/creator/LiteLoaderProjectCreator.kt b/src/main/kotlin/platform/liteloader/creator/LiteLoaderProjectCreator.kt deleted file mode 100644 index ae12564bb..000000000 --- a/src/main/kotlin/platform/liteloader/creator/LiteLoaderProjectCreator.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.liteloader.creator - -import com.demonwav.mcdev.creator.BaseProjectCreator -import com.demonwav.mcdev.creator.BasicJavaClassStep -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.buildsystem.gradle.BasicGradleFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleFiles -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleGitignoreStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleWrapperStep -import com.demonwav.mcdev.creator.buildsystem.gradle.SimpleGradleSetupStep -import com.demonwav.mcdev.platform.forge.creator.SetupDecompWorkspaceStep -import com.intellij.openapi.module.Module -import java.nio.file.Path - -class LiteLoaderProjectCreator( - private val rootDirectory: Path, - private val rootModule: Module, - private val buildSystem: GradleBuildSystem, - private val config: LiteLoaderProjectConfig -) : BaseProjectCreator(rootModule, buildSystem) { - - private fun setupMainClassStep(): BasicJavaClassStep { - return createJavaClassStep(config.mainClass) { packageName, className -> - val modName = config.pluginName - LiteLoaderTemplate.applyMainClass(project, packageName, className, modName, buildSystem.version) - } - } - - override fun getSteps(): Iterable { - val buildText = LiteLoaderTemplate.applyBuildGradle(project, buildSystem, config.mcVersion) - val propText = LiteLoaderTemplate.applyGradleProp(project, config) - val settingsText = LiteLoaderTemplate.applySettingsGradle(project, buildSystem.artifactId) - val files = GradleFiles(buildText, propText, settingsText) - - return listOf( - SimpleGradleSetupStep( - project, - rootDirectory, - buildSystem, - files - ), - setupMainClassStep(), - GradleWrapperStep(project, rootDirectory, buildSystem), - SetupDecompWorkspaceStep(project, rootDirectory), - GradleGitignoreStep(project, rootDirectory), - BasicGradleFinalizerStep(rootModule, rootDirectory, buildSystem) - ) - } -} diff --git a/src/main/kotlin/platform/liteloader/creator/LiteLoaderProjectSettingsWizard.form b/src/main/kotlin/platform/liteloader/creator/LiteLoaderProjectSettingsWizard.form deleted file mode 100644 index b4eeafeda..000000000 --- a/src/main/kotlin/platform/liteloader/creator/LiteLoaderProjectSettingsWizard.form +++ /dev/null @@ -1,179 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/main/kotlin/platform/liteloader/creator/LiteLoaderProjectSettingsWizard.kt b/src/main/kotlin/platform/liteloader/creator/LiteLoaderProjectSettingsWizard.kt deleted file mode 100644 index c9c990d08..000000000 --- a/src/main/kotlin/platform/liteloader/creator/LiteLoaderProjectSettingsWizard.kt +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.liteloader.creator - -import com.demonwav.mcdev.creator.MinecraftModuleWizardStep -import com.demonwav.mcdev.creator.MinecraftProjectCreator -import com.demonwav.mcdev.creator.ValidatedField -import com.demonwav.mcdev.creator.ValidatedFieldType.CLASS_NAME -import com.demonwav.mcdev.creator.ValidatedFieldType.NON_BLANK -import com.demonwav.mcdev.creator.exception.EmptyInputSetupException -import com.demonwav.mcdev.creator.exception.SetupException -import com.demonwav.mcdev.platform.liteloader.version.LiteLoaderVersion -import com.demonwav.mcdev.platform.mcp.version.McpVersion -import com.demonwav.mcdev.platform.mcp.version.McpVersionEntry -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.asyncIO -import com.demonwav.mcdev.util.invokeLater -import com.intellij.openapi.ui.MessageType -import com.intellij.openapi.ui.popup.Balloon -import com.intellij.openapi.ui.popup.JBPopupFactory -import com.intellij.ui.DocumentAdapter -import com.intellij.ui.awt.RelativePoint -import java.awt.event.ActionListener -import java.util.regex.Pattern -import javax.swing.JComboBox -import javax.swing.JComponent -import javax.swing.JLabel -import javax.swing.JPanel -import javax.swing.JProgressBar -import javax.swing.JTextField -import javax.swing.event.DocumentEvent -import javax.swing.text.AbstractDocument -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.launch -import kotlinx.coroutines.swing.Swing -import kotlinx.coroutines.withContext -import org.apache.commons.lang.WordUtils - -class LiteLoaderProjectSettingsWizard(private val creator: MinecraftProjectCreator) : MinecraftModuleWizardStep() { - - private lateinit var panel: JPanel - private lateinit var mcpWarning: JLabel - - @ValidatedField(NON_BLANK) - private lateinit var modNameField: JTextField - - @ValidatedField(NON_BLANK, CLASS_NAME) - private lateinit var mainClassField: JTextField - private lateinit var minecraftVersionBox: JComboBox - private lateinit var mcpVersionBox: JComboBox - private lateinit var loadingBar: JProgressBar - - private var config: LiteLoaderProjectConfig? = null - - private data class LiteLoaderVersions( - val mcpVersion: McpVersion, - val liteloaderVersion: LiteLoaderVersion - ) - - private var versions: LiteLoaderVersions? = null - private var mainClassModified = false - - private var currentJob: Job? = null - - private val mcpBoxActionListener = ActionListener { - mcpWarning.isVisible = (mcpVersionBox.selectedItem as McpVersionEntry).isRed - } - - private val listener = object : DocumentAdapter() { - override fun textChanged(e: DocumentEvent) { - // Make sure they don't try to add spaces or whatever - if (javaClassPattern.matcher(mainClassField.text).find()) { - invokeLater { - mainClassField.document.removeDocumentListener(this) - (e as AbstractDocument.DefaultDocumentEvent).undo() - mainClassField.document.addDocumentListener(this) - } - return - } - - // We just need to make sure they aren't messing up the LiteMod text - val words = mainClassField.text.split(".").dropLastWhile(String::isEmpty).toTypedArray() - if (!words.last().startsWith(LITEMOD)) { - invokeLater { - mainClassField.document.removeDocumentListener(this) - (e as AbstractDocument.DefaultDocumentEvent).undo() - mainClassField.document.addDocumentListener(this) - } - } else { - mainClassModified = true - } - } - } - - init { - mcpWarning.isVisible = false - - minecraftVersionBox.addActionListener { - val mcpVersion = versions?.mcpVersion ?: return@addActionListener - CoroutineScope(Dispatchers.Swing).launch { - val version = minecraftVersionBox.selectedItem as SemanticVersion - val mcpVersions = withContext(Dispatchers.Default) { mcpVersion.getMcpVersionList(version) } - - mcpVersionBox.removeActionListener(mcpBoxActionListener) - mcpVersionBox.removeAllItems() - mcpVersions.forEach { mcpVersionBox.addItem(it) } - mcpVersionBox.addActionListener(mcpBoxActionListener) - mcpBoxActionListener.actionPerformed(null) - } - } - - modNameField.document.addDocumentListener( - object : DocumentAdapter() { - override fun textChanged(e: DocumentEvent) { - if (mainClassModified) { - return - } - - val word = modNameField.text.split(Regex("\\s+")).joinToString("") { WordUtils.capitalize(it) } - - val mainClassWords = mainClassField.text.split('.').toTypedArray() - mainClassWords[mainClassWords.size - 1] = LITEMOD + word - - mainClassField.document.removeDocumentListener(listener) - mainClassField.text = mainClassWords.joinToString(".") - mainClassField.document.addDocumentListener(listener) - } - } - ) - - mainClassField.document.addDocumentListener(listener) - } - - override fun getComponent(): JComponent { - return panel - } - - override fun validate(): Boolean { - try { - if (modNameField.text.isBlank()) { - throw EmptyInputSetupException(modNameField) - } - - if (mainClassField.text.isBlank()) { - throw EmptyInputSetupException(mainClassField) - } - } catch (e: SetupException) { - JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(e.error, MessageType.ERROR, null) - .setFadeoutTime(4000) - .createBalloon() - .show(RelativePoint.getSouthWestOf(e.j), Balloon.Position.below) - return false - } - - return !loadingBar.isVisible - } - - override fun isStepVisible(): Boolean { - return creator.config is LiteLoaderProjectConfig - } - - override fun updateStep() { - config = creator.config as? LiteLoaderProjectConfig - if (config == null) { - return - } - - val buildSystem = creator.buildSystem ?: return - - modNameField.text = WordUtils.capitalizeFully(buildSystem.artifactId.replace('-', ' ')) - - mainClassField.document.removeDocumentListener(listener) - mainClassField.text = generateClassName(buildSystem, modNameField.text) { name -> LITEMOD + name } - mainClassField.document.addDocumentListener(listener) - - if (versions != null || currentJob?.isActive == true) { - return - } - currentJob = updateVersions() - } - - override fun onStepLeaving() { - currentJob?.cancel() - } - - override fun updateDataModel() { - val conf = this.config ?: return - - conf.pluginName = this.modNameField.text - conf.mainClass = this.mainClassField.text - - conf.mcVersion = this.minecraftVersionBox.selectedItem as SemanticVersion - conf.mcpVersion = (this.mcpVersionBox.selectedItem as McpVersionEntry).versionPair - } - - private fun updateVersions() = CoroutineScope(Dispatchers.Swing).launch { - loadingBar.isIndeterminate = true - loadingBar.isVisible = true - - val version = minecraftVersionBox.selectedItem as? SemanticVersion - - val mcpVersionJob = asyncIO { McpVersion.downloadData() } - val liteloaderVersionJob = asyncIO { LiteLoaderVersion.downloadData() } - - val (mcpVersionObj, liteloaderVersionObj) = listOf(mcpVersionJob, liteloaderVersionJob).awaitAll() - val mcpVersion = mcpVersionObj as McpVersion? ?: return@launch - val liteloaderVersion = liteloaderVersionObj as LiteLoaderVersion? ?: return@launch - - val data = withContext(Dispatchers.IO) { - val listVersion = version ?: liteloaderVersion.sortedMcVersions.first() - return@withContext mcpVersion.getMcpVersionList(listVersion) - } - - if (liteloaderVersion.sortedMcVersions.isEmpty()) { - return@launch - } - - minecraftVersionBox.removeAllItems() - - liteloaderVersion.sortedMcVersions.forEach { minecraftVersionBox.addItem(it) } - // Always select most recent - minecraftVersionBox.selectedIndex = 0 - - mcpVersionBox.removeActionListener(mcpBoxActionListener) - mcpVersionBox.removeAllItems() - data.forEach { mcpVersionBox.addItem(it) } - mcpVersionBox.addActionListener(mcpBoxActionListener) - mcpBoxActionListener.actionPerformed(null) - - versions = LiteLoaderVersions(mcpVersion, liteloaderVersion) - - loadingBar.isIndeterminate = false - loadingBar.isVisible = false - - currentJob = null - } - - companion object { - private const val LITEMOD = "LiteMod" - private val javaClassPattern = Pattern.compile("\\s+|-|\\$") - } -} diff --git a/src/main/kotlin/platform/liteloader/creator/LiteLoaderTemplate.kt b/src/main/kotlin/platform/liteloader/creator/LiteLoaderTemplate.kt deleted file mode 100644 index 21d87a0ef..000000000 --- a/src/main/kotlin/platform/liteloader/creator/LiteLoaderTemplate.kt +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.liteloader.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.platform.BaseTemplate -import com.demonwav.mcdev.platform.forge.ForgeModuleType -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.LITELOADER_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.LITELOADER_GRADLE_PROPERTIES_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.LITELOADER_MAIN_CLASS_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.LITELOADER_SETTINGS_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.LITELOADER_SUBMODULE_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.SemanticVersion -import com.intellij.openapi.project.Project - -object LiteLoaderTemplate : BaseTemplate() { - - fun applyMainClass( - project: Project, - packageName: String, - className: String, - modName: String, - modVersion: String - ): String { - val props = mapOf( - "PACKAGE_NAME" to packageName, - "CLASS_NAME" to className, - "MOD_NAME" to modName, - "MOD_VERSION" to modVersion - ) - - return project.applyTemplate(LITELOADER_MAIN_CLASS_TEMPLATE, props) - } - - fun applyBuildGradle(project: Project, buildSystem: BuildSystem, mcVersion: SemanticVersion): String { - val props = mapOf( - "FORGEGRADLE_VERSION" to fgVersion(mcVersion), - "GROUP_ID" to buildSystem.groupId, - "ARTIFACT_ID" to buildSystem.artifactId, - "VERSION" to buildSystem.version - ) - - return project.applyTemplate(LITELOADER_BUILD_GRADLE_TEMPLATE, props) - } - - fun applyGradleProp(project: Project, config: LiteLoaderProjectConfig): String { - val props = mapOf( - "MC_VERSION" to config.mcVersion.toString(), - "MCP_MAPPINGS" to config.mcpVersion.mcpVersion - ) - - return project.applyTemplate(LITELOADER_GRADLE_PROPERTIES_TEMPLATE, props) - } - - fun applySettingsGradle(project: Project, artifactId: String): String { - val props = mapOf( - "ARTIFACT_ID" to artifactId - ) - - return project.applyTemplate(LITELOADER_SETTINGS_GRADLE_TEMPLATE, props) - } - - fun applySubBuildGradle(project: Project, buildSystem: BuildSystem, mcVersion: SemanticVersion): String { - val props = mapOf( - "COMMON_PROJECT_NAME" to buildSystem.commonModuleName, - "FORGEGRADLE_VERSION" to fgVersion(mcVersion), - "ARTIFACT_ID" to buildSystem.artifactId - ) - - return project.applyTemplate(LITELOADER_SUBMODULE_BUILD_GRADLE_TEMPLATE, props) - } - - private fun fgVersion(mcVersion: SemanticVersion): String { - // Fixes builds for MC1.12+, requires FG 2.3 - return if (mcVersion >= ForgeModuleType.FG23_MC_VERSION) { - "2.3" - } else { - "2.2" - } - } -} diff --git a/src/main/kotlin/platform/liteloader/framework/LiteLoaderLibraryKind.kt b/src/main/kotlin/platform/liteloader/framework/LiteLoaderLibraryKind.kt deleted file mode 100644 index 070acea7e..000000000 --- a/src/main/kotlin/platform/liteloader/framework/LiteLoaderLibraryKind.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.liteloader.framework - -import com.demonwav.mcdev.util.libraryKind -import com.intellij.openapi.roots.libraries.LibraryKind - -val LITELOADER_LIBRARY_KIND: LibraryKind = libraryKind("liteloader-library") diff --git a/src/main/kotlin/platform/liteloader/framework/LiteLoaderPresentationProvider.kt b/src/main/kotlin/platform/liteloader/framework/LiteLoaderPresentationProvider.kt deleted file mode 100644 index 294bda89a..000000000 --- a/src/main/kotlin/platform/liteloader/framework/LiteLoaderPresentationProvider.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.liteloader.framework - -import com.demonwav.mcdev.asset.PlatformAssets -import com.demonwav.mcdev.facet.ManifestLibraryPresentationProvider -import com.intellij.framework.library.LibraryVersionProperties - -class LiteLoaderPresentationProvider : - ManifestLibraryPresentationProvider(LITELOADER_LIBRARY_KIND, "LiteLoader", true) { - override fun getIcon(properties: LibraryVersionProperties?) = PlatformAssets.LITELOADER_ICON -} diff --git a/src/main/kotlin/platform/liteloader/util/LiteLoaderConstants.kt b/src/main/kotlin/platform/liteloader/util/LiteLoaderConstants.kt deleted file mode 100644 index 213e5821c..000000000 --- a/src/main/kotlin/platform/liteloader/util/LiteLoaderConstants.kt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.liteloader.util - -object LiteLoaderConstants { - const val LITEMOD_JSON = "litemod.json" -} diff --git a/src/main/kotlin/platform/liteloader/version/LiteLoaderVersion.kt b/src/main/kotlin/platform/liteloader/version/LiteLoaderVersion.kt deleted file mode 100644 index 799b2bb0b..000000000 --- a/src/main/kotlin/platform/liteloader/version/LiteLoaderVersion.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.liteloader.version - -import com.demonwav.mcdev.creator.selectProxy -import com.demonwav.mcdev.update.PluginUtil -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.fromJson -import com.demonwav.mcdev.util.sortVersions -import com.github.kittinunf.fuel.core.FuelManager -import com.github.kittinunf.fuel.core.requests.suspendable -import com.github.kittinunf.fuel.coroutines.awaitString -import com.google.gson.Gson -import com.intellij.openapi.diagnostic.logger -import java.io.IOException - -class LiteLoaderVersion private constructor(private var map: Map<*, *>) { - - val sortedMcVersions: List by lazy { - val mcVersion = map["versions"] as Map<*, *> - - @Suppress("UNCHECKED_CAST") - val keys = mcVersion.keys as Collection - return@lazy sortVersions(keys) - } - - companion object { - private val LOGGER = logger() - - suspend fun downloadData(): LiteLoaderVersion? { - try { - val url = "https://dl.liteloader.com/versions/versions.json" - val manager = FuelManager() - manager.proxy = selectProxy(url) - - val text = manager.get(url) - .header("User-Agent", PluginUtil.useragent) - .suspendable() - .awaitString() - - val map = Gson().fromJson>(text) - val liteLoaderVersion = LiteLoaderVersion(map) - liteLoaderVersion.sortedMcVersions - return liteLoaderVersion - } catch (e: IOException) { - LOGGER.error("Failed to download LiteLoader version json", e) - } - return null - } - } -} diff --git a/src/main/kotlin/platform/mcp/McpModuleSettings.kt b/src/main/kotlin/platform/mcp/McpModuleSettings.kt index 26414416c..d426362b7 100644 --- a/src/main/kotlin/platform/mcp/McpModuleSettings.kt +++ b/src/main/kotlin/platform/mcp/McpModuleSettings.kt @@ -26,7 +26,7 @@ class McpModuleSettings : PersistentStateComponent { var mcpVersion: String? = null, var mappingFile: String? = null, var srgType: SrgType? = null, - var platformVersion: String? = null + var platformVersion: String? = null, ) private var state: State = State(srgType = SrgType.SRG) diff --git a/src/main/kotlin/platform/mcp/actions/CopyAtAction.kt b/src/main/kotlin/platform/mcp/actions/CopyAtAction.kt index 3a57513b9..61a42aaa7 100644 --- a/src/main/kotlin/platform/mcp/actions/CopyAtAction.kt +++ b/src/main/kotlin/platform/mcp/actions/CopyAtAction.kt @@ -31,7 +31,7 @@ class CopyAtAction : SrgActionBase() { copyToClipboard( data.editor, data.element, - classSrg + " " + srg.name + " # " + parent.name + classSrg + " " + srg.name + " # " + parent.name, ) } is PsiMethod -> { @@ -41,7 +41,7 @@ class CopyAtAction : SrgActionBase() { copyToClipboard( data.editor, data.element, - classSrg + " " + srg.name + srg.descriptor + " # " + parent.name + classSrg + " " + srg.name + srg.descriptor + " # " + parent.name, ) } is PsiClass -> { diff --git a/src/main/kotlin/platform/mcp/actions/CopyAwAction.kt b/src/main/kotlin/platform/mcp/actions/CopyAwAction.kt index 3a6d9dc86..86a05ef0b 100644 --- a/src/main/kotlin/platform/mcp/actions/CopyAwAction.kt +++ b/src/main/kotlin/platform/mcp/actions/CopyAwAction.kt @@ -68,7 +68,7 @@ class CopyAwAction : AnAction() { val containing = target.containingClass?.internalName ?: return maybeShow("Could not get owner of method", e) val desc = target.descriptor ?: return maybeShow("Could not get descriptor of method", e) - val text = "accessible method $containing ${target.name} $desc" + val text = "accessible method $containing ${target.internalName} $desc" copyToClipboard(editor, element, text) } else -> maybeShow("Invalid element", e) diff --git a/src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt b/src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt index af5239294..519c7b991 100644 --- a/src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt +++ b/src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt @@ -35,7 +35,7 @@ class CopyCoremodTargetAction : SrgActionBase() { data.element, Pair("target", "FIELD"), Pair("class", classSrg), - Pair("fieldName", srg.name) + Pair("fieldName", srg.name), ) } is PsiMethod -> { @@ -49,7 +49,7 @@ class CopyCoremodTargetAction : SrgActionBase() { Pair("target", "METHOD"), Pair("class", classSrg), Pair("methodName", srg.name), - Pair("methodDesc", srgDescriptor) + Pair("methodDesc", srgDescriptor), ) } is PsiClass -> { diff --git a/src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt b/src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt index 6763ef26d..f96d44d1b 100644 --- a/src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt +++ b/src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt @@ -32,7 +32,7 @@ class FindSrgMappingAction : SrgActionBase() { } is PsiClass -> { val classMcpToSrg = srgMap.getSrgClass(parent) ?: return showBalloon("No SRG name found", e) - showSuccessBalloon(data.editor, data.element, "SRG name: " + classMcpToSrg) + showSuccessBalloon(data.editor, data.element, "SRG name: $classMcpToSrg") } else -> showBalloon("Not a valid element", e) } diff --git a/src/main/kotlin/platform/mcp/actions/GotoAtEntryAction.kt b/src/main/kotlin/platform/mcp/actions/GotoAtEntryAction.kt index c97546abd..a4089360d 100644 --- a/src/main/kotlin/platform/mcp/actions/GotoAtEntryAction.kt +++ b/src/main/kotlin/platform/mcp/actions/GotoAtEntryAction.kt @@ -95,7 +95,7 @@ class GotoAtEntryAction : AnAction() { LocalSearchScope(file), text, UsageSearchContext.ANY, - true + true, ) if (found) { diff --git a/src/main/kotlin/platform/mcp/actions/SrgActionBase.kt b/src/main/kotlin/platform/mcp/actions/SrgActionBase.kt index 294867e20..0a3263ee6 100644 --- a/src/main/kotlin/platform/mcp/actions/SrgActionBase.kt +++ b/src/main/kotlin/platform/mcp/actions/SrgActionBase.kt @@ -29,6 +29,7 @@ import com.intellij.psi.PsiMember import com.intellij.psi.PsiReference import com.intellij.ui.LightColors import com.intellij.ui.awt.RelativePoint +import org.apache.commons.lang.StringEscapeUtils abstract class SrgActionBase : AnAction() { @@ -83,16 +84,19 @@ abstract class SrgActionBase : AnAction() { val pos = editor.offsetToVisualPosition(element.textRange.endOffset - element.textLength / 2) RelativePoint( editor.contentComponent, - editor.visualPositionToXY(VisualPosition(pos.line + 1, pos.column)) + editor.visualPositionToXY(VisualPosition(pos.line + 1, pos.column)), ) - } else RelativePoint.getCenterOf(statusBar.component) + } else { + RelativePoint.getCenterOf(statusBar.component) + } balloon.show(at, Balloon.Position.below) } } fun showSuccessBalloon(editor: Editor, element: PsiElement, text: String) { + val escapedText = StringEscapeUtils.escapeHtml(text) val balloon = JBPopupFactory.getInstance() - .createHtmlTextBalloonBuilder(text, null, LightColors.SLIGHTLY_GREEN, null) + .createHtmlTextBalloonBuilder(escapedText, null, LightColors.SLIGHTLY_GREEN, null) .setHideOnAction(true) .setHideOnClickOutside(true) .setHideOnKeyOutside(true) @@ -102,7 +106,7 @@ abstract class SrgActionBase : AnAction() { val pos = editor.offsetToVisualPosition(element.textRange.endOffset - element.textLength / 2) val at = RelativePoint( editor.contentComponent, - editor.visualPositionToXY(VisualPosition(pos.line + 1, pos.column)) + editor.visualPositionToXY(VisualPosition(pos.line + 1, pos.column)), ) balloon.show(at, Balloon.Position.below) diff --git a/src/main/kotlin/platform/mcp/at/AtAnnotator.kt b/src/main/kotlin/platform/mcp/at/AtAnnotator.kt index b77ffe4ab..c15caef67 100644 --- a/src/main/kotlin/platform/mcp/at/AtAnnotator.kt +++ b/src/main/kotlin/platform/mcp/at/AtAnnotator.kt @@ -73,8 +73,8 @@ class AtAnnotator : Annotator { null, AtSyntaxHighlighter.ELEMENT_NAME.defaultAttributes.foregroundColor, EffectType.BOLD_LINE_UNDERSCORE, - Font.PLAIN - ) + Font.PLAIN, + ), ) .create() } diff --git a/src/main/kotlin/platform/mcp/at/AtColorSettingsPage.kt b/src/main/kotlin/platform/mcp/at/AtColorSettingsPage.kt index 816d7404a..93dfb7c8c 100644 --- a/src/main/kotlin/platform/mcp/at/AtColorSettingsPage.kt +++ b/src/main/kotlin/platform/mcp/at/AtColorSettingsPage.kt @@ -46,7 +46,7 @@ class AtColorSettingsPage : ColorSettingsPage { AttributesDescriptor("Primitive Value", AtSyntaxHighlighter.PRIMITIVE), AttributesDescriptor("Element Name", AtSyntaxHighlighter.ELEMENT_NAME), AttributesDescriptor("Asterisk", AtSyntaxHighlighter.ASTERISK), - AttributesDescriptor("Comment", AtSyntaxHighlighter.COMMENT) + AttributesDescriptor("Comment", AtSyntaxHighlighter.COMMENT), ) } } diff --git a/src/main/kotlin/platform/mcp/at/AtElementFactory.kt b/src/main/kotlin/platform/mcp/at/AtElementFactory.kt index 81b765e6b..163cd65f8 100644 --- a/src/main/kotlin/platform/mcp/at/AtElementFactory.kt +++ b/src/main/kotlin/platform/mcp/at/AtElementFactory.kt @@ -116,7 +116,8 @@ object AtElementFactory { PUBLIC_PLUS_F("public+f"), DEFAULT("default"), DEFAULT_MINUS_F("default-f"), - DEFAULT_PLUS_F("default+f"); + DEFAULT_PLUS_F("default+f"), + ; companion object { fun match(s: String) = values().firstOrNull { it.text == s } diff --git a/src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt b/src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt index fc9be14e8..62edd5de5 100644 --- a/src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt +++ b/src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt @@ -33,7 +33,7 @@ class AtGotoDeclarationHandler : GotoDeclarationHandler { override fun getGotoDeclarationTargets( sourceElement: PsiElement?, offset: Int, - editor: Editor + editor: Editor, ): Array? { if (sourceElement?.language !== AtLanguage) { return null @@ -88,7 +88,7 @@ class AtGotoDeclarationHandler : GotoDeclarationHandler { val psiClass = JavaPsiFacade.getInstance(sourceElement.project).findClass( boxedType, - GlobalSearchScope.allScope(sourceElement.project) + GlobalSearchScope.allScope(sourceElement.project), ) ?: return null arrayOf(psiClass) } diff --git a/src/main/kotlin/platform/mcp/at/AtParserDefinition.kt b/src/main/kotlin/platform/mcp/at/AtParserDefinition.kt index ab844566e..7b13fdb5b 100644 --- a/src/main/kotlin/platform/mcp/at/AtParserDefinition.kt +++ b/src/main/kotlin/platform/mcp/at/AtParserDefinition.kt @@ -53,7 +53,7 @@ class AtParserDefinition : ParserDefinition { (AtTypes.ASTERISK to AtTypes.COMMENT) to ParserDefinition.SpaceRequirements.MUST, (AtTypes.COMMENT to AtTypes.KEYWORD) to ParserDefinition.SpaceRequirements.MUST_LINE_BREAK, (AtTypes.COMMENT to AtTypes.COMMENT) to ParserDefinition.SpaceRequirements.MUST_LINE_BREAK, - (AtTypes.FUNCTION to AtTypes.COMMENT) to ParserDefinition.SpaceRequirements.MUST + (AtTypes.FUNCTION to AtTypes.COMMENT) to ParserDefinition.SpaceRequirements.MUST, ) } } diff --git a/src/main/kotlin/platform/mcp/at/AtUsageInspection.kt b/src/main/kotlin/platform/mcp/at/AtUsageInspection.kt index dec1e50a9..85f774f95 100644 --- a/src/main/kotlin/platform/mcp/at/AtUsageInspection.kt +++ b/src/main/kotlin/platform/mcp/at/AtUsageInspection.kt @@ -26,7 +26,7 @@ import com.intellij.psi.search.searches.ReferencesSearch class AtUsageInspection : LocalInspectionTool() { - override fun getStaticDescription(): String? { + override fun getStaticDescription(): String { return "The declared access transformer is never used" } @@ -48,7 +48,7 @@ class AtUsageInspection : LocalInspectionTool() { val psi = when (member) { is AtFunction -> reference.resolveMember(element.project) ?: srgMap.getMcpMethod(reference)?.resolveMember( - element.project + element.project, ) ?: return is AtFieldName -> reference.resolveMember(element.project) @@ -62,7 +62,7 @@ class AtUsageInspection : LocalInspectionTool() { ?: holder.registerProblem( element, "Access Transformer entry is never used", - ProblemHighlightType.LIKE_UNUSED_SYMBOL + ProblemHighlightType.LIKE_UNUSED_SYMBOL, ) } } diff --git a/src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt b/src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt index d635a70a4..2eb5e3643 100644 --- a/src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt +++ b/src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt @@ -110,8 +110,8 @@ class AtCompletionContributor : CompletionContributor() { kindResult.addElement( PrioritizedLookupElement.withPriority( LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON), - 1.0 + name.getValue(beginning) - ) + 1.0 + name.getValue(beginning), + ), ) } } @@ -131,8 +131,8 @@ class AtCompletionContributor : CompletionContributor() { result.addElement( PrioritizedLookupElement.withPriority( LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON), - 1.0 - ) + 1.0, + ), ) } @@ -143,8 +143,8 @@ class AtCompletionContributor : CompletionContributor() { result.addElement( PrioritizedLookupElement.withPriority( LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON), - 1.0 - ) + 1.0, + ), ) } return @@ -171,8 +171,8 @@ class AtCompletionContributor : CompletionContributor() { result.addElement( PrioritizedLookupElement.withPriority( LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON), - 1.0 - ) + 1.0, + ), ) } used.clear() // help GC @@ -191,8 +191,8 @@ class AtCompletionContributor : CompletionContributor() { result.addElement( PrioritizedLookupElement.withPriority( LookupElementBuilder.create(name).withIcon(PlatformIcons.PACKAGE_ICON), - 0.0 - ) + 0.0, + ), ) } } @@ -232,8 +232,8 @@ class AtCompletionContributor : CompletionContributor() { currentElement.replace( AtElementFactory.createFieldName( context.project, - memberReference.name - ) + memberReference.name, + ), ) // TODO: Fix visibility decrease @@ -243,8 +243,8 @@ class AtCompletionContributor : CompletionContributor() { context.document.insertString(context.editor.caretModel.offset, comment) context.editor.caretModel.moveCaretRelatively(comment.length, 0, false, false, false) }, - 1.0 - ) + 1.0, + ), ) } @@ -287,8 +287,8 @@ class AtCompletionContributor : CompletionContributor() { currentElement.replace( AtElementFactory.createFunction( project, - memberReference.name + memberReference.descriptor - ) + memberReference.name + memberReference.descriptor, + ), ) // TODO: Fix visibility decreases @@ -298,8 +298,8 @@ class AtCompletionContributor : CompletionContributor() { context.document.insertString(context.editor.caretModel.offset, comment) context.editor.caretModel.moveCaretRelatively(comment.length, 0, false, false, false) }, - 0.0 - ) + 0.0, + ), ) } } diff --git a/src/main/kotlin/platform/mcp/aw/AwCompletionContributor.kt b/src/main/kotlin/platform/mcp/aw/AwCompletionContributor.kt index 5239cf3ed..f28066e5e 100644 --- a/src/main/kotlin/platform/mcp/aw/AwCompletionContributor.kt +++ b/src/main/kotlin/platform/mcp/aw/AwCompletionContributor.kt @@ -60,7 +60,7 @@ object AwHeaderCompletionProvider : CompletionProvider() { override fun addCompletions( parameters: CompletionParameters, context: ProcessingContext, - result: CompletionResultSet + result: CompletionResultSet, ) { if (parameters.position.prevLeaf(true) == null) { result.addElement(LookupElementBuilder.create("accessWidener v1 named")) @@ -74,7 +74,7 @@ object AwNamespaceCompletionProvider : CompletionProvider( override fun addCompletions( parameters: CompletionParameters, context: ProcessingContext, - result: CompletionResultSet + result: CompletionResultSet, ) = result.addAllElements(listOf("named", "intermediary").map(LookupElementBuilder::create)) } @@ -83,7 +83,7 @@ object AwAccessCompletionProvider : CompletionProvider() { override fun addCompletions( parameters: CompletionParameters, context: ProcessingContext, - result: CompletionResultSet + result: CompletionResultSet, ) { val elements = listOf( "accessible", @@ -91,7 +91,7 @@ object AwAccessCompletionProvider : CompletionProvider() { "extendable", "transitive-extendable", "mutable", - "transitive-mutable" + "transitive-mutable", ).map { LookupElementBuilder.create(it).withInsertHandler { ctx, _ -> insertWhitespace(ctx) } } result.addAllElements(elements) } @@ -102,7 +102,7 @@ object AwTargetCompletionProvider : CompletionProvider() { override fun addCompletions( parameters: CompletionParameters, context: ProcessingContext, - result: CompletionResultSet + result: CompletionResultSet, ) { val text = parameters.position .prevLeaf { it.elementType == AwTypes.ACCESS_ELEMENT || it.elementType == AwTypes.CRLF }?.text diff --git a/src/main/kotlin/platform/mcp/aw/inspections/DuplicateAwEntryInspection.kt b/src/main/kotlin/platform/mcp/aw/inspections/DuplicateAwEntryInspection.kt index a0317f14f..af401ccfe 100644 --- a/src/main/kotlin/platform/mcp/aw/inspections/DuplicateAwEntryInspection.kt +++ b/src/main/kotlin/platform/mcp/aw/inspections/DuplicateAwEntryInspection.kt @@ -27,27 +27,31 @@ import org.jetbrains.plugins.groovy.codeInspection.fixes.RemoveElementQuickFix class DuplicateAwEntryInspection : LocalInspectionTool() { override fun checkFile(file: PsiFile, manager: InspectionManager, isOnTheFly: Boolean): Array? { - if (file !is AwFile) + if (file !is AwFile) { return null + } val collected = HashMap, MutableList>() file.entries.forEach { val target = it.childOfType()?.resolve() val accessKind = it.accessKind - if (target != null && accessKind != null) + if (target != null && accessKind != null) { (collected.getOrCreate(Pair(target, accessKind)) { ArrayList() }) += it + } } val problems = ArrayList() collected.forEach { (sort, matches) -> - if (sort.first is PsiNamedElement) - if (matches.size > 1) + if (sort.first is PsiNamedElement) { + if (matches.size > 1) { for (match in matches) problems += manager.createProblemDescriptor( match, "Duplicate entry for \"${sort.second} ${(sort.first as PsiNamedElement).name}\"", RemoveElementQuickFix("Remove duplicate"), ProblemHighlightType.WARNING, - isOnTheFly + isOnTheFly, ) + } + } } return problems.toTypedArray() } diff --git a/src/main/kotlin/platform/mcp/aw/psi/mixins/impl/AwDescElementImplMixin.kt b/src/main/kotlin/platform/mcp/aw/psi/mixins/impl/AwDescElementImplMixin.kt index cfd732394..4145e6b25 100644 --- a/src/main/kotlin/platform/mcp/aw/psi/mixins/impl/AwDescElementImplMixin.kt +++ b/src/main/kotlin/platform/mcp/aw/psi/mixins/impl/AwDescElementImplMixin.kt @@ -50,9 +50,11 @@ abstract class AwDescElementImplMixin(node: ASTNode) : ASTWrapperPsiElement(node } private fun asQualifiedName(): String? = - if (text.length > 1) + if (text.length > 1) { text.substring(1, text.length - 1).replace('/', '.') - else null + } else { + null + } override fun isSoft(): Boolean = false } diff --git a/src/main/kotlin/platform/mcp/debug/UngrabMouseDebugSessionListener.kt b/src/main/kotlin/platform/mcp/debug/UngrabMouseDebugSessionListener.kt index 92f22d064..f56b42900 100644 --- a/src/main/kotlin/platform/mcp/debug/UngrabMouseDebugSessionListener.kt +++ b/src/main/kotlin/platform/mcp/debug/UngrabMouseDebugSessionListener.kt @@ -47,7 +47,7 @@ class UngrabMouseDebugSessionListener(private val process: DebugProcessImpl) : X mouseClass: ClassType, virtualMachine: VirtualMachineProxyImpl, debugProcess: DebugProcessImpl, - evaluationContext: EvaluationContextImpl + evaluationContext: EvaluationContextImpl, ) { val isGrabbed = mouseClass.methodsByName("isGrabbed", "()Z")?.singleOrNull() ?: return val setGrabbed = mouseClass.methodsByName("setGrabbed", "(Z)V")?.singleOrNull() ?: return @@ -62,7 +62,7 @@ class UngrabMouseDebugSessionListener(private val process: DebugProcessImpl) : X private fun ungrab3( virtualMachine: VirtualMachineProxyImpl, debugProcess: DebugProcessImpl, - evaluationContext: EvaluationContextImpl + evaluationContext: EvaluationContextImpl, ) { fun findClass(vararg names: String): ClassType? { for (name in names) { @@ -87,17 +87,17 @@ class UngrabMouseDebugSessionListener(private val process: DebugProcessImpl) : X val minecraftClass = findClass( "net.minecraft.client.Minecraft", - "net.minecraft.client.MinecraftClient" + "net.minecraft.client.MinecraftClient", ) ?: return val minecraftGetter = minecraftClass.methodByName( "getInstance" to "()Lnet/minecraft/client/Minecraft;", - "getInstance" to "()Lnet/minecraft/client/MinecraftClient;" + "getInstance" to "()Lnet/minecraft/client/MinecraftClient;", ) ?: return val minecraft = debugProcess.invokeMethod( evaluationContext, minecraftClass, minecraftGetter, - emptyList() + emptyList(), ) as? ObjectReference ?: return val mouseHelperField = minecraftClass.fieldByName("mouseHandler", "mouse", "mouseHelper") ?: return @@ -106,7 +106,7 @@ class UngrabMouseDebugSessionListener(private val process: DebugProcessImpl) : X val ungrabMouse = mouseHelper.referenceType().methodByName( "releaseMouse" to "()V", "unlockCursor" to "()V", - "ungrabMouse" to "()V" + "ungrabMouse" to "()V", ) ?: return debugProcess.invokeMethod(evaluationContext, mouseHelper, ungrabMouse, emptyList()) diff --git a/src/main/kotlin/platform/mcp/fabricloom/FabricLoomData.kt b/src/main/kotlin/platform/mcp/fabricloom/FabricLoomData.kt index 53a17a865..f86d2c4c4 100644 --- a/src/main/kotlin/platform/mcp/fabricloom/FabricLoomData.kt +++ b/src/main/kotlin/platform/mcp/fabricloom/FabricLoomData.kt @@ -20,7 +20,7 @@ data class FabricLoomData( val module: ModuleData, val tinyMappings: File?, val decompileTasks: Map>, - val splitMinecraftJar: Boolean + val splitMinecraftJar: Boolean, ) : AbstractExternalEntityData(module.owner) { data class Decompiler(val name: String, val taskName: String, val sourcesPath: String) diff --git a/src/main/kotlin/platform/mcp/fabricloom/FabricLoomDataService.kt b/src/main/kotlin/platform/mcp/fabricloom/FabricLoomDataService.kt index 473c0f6ab..bf3135fa0 100644 --- a/src/main/kotlin/platform/mcp/fabricloom/FabricLoomDataService.kt +++ b/src/main/kotlin/platform/mcp/fabricloom/FabricLoomDataService.kt @@ -26,7 +26,7 @@ class FabricLoomDataService : AbstractProjectDataService toImport: Collection>, projectData: ProjectData?, project: Project, - modelsProvider: IdeModifiableModelsProvider + modelsProvider: IdeModifiableModelsProvider, ) { // Dummy service to enable platform-side DataNodes cache } diff --git a/src/main/kotlin/platform/mcp/fabricloom/FabricLoomDecompileSourceProvider.kt b/src/main/kotlin/platform/mcp/fabricloom/FabricLoomDecompileSourceProvider.kt index d25d29ba3..8a50c77e9 100644 --- a/src/main/kotlin/platform/mcp/fabricloom/FabricLoomDecompileSourceProvider.kt +++ b/src/main/kotlin/platform/mcp/fabricloom/FabricLoomDecompileSourceProvider.kt @@ -28,7 +28,7 @@ import org.jetbrains.plugins.gradle.util.GradleUtil class FabricLoomDecompileSourceProvider : AttachSourcesProvider { override fun getActions( orderEntries: List, - psiFile: PsiFile + psiFile: PsiFile, ): Collection { if (psiFile !is PsiJavaFile || !psiFile.packageName.startsWith("net.minecraft")) { return emptyList() @@ -82,7 +82,7 @@ class FabricLoomDecompileSourceProvider : AttachSourcesProvider { project, Paths.get(projectPath), { settings -> settings.taskNames = listOf(decompiler.taskName) }, - taskCallback + taskCallback, ) return callback } diff --git a/src/main/kotlin/platform/mcp/fabricloom/TinyUnscrambler.kt b/src/main/kotlin/platform/mcp/fabricloom/TinyUnscrambler.kt index 3e1aaaaf9..be92558ca 100644 --- a/src/main/kotlin/platform/mcp/fabricloom/TinyUnscrambler.kt +++ b/src/main/kotlin/platform/mcp/fabricloom/TinyUnscrambler.kt @@ -61,7 +61,7 @@ class TinyUnscrambler : UnscrambleSupport { Dimension(-1, -1), Dimension(-1, -1), Dimension(-1, -1), - ) + ), ) add( mappingsBox, @@ -77,7 +77,7 @@ class TinyUnscrambler : UnscrambleSupport { Dimension(-1, -1), Dimension(-1, -1), Dimension(-1, -1), - ) + ), ) } } diff --git a/src/main/kotlin/platform/mcp/gradle/McpDataService.kt b/src/main/kotlin/platform/mcp/gradle/McpDataService.kt index d3264406f..9c8e07436 100644 --- a/src/main/kotlin/platform/mcp/gradle/McpDataService.kt +++ b/src/main/kotlin/platform/mcp/gradle/McpDataService.kt @@ -28,7 +28,7 @@ class McpDataService : AbstractProjectDataService() { toImport: Collection>, projectData: ProjectData?, project: Project, - modelsProvider: IdeModifiableModelsProvider + modelsProvider: IdeModifiableModelsProvider, ) { if (projectData == null || toImport.isEmpty()) { return diff --git a/src/main/kotlin/platform/mcp/gradle/McpModelData.kt b/src/main/kotlin/platform/mcp/gradle/McpModelData.kt index 72266ccac..90bf50790 100644 --- a/src/main/kotlin/platform/mcp/gradle/McpModelData.kt +++ b/src/main/kotlin/platform/mcp/gradle/McpModelData.kt @@ -21,7 +21,7 @@ data class McpModelData( val module: ModuleData, val settings: McpModuleSettings.State, val taskName: String?, - val accessTransformers: List? + val accessTransformers: List?, ) : AbstractExternalEntityData(module.owner) { companion object { // Process McpModelData after builtin services (e.g. dependency or module data) diff --git a/src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG2Handler.kt b/src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG2Handler.kt index 5cba7273a..1f06e5aea 100644 --- a/src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG2Handler.kt +++ b/src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG2Handler.kt @@ -25,7 +25,7 @@ object McpModelFG2Handler : McpModelDataHandler { override fun build( gradleModule: IdeaModule, node: DataNode, - resolverCtx: ProjectResolverContext + resolverCtx: ProjectResolverContext, ) { val data = resolverCtx.getExtraProject(gradleModule, McpModelFG2::class.java) ?: return @@ -33,14 +33,14 @@ object McpModelFG2Handler : McpModelDataHandler { data.minecraftVersion, data.mcpVersion, data.mappingFiles.find { it.endsWith("mcp-srg.srg") }, - SrgType.SRG + SrgType.SRG, ) val modelData = McpModelData( node.data, state, null, - null + null, ) node.createChild( @@ -51,11 +51,11 @@ object McpModelFG2Handler : McpModelDataHandler { data.minecraftVersion, data.mcpVersion, data.mappingFiles.find { it.endsWith("mcp-srg.srg") }, - SrgType.SRG + SrgType.SRG, ), null, - null - ) + null, + ), ) for (child in node.children) { diff --git a/src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG3Handler.kt b/src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG3Handler.kt index b1388f6a9..ec4a23b76 100644 --- a/src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG3Handler.kt +++ b/src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG3Handler.kt @@ -30,7 +30,7 @@ object McpModelFG3Handler : McpModelDataHandler { override fun build( gradleModule: IdeaModule, node: DataNode, - resolverCtx: ProjectResolverContext + resolverCtx: ProjectResolverContext, ) { val data = resolverCtx.getExtraProject(gradleModule, McpModelFG3::class.java) ?: return @@ -55,7 +55,7 @@ object McpModelFG3Handler : McpModelDataHandler { data.mcpVersion, data.taskOutputLocation.absolutePath, SrgType.TSRG, - forgeVersion + forgeVersion, ) val gradleProjectPath = gradleModule.gradleProject.projectIdentifier.projectPath diff --git a/src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt b/src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt index d997055d5..99459a2b8 100644 --- a/src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt +++ b/src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt @@ -52,7 +52,7 @@ class StackEmptyInspection : BaseInspection() { "When a stack in an inventory is shrunk, the instance is not replaced with ItemStack.EMPTY, but" + " the stack should still be considered empty. Instead, isEmpty() should be called." - override fun buildFix(vararg infos: Any): InspectionGadgetsFix? { + override fun buildFix(vararg infos: Any): InspectionGadgetsFix { return object : InspectionGadgetsFix() { override fun getFamilyName() = "Replace with .isEmpty()" diff --git a/src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt b/src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt index 64e0aae91..00513e3d3 100644 --- a/src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt +++ b/src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt @@ -54,7 +54,7 @@ class SrgMemberChooseByNameContributor : ChooseByNameContributor { name: String, pattern: String, project: Project, - includeNonProjectItems: Boolean + includeNonProjectItems: Boolean, ): Array { if (!includeNonProjectItems || srgMap == null || module == null) { return emptyArray() diff --git a/src/main/kotlin/platform/mcp/srg/McpSrgMap.kt b/src/main/kotlin/platform/mcp/srg/McpSrgMap.kt index 3e2560fa8..e7551fa2b 100644 --- a/src/main/kotlin/platform/mcp/srg/McpSrgMap.kt +++ b/src/main/kotlin/platform/mcp/srg/McpSrgMap.kt @@ -23,7 +23,7 @@ class McpSrgMap( val classMap: ImmutableBiMap, val fieldMap: ImmutableBiMap, val methodMap: ImmutableBiMap, - private val srgNames: HashMap + private val srgNames: HashMap, ) { fun getSrgClass(fullQualifiedName: String) = classMap[fullQualifiedName] fun getSrgClass(psiClass: PsiClass): String? { diff --git a/src/main/kotlin/platform/mcp/srg/SrgType.kt b/src/main/kotlin/platform/mcp/srg/SrgType.kt index 5734ad861..76cb03b6b 100644 --- a/src/main/kotlin/platform/mcp/srg/SrgType.kt +++ b/src/main/kotlin/platform/mcp/srg/SrgType.kt @@ -12,5 +12,6 @@ package com.demonwav.mcdev.platform.mcp.srg enum class SrgType(val srgParser: SrgParser) { SRG(StandardSrgParser), - TSRG(TinySrgParser); + TSRG(TinySrgParser), + ; } diff --git a/src/main/kotlin/platform/mcp/srg/TinySrgParser.kt b/src/main/kotlin/platform/mcp/srg/TinySrgParser.kt index 0d1be155c..db1859e53 100644 --- a/src/main/kotlin/platform/mcp/srg/TinySrgParser.kt +++ b/src/main/kotlin/platform/mcp/srg/TinySrgParser.kt @@ -38,7 +38,7 @@ object TinySrgParser : SrgParser { classMapBuilder.build(), fieldMapBuilder.build(), methodMapBuilder.build(), - srgNames + srgNames, ) } @@ -47,7 +47,7 @@ object TinySrgParser : SrgParser { classMapBuilder: ImmutableBiMap.Builder, fieldMapBuilder: ImmutableBiMap.Builder, methodMapBuilder: ImmutableBiMap.Builder, - srgNames: HashMap + srgNames: HashMap, ) { var classRef: Pair? = null @@ -93,7 +93,7 @@ object TinySrgParser : SrgParser { classMapBuilder: ImmutableBiMap.Builder, fieldMapBuilder: ImmutableBiMap.Builder, methodMapBuilder: ImmutableBiMap.Builder, - srgNames: HashMap + srgNames: HashMap, ) { val visitor = object : MappingVisitor { var namedNsIndex = -1 @@ -144,15 +144,16 @@ object TinySrgParser : SrgParser { else -> return } - if (targetKind == MappedElementKind.CLASS && named != null) { - classMapBuilder.put(cls, named!!.replace('/', '.')) - } else if (inter != null && named != null) { + if (targetKind == MappedElementKind.CLASS) { + classMapBuilder.put(cls, name.replace('/', '.')) + } else if (inter != null) { + val inter = inter!! if (targetKind == MappedElementKind.FIELD) { - fieldMapBuilder.put(MemberReference(inter!!, null, cls), MemberReference(named!!, null, cls)) - srgNames[inter!!] = named!! + fieldMapBuilder.put(MemberReference(inter, null, cls), MemberReference(name, null, cls)) + srgNames[inter] = name } else if (targetKind == MappedElementKind.METHOD) { - methodMapBuilder.put(MemberReference(inter!!, desc, cls), MemberReference(named!!, desc, cls)) - srgNames[inter!!] = named!! + methodMapBuilder.put(MemberReference(inter, desc, cls), MemberReference(name, desc, cls)) + srgNames[inter] = name } } } diff --git a/src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleData.kt b/src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleData.kt index 805ede442..4a05cd923 100644 --- a/src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleData.kt +++ b/src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleData.kt @@ -17,7 +17,7 @@ import com.intellij.openapi.externalSystem.model.project.ModuleData data class VanillaGradleData( val module: ModuleData, - val decompileTaskName: String + val decompileTaskName: String, ) : AbstractExternalEntityData(module.owner) { companion object { val KEY = Key.create(VanillaGradleData::class.java, ProjectKeys.TASK.processingWeight + 1) diff --git a/src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDataService.kt b/src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDataService.kt index 8f1c1eb7f..fd5169ee1 100644 --- a/src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDataService.kt +++ b/src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDataService.kt @@ -26,7 +26,7 @@ class VanillaGradleDataService : AbstractProjectDataService>, projectData: ProjectData?, project: Project, - modelsProvider: IdeModifiableModelsProvider + modelsProvider: IdeModifiableModelsProvider, ) { // Dummy service to enable platform-side DataNodes cache } diff --git a/src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDecompileSourceProvider.kt b/src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDecompileSourceProvider.kt index 97e27eb1a..4af0eb5ab 100644 --- a/src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDecompileSourceProvider.kt +++ b/src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDecompileSourceProvider.kt @@ -30,7 +30,7 @@ import org.jetbrains.plugins.gradle.util.GradleUtil class VanillaGradleDecompileSourceProvider : AttachSourcesProvider { override fun getActions( orderEntries: List, - psiFile: PsiFile + psiFile: PsiFile, ): Collection { if (psiFile !is PsiJavaFile || !psiFile.packageName.startsWith("net.minecraft")) { return emptyList() @@ -64,10 +64,10 @@ class VanillaGradleDecompileSourceProvider : AttachSourcesProvider { override fun onFailure(errorMessage: String, errorDetails: String?) { callback.reject( - if (errorDetails == null) errorMessage else "$errorMessage: $errorDetails" + if (errorDetails == null) errorMessage else "$errorMessage: $errorDetails", ) } - } + }, ) ExternalSystemUtil.refreshProject(projectPath, importSpec) } @@ -78,7 +78,7 @@ class VanillaGradleDecompileSourceProvider : AttachSourcesProvider { project, Paths.get(projectPath), { settings -> settings.taskNames = listOf(decompileTaskName) }, - taskCallback + taskCallback, ) return callback } diff --git a/src/main/kotlin/platform/mixin/MixinCustomJavaDocTagProvider.kt b/src/main/kotlin/platform/mixin/MixinCustomJavaDocTagProvider.kt index faeb9cb4a..4c30157db 100644 --- a/src/main/kotlin/platform/mixin/MixinCustomJavaDocTagProvider.kt +++ b/src/main/kotlin/platform/mixin/MixinCustomJavaDocTagProvider.kt @@ -10,9 +10,8 @@ package com.demonwav.mcdev.platform.mixin -import com.demonwav.mcdev.platform.mixin.handlers.MixinAnnotationHandler +import com.demonwav.mcdev.platform.mixin.util.isMixinEntryPoint import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod import com.intellij.psi.PsiReference import com.intellij.psi.javadoc.CustomJavadocTagProvider import com.intellij.psi.javadoc.JavadocTagInfo @@ -26,20 +25,7 @@ class MixinCustomJavaDocTagProvider : CustomJavadocTagProvider { override fun isInline() = false - override fun isValidInContext(element: PsiElement?): Boolean { - if (element !is PsiMethod) { - return false - } - val project = element.project - for (annotation in element.annotations) { - val qName = annotation.qualifiedName ?: continue - val handler = MixinAnnotationHandler.forMixinAnnotation(qName, project) - if (handler != null && handler.isEntryPoint) { - return true - } - } - return false - } + override fun isValidInContext(element: PsiElement?) = isMixinEntryPoint(element) override fun checkTagValue(value: PsiDocTagValue?): String? = null override fun getReference(value: PsiDocTagValue?): PsiReference? = null diff --git a/src/main/kotlin/platform/mixin/MixinModule.kt b/src/main/kotlin/platform/mixin/MixinModule.kt index f46c84aad..bfe1d025e 100644 --- a/src/main/kotlin/platform/mixin/MixinModule.kt +++ b/src/main/kotlin/platform/mixin/MixinModule.kt @@ -50,7 +50,7 @@ class MixinModule(facet: MinecraftFacet) : AbstractModule(facet) { fun getMixinConfigs( project: Project, - scope: GlobalSearchScope + scope: GlobalSearchScope, ): Collection { return FileTypeIndex.getFiles(mixinFileType, scope) .mapNotNull { @@ -61,7 +61,7 @@ class MixinModule(facet: MinecraftFacet) : AbstractModule(facet) { fun getAllMixinClasses( project: Project, - scope: GlobalSearchScope + scope: GlobalSearchScope, ): Collection { return getMixinConfigs(project, scope).asSequence() .flatMap { (it.qualifiedMixins + it.qualifiedClient + it.qualifiedServer).asSequence() } @@ -75,7 +75,7 @@ class MixinModule(facet: MinecraftFacet) : AbstractModule(facet) { fun getBestWritableConfigForMixinClass( project: Project, scope: GlobalSearchScope, - mixinClassName: String + mixinClassName: String, ): MixinConfig? { return getMixinConfigs(project, scope) .filter { it.isWritable && mixinClassName.startsWith("${it.pkg}.") } diff --git a/src/main/kotlin/platform/mixin/action/FindMixinsAction.kt b/src/main/kotlin/platform/mixin/action/FindMixinsAction.kt index e12c9cf34..d1d095adf 100644 --- a/src/main/kotlin/platform/mixin/action/FindMixinsAction.kt +++ b/src/main/kotlin/platform/mixin/action/FindMixinsAction.kt @@ -54,7 +54,7 @@ class FindMixinsAction : AnAction() { fun findMixins( clazz: PsiClass, project: Project, - indicator: ProgressIndicator? = null + indicator: ProgressIndicator? = null, ): List? { return clazz.cached(PsiModificationTracker.MODIFICATION_COUNT) { val targetInternalName = clazz.fullQualifiedName?.replace('.', '/') @@ -62,13 +62,13 @@ class FindMixinsAction : AnAction() { val mixinAnnotation = JavaPsiFacade.getInstance(project).findClass( MixinConstants.Annotations.MIXIN, - GlobalSearchScope.allScope(project) + GlobalSearchScope.allScope(project), ) ?: return@cached null // Check all classes with the Mixin annotation val classes = AnnotatedElementsSearch.searchPsiClasses( mixinAnnotation, - GlobalSearchScope.projectScope(project) + GlobalSearchScope.projectScope(project), ) .filter { indicator?.text = "Checking ${it.name}..." diff --git a/src/main/kotlin/platform/mixin/action/GenerateAccessorAction.kt b/src/main/kotlin/platform/mixin/action/GenerateAccessorAction.kt index c7c91352d..f610077ee 100644 --- a/src/main/kotlin/platform/mixin/action/GenerateAccessorAction.kt +++ b/src/main/kotlin/platform/mixin/action/GenerateAccessorAction.kt @@ -60,7 +60,7 @@ class GenerateAccessorAction : BaseGenerateAction(GenerateAccessorHandler()) { }, commandName, DocCommandGroupId.noneGroupId(editor.document), - editor.document + editor.document, ) } diff --git a/src/main/kotlin/platform/mixin/action/GenerateAccessorHandler.kt b/src/main/kotlin/platform/mixin/action/GenerateAccessorHandler.kt index 8920caf11..885cc8367 100644 --- a/src/main/kotlin/platform/mixin/action/GenerateAccessorHandler.kt +++ b/src/main/kotlin/platform/mixin/action/GenerateAccessorHandler.kt @@ -79,7 +79,7 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In fun customInvoke( project: Project, editor: Editor, - file: PsiFile + file: PsiFile, ) { val aClass = OverrideImplementUtil.getContextClass(project, editor, file, false) if (aClass == null || aClass.isInterface) { @@ -111,15 +111,15 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In Project::class.java, Editor::class.java, PsiClass::class.java, - Array::class.java + Array::class.java, ), args = arrayOf( project, mixinEditor, mixinClass, - members + members, ), - owner = GenerateMembersHandlerBase::class.java + owner = GenerateMembersHandlerBase::class.java, ) } catch (e: GenerateCodeException) { val message = e.message ?: "Unknown error" @@ -130,12 +130,12 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In HintManager.getInstance().showErrorHint(editor, message) } }, - project.disposed + project.disposed, ) } }, null, - null + null, ) } finally { cleanup() @@ -162,12 +162,12 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In members.addAll( aClass.fields .filter { canHaveAccessor(it) } - .map { PsiFieldMember(it) } + .map { PsiFieldMember(it) }, ) members.addAll( aClass.methods .filter { canHaveInvoker(it) } - .map { PsiMethodMember(it) } + .map { PsiMethodMember(it) }, ) return members.toTypedArray() } @@ -189,7 +189,7 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In } val range = candidate.element.textRange return@filter range != null && range.contains(offset) - }.toTypedArray() + }.toTypedArray(), ) if (!chooser.showAndGet()) { @@ -261,7 +261,7 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In defaultPkg, CreateClassKind.CLASS, true, - defaultModule + defaultModule, ) if (!dialog.showAndGet()) { return null @@ -281,12 +281,12 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In val message = MCDevBundle.message( "intention.error.cannot.create.class.message", name, - e.localizedMessage + e.localizedMessage, ) Messages.showErrorDialog( project, message, - MCDevBundle.message("intention.error.cannot.create.class.title") + MCDevBundle.message("intention.error.cannot.create.class.title"), ) } return@compute null @@ -307,7 +307,7 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In val configToWrite = MixinModule.getBestWritableConfigForMixinClass( project, GlobalSearchScope.moduleScope(module), - clazz.fullQualifiedName ?: "" + clazz.fullQualifiedName ?: "", ) configToWrite?.qualifiedMixins?.add(clazz.fullQualifiedName) @@ -367,7 +367,7 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In originalMember.element, aClass, generateGetters, - generateSetters + generateSetters, ) OverrideImplementUtil.convert2GenerationInfos(accessors).toTypedArray() } @@ -375,7 +375,7 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In val invoker = generateInvoker( aClass.project, originalMember.element, - aClass + aClass, ) ?: return GenerationInfo.EMPTY_ARRAY arrayOf(OverrideImplementUtil.createGenerationInfo(invoker)) } @@ -388,7 +388,7 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In target: PsiField, mixin: PsiClass, generateGetter: Boolean, - generateSetter: Boolean + generateSetter: Boolean, ): List { val factory = JavaPsiFacade.getElementFactory(project) @@ -403,7 +403,7 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In @${MixinConstants.Annotations.ACCESSOR} ${staticPrefix(isStatic)}ReturnType $prefix${target.name.capitalize()}()${methodBody(isStatic)} """.trimIndent(), - mixin + mixin, ) target.typeElement?.let { method.returnTypeElement?.replace(it) } accessors.add(method) @@ -413,7 +413,7 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In "@${MixinConstants.Annotations.ACCESSOR}\n" + staticPrefix(isStatic) + "void set${target.name.capitalize()}" + "(ParamType ${target.name})" + methodBody(isStatic), - mixin + mixin, ) target.typeElement?.let { method.parameterList.parameters[0].typeElement?.replace(it) } if (target.modifierList?.hasExplicitModifier(PsiModifier.FINAL) == true) { @@ -445,7 +445,7 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In @${MixinConstants.Annotations.INVOKER}$invokerParams ${staticPrefix(isStatic)}ReturnType $name()${methodBody(isStatic)} """.trimIndent(), - mixin + mixin, ) if (target.isConstructor) { val targetClass = target.containingClass ?: return null diff --git a/src/main/kotlin/platform/mixin/action/GenerateOverwriteAction.kt b/src/main/kotlin/platform/mixin/action/GenerateOverwriteAction.kt index 406390fad..8c69dd115 100644 --- a/src/main/kotlin/platform/mixin/action/GenerateOverwriteAction.kt +++ b/src/main/kotlin/platform/mixin/action/GenerateOverwriteAction.kt @@ -15,12 +15,11 @@ import com.demonwav.mcdev.platform.mixin.util.findMethods import com.demonwav.mcdev.platform.mixin.util.findOrConstructSourceMethod import com.demonwav.mcdev.util.MinecraftTemplates.Companion.MIXIN_OVERWRITE_FALLBACK import com.demonwav.mcdev.util.findContainingClass +import com.demonwav.mcdev.util.generationInfoFromMethod import com.demonwav.mcdev.util.ifEmpty -import com.demonwav.mcdev.util.realName import com.demonwav.mcdev.util.toTypedArray import com.intellij.codeInsight.generation.GenerateMembersUtil import com.intellij.codeInsight.generation.OverrideImplementUtil -import com.intellij.codeInsight.generation.PsiGenerationInfo import com.intellij.codeInsight.generation.PsiMethodMember import com.intellij.codeInsight.hint.HintManager import com.intellij.ide.fileTemplates.FileTemplateManager @@ -28,7 +27,6 @@ import com.intellij.ide.util.MemberChooser import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project -import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiFile import com.intellij.psi.PsiMember @@ -46,8 +44,8 @@ class GenerateOverwriteAction : MixinCodeInsightAction() { classAndMethodNode.method.findOrConstructSourceMethod( classAndMethodNode.clazz, project, - canDecompile = true - ) + canDecompile = true, + ), ) }?.toTypedArray() ?: return @@ -98,7 +96,7 @@ class GenerateOverwriteAction : MixinCodeInsightAction() { newMethod, method, psiClass, - FileTemplateManager.getInstance(project).getCodeTemplate(MIXIN_OVERWRITE_FALLBACK) + FileTemplateManager.getInstance(project).getCodeTemplate(MIXIN_OVERWRITE_FALLBACK), ) } @@ -106,16 +104,7 @@ class GenerateOverwriteAction : MixinCodeInsightAction() { // Add @Overwrite annotation val annotation = newMethod.modifierList.addAnnotation(MixinConstants.Annotations.OVERWRITE) - val realName = method.realName - if (realName != null && realName != method.name) { - val elementFactory = JavaPsiFacade.getElementFactory(project) - val value = elementFactory.createExpressionFromText( - "\"${StringUtil.escapeStringCharacters(realName)}\"", - annotation - ) - annotation.setDeclaredAttributeValue("aliases", value) - } - PsiGenerationInfo(newMethod) + generationInfoFromMethod(method, annotation, newMethod) } // Insert new methods diff --git a/src/main/kotlin/platform/mixin/action/GenerateShadowAction.kt b/src/main/kotlin/platform/mixin/action/GenerateShadowAction.kt index f79bb0fbe..a3f2c39ab 100644 --- a/src/main/kotlin/platform/mixin/action/GenerateShadowAction.kt +++ b/src/main/kotlin/platform/mixin/action/GenerateShadowAction.kt @@ -19,8 +19,8 @@ import com.demonwav.mcdev.util.findContainingClass import com.demonwav.mcdev.util.findFirstMember import com.demonwav.mcdev.util.findLastChild import com.demonwav.mcdev.util.findNextMember +import com.demonwav.mcdev.util.generationInfoFromMethod import com.demonwav.mcdev.util.ifEmpty -import com.demonwav.mcdev.util.realName import com.demonwav.mcdev.util.toTypedArray import com.intellij.application.options.CodeStyle import com.intellij.codeInsight.generation.GenerateMembersUtil @@ -37,7 +37,6 @@ import com.intellij.lang.java.JavaLanguage import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project -import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.CommonClassNames import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiClass @@ -61,14 +60,14 @@ class GenerateShadowAction : MixinCodeInsightAction() { fieldNode.findOrConstructSourceField( classNode, project, - canDecompile = false + canDecompile = false, ).let(::PsiFieldMember) } ?: emptySequence() val methods = findMethods(psiClass, allowClinit = false)?.map { (classNode, fieldNode) -> fieldNode.findOrConstructSourceMethod( classNode, project, - canDecompile = false + canDecompile = false, ).let(::PsiMethodMember) } ?: emptySequence() @@ -92,8 +91,8 @@ class GenerateShadowAction : MixinCodeInsightAction() { createShadowMembers( project, psiClass, - elements.asSequence().map(PsiElementClassMember<*>::getElement) - ) + elements.asSequence().map(PsiElementClassMember<*>::getElement), + ), // Select first element in editor ).firstOrNull()?.positionCaret(editor, false) } @@ -120,7 +119,7 @@ fun insertShadows(psiClass: PsiClass, shadows: List) { fun createShadowMembers( project: Project, psiClass: PsiClass, - members: Sequence + members: Sequence, ): List> { var methodAdded = false @@ -136,17 +135,7 @@ fun createShadowMembers( // Add @Shadow annotation val annotation = shadowMember.modifierList!!.addAnnotation(MixinConstants.Annotations.SHADOW) - val realName = m.realName - if (realName != null && realName != m.name) { - val elementFactory = JavaPsiFacade.getElementFactory(project) - val value = elementFactory.createExpressionFromText( - "\"${StringUtil.escapeStringCharacters(realName)}\"", - annotation - ) - annotation.setDeclaredAttributeValue("aliases", value) - } - - PsiGenerationInfo(shadowMember) + generationInfoFromMethod(m, annotation, shadowMember) }.toList() // Make the class abstract (if not already) diff --git a/src/main/kotlin/platform/mixin/action/GenerateSoftImplementsAction.kt b/src/main/kotlin/platform/mixin/action/GenerateSoftImplementsAction.kt index d1a7d7dc0..af445a47a 100644 --- a/src/main/kotlin/platform/mixin/action/GenerateSoftImplementsAction.kt +++ b/src/main/kotlin/platform/mixin/action/GenerateSoftImplementsAction.kt @@ -64,7 +64,7 @@ class GenerateSoftImplementsAction : MixinCodeInsightAction() { return } - val chooser = MemberChooser(methods.keys.toTypedArray(), false, true, project) + val chooser = MemberChooser(methods.keys.toTypedArray(), false, true, project) chooser.title = "Select Methods to Soft-implement" chooser.show() @@ -83,14 +83,14 @@ class GenerateSoftImplementsAction : MixinCodeInsightAction() { method, it.substitutor, chooser.isCopyJavadoc, - false + false, ) .map { m -> // Apply prefix m.name = prefix + m.name OverrideImplementUtil.createGenerationInfo(m) } - } + }, ).firstOrNull()?.positionCaret(editor, true) } } diff --git a/src/main/kotlin/platform/mixin/completion/MixinCompletionConfidence.kt b/src/main/kotlin/platform/mixin/completion/MixinCompletionConfidence.kt index 29cf0d2f8..6d3e53eb7 100644 --- a/src/main/kotlin/platform/mixin/completion/MixinCompletionConfidence.kt +++ b/src/main/kotlin/platform/mixin/completion/MixinCompletionConfidence.kt @@ -26,7 +26,7 @@ class MixinCompletionConfidence : CompletionConfidence() { .inside( false, PsiJavaPatterns.psiAnnotation().qName(StandardPatterns.string().startsWith(MixinConstants.PACKAGE)), - PlatformPatterns.psiFile() + PlatformPatterns.psiFile(), )!! override fun shouldSkipAutopopup(element: PsiElement, psiFile: PsiFile, offset: Int): ThreeState { diff --git a/src/main/kotlin/platform/mixin/completion/MixinCompletionWeigher.kt b/src/main/kotlin/platform/mixin/completion/MixinCompletionWeigher.kt index 95861f7e4..1aee75af5 100644 --- a/src/main/kotlin/platform/mixin/completion/MixinCompletionWeigher.kt +++ b/src/main/kotlin/platform/mixin/completion/MixinCompletionWeigher.kt @@ -25,7 +25,7 @@ class MixinCompletionWeigher : CompletionWeigher() { .inside( false, PsiJavaPatterns.psiAnnotation().qName(MixinConstants.Annotations.MIXIN), - PlatformPatterns.psiFile() + PlatformPatterns.psiFile(), )!! override fun weigh(element: LookupElement, location: CompletionLocation): Int { diff --git a/src/main/kotlin/platform/mixin/completion/MixinLookupItem.kt b/src/main/kotlin/platform/mixin/completion/MixinLookupItem.kt index 79d46faf0..11b5600c9 100644 --- a/src/main/kotlin/platform/mixin/completion/MixinLookupItem.kt +++ b/src/main/kotlin/platform/mixin/completion/MixinLookupItem.kt @@ -51,7 +51,7 @@ private class MixinMethodLookupItem(private val shadow: MethodTargetMember, priv val psiMethod = shadow.classAndMethod.method.findOrConstructSourceMethod( shadow.classAndMethod.clazz, project, - canDecompile = false + canDecompile = false, ) return MixinMethodLookupItem(shadow, psiMethod) } @@ -60,7 +60,7 @@ private class MixinMethodLookupItem(private val shadow: MethodTargetMember, priv private class MixinFieldLookupItem( private val shadow: FieldTargetMember, - private val field: PsiField + private val field: PsiField, ) : VariableLookupItem(field) { override fun handleInsert(context: InsertionContext) { @@ -78,7 +78,7 @@ private class MixinFieldLookupItem( val psiField = shadow.classAndField.field.findOrConstructSourceField( shadow.classAndField.clazz, project, - canDecompile = false + canDecompile = false, ) return MixinFieldLookupItem(shadow, psiField) } @@ -100,7 +100,7 @@ private fun insertShadow(context: InsertionContext, shadow: MixinTargetMember, e context.setLaterRunnable { HintManager.getInstance().showInformationHint( context.editor, - "Added @Shadow for '${element.name}' to super Mixin ${mixinClass.shortName}" + "Added @Shadow for '${element.name}' to super Mixin ${mixinClass.shortName}", ) } } diff --git a/src/main/kotlin/platform/mixin/config/MixinConfig.kt b/src/main/kotlin/platform/mixin/config/MixinConfig.kt index 6ff219119..247ed9587 100644 --- a/src/main/kotlin/platform/mixin/config/MixinConfig.kt +++ b/src/main/kotlin/platform/mixin/config/MixinConfig.kt @@ -112,31 +112,28 @@ class MixinConfig(private val project: Project, private var json: JsonObject) { get() = FullyQualifiedMixinList(MixinList("server")) private fun deleteCommaAround(element: PsiElement) { - // Delete the comma before, if it exists - var elem = element.prevSibling - while (elem != null) { - if (elem.node.elementType === JsonElementTypes.COMMA || (elem is PsiErrorElement && elem.text == ",")) { - elem.delete() - return - } else if (elem is PsiComment || elem is PsiWhiteSpace) { - elem = elem.prevSibling - } else { - break + fun deleteComma(element: PsiElement?): Boolean { + var elem = element + while (elem != null) { + if (elem.node.elementType === JsonElementTypes.COMMA || (elem is PsiErrorElement && elem.text == ",")) { + elem.delete() + return true + } else if (elem is PsiComment || elem is PsiWhiteSpace) { + elem = elem.prevSibling + } else { + return false + } } + return false } - // If it didn't exist, delete the comma after if it exists - elem = element.nextSibling - while (elem != null) { - if (elem.node.elementType === JsonElementTypes.COMMA || (elem is PsiErrorElement && elem.text == ",")) { - elem.delete() - return - } else if (elem is PsiComment || elem is PsiWhiteSpace) { - elem = elem.nextSibling - } else { - break - } + // Delete the comma before, if it exists + if (deleteComma(element.prevSibling)) { + return } + + // If it didn't exist, delete the comma after if it exists + deleteComma(element.nextSibling) } private fun reformat() { diff --git a/src/main/kotlin/platform/mixin/config/MixinConfigImportOptimizer.kt b/src/main/kotlin/platform/mixin/config/MixinConfigImportOptimizer.kt index 084d27e7c..c17552827 100644 --- a/src/main/kotlin/platform/mixin/config/MixinConfigImportOptimizer.kt +++ b/src/main/kotlin/platform/mixin/config/MixinConfigImportOptimizer.kt @@ -23,6 +23,7 @@ import com.intellij.openapi.util.EmptyRunnable import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile +import kotlin.math.min class MixinConfigImportOptimizer : ImportOptimizer { @@ -52,7 +53,7 @@ class MixinConfigImportOptimizer : ImportOptimizer { val parts1 = class1.split('.') val parts2 = class2.split('.') - val end = Math.min(parts1.size - 1, parts2.size - 1) + val end = min(parts1.size - 1, parts2.size - 1) for (i in 0 until end) { val result = parts1[i].compareTo(parts2[i], ignoreCase = true) if (result != 0) { @@ -62,7 +63,7 @@ class MixinConfigImportOptimizer : ImportOptimizer { if (parts1.size != parts2.size) { // Default package always comes first - return Integer.compare(parts1.size, parts2.size) + return parts1.size.compareTo(parts2.size) } // Compare class names @@ -106,7 +107,7 @@ class MixinConfigImportOptimizer : ImportOptimizer { private val file: JsonFile, private val mixins: JsonArray?, private val server: JsonArray?, - private val client: JsonArray? + private val client: JsonArray?, ) : Runnable { override fun run() { diff --git a/src/main/kotlin/platform/mixin/config/inspection/ConfigValueInspection.kt b/src/main/kotlin/platform/mixin/config/inspection/ConfigValueInspection.kt index ff2a9b38e..0f49c25d3 100644 --- a/src/main/kotlin/platform/mixin/config/inspection/ConfigValueInspection.kt +++ b/src/main/kotlin/platform/mixin/config/inspection/ConfigValueInspection.kt @@ -112,7 +112,7 @@ class ConfigValueInspection : MixinConfigInspection() { JAVA_LANG_FLOAT, JAVA_LANG_INTEGER, JAVA_LANG_LONG, - JAVA_LANG_SHORT + JAVA_LANG_SHORT, ) } } diff --git a/src/main/kotlin/platform/mixin/config/inspection/UnresolvedReferenceInspection.kt b/src/main/kotlin/platform/mixin/config/inspection/UnresolvedReferenceInspection.kt index 279057c7f..0199c9cd4 100644 --- a/src/main/kotlin/platform/mixin/config/inspection/UnresolvedReferenceInspection.kt +++ b/src/main/kotlin/platform/mixin/config/inspection/UnresolvedReferenceInspection.kt @@ -36,7 +36,7 @@ class UnresolvedReferenceInspection : MixinConfigInspection() { literal, "Cannot resolve ${reference.description}".format(reference.canonicalText), ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, - reference.rangeInElement + reference.rangeInElement, ) } } diff --git a/src/main/kotlin/platform/mixin/debug/MixinDebuggerClassFilterProvider.kt b/src/main/kotlin/platform/mixin/debug/MixinDebuggerClassFilterProvider.kt index 36427f894..520682ba9 100644 --- a/src/main/kotlin/platform/mixin/debug/MixinDebuggerClassFilterProvider.kt +++ b/src/main/kotlin/platform/mixin/debug/MixinDebuggerClassFilterProvider.kt @@ -19,7 +19,7 @@ import com.intellij.ui.classFilter.DebuggerClassFilterProvider class MixinDebuggerClassFilterProvider : DebuggerClassFilterProvider { private val filters = listOf( - ClassFilter("org.spongepowered.asm.mixin.injection.callback.*") + ClassFilter("org.spongepowered.asm.mixin.injection.callback.*"), ) override fun getFilters(): List { diff --git a/src/main/kotlin/platform/mixin/debug/MixinPositionManager.kt b/src/main/kotlin/platform/mixin/debug/MixinPositionManager.kt index 53a922cc3..281db7307 100644 --- a/src/main/kotlin/platform/mixin/debug/MixinPositionManager.kt +++ b/src/main/kotlin/platform/mixin/debug/MixinPositionManager.kt @@ -61,7 +61,7 @@ class MixinPositionManager(private val debugProcess: DebugProcess) : MultiReques ?: DebuggerUtils.findClass( className, debugProcess.project, - debugProcess.searchScope + debugProcess.searchScope, )?.navigationElement?.containingFile if (psiFile != null) { @@ -104,13 +104,13 @@ class MixinPositionManager(private val debugProcess: DebugProcess) : MultiReques override fun createPrepareRequest(requestor: ClassPrepareRequestor, position: SourcePosition): ClassPrepareRequest { throw UnsupportedOperationException( "This class implements MultiRequestPositionManager, " + - "corresponding createPrepareRequests version should be used" + "corresponding createPrepareRequests version should be used", ) } override fun createPrepareRequests( requestor: ClassPrepareRequestor, - position: SourcePosition + position: SourcePosition, ): List { return runReadAction { findMatchingClasses(position) diff --git a/src/main/kotlin/platform/mixin/debug/MixinPositionManagerFactory.kt b/src/main/kotlin/platform/mixin/debug/MixinPositionManagerFactory.kt index f51c5e667..4ac30ee3f 100644 --- a/src/main/kotlin/platform/mixin/debug/MixinPositionManagerFactory.kt +++ b/src/main/kotlin/platform/mixin/debug/MixinPositionManagerFactory.kt @@ -16,5 +16,5 @@ import com.intellij.debugger.engine.DebugProcess class MixinPositionManagerFactory : PositionManagerFactory() { - override fun createPositionManager(process: DebugProcess): PositionManager? = MixinPositionManager(process) + override fun createPositionManager(process: DebugProcess): PositionManager = MixinPositionManager(process) } diff --git a/src/main/kotlin/platform/mixin/folding/AccessorMixinFoldingBuilder.kt b/src/main/kotlin/platform/mixin/folding/AccessorMixinFoldingBuilder.kt index 6a58f8c3e..7f0bc531e 100644 --- a/src/main/kotlin/platform/mixin/folding/AccessorMixinFoldingBuilder.kt +++ b/src/main/kotlin/platform/mixin/folding/AccessorMixinFoldingBuilder.kt @@ -102,7 +102,7 @@ class AccessorMixinFoldingBuilder : CustomFoldingBuilder() { descriptors: MutableList, root: PsiElement, document: Document, - quick: Boolean + quick: Boolean, ) { if (root !is PsiJavaFile || !MixinModuleType.isInModule(root)) { return @@ -146,8 +146,8 @@ class AccessorMixinFoldingBuilder : CustomFoldingBuilder() { descriptors.add( FoldingDescriptor( identifier.node, - identifier.textRange - ) + identifier.textRange, + ), ) } @@ -174,15 +174,15 @@ class AccessorMixinFoldingBuilder : CustomFoldingBuilder() { descriptors.add( FoldingDescriptor( parenthetical.node, - parenthetical.textRange - ) + parenthetical.textRange, + ), ) } } private fun foldAccessorMethodCall( expression: PsiMethodCallExpression, - identifier: PsiIdentifier + identifier: PsiIdentifier, ) { val argumentList = expression.argumentList val openParen = argumentList.firstChild @@ -202,23 +202,23 @@ class AccessorMixinFoldingBuilder : CustomFoldingBuilder() { FoldingDescriptor( openParen.node, openParen.textRange, - group - ) + group, + ), ) descriptors.add( FoldingDescriptor( closeParen.node, closeParen.textRange, - group - ) + group, + ), ) descriptors.add( FoldingDescriptor( identifier.node, identifier.textRange, - group - ) + group, + ), ) } } diff --git a/src/main/kotlin/platform/mixin/folding/MixinFoldingOptionsProvider.kt b/src/main/kotlin/platform/mixin/folding/MixinFoldingOptionsProvider.kt index f17392460..ce2e8ff23 100644 --- a/src/main/kotlin/platform/mixin/folding/MixinFoldingOptionsProvider.kt +++ b/src/main/kotlin/platform/mixin/folding/MixinFoldingOptionsProvider.kt @@ -23,28 +23,28 @@ class MixinFoldingOptionsProvider : checkBox( "Target descriptors", { settings.state.foldTargetDescriptors }, - { b -> settings.state.foldTargetDescriptors = b } + { b -> settings.state.foldTargetDescriptors = b }, ) checkBox("Object casts", { settings.state.foldObjectCasts }, { b -> settings.state.foldObjectCasts = b }) checkBox( "Invoker casts", { settings.state.foldInvokerCasts }, - { b -> settings.state.foldInvokerCasts = b } + { b -> settings.state.foldInvokerCasts = b }, ) checkBox( "Invoker method calls", { settings.state.foldInvokerMethodCalls }, - { b -> settings.state.foldInvokerMethodCalls = b } + { b -> settings.state.foldInvokerMethodCalls = b }, ) checkBox( "Accessor casts", { settings.state.foldAccessorCasts }, - { b -> settings.state.foldAccessorCasts = b } + { b -> settings.state.foldAccessorCasts = b }, ) checkBox( "Accessor method calls", { settings.state.foldAccessorMethodCalls }, - { b -> settings.state.foldAccessorMethodCalls = b } + { b -> settings.state.foldAccessorMethodCalls = b }, ) } } diff --git a/src/main/kotlin/platform/mixin/folding/MixinObjectCastFoldingBuilder.kt b/src/main/kotlin/platform/mixin/folding/MixinObjectCastFoldingBuilder.kt index 02355c20d..a67ae8cb3 100644 --- a/src/main/kotlin/platform/mixin/folding/MixinObjectCastFoldingBuilder.kt +++ b/src/main/kotlin/platform/mixin/folding/MixinObjectCastFoldingBuilder.kt @@ -42,7 +42,7 @@ class MixinObjectCastFoldingBuilder : CustomFoldingBuilder() { descriptors: MutableList, root: PsiElement, document: Document, - quick: Boolean + quick: Boolean, ) { if (root !is PsiJavaFile || !MixinModuleType.isInModule(root)) { return @@ -73,8 +73,8 @@ class MixinObjectCastFoldingBuilder : CustomFoldingBuilder() { descriptors.add( FoldingDescriptor( expression.node, - TextRange(start.startOffset, end.startOffset + end.textLength) - ) + TextRange(start.startOffset, end.startOffset + end.textLength), + ), ) } } diff --git a/src/main/kotlin/platform/mixin/folding/MixinTargetDescriptorFoldingBuilder.kt b/src/main/kotlin/platform/mixin/folding/MixinTargetDescriptorFoldingBuilder.kt index 676ec1c54..e9589aec3 100644 --- a/src/main/kotlin/platform/mixin/folding/MixinTargetDescriptorFoldingBuilder.kt +++ b/src/main/kotlin/platform/mixin/folding/MixinTargetDescriptorFoldingBuilder.kt @@ -63,7 +63,7 @@ class MixinTargetDescriptorFoldingBuilder : CustomFoldingBuilder() { descriptors: MutableList, root: PsiElement, document: Document, - quick: Boolean + quick: Boolean, ) { if (root !is PsiJavaFile || !MixinModuleType.isInModule(root)) { return diff --git a/src/main/kotlin/platform/mixin/handlers/AccessorHandler.kt b/src/main/kotlin/platform/mixin/handlers/AccessorHandler.kt index 9141212c7..4a7c1dc14 100644 --- a/src/main/kotlin/platform/mixin/handlers/AccessorHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/AccessorHandler.kt @@ -92,7 +92,7 @@ class AccessorHandler : MixinMemberAnnotationHandler { targetMember.classAndField.clazz, method.project, method.resolveScope, - canDecompile = false + canDecompile = false, ).createSmartPointer() } @@ -103,6 +103,7 @@ class AccessorHandler : MixinMemberAnnotationHandler { enum class AccessorType(val allowGetters: Boolean, val allowSetters: Boolean) { GETTER(true, false), SETTER(false, true), - UNKNOWN(true, true); + UNKNOWN(true, true), + ; } } diff --git a/src/main/kotlin/platform/mixin/handlers/InjectAnnotationHandler.kt b/src/main/kotlin/platform/mixin/handlers/InjectAnnotationHandler.kt index 112c990d6..11b5e7904 100644 --- a/src/main/kotlin/platform/mixin/handlers/InjectAnnotationHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/InjectAnnotationHandler.kt @@ -36,7 +36,7 @@ class InjectAnnotationHandler : InjectorAnnotationHandler() { override fun expectedMethodSignature( annotation: PsiAnnotation, targetClass: ClassNode, - targetMethod: MethodNode + targetMethod: MethodNode, ): List { val returnType = targetMethod.getGenericReturnType(targetClass, annotation.project) @@ -47,8 +47,8 @@ class InjectAnnotationHandler : InjectorAnnotationHandler() { ParameterGroup( collectTargetMethodParameters(annotation.project, targetClass, targetMethod), required = ParameterGroup.RequiredLevel.OPTIONAL, - default = true - ) + default = true, + ), ) // Callback info (required) @@ -60,11 +60,11 @@ class InjectAnnotationHandler : InjectorAnnotationHandler() { } else { Parameter( "cir", - callbackInfoReturnableType(annotation.project, annotation, returnType)!! + callbackInfoReturnableType(annotation.project, annotation, returnType)!!, ) - } - ) - ) + }, + ), + ), ) // Captured locals (only if local capture is enabled) @@ -78,7 +78,7 @@ class InjectAnnotationHandler : InjectorAnnotationHandler() { val locals = LocalVariables.getLocals(module, targetClass, targetMethod, insn.insn) ?.drop( Type.getArgumentTypes(targetMethod.desc).size + - if (targetMethod.hasAccess(Opcodes.ACC_STATIC)) 0 else 1 + if (targetMethod.hasAccess(Opcodes.ACC_STATIC)) 0 else 1, ) ?.filterNotNull() ?.filter { it.desc != null } @@ -110,8 +110,8 @@ class InjectAnnotationHandler : InjectorAnnotationHandler() { localParams, default = true, required = requiredLevel, - isVarargs = true - ) + isVarargs = true, + ), ) } } diff --git a/src/main/kotlin/platform/mixin/handlers/InjectorAnnotationHandler.kt b/src/main/kotlin/platform/mixin/handlers/InjectorAnnotationHandler.kt index 2d3d5642e..db1eaff0b 100644 --- a/src/main/kotlin/platform/mixin/handlers/InjectorAnnotationHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/InjectorAnnotationHandler.kt @@ -74,12 +74,11 @@ abstract class InjectorAnnotationHandler : MixinAnnotationHandler { protected open fun isUnresolved( annotation: PsiAnnotation, targetClass: ClassNode, - targetMethod: MethodNode + targetMethod: MethodNode, ): InsnResolutionInfo.Failure? { return annotation.findAttributeValue("at")?.findAnnotations() .ifNullOrEmpty { return InsnResolutionInfo.Failure() }!! - .mapNotNull { AtResolver(it, targetClass, targetMethod).isUnresolved() } - .firstOrNull() + .firstNotNullOfOrNull { AtResolver(it, targetClass, targetMethod).isUnresolved() } } override fun resolveForNavigation(annotation: PsiAnnotation, targetClass: ClassNode): List { @@ -92,7 +91,7 @@ abstract class InjectorAnnotationHandler : MixinAnnotationHandler { protected open fun resolveForNavigation( annotation: PsiAnnotation, targetClass: ClassNode, - targetMethod: MethodNode + targetMethod: MethodNode, ): List { return annotation.findAttributeValue("at")?.findAnnotations() .ifNullOrEmpty { return emptyList() }!! @@ -118,7 +117,7 @@ abstract class InjectorAnnotationHandler : MixinAnnotationHandler { annotation: PsiAnnotation, targetClass: ClassNode, targetMethod: MethodNode, - mode: CollectVisitor.Mode = CollectVisitor.Mode.MATCH_ALL + mode: CollectVisitor.Mode = CollectVisitor.Mode.MATCH_ALL, ): List> { return annotation.findAttributeValue("at")?.findAnnotations() .ifNullOrEmpty { return emptyList() }!! @@ -133,7 +132,7 @@ abstract class InjectorAnnotationHandler : MixinAnnotationHandler { abstract fun expectedMethodSignature( annotation: PsiAnnotation, targetClass: ClassNode, - targetMethod: MethodNode + targetMethod: MethodNode, ): List? open fun isInsnAllowed(insn: AbstractInsnNode): Boolean { @@ -155,7 +154,7 @@ abstract class InjectorAnnotationHandler : MixinAnnotationHandler { protected fun collectTargetMethodParameters( project: Project, clazz: ClassNode, - targetMethod: MethodNode + targetMethod: MethodNode, ): List { val numLocalsToDrop = if (targetMethod.hasAccess(Opcodes.ACC_STATIC)) 0 else 1 val localVariables = targetMethod.localVariables?.sortedBy { it.index } @@ -188,7 +187,7 @@ object DefaultInjectorAnnotationHandler : InjectorAnnotationHandler() { override fun expectedMethodSignature( annotation: PsiAnnotation, targetClass: ClassNode, - targetMethod: MethodNode + targetMethod: MethodNode, ) = null override val isSoft = true diff --git a/src/main/kotlin/platform/mixin/handlers/InvokerHandler.kt b/src/main/kotlin/platform/mixin/handlers/InvokerHandler.kt index 5335c0f0f..4e2d4554e 100644 --- a/src/main/kotlin/platform/mixin/handlers/InvokerHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/InvokerHandler.kt @@ -89,7 +89,7 @@ class InvokerHandler : MixinMemberAnnotationHandler { invokerTarget.classAndMethod.clazz, member.project, member.resolveScope, - canDecompile = false + canDecompile = false, ).createSmartPointer() } diff --git a/src/main/kotlin/platform/mixin/handlers/MixinAnnotationHandler.kt b/src/main/kotlin/platform/mixin/handlers/MixinAnnotationHandler.kt index 85e9e53dd..fc5c73f16 100644 --- a/src/main/kotlin/platform/mixin/handlers/MixinAnnotationHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/MixinAnnotationHandler.kt @@ -74,7 +74,7 @@ interface MixinAnnotationHandler { companion object { private val EP_NAME = ExtensionPointName>( - "com.demonwav.minecraft-dev.mixinAnnotationHandler" + "com.demonwav.minecraft-dev.mixinAnnotationHandler", ) private val COLLECTOR = KeyedExtensionCollector(EP_NAME) @@ -94,7 +94,7 @@ interface MixinAnnotationHandler { ?.let { annotationType -> AnnotatedElementsSearch.searchPsiClasses( annotationType, - GlobalSearchScope.allScope(project) + GlobalSearchScope.allScope(project), ).mapNotNull { injectionInfoClass -> injectionInfoClass.findAnnotation(MixinConstants.Annotations.ANNOTATION_TYPE) ?.findAttributeValue("value") diff --git a/src/main/kotlin/platform/mixin/handlers/MixinMemberAnnotationHandler.kt b/src/main/kotlin/platform/mixin/handlers/MixinMemberAnnotationHandler.kt index c280824d6..e6d257533 100644 --- a/src/main/kotlin/platform/mixin/handlers/MixinMemberAnnotationHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/MixinMemberAnnotationHandler.kt @@ -37,14 +37,14 @@ interface MixinMemberAnnotationHandler : MixinAnnotationHandler { it.classAndField.clazz, annotation.project, annotation.resolveScope, - canDecompile = true + canDecompile = true, ) is MethodTargetMember -> it.classAndMethod.method.findSourceElement( it.classAndMethod.clazz, annotation.project, annotation.resolveScope, - canDecompile = true + canDecompile = true, ) } } diff --git a/src/main/kotlin/platform/mixin/handlers/ModifyArgHandler.kt b/src/main/kotlin/platform/mixin/handlers/ModifyArgHandler.kt index 3b714b565..e3fcdb2c2 100644 --- a/src/main/kotlin/platform/mixin/handlers/ModifyArgHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/ModifyArgHandler.kt @@ -34,7 +34,7 @@ class ModifyArgHandler : InjectorAnnotationHandler() { override fun expectedMethodSignature( annotation: PsiAnnotation, targetClass: ClassNode, - targetMethod: MethodNode + targetMethod: MethodNode, ): List? { val index = annotation.findDeclaredAttributeValue("index")?.constantValue as? Int val validSingleArgTypes = mutableSetOf() @@ -59,7 +59,7 @@ class ModifyArgHandler : InjectorAnnotationHandler() { if (validSingleArgTypes.isEmpty()) { validSingleArgTypes.addAll(validArgTypes) } else { - validSingleArgTypes.retainAll(validArgTypes) + validSingleArgTypes.retainAll(validArgTypes.toSet()) if (validSingleArgTypes.isEmpty()) { return listOf() } @@ -100,11 +100,11 @@ class ModifyArgHandler : InjectorAnnotationHandler() { listOf( ParameterGroup( listOf( - sanitizedParameter(psiType, psiParameter?.name) - ) - ) + sanitizedParameter(psiType, psiParameter?.name), + ), + ), ), - psiType + psiType, ) if (validFullSignature != null) { val fullParamGroup = ParameterGroup( @@ -112,13 +112,13 @@ class ModifyArgHandler : InjectorAnnotationHandler() { val psiParam = paramList?.let { bytecodeMethod.getParameter(bytecodeClass, index, it) } sanitizedParameter( psiParam?.type ?: argType.toPsiType(elementFactory), - psiParam?.name + psiParam?.name, ) - } + }, ) listOf( singleSignature, - MethodSignature(listOf(fullParamGroup), psiType) + MethodSignature(listOf(fullParamGroup), psiType), ) } else { listOf(singleSignature) diff --git a/src/main/kotlin/platform/mixin/handlers/ModifyArgsHandler.kt b/src/main/kotlin/platform/mixin/handlers/ModifyArgsHandler.kt index 8fa3d6fe7..8f814c93f 100644 --- a/src/main/kotlin/platform/mixin/handlers/ModifyArgsHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/ModifyArgsHandler.kt @@ -30,7 +30,7 @@ class ModifyArgsHandler : InjectorAnnotationHandler() { override fun expectedMethodSignature( annotation: PsiAnnotation, targetClass: ClassNode, - targetMethod: MethodNode + targetMethod: MethodNode, ): List { val argsType = JavaPsiFacade.getElementFactory(annotation.project) .createTypeByFQClassName(ARGS, annotation.resolveScope) @@ -41,11 +41,11 @@ class ModifyArgsHandler : InjectorAnnotationHandler() { ParameterGroup( collectTargetMethodParameters(annotation.project, targetClass, targetMethod), required = ParameterGroup.RequiredLevel.OPTIONAL, - isVarargs = true - ) + isVarargs = true, + ), ), - PsiType.VOID - ) + PsiType.VOID, + ), ) } } diff --git a/src/main/kotlin/platform/mixin/handlers/ModifyConstantHandler.kt b/src/main/kotlin/platform/mixin/handlers/ModifyConstantHandler.kt index 4d99d31c4..d3be8a35f 100644 --- a/src/main/kotlin/platform/mixin/handlers/ModifyConstantHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/ModifyConstantHandler.kt @@ -59,12 +59,12 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { Opcodes.IFLT, Opcodes.IFGE, Opcodes.IFGT, - Opcodes.IFLE + Opcodes.IFLE, ) private class ModifyConstantInfo( val constantInfo: ConstantInjectionPoint.ConstantInfo, - val constantAnnotation: PsiAnnotation + val constantAnnotation: PsiAnnotation, ) private fun getConstantInfos(modifyConstant: PsiAnnotation): List? { @@ -81,7 +81,7 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { val stringValue = constant.findDeclaredAttributeValue("stringValue")?.constantValue as? String val classValue = constant.findDeclaredAttributeValue("classValue")?.resolveClass()?.descriptor?.let { Type.getType( - it + it, ) } @@ -129,7 +129,7 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { override fun expectedMethodSignature( annotation: PsiAnnotation, targetClass: ClassNode, - targetMethod: MethodNode + targetMethod: MethodNode, ): List? { val constantInfos = getConstantInfos(annotation) ?: return null val psiManager = PsiManager.getInstance(annotation.project) @@ -151,10 +151,10 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { ParameterGroup( collectTargetMethodParameters(annotation.project, targetClass, targetMethod), isVarargs = true, - required = ParameterGroup.RequiredLevel.OPTIONAL - ) + required = ParameterGroup.RequiredLevel.OPTIONAL, + ), ), - type + type, ) }.toList() } @@ -162,7 +162,7 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { override fun resolveForNavigation( annotation: PsiAnnotation, targetClass: ClassNode, - targetMethod: MethodNode + targetMethod: MethodNode, ): List { val constantInfos = getConstantInfos(annotation) ?: return emptyList() @@ -170,7 +170,7 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { targetClass, annotation.project, GlobalSearchScope.allScope(annotation.project), - canDecompile = true + canDecompile = true, ) ?: return emptyList() val constantInjectionPoint = InjectionPoint.byAtCode("CONSTANT") as? ConstantInjectionPoint @@ -180,12 +180,12 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { val collectVisitor = ConstantInjectionPoint.MyCollectVisitor( annotation.project, CollectVisitor.Mode.MATCH_ALL, - modifyConstantInfo.constantInfo + modifyConstantInfo.constantInfo, ) constantInjectionPoint.addStandardFilters( modifyConstantInfo.constantAnnotation, targetClass, - collectVisitor + collectVisitor, ) collectVisitor.visit(targetMethod) val bytecodeResults = collectVisitor.result @@ -203,7 +203,7 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { annotation: PsiAnnotation, targetClass: ClassNode, targetMethod: MethodNode, - mode: CollectVisitor.Mode + mode: CollectVisitor.Mode, ): List> { val constantInfos = getConstantInfos(annotation) ?: return emptyList() val constantInjectionPoint = InjectionPoint.byAtCode("CONSTANT") as? ConstantInjectionPoint @@ -212,12 +212,12 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { val collectVisitor = ConstantInjectionPoint.MyCollectVisitor( annotation.project, mode, - modifyConstantInfo.constantInfo + modifyConstantInfo.constantInfo, ) constantInjectionPoint.addStandardFilters( modifyConstantInfo.constantAnnotation, targetClass, - collectVisitor + collectVisitor, ) collectVisitor.visit(targetMethod) collectVisitor.result.asSequence() @@ -227,7 +227,7 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { override fun isUnresolved( annotation: PsiAnnotation, targetClass: ClassNode, - targetMethod: MethodNode + targetMethod: MethodNode, ): InsnResolutionInfo.Failure? { val constantInfos = getConstantInfos(annotation) ?: return InsnResolutionInfo.Failure() val constantInjectionPoint = InjectionPoint.byAtCode("CONSTANT") as? ConstantInjectionPoint @@ -236,12 +236,12 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { val collectVisitor = ConstantInjectionPoint.MyCollectVisitor( annotation.project, CollectVisitor.Mode.MATCH_FIRST, - modifyConstantInfo.constantInfo + modifyConstantInfo.constantInfo, ) constantInjectionPoint.addStandardFilters( modifyConstantInfo.constantAnnotation, targetClass, - collectVisitor + collectVisitor, ) collectVisitor.visit(targetMethod) if (collectVisitor.result.isEmpty()) { diff --git a/src/main/kotlin/platform/mixin/handlers/ModifyVariableHandler.kt b/src/main/kotlin/platform/mixin/handlers/ModifyVariableHandler.kt index 2ae1f399f..e25ccc0c6 100644 --- a/src/main/kotlin/platform/mixin/handlers/ModifyVariableHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/ModifyVariableHandler.kt @@ -38,7 +38,7 @@ class ModifyVariableHandler : InjectorAnnotationHandler() { override fun expectedMethodSignature( annotation: PsiAnnotation, targetClass: ClassNode, - targetMethod: MethodNode + targetMethod: MethodNode, ): List? { val module = annotation.findModule() ?: return null @@ -51,7 +51,7 @@ class ModifyVariableHandler : InjectorAnnotationHandler() { val targetParamsGroup = ParameterGroup( collectTargetMethodParameters(annotation.project, targetClass, targetMethod), required = ParameterGroup.RequiredLevel.OPTIONAL, - isVarargs = true + isVarargs = true, ) val info = ModifyVariableInfo.getModifyVariableInfo(annotation, CollectVisitor.Mode.COMPLETION) @@ -74,9 +74,9 @@ class ModifyVariableHandler : InjectorAnnotationHandler() { result += MethodSignature( listOf( ParameterGroup(listOf(sanitizedParameter(psiType, "value"))), - targetParamsGroup + targetParamsGroup, ), - psiType + psiType, ) } @@ -89,13 +89,13 @@ class ModifyVariableInfo( val argsOnly: Boolean, val index: Int?, val ordinal: Int?, - val names: Set + val names: Set, ) { fun getLocals( module: Module, targetClass: ClassNode, methodNode: MethodNode, - insn: AbstractInsnNode + insn: AbstractInsnNode, ): Array? { return if (argsOnly) { val args = mutableListOf() @@ -105,7 +105,7 @@ class ModifyVariableInfo( } for (argType in Type.getArgumentTypes(methodNode.desc)) { args.add( - LocalVariables.LocalVariable("arg${args.size}", argType.descriptor, null, null, null, args.size) + LocalVariables.LocalVariable("arg${args.size}", argType.descriptor, null, null, null, args.size), ) if (argType.size == 2) { args.add(null) @@ -120,7 +120,7 @@ class ModifyVariableInfo( fun matchLocals( locals: Array, mode: CollectVisitor.Mode, - matchType: Boolean = true + matchType: Boolean = true, ): List { val typeDesc = type?.descriptor if (ordinal != null) { diff --git a/src/main/kotlin/platform/mixin/handlers/RedirectInjectorHandler.kt b/src/main/kotlin/platform/mixin/handlers/RedirectInjectorHandler.kt index ac4086065..d43c06905 100644 --- a/src/main/kotlin/platform/mixin/handlers/RedirectInjectorHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/RedirectInjectorHandler.kt @@ -25,6 +25,7 @@ import com.demonwav.mcdev.util.toJavaIdentifier import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiArrayType +import com.intellij.psi.PsiElementFactory import com.intellij.psi.PsiManager import com.intellij.psi.PsiType import org.objectweb.asm.Opcodes @@ -72,20 +73,20 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { override fun expectedMethodSignature( annotation: PsiAnnotation, targetClass: ClassNode, - targetMethod: MethodNode + targetMethod: MethodNode, ): List? { val insns = resolveInstructions(annotation, targetClass, targetMethod).ifEmpty { return emptyList() } return getRedirectType(insns[0].insn)?.expectedMethodSignature( annotation, targetClass, targetMethod, - insns.map { it.insn } + insns.map { it.insn }, )?.map { (paramGroups, returnType) -> // add a parameter group for capturing the target method parameters val extraGroup = ParameterGroup( collectTargetMethodParameters(annotation.project, targetClass, targetMethod), required = ParameterGroup.RequiredLevel.OPTIONAL, - isVarargs = true + isVarargs = true, ) MethodSignature(paramGroups + extraGroup, returnType) } @@ -100,16 +101,34 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { annotation: PsiAnnotation, targetClass: ClassNode, targetMethod: MethodNode, - insns: List + insns: List, ): List? } - private object FieldGet : RedirectType { + private abstract class FieldAccess : RedirectType { + protected fun determineFieldType( + firstMatch: FieldInsnNode, + annotation: PsiAnnotation, + ): Pair { + val elementFactory = JavaPsiFacade.getElementFactory(annotation.project) + + val sourceClassAndField = ( + MemberReference(firstMatch.name, firstMatch.desc, firstMatch.owner.replace('/', '.')) + .resolveAsm(annotation.project) as? FieldTargetMember + )?.classAndField + val fieldType = sourceClassAndField?.field?.getGenericType(sourceClassAndField.clazz, annotation.project) + ?: Type.getType(firstMatch.desc).toPsiType(elementFactory) + + return elementFactory to fieldType + } + } + + private object FieldGet : FieldAccess() { override fun expectedMethodSignature( annotation: PsiAnnotation, targetClass: ClassNode, targetMethod: MethodNode, - insns: List + insns: List, ): List { val firstMatch = insns.first() as FieldInsnNode val isValid = insns.all { @@ -122,16 +141,9 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { return emptyList() } - val elementFactory = JavaPsiFacade.getElementFactory(annotation.project) - - val sourceClassAndField = ( - MemberReference(firstMatch.name, firstMatch.desc, firstMatch.owner.replace('/', '.')) - .resolveAsm(annotation.project) as? FieldTargetMember - )?.classAndField - val fieldType = sourceClassAndField?.field?.getGenericType(sourceClassAndField.clazz, annotation.project) - ?: Type.getType(firstMatch.desc).toPsiType(elementFactory) - + val (elementFactory, fieldType) = determineFieldType(firstMatch, annotation) val parameters = mutableListOf() + if (firstMatch.opcode == Opcodes.GETFIELD) { parameters += Parameter("instance", Type.getObjectType(firstMatch.owner).toPsiType(elementFactory)) } @@ -139,18 +151,18 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { return listOf( MethodSignature( listOf(ParameterGroup(parameters)), - fieldType - ) + fieldType, + ), ) } } - private object FieldSet : RedirectType { + private object FieldSet : FieldAccess() { override fun expectedMethodSignature( annotation: PsiAnnotation, targetClass: ClassNode, targetMethod: MethodNode, - insns: List + insns: List, ): List { val firstMatch = insns.first() as FieldInsnNode val isValid = insns.all { @@ -163,16 +175,9 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { return emptyList() } - val elementFactory = JavaPsiFacade.getElementFactory(annotation.project) - - val sourceClassAndField = ( - MemberReference(firstMatch.name, firstMatch.desc, firstMatch.owner.replace('/', '.')) - .resolveAsm(annotation.project) as? FieldTargetMember - )?.classAndField - val fieldType = sourceClassAndField?.field?.getGenericType(sourceClassAndField.clazz, annotation.project) - ?: Type.getType(firstMatch.desc).toPsiType(elementFactory) - + val (elementFactory, fieldType) = determineFieldType(firstMatch, annotation) val parameters = mutableListOf() + if (firstMatch.opcode == Opcodes.PUTFIELD) { parameters += Parameter("instance", Type.getObjectType(firstMatch.owner).toPsiType(elementFactory)) } @@ -181,8 +186,8 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { return listOf( MethodSignature( listOf(ParameterGroup(parameters)), - PsiType.VOID - ) + PsiType.VOID, + ), ) } } @@ -196,7 +201,7 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { annotation: PsiAnnotation, targetClass: ClassNode, targetMethod: MethodNode, - insns: List + insns: List, ): List { val firstMatch = insns.first() as MethodInsnNode val isValid = insns.all { @@ -219,7 +224,7 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { )?.classAndMethod val signature = sourceClassAndMethod?.method?.getGenericSignature( sourceClassAndMethod.clazz, - annotation.project + annotation.project, ) val parameters = mutableListOf() @@ -252,7 +257,7 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { annotation: PsiAnnotation, targetClass: ClassNode, targetMethod: MethodNode, - insns: List + insns: List, ): List? { val firstMatch = insns.first() val isValid = insns.all { it.opcode == firstMatch.opcode } @@ -271,12 +276,12 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { listOf( ParameterGroup( listOf( - Parameter("array", arrayType.toPsiType(elementFactory)) - ) - ) + Parameter("array", arrayType.toPsiType(elementFactory)), + ), + ), ), - PsiType.INT - ) + PsiType.INT, + ), ) } } @@ -286,7 +291,7 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { annotation: PsiAnnotation, targetClass: ClassNode, targetMethod: MethodNode, - insns: List + insns: List, ): List? { val firstMatch = insns.first() val isValid = insns.all { it.opcode == firstMatch.opcode } @@ -307,12 +312,12 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { ParameterGroup( listOf( Parameter("array", psiArrayType), - Parameter("index", PsiType.INT) - ) - ) + Parameter("index", PsiType.INT), + ), + ), ), - psiArrayType.componentType - ) + psiArrayType.componentType, + ), ) } } @@ -322,7 +327,7 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { annotation: PsiAnnotation, targetClass: ClassNode, targetMethod: MethodNode, - insns: List + insns: List, ): List? { val firstMatch = insns.first() val isValid = insns.all { it.opcode == firstMatch.opcode } @@ -344,12 +349,12 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { listOf( Parameter("array", psiArrayType), Parameter("index", PsiType.INT), - Parameter("value", psiArrayType.componentType) - ) - ) + Parameter("value", psiArrayType.componentType), + ), + ), ), - PsiType.VOID - ) + PsiType.VOID, + ), ) } } @@ -363,7 +368,7 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { annotation: PsiAnnotation, targetClass: ClassNode, targetMethod: MethodNode, - insns: List + insns: List, ): List { val firstMatch = insns.first() as TypeInsnNode val isValid = insns.all { @@ -383,7 +388,7 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { targetMethod, insns.mapNotNull { NewInsnInjectionPoint.findInitCall(it as TypeInsnNode) - } + }, ).map { (paramGroups, _) -> // drop the instance parameter, return the constructed type MethodSignature(listOf(ParameterGroup(paramGroups[0].parameters.drop(1))), constructedType) @@ -396,7 +401,7 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { annotation: PsiAnnotation, targetClass: ClassNode, targetMethod: MethodNode, - insns: List + insns: List, ): List { val firstMatch = insns.first() val isValid = insns.all { it.opcode == firstMatch.opcode } @@ -409,12 +414,12 @@ class RedirectInjectorHandler : InjectorAnnotationHandler() { val parameters = ParameterGroup( listOf( Parameter("instance", objectType), - Parameter("type", classType) - ) + Parameter("type", classType), + ), ) return listOf( MethodSignature(listOf(parameters), PsiType.BOOLEAN), - MethodSignature(listOf(parameters), classType) + MethodSignature(listOf(parameters), classType), ) } } diff --git a/src/main/kotlin/platform/mixin/handlers/ShadowHandler.kt b/src/main/kotlin/platform/mixin/handlers/ShadowHandler.kt index e3f45aa22..9de9c75fd 100644 --- a/src/main/kotlin/platform/mixin/handlers/ShadowHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/ShadowHandler.kt @@ -45,10 +45,10 @@ class ShadowHandler : MixinMemberAnnotationHandler { return when (member) { is PsiMethod -> listOfNotNull( targetClass.findMethod(MemberReference(name, member.descriptor)) - ?.let { MethodTargetMember(targetClass, it) } + ?.let { MethodTargetMember(targetClass, it) }, ) is PsiField -> listOfNotNull( - targetClass.findFieldByName(name)?.let { FieldTargetMember(targetClass, it) } + targetClass.findFieldByName(name)?.let { FieldTargetMember(targetClass, it) }, ) else -> emptyList() } @@ -79,13 +79,13 @@ class ShadowHandler : MixinMemberAnnotationHandler { shadowTarget.classAndField.clazz, member.project, member.resolveScope, - canDecompile = false + canDecompile = false, ) is MethodTargetMember -> shadowTarget.classAndMethod.method.findSourceElement( shadowTarget.classAndMethod.clazz, member.project, member.resolveScope, - canDecompile = false + canDecompile = false, ) }?.createSmartPointer() } @@ -98,13 +98,13 @@ class ShadowHandler : MixinMemberAnnotationHandler { shadowTarget.classAndField.clazz, member.project, member.resolveScope, - canDecompile = false + canDecompile = false, ) is MethodTargetMember -> shadowTarget.classAndMethod.method.findOrConstructSourceMethod( shadowTarget.classAndMethod.clazz, member.project, member.resolveScope, - canDecompile = false + canDecompile = false, ) }.createSmartPointer() } diff --git a/src/main/kotlin/platform/mixin/handlers/injectionPoint/AtResolver.kt b/src/main/kotlin/platform/mixin/handlers/injectionPoint/AtResolver.kt index 9ae7c5138..1f6242d0f 100644 --- a/src/main/kotlin/platform/mixin/handlers/injectionPoint/AtResolver.kt +++ b/src/main/kotlin/platform/mixin/handlers/injectionPoint/AtResolver.kt @@ -55,7 +55,7 @@ import org.objectweb.asm.tree.MethodNode class AtResolver( private val at: PsiAnnotation, private val targetClass: ClassNode, - private val targetMethod: MethodNode + private val targetMethod: MethodNode, ) { companion object { private fun getInjectionPoint(at: PsiAnnotation): InjectionPoint<*>? { @@ -102,7 +102,7 @@ class AtResolver( at, target, targetClass, - CollectVisitor.Mode.MATCH_FIRST + CollectVisitor.Mode.MATCH_FIRST, ) if (collectVisitor == null) { // syntax error in target @@ -153,7 +153,7 @@ class AtResolver( targetClass, at.project, GlobalSearchScope.allScope(at.project), - canDecompile = true + canDecompile = true, ) ?: return emptyList() val targetPsiClass = targetElement.parentOfType() ?: return emptyList() diff --git a/src/main/kotlin/platform/mixin/handlers/injectionPoint/ConstantInjectionPoint.kt b/src/main/kotlin/platform/mixin/handlers/injectionPoint/ConstantInjectionPoint.kt index 1578401c0..3ef23f0ab 100644 --- a/src/main/kotlin/platform/mixin/handlers/injectionPoint/ConstantInjectionPoint.kt +++ b/src/main/kotlin/platform/mixin/handlers/injectionPoint/ConstantInjectionPoint.kt @@ -29,7 +29,6 @@ import com.intellij.psi.PsiForeachStatement import com.intellij.psi.PsiLiteralExpression import com.intellij.psi.PsiSwitchLabelStatementBase import com.intellij.psi.util.PsiUtil -import java.lang.IllegalArgumentException import java.util.Locale import org.objectweb.asm.Opcodes import org.objectweb.asm.Type @@ -92,7 +91,7 @@ class ConstantInjectionPoint : InjectionPoint() { override fun createNavigationVisitor( at: PsiAnnotation, target: MixinSelector?, - targetClass: PsiClass + targetClass: PsiClass, ): NavigationVisitor? { val constantInfo = getConstantInfo(at) ?: return null return MyNavigationVisitor(constantInfo) @@ -102,7 +101,7 @@ class ConstantInjectionPoint : InjectionPoint() { at: PsiAnnotation, target: MixinSelector?, targetClass: ClassNode, - mode: CollectVisitor.Mode + mode: CollectVisitor.Mode, ): CollectVisitor? { val constantInfo = getConstantInfo(at) ?: return null return MyCollectVisitor(at.project, mode, constantInfo) @@ -110,7 +109,7 @@ class ConstantInjectionPoint : InjectionPoint() { override fun createLookup( targetClass: ClassNode, - result: CollectVisitor.Result + result: CollectVisitor.Result, ): LookupElementBuilder? { return null } @@ -125,7 +124,7 @@ class ConstantInjectionPoint : InjectionPoint() { } class MyNavigationVisitor( - private val constantInfo: ConstantInfo + private val constantInfo: ConstantInfo, ) : NavigationVisitor() { override fun visitForeachStatement(statement: PsiForeachStatement) { if (statement.iteratedValue?.type is PsiArrayType) { @@ -197,7 +196,7 @@ class ConstantInjectionPoint : InjectionPoint() { class MyCollectVisitor( private val project: Project, mode: Mode, - private val constantInfo: ConstantInfo + private val constantInfo: ConstantInfo, ) : CollectVisitor(mode) { override fun accept(methodNode: MethodNode) { val elementFactory = JavaPsiFacade.getElementFactory(project) diff --git a/src/main/kotlin/platform/mixin/handlers/injectionPoint/ConstantStringMethodInjectionPoint.kt b/src/main/kotlin/platform/mixin/handlers/injectionPoint/ConstantStringMethodInjectionPoint.kt index 5084ac9fc..6314dee48 100644 --- a/src/main/kotlin/platform/mixin/handlers/injectionPoint/ConstantStringMethodInjectionPoint.kt +++ b/src/main/kotlin/platform/mixin/handlers/injectionPoint/ConstantStringMethodInjectionPoint.kt @@ -30,7 +30,7 @@ class ConstantStringMethodInjectionPoint : AbstractMethodInjectionPoint() { override fun createNavigationVisitor( at: PsiAnnotation, target: MixinSelector?, - targetClass: PsiClass + targetClass: PsiClass, ): NavigationVisitor? { return target?.let { MyNavigationVisitor(targetClass, it, AtResolver.getArgs(at)["ldc"]) } } @@ -39,7 +39,7 @@ class ConstantStringMethodInjectionPoint : AbstractMethodInjectionPoint() { at: PsiAnnotation, target: MixinSelector?, targetClass: ClassNode, - mode: CollectVisitor.Mode + mode: CollectVisitor.Mode, ): CollectVisitor? { if (mode == CollectVisitor.Mode.COMPLETION) { return MyCollectVisitor(mode, at.project, MemberReference(""), null) @@ -50,7 +50,7 @@ class ConstantStringMethodInjectionPoint : AbstractMethodInjectionPoint() { private class MyNavigationVisitor( private val targetClass: PsiClass, private val selector: MixinSelector, - private val ldc: String? + private val ldc: String?, ) : NavigationVisitor() { private fun isConstantStringMethodCall(expression: PsiMethodCallExpression): Boolean { // Must return void @@ -62,7 +62,7 @@ class ConstantStringMethodInjectionPoint : AbstractMethodInjectionPoint() { val argumentTypes = arguments.expressionTypes val javaStringType = PsiType.getJavaLangString( expression.manager, - expression.resolveScope + expression.resolveScope, ) if (argumentTypes.size != 1 || argumentTypes[0] != javaStringType) { @@ -80,7 +80,7 @@ class ConstantStringMethodInjectionPoint : AbstractMethodInjectionPoint() { expression.resolveMethod()?.let { method -> val matches = selector.matchMethod( method, - QualifiedMember.resolveQualifier(expression.methodExpression) ?: targetClass + QualifiedMember.resolveQualifier(expression.methodExpression) ?: targetClass, ) if (matches) { addResult(expression) @@ -96,7 +96,7 @@ class ConstantStringMethodInjectionPoint : AbstractMethodInjectionPoint() { mode: Mode, private val project: Project, private val selector: MixinSelector, - private val ldc: String? + private val ldc: String?, ) : CollectVisitor(mode) { override fun accept(methodNode: MethodNode) { val insns = methodNode.instructions ?: return @@ -136,9 +136,9 @@ class ConstantStringMethodInjectionPoint : AbstractMethodInjectionPoint() { fakeMethod.method.findOrConstructSourceMethod( fakeMethod.clazz, project, - canDecompile = false + canDecompile = false, ), - qualifier = insn.owner.replace('/', '.') + qualifier = insn.owner.replace('/', '.'), ) } } diff --git a/src/main/kotlin/platform/mixin/handlers/injectionPoint/FieldInjectionPoint.kt b/src/main/kotlin/platform/mixin/handlers/injectionPoint/FieldInjectionPoint.kt index d3381e8fb..2861434c6 100644 --- a/src/main/kotlin/platform/mixin/handlers/injectionPoint/FieldInjectionPoint.kt +++ b/src/main/kotlin/platform/mixin/handlers/injectionPoint/FieldInjectionPoint.kt @@ -52,7 +52,7 @@ class FieldInjectionPoint : QualifiedInjectionPoint() { override fun createNavigationVisitor( at: PsiAnnotation, target: MixinSelector?, - targetClass: PsiClass + targetClass: PsiClass, ): NavigationVisitor? { val opcode = (at.findDeclaredAttributeValue("opcode")?.constantValue as? Int) ?.takeIf { it in VALID_OPCODES } ?: -1 @@ -65,7 +65,7 @@ class FieldInjectionPoint : QualifiedInjectionPoint() { at: PsiAnnotation, target: MixinSelector?, targetClass: ClassNode, - mode: CollectVisitor.Mode + mode: CollectVisitor.Mode, ): CollectVisitor? { if (mode == CollectVisitor.Mode.COMPLETION) { return MyCollectVisitor(mode, at.project, MemberReference(""), -1, null, 8) @@ -82,7 +82,7 @@ class FieldInjectionPoint : QualifiedInjectionPoint() { return JavaLookupElementBuilder.forField( m, m.getQualifiedMemberReference(owner).toMixinString(), - null + null, ) .setBoldIfInClass(m, targetClass) .withPresentableText(m.name) @@ -93,7 +93,7 @@ class FieldInjectionPoint : QualifiedInjectionPoint() { private val targetClass: PsiClass, private val selector: MixinSelector, private val opcode: Int, - private val arrayAccess: ArrayAccessType? + private val arrayAccess: ArrayAccessType?, ) : NavigationVisitor() { override fun visitReferenceExpression(expression: PsiReferenceExpression) { if (expression !is PsiMethodReferenceExpression) { @@ -103,7 +103,7 @@ class FieldInjectionPoint : QualifiedInjectionPoint() { (expression.resolve() as? PsiField)?.let { resolved -> var matches = selector.matchField( resolved, - QualifiedMember.resolveQualifier(expression) ?: targetClass + QualifiedMember.resolveQualifier(expression) ?: targetClass, ) if (matches && opcode != -1) { // check if we match the opcode @@ -157,7 +157,7 @@ class FieldInjectionPoint : QualifiedInjectionPoint() { private val selector: MixinSelector, private val opcode: Int, private val arrayAccess: ArrayAccessType?, - private val fuzz: Int + private val fuzz: Int, ) : CollectVisitor(mode) { override fun accept(methodNode: MethodNode) { val insns = methodNode.instructions ?: return @@ -180,7 +180,7 @@ class FieldInjectionPoint : QualifiedInjectionPoint() { val psiField = fieldNode.field.findOrConstructSourceField( fieldNode.clazz, project, - canDecompile = false + canDecompile = false, ) addResult(actualInsn, psiField, qualifier = insn.owner.replace('/', '.')) } diff --git a/src/main/kotlin/platform/mixin/handlers/injectionPoint/HeadInjectionPoint.kt b/src/main/kotlin/platform/mixin/handlers/injectionPoint/HeadInjectionPoint.kt index bbf6948f2..997c5278d 100644 --- a/src/main/kotlin/platform/mixin/handlers/injectionPoint/HeadInjectionPoint.kt +++ b/src/main/kotlin/platform/mixin/handlers/injectionPoint/HeadInjectionPoint.kt @@ -27,7 +27,7 @@ class HeadInjectionPoint : InjectionPoint() { at: PsiAnnotation, target: MixinSelector?, targetClass: ClassNode, - mode: CollectVisitor.Mode + mode: CollectVisitor.Mode, ): CollectVisitor { return MyCollectVisitor(at.project, targetClass, mode) } @@ -35,14 +35,14 @@ class HeadInjectionPoint : InjectionPoint() { override fun createNavigationVisitor( at: PsiAnnotation, target: MixinSelector?, - targetClass: PsiClass + targetClass: PsiClass, ): NavigationVisitor { return MyNavigationVisitor() } override fun createLookup( targetClass: ClassNode, - result: CollectVisitor.Result + result: CollectVisitor.Result, ): LookupElementBuilder? { return null } @@ -50,7 +50,7 @@ class HeadInjectionPoint : InjectionPoint() { private class MyCollectVisitor( private val project: Project, private val clazz: ClassNode, - mode: Mode + mode: Mode, ) : CollectVisitor(mode) { override fun accept(methodNode: MethodNode) { val insns = methodNode.instructions ?: return diff --git a/src/main/kotlin/platform/mixin/handlers/injectionPoint/InjectionPoint.kt b/src/main/kotlin/platform/mixin/handlers/injectionPoint/InjectionPoint.kt index ca37e22a2..8c54088fb 100644 --- a/src/main/kotlin/platform/mixin/handlers/injectionPoint/InjectionPoint.kt +++ b/src/main/kotlin/platform/mixin/handlers/injectionPoint/InjectionPoint.kt @@ -13,6 +13,8 @@ package com.demonwav.mcdev.platform.mixin.handlers.injectionPoint import com.demonwav.mcdev.platform.mixin.reference.MixinSelector import com.demonwav.mcdev.platform.mixin.reference.toMixinString import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Classes.SHIFT +import com.demonwav.mcdev.platform.mixin.util.fakeResolve +import com.demonwav.mcdev.platform.mixin.util.findOrConstructSourceMethod import com.demonwav.mcdev.util.constantStringValue import com.demonwav.mcdev.util.constantValue import com.demonwav.mcdev.util.equivalentTo @@ -25,6 +27,7 @@ import com.demonwav.mcdev.util.shortName import com.intellij.codeInsight.completion.JavaLookupElementBuilder import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.openapi.extensions.RequiredElement +import com.intellij.openapi.project.Project import com.intellij.openapi.util.KeyedExtensionCollector import com.intellij.psi.JavaPsiFacade import com.intellij.psi.JavaRecursiveElementVisitor @@ -48,6 +51,7 @@ import com.intellij.util.xmlb.annotations.Attribute import org.objectweb.asm.tree.AbstractInsnNode import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.InsnList +import org.objectweb.asm.tree.MethodInsnNode import org.objectweb.asm.tree.MethodNode abstract class InjectionPoint { @@ -65,21 +69,21 @@ abstract class InjectionPoint { abstract fun createNavigationVisitor( at: PsiAnnotation, target: MixinSelector?, - targetClass: PsiClass + targetClass: PsiClass, ): NavigationVisitor? abstract fun doCreateCollectVisitor( at: PsiAnnotation, target: MixinSelector?, targetClass: ClassNode, - mode: CollectVisitor.Mode + mode: CollectVisitor.Mode, ): CollectVisitor? fun createCollectVisitor( at: PsiAnnotation, target: MixinSelector?, targetClass: ClassNode, - mode: CollectVisitor.Mode + mode: CollectVisitor.Mode, ): CollectVisitor? { return doCreateCollectVisitor(at, target, targetClass, mode)?.also { addFilters(at, targetClass, it) @@ -146,7 +150,7 @@ abstract class InjectionPoint { sliceAt: PsiAnnotation?, selector: SliceSelector, insns: InsnList, - method: MethodNode + method: MethodNode, ): Int? { return sliceAt?.let { val results = AtResolver(sliceAt, targetClass, method).resolveInstructions() @@ -224,19 +228,19 @@ abstract class QualifiedInjectionPoint : InjectionPoint() { final override fun createLookup( targetClass: ClassNode, - result: CollectVisitor.Result + result: CollectVisitor.Result, ): LookupElementBuilder { return qualifyLookup( createLookup(targetClass, result.target, result.qualifier ?: targetClass.name), targetClass, - result.target + result.target, ) } private fun qualifyLookup( builder: LookupElementBuilder, targetClass: ClassNode, - m: T + m: T, ): LookupElementBuilder { val owner = m.containingClass ?: return builder return if (targetClass.name == owner.fullQualifiedName?.replace('.', '/')) { @@ -255,7 +259,7 @@ abstract class AbstractMethodInjectionPoint : QualifiedInjectionPoint m, m.getQualifiedMemberReference(owner).toMixinString(), PsiSubstitutor.EMPTY, - null + null, ) .setBoldIfInClass(m, targetClass) .withPresentableText(m.internalName) // Display internal name (e.g. for constructors) @@ -350,7 +354,7 @@ abstract class CollectVisitor(protected val mode: Mode) { protected fun addResult( insn: AbstractInsnNode, element: T, - qualifier: String? = null + qualifier: String? = null, ) { // apply shift. // being able to break out of the shift loops is important to prevent IDE freezes in case of large shift bys. @@ -390,6 +394,7 @@ abstract class CollectVisitor(protected val mode: Mode) { } } + @Suppress("MemberVisibilityCanBePrivate") protected fun stopWalking() { throw StopWalkingException() } @@ -405,10 +410,31 @@ abstract class CollectVisitor(protected val mode: Mode) { val originalInsn: AbstractInsnNode, val insn: AbstractInsnNode, val target: T, - val qualifier: String? = null + val qualifier: String? = null, ) enum class Mode { MATCH_ALL, MATCH_FIRST, COMPLETION } } +fun nodeMatchesSelector( + insn: MethodInsnNode, + mode: CollectVisitor.Mode, + selector: MixinSelector, + project: Project, +): PsiMethod? { + if (mode != CollectVisitor.Mode.COMPLETION) { + if (!selector.matchMethod(insn.owner, insn.name, insn.desc)) { + return null + } + } + + val fakeMethod = insn.fakeResolve() + + return fakeMethod.method.findOrConstructSourceMethod( + fakeMethod.clazz, + project, + canDecompile = false, + ) +} + typealias CollectResultFilter = (CollectVisitor.Result, MethodNode) -> Boolean diff --git a/src/main/kotlin/platform/mixin/handlers/injectionPoint/LoadInjectionPoint.kt b/src/main/kotlin/platform/mixin/handlers/injectionPoint/LoadInjectionPoint.kt index c4e5a8016..b1194e0b5 100644 --- a/src/main/kotlin/platform/mixin/handlers/injectionPoint/LoadInjectionPoint.kt +++ b/src/main/kotlin/platform/mixin/handlers/injectionPoint/LoadInjectionPoint.kt @@ -54,7 +54,7 @@ abstract class AbstractLoadInjectionPoint(private val store: Boolean) : Injectio override fun createNavigationVisitor( at: PsiAnnotation, target: MixinSelector?, - targetClass: PsiClass + targetClass: PsiClass, ): NavigationVisitor? { val info = getModifyVariableInfo(at, null) ?: return null return MyNavigationVisitor(info, store) @@ -64,7 +64,7 @@ abstract class AbstractLoadInjectionPoint(private val store: Boolean) : Injectio at: PsiAnnotation, target: MixinSelector?, targetClass: ClassNode, - mode: CollectVisitor.Mode + mode: CollectVisitor.Mode, ): CollectVisitor? { val module = at.findModule() ?: return null val info = getModifyVariableInfo(at, mode) ?: return null @@ -73,7 +73,7 @@ abstract class AbstractLoadInjectionPoint(private val store: Boolean) : Injectio override fun createLookup( targetClass: ClassNode, - result: CollectVisitor.Result + result: CollectVisitor.Result, ): LookupElementBuilder? { return null } @@ -95,7 +95,7 @@ abstract class AbstractLoadInjectionPoint(private val store: Boolean) : Injectio targetClass, method, localInsn, - result.originalInsn.`var` + result.originalInsn.`var`, ) ?: return@addResultFilter true val desc = localType.descriptor val ord = ordinals[desc] ?: 0 @@ -106,7 +106,7 @@ abstract class AbstractLoadInjectionPoint(private val store: Boolean) : Injectio private class MyNavigationVisitor( private val info: ModifyVariableInfo, - private val store: Boolean + private val store: Boolean, ) : NavigationVisitor() { override fun visitThisExpression(expression: PsiThisExpression) { super.visitThisExpression(expression) @@ -187,25 +187,15 @@ abstract class AbstractLoadInjectionPoint(private val store: Boolean) : Injectio } private fun checkImplicitLocalsPre(location: PsiElement) { - val localsHere = LocalVariables.guessLocalsAt(location, info.argsOnly, true) - val localIndex = LocalVariables.guessLocalVariableIndex(location) ?: return - val localCount = LocalVariables.getLocalVariableSize(location) - for (i in localIndex until (localIndex + localCount)) { - val local = localsHere.firstOrNull { it.index == i } ?: continue - if (store) { - repeat(local.implicitStoreCountBefore) { - addLocalUsage(location, local.name, localsHere) - } - } else { - repeat(local.implicitLoadCountBefore) { - addLocalUsage(location, local.name, localsHere) - } - } - } + checkImplicitLocals(location, true) } private fun checkImplicitLocalsPost(location: PsiElement) { - val localsHere = LocalVariables.guessLocalsAt(location, info.argsOnly, false) + checkImplicitLocals(location, false) + } + + private fun checkImplicitLocals(location: PsiElement, isPre: Boolean) { + val localsHere = LocalVariables.guessLocalsAt(location, info.argsOnly, isPre) val localIndex = LocalVariables.guessLocalVariableIndex(location) ?: return val localCount = LocalVariables.getLocalVariableSize(location) for (i in localIndex until (localIndex + localCount)) { @@ -230,7 +220,7 @@ abstract class AbstractLoadInjectionPoint(private val store: Boolean) : Injectio private fun addLocalUsage( location: PsiElement, name: String, - localsHere: List + localsHere: List, ) { if (info.ordinal != null) { val local = localsHere.asSequence().filter { @@ -277,7 +267,7 @@ abstract class AbstractLoadInjectionPoint(private val store: Boolean) : Injectio private val targetClass: ClassNode, mode: Mode, private val info: ModifyVariableInfo, - private val store: Boolean + private val store: Boolean, ) : CollectVisitor(mode) { override fun accept(methodNode: MethodNode) { var opcode = when (info.type) { diff --git a/src/main/kotlin/platform/mixin/handlers/injectionPoint/MethodInjectionPoint.kt b/src/main/kotlin/platform/mixin/handlers/injectionPoint/MethodInjectionPoint.kt index 856d9d149..788e3f238 100644 --- a/src/main/kotlin/platform/mixin/handlers/injectionPoint/MethodInjectionPoint.kt +++ b/src/main/kotlin/platform/mixin/handlers/injectionPoint/MethodInjectionPoint.kt @@ -11,8 +11,6 @@ package com.demonwav.mcdev.platform.mixin.handlers.injectionPoint import com.demonwav.mcdev.platform.mixin.reference.MixinSelector -import com.demonwav.mcdev.platform.mixin.util.fakeResolve -import com.demonwav.mcdev.platform.mixin.util.findOrConstructSourceMethod import com.demonwav.mcdev.util.MemberReference import com.intellij.openapi.project.Project import com.intellij.psi.CommonClassNames @@ -33,7 +31,7 @@ class MethodInjectionPoint : AbstractMethodInjectionPoint() { override fun createNavigationVisitor( at: PsiAnnotation, target: MixinSelector?, - targetClass: PsiClass + targetClass: PsiClass, ): NavigationVisitor? { return target?.let { MyNavigationVisitor(targetClass, it) } } @@ -42,7 +40,7 @@ class MethodInjectionPoint : AbstractMethodInjectionPoint() { at: PsiAnnotation, target: MixinSelector?, targetClass: ClassNode, - mode: CollectVisitor.Mode + mode: CollectVisitor.Mode, ): CollectVisitor? { if (mode == CollectVisitor.Mode.COMPLETION) { return MyCollectVisitor(mode, at.project, MemberReference("")) @@ -52,7 +50,7 @@ class MethodInjectionPoint : AbstractMethodInjectionPoint() { private class MyNavigationVisitor( private val targetClass: PsiClass, - private val selector: MixinSelector + private val selector: MixinSelector, ) : NavigationVisitor() { private fun visitMethodUsage(method: PsiMethod, qualifier: PsiClass?, expression: PsiElement) { @@ -132,28 +130,20 @@ class MethodInjectionPoint : AbstractMethodInjectionPoint() { private class MyCollectVisitor( mode: Mode, private val project: Project, - private val selector: MixinSelector + private val selector: MixinSelector, ) : CollectVisitor(mode) { override fun accept(methodNode: MethodNode) { val insns = methodNode.instructions ?: return insns.iterator().forEachRemaining { insn -> - if (insn !is MethodInsnNode) return@forEachRemaining - - if (mode != Mode.COMPLETION) { - if (!selector.matchMethod(insn.owner, insn.name, insn.desc)) { - return@forEachRemaining - } + if (insn !is MethodInsnNode) { + return@forEachRemaining } - val fakeMethod = insn.fakeResolve() + val sourceMethod = nodeMatchesSelector(insn, mode, selector, project) ?: return@forEachRemaining addResult( insn, - fakeMethod.method.findOrConstructSourceMethod( - fakeMethod.clazz, - project, - canDecompile = false - ), - qualifier = insn.owner.replace('/', '.') + sourceMethod, + qualifier = insn.owner.replace('/', '.'), ) } } diff --git a/src/main/kotlin/platform/mixin/handlers/injectionPoint/NewInsnInjectionPoint.kt b/src/main/kotlin/platform/mixin/handlers/injectionPoint/NewInsnInjectionPoint.kt index 14657cf5d..5f7a5d1bb 100644 --- a/src/main/kotlin/platform/mixin/handlers/injectionPoint/NewInsnInjectionPoint.kt +++ b/src/main/kotlin/platform/mixin/handlers/injectionPoint/NewInsnInjectionPoint.kt @@ -14,8 +14,6 @@ import com.demonwav.mcdev.platform.mixin.reference.MixinSelector import com.demonwav.mcdev.platform.mixin.reference.MixinSelectorParser import com.demonwav.mcdev.platform.mixin.reference.toMixinString import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Annotations.AT -import com.demonwav.mcdev.platform.mixin.util.fakeResolve -import com.demonwav.mcdev.platform.mixin.util.findOrConstructSourceMethod import com.demonwav.mcdev.platform.mixin.util.shortName import com.demonwav.mcdev.util.MemberReference import com.demonwav.mcdev.util.constantStringValue @@ -58,7 +56,7 @@ class NewInsnInjectionPoint : InjectionPoint() { override fun createNavigationVisitor( at: PsiAnnotation, target: MixinSelector?, - targetClass: PsiClass + targetClass: PsiClass, ): NavigationVisitor? { return getTarget(at, target)?.let { MyNavigationVisitor(it) } } @@ -67,7 +65,7 @@ class NewInsnInjectionPoint : InjectionPoint() { at: PsiAnnotation, target: MixinSelector?, targetClass: ClassNode, - mode: CollectVisitor.Mode + mode: CollectVisitor.Mode, ): CollectVisitor? { if (mode == CollectVisitor.Mode.COMPLETION) { return MyCollectVisitor(mode, at.project, MemberReference("")) @@ -87,7 +85,7 @@ class NewInsnInjectionPoint : InjectionPoint() { target, target.getQualifiedMemberReference(result.qualifier).toMixinString(), PsiSubstitutor.EMPTY, - null + null, ) .setBoldIfInClass(target, targetClass) .withPresentableText(ownerName + "." + target.internalName) @@ -98,7 +96,7 @@ class NewInsnInjectionPoint : InjectionPoint() { } private class MyNavigationVisitor( - private val selector: MixinSelector + private val selector: MixinSelector, ) : NavigationVisitor() { override fun visitNewExpression(expression: PsiNewExpression) { val anonymousName = expression.anonymousClass?.fullQualifiedName?.replace('.', '/') @@ -110,7 +108,7 @@ class NewInsnInjectionPoint : InjectionPoint() { val bytecodeArgTypes = if (thisType != null) listOf(thisType) + argTypes else argTypes val methodDesc = Type.getMethodDescriptor( Type.VOID_TYPE, - *bytecodeArgTypes.mapToArray { Type.getType(it) } + *bytecodeArgTypes.mapToArray { Type.getType(it) }, ) if (selector.matchMethod(anonymousName, "", methodDesc)) { addResult(expression) @@ -131,7 +129,7 @@ class NewInsnInjectionPoint : InjectionPoint() { private class MyCollectVisitor( mode: Mode, private val project: Project, - private val selector: MixinSelector + private val selector: MixinSelector, ) : CollectVisitor(mode) { override fun accept(methodNode: MethodNode) { val insns = methodNode.instructions ?: return @@ -139,21 +137,12 @@ class NewInsnInjectionPoint : InjectionPoint() { if (insn !is TypeInsnNode) return@forEachRemaining if (insn.opcode != Opcodes.NEW) return@forEachRemaining val initCall = findInitCall(insn) ?: return@forEachRemaining - if (mode != Mode.COMPLETION) { - if (!selector.matchMethod(initCall.owner, initCall.name, initCall.desc)) { - return@forEachRemaining - } - } - val targetMethod = initCall.fakeResolve() + val sourceMethod = nodeMatchesSelector(initCall, mode, selector, project) ?: return@forEachRemaining addResult( insn, - targetMethod.method.findOrConstructSourceMethod( - targetMethod.clazz, - project, - canDecompile = false - ), - qualifier = insn.desc.replace('/', '.') + sourceMethod, + qualifier = initCall.owner.replace('/', '.'), ) } } diff --git a/src/main/kotlin/platform/mixin/handlers/injectionPoint/ReturnInjectionPoint.kt b/src/main/kotlin/platform/mixin/handlers/injectionPoint/ReturnInjectionPoint.kt index 8add5a7e3..a39df9b3a 100644 --- a/src/main/kotlin/platform/mixin/handlers/injectionPoint/ReturnInjectionPoint.kt +++ b/src/main/kotlin/platform/mixin/handlers/injectionPoint/ReturnInjectionPoint.kt @@ -36,7 +36,7 @@ abstract class AbstractReturnInjectionPoint(private val tailOnly: Boolean) : Inj override fun createNavigationVisitor( at: PsiAnnotation, target: MixinSelector?, - targetClass: PsiClass + targetClass: PsiClass, ): NavigationVisitor { return MyNavigationVisitor(tailOnly) } @@ -45,14 +45,14 @@ abstract class AbstractReturnInjectionPoint(private val tailOnly: Boolean) : Inj at: PsiAnnotation, target: MixinSelector?, targetClass: ClassNode, - mode: CollectVisitor.Mode + mode: CollectVisitor.Mode, ): CollectVisitor { return MyCollectVisitor(at.project, mode, tailOnly) } override fun createLookup( targetClass: ClassNode, - result: CollectVisitor.Result + result: CollectVisitor.Result, ): LookupElementBuilder? { return null } @@ -116,7 +116,7 @@ abstract class AbstractReturnInjectionPoint(private val tailOnly: Boolean) : Inj private class MyCollectVisitor( private val project: Project, mode: Mode, - private val tailOnly: Boolean + private val tailOnly: Boolean, ) : CollectVisitor(mode) { override fun accept(methodNode: MethodNode) { val insns = methodNode.instructions ?: return diff --git a/src/main/kotlin/platform/mixin/insight/MixinEntryPoint.kt b/src/main/kotlin/platform/mixin/insight/MixinEntryPoint.kt index 3833375ae..2c7f98d11 100644 --- a/src/main/kotlin/platform/mixin/insight/MixinEntryPoint.kt +++ b/src/main/kotlin/platform/mixin/insight/MixinEntryPoint.kt @@ -12,6 +12,7 @@ package com.demonwav.mcdev.platform.mixin.insight import com.demonwav.mcdev.platform.mixin.handlers.InjectorAnnotationHandler import com.demonwav.mcdev.platform.mixin.handlers.MixinAnnotationHandler +import com.demonwav.mcdev.platform.mixin.util.isMixinEntryPoint import com.demonwav.mcdev.util.toTypedArray import com.intellij.codeInspection.reference.RefElement import com.intellij.codeInspection.visibility.EntryPointWithVisibilityLevel @@ -25,7 +26,7 @@ import org.jdom.Element class MixinEntryPoint : EntryPointWithVisibilityLevel() { @JvmField - var MIXIN_ENTRY_POINT = true + var mixinEntryPoint = true override fun getId() = "mixin" override fun getDisplayName() = "Mixin injectors" @@ -39,20 +40,7 @@ class MixinEntryPoint : EntryPointWithVisibilityLevel() { .map { (name, _) -> name } .toTypedArray() - override fun isEntryPoint(element: PsiElement): Boolean { - if (element !is PsiMethod) { - return false - } - val project = element.project - for (annotation in element.annotations) { - val qName = annotation.qualifiedName ?: continue - val handler = MixinAnnotationHandler.forMixinAnnotation(qName, project) - if (handler != null && handler.isEntryPoint) { - return true - } - } - return false - } + override fun isEntryPoint(element: PsiElement) = isMixinEntryPoint(element) override fun isEntryPoint(refElement: RefElement, psiElement: PsiElement) = isEntryPoint(psiElement) @@ -71,9 +59,9 @@ class MixinEntryPoint : EntryPointWithVisibilityLevel() { return -1 } - override fun isSelected() = MIXIN_ENTRY_POINT + override fun isSelected() = mixinEntryPoint override fun setSelected(selected: Boolean) { - MIXIN_ENTRY_POINT = selected + mixinEntryPoint = selected } override fun readExternal(element: Element) = XmlSerializer.serializeInto(this, element) diff --git a/src/main/kotlin/platform/mixin/insight/MixinLineMarkerProvider.kt b/src/main/kotlin/platform/mixin/insight/MixinLineMarkerProvider.kt index 42a442ddb..48a3fd591 100644 --- a/src/main/kotlin/platform/mixin/insight/MixinLineMarkerProvider.kt +++ b/src/main/kotlin/platform/mixin/insight/MixinLineMarkerProvider.kt @@ -47,7 +47,7 @@ class MixinLineMarkerProvider : LineMarkerProviderDescriptor(), GutterIconNaviga { "Go to target class" }, this, GutterIconRenderer.Alignment.LEFT, - { "mixin target class indicator" } + { "mixin target class indicator" }, ) } @@ -62,7 +62,7 @@ class MixinLineMarkerProvider : LineMarkerProviderDescriptor(), GutterIconNaviga targets.toTypedArray(), "Choose target class of $name", null, - PsiClassListCellRenderer() + PsiClassListCellRenderer(), ) } } diff --git a/src/main/kotlin/platform/mixin/insight/MixinTargetLineMarkerProvider.kt b/src/main/kotlin/platform/mixin/insight/MixinTargetLineMarkerProvider.kt index d707115b6..5da5322c9 100644 --- a/src/main/kotlin/platform/mixin/insight/MixinTargetLineMarkerProvider.kt +++ b/src/main/kotlin/platform/mixin/insight/MixinTargetLineMarkerProvider.kt @@ -70,14 +70,14 @@ class MixinTargetLineMarkerProvider : LineMarkerProviderDescriptor() { { "Go to the $simpleName target" }, MixinGutterIconNavigationHandler(identifier.createSmartPointer(), annotation.createSmartPointer(), handler), GutterIconRenderer.Alignment.LEFT, - { "mixin $simpleName target indicator" } + { "mixin $simpleName target indicator" }, ) } private class MixinGutterIconNavigationHandler( private val identifierPointer: SmartPsiElementPointer, private val annotationPointer: SmartPsiElementPointer, - private val handler: MixinAnnotationHandler + private val handler: MixinAnnotationHandler, ) : GutterIconNavigationHandler { override fun navigate(e: MouseEvent, elt: PsiIdentifier) { val element = identifierPointer.element ?: return @@ -92,7 +92,7 @@ class MixinTargetLineMarkerProvider : LineMarkerProviderDescriptor() { if (editor != null) { HintManager.getInstance().showErrorHint( editor, - "Cannot find corresponding element in source code" + "Cannot find corresponding element in source code", ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/MixinAnnotationAttributeInspection.kt b/src/main/kotlin/platform/mixin/inspection/MixinAnnotationAttributeInspection.kt index 57d2075c5..d18a99fcd 100644 --- a/src/main/kotlin/platform/mixin/inspection/MixinAnnotationAttributeInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/MixinAnnotationAttributeInspection.kt @@ -20,7 +20,7 @@ import com.intellij.psi.PsiNameValuePair abstract class MixinAnnotationAttributeInspection( private val annotation: String?, - private val attribute: String? + private val attribute: String?, ) : MixinInspection() { constructor(attribute: String?) : this(null, attribute) @@ -28,7 +28,7 @@ abstract class MixinAnnotationAttributeInspection( protected abstract fun visitAnnotationAttribute( annotation: PsiAnnotation, value: PsiAnnotationMemberValue, - holder: ProblemsHolder + holder: ProblemsHolder, ) final override fun buildVisitor(holder: ProblemsHolder): PsiElementVisitor = Visitor(holder) diff --git a/src/main/kotlin/platform/mixin/inspection/MixinAnnotationsInspection.kt b/src/main/kotlin/platform/mixin/inspection/MixinAnnotationsInspection.kt index da271b46e..4f218acc9 100644 --- a/src/main/kotlin/platform/mixin/inspection/MixinAnnotationsInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/MixinAnnotationsInspection.kt @@ -43,7 +43,7 @@ class MixinAnnotationsInspection : MixinInspection() { holder.registerProblem( annotation, "@${annotation.nameReferenceElement?.text} can be only used in a @Mixin class", - RemoveAnnotationQuickFix(annotation, null) + RemoveAnnotationQuickFix(annotation, null), ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/MixinCancellableInspection.kt b/src/main/kotlin/platform/mixin/inspection/MixinCancellableInspection.kt index bf0876def..501433e23 100644 --- a/src/main/kotlin/platform/mixin/inspection/MixinCancellableInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/MixinCancellableInspection.kt @@ -77,14 +77,14 @@ class MixinCancellableInspection : MixinInspection() { method.nameIdentifier ?: method, "@Inject must be marked as cancellable in order to be cancelled", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - MakeInjectCancellableFix(injectAnnotation) + MakeInjectCancellableFix(injectAnnotation), ) } else if (!definitelyUsesCancel && !mayUseCancel && isCancellable) { holder.registerProblem( cancellableAttribute.parent, "@Inject is cancellable but is never cancelled", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - RemoveInjectCancellableFix(injectAnnotation) + RemoveInjectCancellableFix(injectAnnotation), ) } } @@ -102,7 +102,7 @@ class MixinCancellableInspection : MixinInspection() { file: PsiFile, editor: Editor?, startElement: PsiElement, - endElement: PsiElement + endElement: PsiElement, ) { val annotation = startElement as PsiAnnotation val value = PsiElementFactory.getInstance(project).createExpressionFromText("true", annotation) @@ -122,7 +122,7 @@ class MixinCancellableInspection : MixinInspection() { file: PsiFile, editor: Editor?, startElement: PsiElement, - endElement: PsiElement + endElement: PsiElement, ) { val annotation = startElement as PsiAnnotation annotation.setDeclaredAttributeValue("cancellable", null) diff --git a/src/main/kotlin/platform/mixin/inspection/MixinInnerClassInspection.kt b/src/main/kotlin/platform/mixin/inspection/MixinInnerClassInspection.kt index 532d710bb..813620e82 100644 --- a/src/main/kotlin/platform/mixin/inspection/MixinInnerClassInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/MixinInnerClassInspection.kt @@ -35,7 +35,7 @@ class MixinInnerClassInspection : MixinInspection() { if (outerClass is PsiAnonymousClass && outerClass.parentOfType()?.isMixin == true) { holder.registerProblem( psiClass, - "Inner class not allowed inside anonymous classes inside mixins" + "Inner class not allowed inside anonymous classes inside mixins", ) } @@ -49,7 +49,7 @@ class MixinInnerClassInspection : MixinInspection() { holder.registerProblem( psiClass.modifierList!!, "@Mixin inner class must be static", - QuickFixFactory.getInstance().createModifierListFix(psiClass, PsiModifier.STATIC, true, false) + QuickFixFactory.getInstance().createModifierListFix(psiClass, PsiModifier.STATIC, true, false), ) } } else { diff --git a/src/main/kotlin/platform/mixin/inspection/MixinSuperClassInspection.kt b/src/main/kotlin/platform/mixin/inspection/MixinSuperClassInspection.kt index e95ec0469..cef78d659 100644 --- a/src/main/kotlin/platform/mixin/inspection/MixinSuperClassInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/MixinSuperClassInspection.kt @@ -55,7 +55,7 @@ class MixinSuperClassInspection : MixinInspection() { reportSuperClass( psiClass, "Cannot find '${superClass.shortName}' " + - "in the hierarchy of target class '${targetClass.shortName}'" + "in the hierarchy of target class '${targetClass.shortName}'", ) } } @@ -69,7 +69,7 @@ class MixinSuperClassInspection : MixinInspection() { ) { reportSuperClass( psiClass, - "Cannot find '${targetClass.shortName}' in the hierarchy of the super mixin" + "Cannot find '${targetClass.shortName}' in the hierarchy of the super mixin", ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/StaticMemberInspection.kt b/src/main/kotlin/platform/mixin/inspection/StaticMemberInspection.kt index f170ff62d..a54bc630a 100644 --- a/src/main/kotlin/platform/mixin/inspection/StaticMemberInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/StaticMemberInspection.kt @@ -47,7 +47,7 @@ class StaticMemberInspection : MixinInspection() { holder.registerProblem( member, "Public static members are not allowed in Mixin classes", - QuickFixFactory.getInstance().createModifierListFix(member, PsiModifier.PRIVATE, true, false) + QuickFixFactory.getInstance().createModifierListFix(member, PsiModifier.PRIVATE, true, false), ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/UnusedMixinInspection.kt b/src/main/kotlin/platform/mixin/inspection/UnusedMixinInspection.kt index 1bd1cc781..7ccef5665 100644 --- a/src/main/kotlin/platform/mixin/inspection/UnusedMixinInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/UnusedMixinInspection.kt @@ -57,7 +57,7 @@ class UnusedMixinInspection : MixinInspection() { val bestQuickFixConfig = MixinModule.getBestWritableConfigForMixinClass( module.project, GlobalSearchScope.moduleScope(module), - clazz.fullQualifiedName ?: "" + clazz.fullQualifiedName ?: "", ) val problematicElement = clazz.nameIdentifier if (problematicElement != null) { @@ -84,7 +84,7 @@ class UnusedMixinInspection : MixinInspection() { private class QuickFix( private val quickFixFile: VirtualFile, private val qualifiedName: String, - private val side: Side + private val side: Side, ) : LocalQuickFix { private val sideDisplayName = when (side) { diff --git a/src/main/kotlin/platform/mixin/inspection/implements/DuplicateInterfaceInspection.kt b/src/main/kotlin/platform/mixin/inspection/implements/DuplicateInterfaceInspection.kt index 27a768a33..797e6cf18 100644 --- a/src/main/kotlin/platform/mixin/inspection/implements/DuplicateInterfaceInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/implements/DuplicateInterfaceInspection.kt @@ -29,7 +29,7 @@ class DuplicateInterfaceInspection : MixinAnnotationAttributeInspection(MixinCon override fun visitAnnotationAttribute( annotation: PsiAnnotation, value: PsiAnnotationMemberValue, - holder: ProblemsHolder + holder: ProblemsHolder, ) { val interfaces = value.findAnnotations().ifEmpty { return } diff --git a/src/main/kotlin/platform/mixin/inspection/implements/DuplicateInterfacePrefixInspection.kt b/src/main/kotlin/platform/mixin/inspection/implements/DuplicateInterfacePrefixInspection.kt index b59792e64..a8bccd5a1 100644 --- a/src/main/kotlin/platform/mixin/inspection/implements/DuplicateInterfacePrefixInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/implements/DuplicateInterfacePrefixInspection.kt @@ -26,7 +26,7 @@ class DuplicateInterfacePrefixInspection : MixinAnnotationAttributeInspection(IM override fun visitAnnotationAttribute( annotation: PsiAnnotation, value: PsiAnnotationMemberValue, - holder: ProblemsHolder + holder: ProblemsHolder, ) { val interfaces = value.findAnnotations().ifEmpty { return } diff --git a/src/main/kotlin/platform/mixin/inspection/implements/EmptyImplementsInspection.kt b/src/main/kotlin/platform/mixin/inspection/implements/EmptyImplementsInspection.kt index c87926dd0..363c73427 100644 --- a/src/main/kotlin/platform/mixin/inspection/implements/EmptyImplementsInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/implements/EmptyImplementsInspection.kt @@ -33,11 +33,11 @@ class EmptyImplementsInspection : MixinInspection() { } val interfaces = annotation.findDeclaredAttributeValue(null)?.findAnnotations() - if (interfaces == null || interfaces.isEmpty()) { + if (interfaces.isNullOrEmpty()) { holder.registerProblem( annotation, "@Implements is redundant", - RemoveAnnotationQuickFix(annotation, null) + RemoveAnnotationQuickFix(annotation, null), ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/implements/InterfaceIsInterfaceInspection.kt b/src/main/kotlin/platform/mixin/inspection/implements/InterfaceIsInterfaceInspection.kt index f277eef9f..f9ed85ffd 100644 --- a/src/main/kotlin/platform/mixin/inspection/implements/InterfaceIsInterfaceInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/implements/InterfaceIsInterfaceInspection.kt @@ -24,7 +24,7 @@ class InterfaceIsInterfaceInspection : MixinAnnotationAttributeInspection(INTERF override fun visitAnnotationAttribute( annotation: PsiAnnotation, value: PsiAnnotationMemberValue, - holder: ProblemsHolder + holder: ProblemsHolder, ) { val psiClass = value.resolveClass() ?: return if (!psiClass.isInterface) { diff --git a/src/main/kotlin/platform/mixin/inspection/implements/InterfacePrefixInspection.kt b/src/main/kotlin/platform/mixin/inspection/implements/InterfacePrefixInspection.kt index 8c2ba6b79..5f8859912 100644 --- a/src/main/kotlin/platform/mixin/inspection/implements/InterfacePrefixInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/implements/InterfacePrefixInspection.kt @@ -25,7 +25,7 @@ class InterfacePrefixInspection : MixinAnnotationAttributeInspection(INTERFACE, override fun visitAnnotationAttribute( annotation: PsiAnnotation, value: PsiAnnotationMemberValue, - holder: ProblemsHolder + holder: ProblemsHolder, ) { val prefix = value.constantStringValue ?: return if (!prefix.endsWith('$')) { diff --git a/src/main/kotlin/platform/mixin/inspection/implements/SoftImplementOverridesInspection.kt b/src/main/kotlin/platform/mixin/inspection/implements/SoftImplementOverridesInspection.kt index 98b75196f..f0bb7f40e 100644 --- a/src/main/kotlin/platform/mixin/inspection/implements/SoftImplementOverridesInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/implements/SoftImplementOverridesInspection.kt @@ -30,7 +30,7 @@ class SoftImplementOverridesInspection : MixinInspection() { if (method.isSoftImplementMissingParent()) { holder.registerProblem( method.nameIdentifier ?: method, - "Method does not soft-implement a method from its interfaces" + "Method does not soft-implement a method from its interfaces", ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/injector/ImplicitConstructorInvokerInspection.kt b/src/main/kotlin/platform/mixin/inspection/injector/ImplicitConstructorInvokerInspection.kt index 42730e985..c133a7752 100644 --- a/src/main/kotlin/platform/mixin/inspection/injector/ImplicitConstructorInvokerInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/injector/ImplicitConstructorInvokerInspection.kt @@ -36,7 +36,7 @@ class ImplicitConstructorInvokerInspection : MixinInspection() { holder.registerProblem( invokerAnnotation.nameReferenceElement ?: return, "Implicit constructor invokers should be explicit (fails outside of dev)", - ImplicitConstructorInvokerQuickFix(invokerAnnotation) + ImplicitConstructorInvokerQuickFix(invokerAnnotation), ) } } @@ -47,7 +47,7 @@ class ImplicitConstructorInvokerInspection : MixinInspection() { override fun getStaticDescription() = "Implicit constructor invoker (fails outside of dev)" private class ImplicitConstructorInvokerQuickFix( - annotation: PsiAnnotation + annotation: PsiAnnotation, ) : LocalQuickFixOnPsiElement(annotation) { override fun getFamilyName() = "Make constructor invoker explicit" override fun getText() = "Make constructor invoker explicit" diff --git a/src/main/kotlin/platform/mixin/inspection/injector/InjectIntoConstructorInspection.kt b/src/main/kotlin/platform/mixin/inspection/injector/InjectIntoConstructorInspection.kt index 1288d8d8d..6108e6fd5 100644 --- a/src/main/kotlin/platform/mixin/inspection/injector/InjectIntoConstructorInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/injector/InjectIntoConstructorInspection.kt @@ -32,13 +32,13 @@ import org.objectweb.asm.Opcodes class InjectIntoConstructorInspection : MixinInspection() { @JvmField - var ALLOW_ON_FABRIC = true + var allowOnFabric = true override fun createOptionsPanel(): JComponent { val panel = JPanel(FlowLayout(FlowLayout.LEFT)) - val checkbox = JCheckBox("Allow @Inject into constructors in Fabric", ALLOW_ON_FABRIC) + val checkbox = JCheckBox("Allow @Inject into constructors in Fabric", allowOnFabric) checkbox.addActionListener { - ALLOW_ON_FABRIC = checkbox.isSelected + allowOnFabric = checkbox.isSelected } panel.add(checkbox) return panel @@ -47,7 +47,7 @@ class InjectIntoConstructorInspection : MixinInspection() { override fun buildVisitor(holder: ProblemsHolder): PsiElementVisitor { val isFabric = holder.file.findModule()?.let { MinecraftFacet.getInstance(it) }?.isOfType(FabricModuleType) ?: false - if (isFabric && ALLOW_ON_FABRIC) { + if (isFabric && allowOnFabric) { return PsiElementVisitor.EMPTY_VISITOR } @@ -67,7 +67,7 @@ class InjectIntoConstructorInspection : MixinInspection() { if (instructions.any { it.insn.opcode != Opcodes.RETURN }) { holder.registerProblem( problemElement, - "Cannot inject into constructors at non-return instructions" + "Cannot inject into constructors at non-return instructions", ) return } diff --git a/src/main/kotlin/platform/mixin/inspection/injector/InvalidInjectorMethodSignatureInspection.kt b/src/main/kotlin/platform/mixin/inspection/injector/InvalidInjectorMethodSignatureInspection.kt index 9ab912cfd..5bf7f5aca 100644 --- a/src/main/kotlin/platform/mixin/inspection/injector/InvalidInjectorMethodSignatureInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/injector/InvalidInjectorMethodSignatureInspection.kt @@ -20,9 +20,11 @@ import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Annotations.COERCE import com.demonwav.mcdev.platform.mixin.util.hasAccess import com.demonwav.mcdev.platform.mixin.util.isAssignable import com.demonwav.mcdev.platform.mixin.util.isConstructor +import com.demonwav.mcdev.platform.mixin.util.isMixinExtrasSugar import com.demonwav.mcdev.util.Parameter import com.demonwav.mcdev.util.fullQualifiedName import com.demonwav.mcdev.util.synchronize +import com.intellij.codeInsight.intention.FileModifier.SafeFieldForPreview import com.intellij.codeInsight.intention.QuickFixFactory import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemDescriptor @@ -79,7 +81,7 @@ class InvalidInjectorMethodSignatureInspection : MixinInspection() { val insns = handler.resolveInstructions( annotation, targetMethod.clazz, - targetMethod.method + targetMethod.method, ) shouldBeStatic = insns.any { methodInsns.indexOf(it.insn) <= methodInsns.indexOf(superCtorCall) @@ -96,8 +98,8 @@ class InvalidInjectorMethodSignatureInspection : MixinInspection() { modifiers, PsiModifier.STATIC, true, - false - ) + false, + ), ) } } @@ -108,7 +110,7 @@ class InvalidInjectorMethodSignatureInspection : MixinInspection() { val possibleSignatures = handler.expectedMethodSignature( annotation, targetMethod.clazz, - targetMethod.method + targetMethod.method, ) ?: continue val annotationName = annotation.nameReferenceElement?.referenceName @@ -117,7 +119,7 @@ class InvalidInjectorMethodSignatureInspection : MixinInspection() { reportedSignature = true holder.registerProblem( parameters, - "There are no possible signatures for this injector" + "There are no possible signatures for this injector", ) continue } @@ -148,7 +150,7 @@ class InvalidInjectorMethodSignatureInspection : MixinInspection() { "Method parameters do not match expected parameters for $annotationName" val quickFix = ParametersQuickFix( expectedParameters, - handler is InjectAnnotationHandler + handler is InjectAnnotationHandler, ) if (checkResult == CheckResult.ERROR) { holder.registerProblem(parameters, description, quickFix) @@ -157,7 +159,7 @@ class InvalidInjectorMethodSignatureInspection : MixinInspection() { parameters, description, ProblemHighlightType.WARNING, - quickFix + quickFix, ) } } @@ -175,8 +177,8 @@ class InvalidInjectorMethodSignatureInspection : MixinInspection() { QuickFixFactory.getInstance().createMethodReturnFix( method, expectedReturnType, - false - ) + false, + ), ) } } @@ -210,7 +212,7 @@ class InvalidInjectorMethodSignatureInspection : MixinInspection() { expectedReturnType: PsiType, methodReturnType: PsiType, method: PsiMethod, - allowCoerce: Boolean + allowCoerce: Boolean, ): Boolean { val expectedErasure = TypeConversionUtil.erasure(expectedReturnType) val returnErasure = TypeConversionUtil.erasure(methodReturnType) @@ -229,14 +231,15 @@ class InvalidInjectorMethodSignatureInspection : MixinInspection() { private fun checkParameters( parameterList: PsiParameterList, expected: List, - allowCoerce: Boolean + allowCoerce: Boolean, ): CheckResult { val parameters = parameterList.parameters + val parametersWithoutSugar = parameters.dropLastWhile { it.isMixinExtrasSugar }.toTypedArray() var pos = 0 for (group in expected) { // Check if parameter group matches - if (group.match(parameters, pos, allowCoerce)) { + if (group.match(parametersWithoutSugar, pos, allowCoerce)) { pos += group.size } else if (group.required != ParameterGroup.RequiredLevel.OPTIONAL) { return if (group.required == ParameterGroup.RequiredLevel.ERROR_IF_ABSENT) { @@ -247,6 +250,15 @@ class InvalidInjectorMethodSignatureInspection : MixinInspection() { } } + // Sugars are valid on any injector and should be ignored, as long as they're at the end. + while (pos < parameters.size) { + if (parameters[pos].isMixinExtrasSugar) { + pos++ + } else { + break + } + } + // check we have consumed all the parameters if (pos < parameters.size) { return if ( @@ -268,8 +280,9 @@ class InvalidInjectorMethodSignatureInspection : MixinInspection() { } private class ParametersQuickFix( + @SafeFieldForPreview private val expected: List, - isInject: Boolean + isInject: Boolean, ) : LocalQuickFix { private val fixName = if (isInject) { @@ -288,6 +301,11 @@ class InvalidInjectorMethodSignatureInspection : MixinInspection() { return@dropWhile fqname != MixinConstants.Classes.CALLBACK_INFO && fqname != MixinConstants.Classes.CALLBACK_INFO_RETURNABLE }.drop(1) // the first element in the list is the CallbackInfo but we don't want it + .takeWhile { !it.isMixinExtrasSugar } + + // We want to preserve sugars, and while we're at it, we might as well move them all to the end + val sugars = parameters.parameters.filter { it.isMixinExtrasSugar } + val newParams = expected.flatMapTo(mutableListOf()) { if (it.default) { it.parameters.mapIndexed { i: Int, p: Parameter -> @@ -295,15 +313,16 @@ class InvalidInjectorMethodSignatureInspection : MixinInspection() { p.name ?: JavaCodeStyleManager.getInstance(project) .suggestVariableName(VariableKind.PARAMETER, null, null, p.type).names .firstOrNull() ?: "var$i", - p.type + p.type, ) } } else { emptyList() } } - // Restore the captured locals before applying the fix + // Restore the captured locals and sugars before applying the fix newParams.addAll(locals) + newParams.addAll(sugars) parameters.synchronize(newParams) } } diff --git a/src/main/kotlin/platform/mixin/inspection/injector/ParameterGroup.kt b/src/main/kotlin/platform/mixin/inspection/injector/ParameterGroup.kt index 53322d964..3eb295aa0 100644 --- a/src/main/kotlin/platform/mixin/inspection/injector/ParameterGroup.kt +++ b/src/main/kotlin/platform/mixin/inspection/injector/ParameterGroup.kt @@ -22,7 +22,7 @@ data class ParameterGroup( val parameters: List, val required: RequiredLevel = RequiredLevel.ERROR_IF_ABSENT, val default: Boolean = required != RequiredLevel.OPTIONAL, - val isVarargs: Boolean = false + val isVarargs: Boolean = false, ) { val size diff --git a/src/main/kotlin/platform/mixin/inspection/overwrite/OverwriteAuthorInspection.kt b/src/main/kotlin/platform/mixin/inspection/overwrite/OverwriteAuthorInspection.kt index 54e8f4f02..41d009061 100644 --- a/src/main/kotlin/platform/mixin/inspection/overwrite/OverwriteAuthorInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/overwrite/OverwriteAuthorInspection.kt @@ -47,7 +47,7 @@ class OverwriteAuthorInspection : OverwriteInspection() { holder.registerProblem( element, "@Overwrite methods must have an associated JavaDoc with a filled in @$tag tag", - QuickFix(tag) + QuickFix(tag), ) } @@ -55,7 +55,7 @@ class OverwriteAuthorInspection : OverwriteInspection() { holder.registerProblem( element, "@Overwrite methods must have an associated JavaDoc with filled in @author and @reason tags", - QuickFix() + QuickFix(), ) } @@ -75,7 +75,7 @@ class OverwriteAuthorInspection : OverwriteInspection() { method.addBefore( JavaPsiFacade.getElementFactory(project) .createDocCommentFromText("/**\n * @author \n * @reason \n */"), - method.modifierList + method.modifierList, ) return } diff --git a/src/main/kotlin/platform/mixin/inspection/overwrite/OverwriteModifiersInspection.kt b/src/main/kotlin/platform/mixin/inspection/overwrite/OverwriteModifiersInspection.kt index b868ffd7b..678f6a10c 100644 --- a/src/main/kotlin/platform/mixin/inspection/overwrite/OverwriteModifiersInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/overwrite/OverwriteModifiersInspection.kt @@ -53,7 +53,7 @@ class OverwriteModifiersInspection : OverwriteInspection() { modifierList.findKeyword(currentModifier) ?: nameIdentifier, "$currentModifier @Overwrite cannot reduce visibility of " + "${PsiUtil.getAccessModifier(targetAccessLevel)} target method", - QuickFixFactory.getInstance().createModifierListFix(modifierList, targetModifier, true, false) + QuickFixFactory.getInstance().createModifierListFix(modifierList, targetModifier, true, false), ) } @@ -82,7 +82,7 @@ class OverwriteModifiersInspection : OverwriteInspection() { holder.registerProblem( marker, message, - QuickFixFactory.getInstance().createModifierListFix(modifierList, modifier, targetModifier, false) + QuickFixFactory.getInstance().createModifierListFix(modifierList, modifier, targetModifier, false), ) } } @@ -101,13 +101,13 @@ class OverwriteModifiersInspection : OverwriteInspection() { nameIdentifier, "Missing @${internalNameToShortName(internalName)} annotation", ProblemHighlightType.WARNING, - AddAnnotationFix(qualifiedName, method, targetAnnPsi.parameterList.attributes) + AddAnnotationFix(qualifiedName, method, targetAnnPsi.parameterList.attributes), ) } else { holder.registerProblem( nameIdentifier, "Missing @${internalNameToShortName(internalName)} annotation", - ProblemHighlightType.WARNING + ProblemHighlightType.WARNING, ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/reference/AmbiguousReferenceInspection.kt b/src/main/kotlin/platform/mixin/inspection/reference/AmbiguousReferenceInspection.kt index f3ca1be89..e64136b92 100644 --- a/src/main/kotlin/platform/mixin/inspection/reference/AmbiguousReferenceInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/reference/AmbiguousReferenceInspection.kt @@ -34,7 +34,7 @@ class AmbiguousReferenceInspection : MixinAnnotationAttributeInspection("method" override fun visitAnnotationAttribute( annotation: PsiAnnotation, value: PsiAnnotationMemberValue, - holder: ProblemsHolder + holder: ProblemsHolder, ) { val qName = annotation.qualifiedName ?: return val handler = MixinAnnotationHandler.forMixinAnnotation(qName, annotation.project) @@ -57,7 +57,7 @@ class AmbiguousReferenceInspection : MixinAnnotationAttributeInspection("method" holder.registerProblem( value, "Ambiguous reference to method '${ambiguousReference.name}' in target class", - QuickFix + QuickFix, ) } diff --git a/src/main/kotlin/platform/mixin/inspection/reference/InvalidMemberReferenceInspection.kt b/src/main/kotlin/platform/mixin/inspection/reference/InvalidMemberReferenceInspection.kt index f8489645c..195403226 100644 --- a/src/main/kotlin/platform/mixin/inspection/reference/InvalidMemberReferenceInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/reference/InvalidMemberReferenceInspection.kt @@ -33,7 +33,7 @@ class InvalidMemberReferenceInspection : MixinInspection() { |Reports invalid usages of member references in Mixin annotations. Two different formats are supported by Mixin: | - Lcom/example/ExampleClass;execute(II)V | - com.example.ExampleClass.execute(II)V - """.trimMargin() + """.trimMargin() override fun buildVisitor(holder: ProblemsHolder): PsiElementVisitor = Visitor(holder) diff --git a/src/main/kotlin/platform/mixin/inspection/reference/UnnecessaryQualifiedMemberReferenceInspection.kt b/src/main/kotlin/platform/mixin/inspection/reference/UnnecessaryQualifiedMemberReferenceInspection.kt index 7e1198b51..c504d1fab 100644 --- a/src/main/kotlin/platform/mixin/inspection/reference/UnnecessaryQualifiedMemberReferenceInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/reference/UnnecessaryQualifiedMemberReferenceInspection.kt @@ -33,7 +33,7 @@ class UnnecessaryQualifiedMemberReferenceInspection : MixinAnnotationAttributeIn override fun visitAnnotationAttribute( annotation: PsiAnnotation, value: PsiAnnotationMemberValue, - holder: ProblemsHolder + holder: ProblemsHolder, ) { val qName = annotation.qualifiedName ?: return if (MixinAnnotationHandler.forMixinAnnotation(qName, annotation.project) !is InjectorAnnotationHandler) { @@ -52,7 +52,7 @@ class UnnecessaryQualifiedMemberReferenceInspection : MixinAnnotationAttributeIn holder.registerProblem( value, "Unnecessary qualified reference to '${selector.displayName}' in target class", - QuickFix(selector) + QuickFix(selector), ) } } @@ -65,7 +65,7 @@ class UnnecessaryQualifiedMemberReferenceInspection : MixinAnnotationAttributeIn val element = descriptor.psiElement element.replace( JavaPsiFacade.getElementFactory(project) - .createExpressionFromText("\"${reference.withoutOwner.toMixinString()}\"", element) + .createExpressionFromText("\"${reference.withoutOwner.toMixinString()}\"", element), ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/reference/UnqualifiedMemberReferenceInspection.kt b/src/main/kotlin/platform/mixin/inspection/reference/UnqualifiedMemberReferenceInspection.kt index b7f667f32..dfe4a5371 100644 --- a/src/main/kotlin/platform/mixin/inspection/reference/UnqualifiedMemberReferenceInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/reference/UnqualifiedMemberReferenceInspection.kt @@ -25,7 +25,7 @@ class UnqualifiedMemberReferenceInspection : MixinAnnotationAttributeInspection( override fun visitAnnotationAttribute( annotation: PsiAnnotation, value: PsiAnnotationMemberValue, - holder: ProblemsHolder + holder: ProblemsHolder, ) { // Check if the specified target reference uses member descriptors if (!AtResolver.usesMemberReference(annotation)) { diff --git a/src/main/kotlin/platform/mixin/inspection/reference/UnresolvedReferenceInspection.kt b/src/main/kotlin/platform/mixin/inspection/reference/UnresolvedReferenceInspection.kt index a4fc8f56a..76b47beb9 100644 --- a/src/main/kotlin/platform/mixin/inspection/reference/UnresolvedReferenceInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/reference/UnresolvedReferenceInspection.kt @@ -36,8 +36,7 @@ class UnresolvedReferenceInspection : MixinInspection() { private class Visitor(private val holder: ProblemsHolder) : JavaElementVisitor() { override fun visitNameValuePair(pair: PsiNameValuePair) { - val name = pair.name ?: PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME - val resolvers: Array = when (name) { + val resolvers: Array = when (pair.name ?: PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME) { "method" -> arrayOf(MethodReference) "target" -> arrayOf(TargetReference) "value" -> arrayOf(InjectionPointReference, DescReference) @@ -63,7 +62,7 @@ class UnresolvedReferenceInspection : MixinInspection() { holder.registerProblem( value, "Cannot resolve ${resolver.description}".format(value.constantStringValue), - ProblemHighlightType.LIKE_UNKNOWN_SYMBOL + ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/shadow/ShadowFieldPrefixInspection.kt b/src/main/kotlin/platform/mixin/inspection/shadow/ShadowFieldPrefixInspection.kt index d2799a570..1b563e6d1 100644 --- a/src/main/kotlin/platform/mixin/inspection/shadow/ShadowFieldPrefixInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/shadow/ShadowFieldPrefixInspection.kt @@ -52,8 +52,8 @@ class ShadowFieldPrefixInspection : MixinInspection() { "Cannot use prefix for @Shadow fields", QuickFixFactory.getInstance().createRenameElementFix( field, - fieldName.removePrefix(DEFAULT_SHADOW_PREFIX) - ) + fieldName.removePrefix(DEFAULT_SHADOW_PREFIX), + ), ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/shadow/ShadowFinalInspection.kt b/src/main/kotlin/platform/mixin/inspection/shadow/ShadowFinalInspection.kt index 69acce2c3..20252d9e7 100644 --- a/src/main/kotlin/platform/mixin/inspection/shadow/ShadowFinalInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/shadow/ShadowFinalInspection.kt @@ -40,7 +40,7 @@ class ShadowFinalInspection : MixinInspection() { holder.registerProblem( expression, "@Final fields cannot be modified", - AddAnnotationFix(MUTABLE, resolved) + AddAnnotationFix(MUTABLE, resolved), ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/shadow/ShadowModifiersInspection.kt b/src/main/kotlin/platform/mixin/inspection/shadow/ShadowModifiersInspection.kt index 466b60d04..89f0c8e29 100644 --- a/src/main/kotlin/platform/mixin/inspection/shadow/ShadowModifiersInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/shadow/ShadowModifiersInspection.kt @@ -70,8 +70,8 @@ class ShadowModifiersInspection : MixinInspection() { shadowModifierList, PsiModifier.STATIC, targetStatic, - false - ) + false, + ), ) } @@ -85,7 +85,8 @@ class ShadowModifiersInspection : MixinInspection() { shadowModifierList.findKeyword(shadowModifier) ?: annotation, "Invalid access modifiers, has: $shadowModifier, but target member has: " + PsiUtil.getAccessModifier(targetAccessLevel), - QuickFixFactory.getInstance().createModifierListFix(shadowModifierList, targetModifier, true, false) + QuickFixFactory.getInstance() + .createModifierListFix(shadowModifierList, targetModifier, true, false) ) } @@ -102,13 +103,13 @@ class ShadowModifiersInspection : MixinInspection() { holder.registerProblem( annotation, "@Shadow for final member should be annotated as @Final", - AddAnnotationFix(FINAL, member) + AddAnnotationFix(FINAL, member), ) } else { holder.registerProblem( shadowFinal!!, "Target method is not final", - RemoveAnnotationQuickFix(shadowFinal, member) + RemoveAnnotationQuickFix(shadowFinal, member), ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/shadow/UnusedShadowMethodPrefixInspection.kt b/src/main/kotlin/platform/mixin/inspection/shadow/UnusedShadowMethodPrefixInspection.kt index d64a65fd5..ddcf3dc7e 100644 --- a/src/main/kotlin/platform/mixin/inspection/shadow/UnusedShadowMethodPrefixInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/shadow/UnusedShadowMethodPrefixInspection.kt @@ -37,7 +37,7 @@ class UnusedShadowMethodPrefixInspection : MixinInspection() { holder.registerProblem( prefixValue, "Unused @Shadow prefix", - RemoveAnnotationAttributeQuickFix("@Shadow", "prefix") + RemoveAnnotationAttributeQuickFix("@Shadow", "prefix"), ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/suppress/DefaultAnnotationParamInspectionSuppressor.kt b/src/main/kotlin/platform/mixin/inspection/suppress/DefaultAnnotationParamInspectionSuppressor.kt index 3f38648a5..2ecce52c6 100644 --- a/src/main/kotlin/platform/mixin/inspection/suppress/DefaultAnnotationParamInspectionSuppressor.kt +++ b/src/main/kotlin/platform/mixin/inspection/suppress/DefaultAnnotationParamInspectionSuppressor.kt @@ -82,7 +82,7 @@ class DefaultAnnotationParamInspectionSuppressor : InspectionSuppressor { REDIRECT, ACCESSOR, INVOKER, - MIXIN + MIXIN, ) private val CONSTANT_SUPPRESSED = setOf( "intValue", @@ -90,7 +90,7 @@ class DefaultAnnotationParamInspectionSuppressor : InspectionSuppressor { "longValue", "doubleValue", "stringValue", - "classValue" + "classValue", ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/suppress/DynamicInspectionSuppressor.kt b/src/main/kotlin/platform/mixin/inspection/suppress/DynamicInspectionSuppressor.kt index 1beb43e86..bdc674e9e 100644 --- a/src/main/kotlin/platform/mixin/inspection/suppress/DynamicInspectionSuppressor.kt +++ b/src/main/kotlin/platform/mixin/inspection/suppress/DynamicInspectionSuppressor.kt @@ -27,7 +27,7 @@ class DynamicInspectionSuppressor : InspectionSuppressor { "ShadowModifiers", "UnqualifiedMemberReference", "UnnecessaryQualifiedMemberReference", - "UnresolvedMixinReference" + "UnresolvedMixinReference", ) override fun isSuppressedFor(element: PsiElement, toolId: String): Boolean { diff --git a/src/main/kotlin/platform/mixin/inspection/suppress/ShadowOverwriteInspectionSuppressor.kt b/src/main/kotlin/platform/mixin/inspection/suppress/ShadowOverwriteInspectionSuppressor.kt index 4add503aa..37dc210a0 100644 --- a/src/main/kotlin/platform/mixin/inspection/suppress/ShadowOverwriteInspectionSuppressor.kt +++ b/src/main/kotlin/platform/mixin/inspection/suppress/ShadowOverwriteInspectionSuppressor.kt @@ -21,14 +21,6 @@ import com.intellij.psi.PsiMethod class ShadowOverwriteInspectionSuppressor : InspectionSuppressor { - private val SUPPRESSED_INSPECTIONS = setOf( - "UnusedReturnValue", - "SameParameterValue", - "Guava", - VisibilityInspection.SHORT_NAME, - "MethodMayBeStatic" - ) - override fun isSuppressedFor(element: PsiElement, toolId: String): Boolean { if (toolId !in SUPPRESSED_INSPECTIONS) { return false @@ -40,4 +32,14 @@ class ShadowOverwriteInspectionSuppressor : InspectionSuppressor { override fun getSuppressActions(element: PsiElement?, toolId: String): Array = SuppressQuickFix.EMPTY_ARRAY + + companion object { + private val SUPPRESSED_INSPECTIONS = setOf( + "UnusedReturnValue", + "SameParameterValue", + "Guava", + VisibilityInspection.SHORT_NAME, + "MethodMayBeStatic", + ) + } } diff --git a/src/main/kotlin/platform/mixin/reference/AbstractMethodReference.kt b/src/main/kotlin/platform/mixin/reference/AbstractMethodReference.kt index ad08c1f77..efff77c3e 100644 --- a/src/main/kotlin/platform/mixin/reference/AbstractMethodReference.kt +++ b/src/main/kotlin/platform/mixin/reference/AbstractMethodReference.kt @@ -112,7 +112,7 @@ abstract class AbstractMethodReference : PolyReferenceResolver(), MixinReference private fun resolve( targets: Collection, - selector: MixinSelector + selector: MixinSelector, ): Sequence { return targets.asSequence() .flatMap { target -> target.findMethods(selector).map { ClassAndMethodNode(target, it) } } @@ -135,7 +135,7 @@ abstract class AbstractMethodReference : PolyReferenceResolver(), MixinReference val targetReference = parseSelector(method, context) ?: return@flatMap emptySequence() if (targetReference is MemberReference && targetReference.descriptor == null && isAmbiguous( targets, - targetReference + targetReference, ) ) { return@flatMap emptySequence() @@ -150,7 +150,7 @@ abstract class AbstractMethodReference : PolyReferenceResolver(), MixinReference it.clazz, context.project, scope = context.resolveScope, - canDecompile = true + canDecompile = true, ) }?.toTypedArray() } @@ -161,7 +161,7 @@ abstract class AbstractMethodReference : PolyReferenceResolver(), MixinReference it.clazz, context.project, scope = context.resolveScope, - canDecompile = false + canDecompile = false, ) }?.toResolveResults() ?: ResolveResult.EMPTY_ARRAY } @@ -227,7 +227,7 @@ abstract class AbstractMethodReference : PolyReferenceResolver(), MixinReference private fun createLookup( context: PsiElement, methods: Sequence, - uniqueMethods: Set + uniqueMethods: Set, ): Array { return methods .map { m -> @@ -241,13 +241,13 @@ abstract class AbstractMethodReference : PolyReferenceResolver(), MixinReference m.clazz, context.project, scope = context.resolveScope, - canDecompile = false + canDecompile = false, ) val builder = JavaLookupElementBuilder.forMethod( sourceMethod, targetMethodInfo.toMixinString(), PsiSubstitutor.EMPTY, - null + null, ) .withPresentableText(m.method.name) addCompletionInfo(builder, context, targetMethodInfo) @@ -259,7 +259,7 @@ abstract class AbstractMethodReference : PolyReferenceResolver(), MixinReference open fun addCompletionInfo( builder: LookupElementBuilder, context: PsiElement, - targetMethodInfo: MemberReference + targetMethodInfo: MemberReference, ): LookupElementBuilder { return builder.completeToLiteral(context) } diff --git a/src/main/kotlin/platform/mixin/reference/DescGTDHandler.kt b/src/main/kotlin/platform/mixin/reference/DescGTDHandler.kt index 2158b6b81..74ec02fd4 100644 --- a/src/main/kotlin/platform/mixin/reference/DescGTDHandler.kt +++ b/src/main/kotlin/platform/mixin/reference/DescGTDHandler.kt @@ -20,7 +20,7 @@ class DescGTDHandler : GotoDeclarationHandler { override fun getGotoDeclarationTargets( sourceElement: PsiElement?, offset: Int, - editor: Editor? + editor: Editor?, ): Array? { if (sourceElement == null) return null val stringLiteral = sourceElement.parentOfType() ?: return null diff --git a/src/main/kotlin/platform/mixin/reference/DescReference.kt b/src/main/kotlin/platform/mixin/reference/DescReference.kt index d2ed5de43..67fb94e73 100644 --- a/src/main/kotlin/platform/mixin/reference/DescReference.kt +++ b/src/main/kotlin/platform/mixin/reference/DescReference.kt @@ -38,7 +38,7 @@ import org.objectweb.asm.tree.ClassNode object DescReference : AbstractMethodReference() { val ELEMENT_PATTERN: ElementPattern = PsiJavaPatterns.psiLiteral(StandardPatterns.string()).insideAnnotationParam( - StandardPatterns.string().equalTo(DESC) + StandardPatterns.string().equalTo(DESC), ) override val description = "method '%s'" @@ -59,7 +59,7 @@ object DescReference : AbstractMethodReference() { override fun addCompletionInfo( builder: LookupElementBuilder, context: PsiElement, - targetMethodInfo: MemberReference + targetMethodInfo: MemberReference, ): LookupElementBuilder { return builder.withInsertHandler { insertionContext, _ -> insertionContext.laterRunnable = @@ -72,11 +72,11 @@ object DescReference : AbstractMethodReference() { private class CompleteDescReference( private val editor: Editor, private val file: PsiFile, - private val targetMethodInfo: MemberReference + private val targetMethodInfo: MemberReference, ) : Runnable { private fun PsiElementFactory.createAnnotationMemberValueFromText( text: String, - context: PsiElement? + context: PsiElement?, ): PsiAnnotationMemberValue { val annotation = this.createAnnotationFromText("@Foo($text)", context) return annotation.findDeclaredAttributeValue("value")!! @@ -97,8 +97,8 @@ object DescReference : AbstractMethodReference() { "value", elementFactory.createExpressionFromText( "\"${StringUtil.escapeStringCharacters(targetMethodInfo.name)}\"", - descAnnotation - ) + descAnnotation, + ), ) val desc = targetMethodInfo.descriptor ?: return@runWriteAction val argTypes = Type.getArgumentTypes(desc) @@ -114,7 +114,7 @@ object DescReference : AbstractMethodReference() { } descAnnotation.setDeclaredAttributeValue( "args", - elementFactory.createAnnotationMemberValueFromText(argsText, descAnnotation) + elementFactory.createAnnotationMemberValueFromText(argsText, descAnnotation), ) } else { descAnnotation.setDeclaredAttributeValue("desc", null) @@ -125,8 +125,8 @@ object DescReference : AbstractMethodReference() { "ret", elementFactory.createAnnotationMemberValueFromText( "${returnType.className.replace('$', '.')}.class", - descAnnotation - ) + descAnnotation, + ), ) } else { descAnnotation.setDeclaredAttributeValue("ret", null) diff --git a/src/main/kotlin/platform/mixin/reference/InjectionPointReference.kt b/src/main/kotlin/platform/mixin/reference/InjectionPointReference.kt index 41549304b..baf4fa899 100644 --- a/src/main/kotlin/platform/mixin/reference/InjectionPointReference.kt +++ b/src/main/kotlin/platform/mixin/reference/InjectionPointReference.kt @@ -79,14 +79,14 @@ object InjectionPointReference : ReferenceResolver(), MixinReference { .map { PrioritizedLookupElement.withPriority( LookupElementBuilder.create(it).completeToLiteral(context), - 1.0 + 1.0, ) } + getCustomInjectionPointInheritors(context.project).asSequence() .map { PrioritizedLookupElement.withPriority( LookupElementBuilder.create(it).completeToLiteral(context), - 0.0 + 0.0, ) } ).toTypedArray() @@ -103,12 +103,12 @@ object InjectionPointReference : ReferenceResolver(), MixinReference { .findClass(SELECTOR, GlobalSearchScope.allScope(project)) ?: return@getCachedValue CachedValueProvider.Result( emptyList(), - PsiModificationTracker.MODIFICATION_COUNT + PsiModificationTracker.MODIFICATION_COUNT, ) val enumConstants = selectorClass.fields.mapNotNull { (it as? PsiEnumConstant)?.name } CachedValueProvider.Result(enumConstants, PsiModificationTracker.MODIFICATION_COUNT) }, - false + false, ) } @@ -123,7 +123,7 @@ object InjectionPointReference : ReferenceResolver(), MixinReference { .findClass(INJECTION_POINT, GlobalSearchScope.allScope(project)) ?: return@getCachedValue CachedValueProvider.Result( emptyList(), - PsiModificationTracker.MODIFICATION_COUNT + PsiModificationTracker.MODIFICATION_COUNT, ) val inheritors = ClassInheritorsSearch.search(injectionPointClass).mapNotNull { c -> if (c.qualifiedName == INJECTION_POINT) return@mapNotNull null @@ -140,7 +140,7 @@ object InjectionPointReference : ReferenceResolver(), MixinReference { } CachedValueProvider.Result(inheritors, PsiModificationTracker.MODIFICATION_COUNT) }, - false + false, ) } diff --git a/src/main/kotlin/platform/mixin/reference/MethodGTDHandler.kt b/src/main/kotlin/platform/mixin/reference/MethodGTDHandler.kt index 46c38c9aa..f4e1faaff 100644 --- a/src/main/kotlin/platform/mixin/reference/MethodGTDHandler.kt +++ b/src/main/kotlin/platform/mixin/reference/MethodGTDHandler.kt @@ -20,7 +20,7 @@ class MethodGTDHandler : GotoDeclarationHandler { override fun getGotoDeclarationTargets( sourceElement: PsiElement?, offset: Int, - editor: Editor? + editor: Editor?, ): Array? { if (sourceElement == null) return null val stringLiteral = sourceElement.parentOfType() ?: return null diff --git a/src/main/kotlin/platform/mixin/reference/MethodReference.kt b/src/main/kotlin/platform/mixin/reference/MethodReference.kt index a1d333fe3..39752f4d4 100644 --- a/src/main/kotlin/platform/mixin/reference/MethodReference.kt +++ b/src/main/kotlin/platform/mixin/reference/MethodReference.kt @@ -26,16 +26,19 @@ import com.intellij.util.ProcessingContext object MethodReference : AbstractMethodReference() { val ELEMENT_PATTERN: ElementPattern = - PsiJavaPatterns.psiLiteral(StandardPatterns.string()).insideAnnotationAttribute( - PsiJavaPatterns.psiAnnotation().with( - object : PatternCondition("injector") { - override fun accepts(t: PsiAnnotation, context: ProcessingContext?): Boolean { - val qName = t.qualifiedName ?: return false - return MixinAnnotationHandler.forMixinAnnotation(qName, t.project) is InjectorAnnotationHandler - } - } + PsiJavaPatterns.psiLiteral(StandardPatterns.string()).withAncestor( + 1, + PsiJavaPatterns.psiElement().insideAnnotationAttribute( + PsiJavaPatterns.psiAnnotation().with( + object : PatternCondition("injector") { + override fun accepts(t: PsiAnnotation, context: ProcessingContext?): Boolean { + val qName = t.qualifiedName ?: return false + return isValidAnnotation(qName, t.project) + } + }, + ), + "method", ), - "method" ) override val description = "method '%s' in target class" diff --git a/src/main/kotlin/platform/mixin/reference/MixinReferenceContributor.kt b/src/main/kotlin/platform/mixin/reference/MixinReferenceContributor.kt index 27419f6e4..3cdf783c0 100644 --- a/src/main/kotlin/platform/mixin/reference/MixinReferenceContributor.kt +++ b/src/main/kotlin/platform/mixin/reference/MixinReferenceContributor.kt @@ -24,26 +24,26 @@ class MixinReferenceContributor : PsiReferenceContributor() { // Method references registrar.registerReferenceProvider( MethodReference.ELEMENT_PATTERN, - MethodReference + MethodReference, ) // Desc references registrar.registerReferenceProvider( DescReference.ELEMENT_PATTERN, - DescReference + DescReference, ) // Injection point types registrar.registerReferenceProvider( PsiJavaPatterns.psiLiteral(StandardPatterns.string()) .insideAnnotationAttribute(AT), - InjectionPointReference + InjectionPointReference, ) // Target references registrar.registerReferenceProvider( TargetReference.ELEMENT_PATTERN, - TargetReference + TargetReference, ) } } diff --git a/src/main/kotlin/platform/mixin/reference/MixinSelectors.kt b/src/main/kotlin/platform/mixin/reference/MixinSelectors.kt index bbb3d72db..67dc30bfd 100644 --- a/src/main/kotlin/platform/mixin/reference/MixinSelectors.kt +++ b/src/main/kotlin/platform/mixin/reference/MixinSelectors.kt @@ -131,7 +131,7 @@ interface MixinSelector { fun resolve( project: Project, - scope: GlobalSearchScope = GlobalSearchScope.allScope(project) + scope: GlobalSearchScope = GlobalSearchScope.allScope(project), ): Pair? { return resolve(project, scope, ::Pair) } @@ -142,7 +142,7 @@ interface MixinSelector { fun resolveAsm( project: Project, - scope: GlobalSearchScope = GlobalSearchScope.allScope(project) + scope: GlobalSearchScope = GlobalSearchScope.allScope(project), ): MixinTargetMember? { val owner = this.owner ?: return null @@ -306,7 +306,7 @@ class MixinRegexParser : MixinSelectorParser { namePattern, descPattern, ownerPattern.getConstantString(), - descPattern.getConstantString() + descPattern.getConstantString(), ) } @@ -345,7 +345,7 @@ private class MixinRegexSelector( val namePattern: Regex, val descPattern: Regex, override val owner: String?, - descriptor: String? + descriptor: String?, ) : MixinSelector { override fun matchField(owner: String, name: String, desc: String): Boolean { return ownerPattern.containsMatchIn(owner) && @@ -517,7 +517,7 @@ class DescSelectorParser : DynamicSelectorParser("Desc", "mixin:Desc") { element, PsiAnnotation::class.java, PsiMethod::class.java, - PsiClass::class.java + PsiClass::class.java, ) } } @@ -566,7 +566,7 @@ class DescSelectorParser : DynamicSelectorParser("Desc", "mixin:Desc") { val ret = descAnnotation.findAttributeValue("ret")?.resolveType() ?: PsiType.VOID val desc = Type.getMethodDescriptor( Type.getType(ret.descriptor), - *argTypes.mapToArray { Type.getType(it.descriptor) } + *argTypes.mapToArray { Type.getType(it.descriptor) }, ) return DescSelector(owners, name, desc) @@ -577,7 +577,7 @@ class DescSelectorParser : DynamicSelectorParser("Desc", "mixin:Desc") { data class DescSelector( val owners: Set, val name: String, - override val methodDescriptor: String + override val methodDescriptor: String, ) : MixinSelector { override fun matchField(owner: String, name: String, desc: String): Boolean { return this.owners.contains(owner) && this.name == name && this.fieldDescriptor.substringBefore("(") == desc diff --git a/src/main/kotlin/platform/mixin/reference/target/TargetGTDHandler.kt b/src/main/kotlin/platform/mixin/reference/target/TargetGTDHandler.kt index 8c918726e..881b9dd47 100644 --- a/src/main/kotlin/platform/mixin/reference/target/TargetGTDHandler.kt +++ b/src/main/kotlin/platform/mixin/reference/target/TargetGTDHandler.kt @@ -20,7 +20,7 @@ class TargetGTDHandler : GotoDeclarationHandler { override fun getGotoDeclarationTargets( sourceElement: PsiElement?, offset: Int, - editor: Editor? + editor: Editor?, ): Array? { if (sourceElement == null) return null val stringLiteral = sourceElement.parentOfType() ?: return null diff --git a/src/main/kotlin/platform/mixin/search/MixinSoftImplementMethodSuperSearcher.kt b/src/main/kotlin/platform/mixin/search/MixinSoftImplementMethodSuperSearcher.kt index 342213950..bbd12fd53 100644 --- a/src/main/kotlin/platform/mixin/search/MixinSoftImplementMethodSuperSearcher.kt +++ b/src/main/kotlin/platform/mixin/search/MixinSoftImplementMethodSuperSearcher.kt @@ -24,7 +24,7 @@ class MixinSoftImplementMethodSuperSearcher : override fun execute( queryParameters: SuperMethodsSearch.SearchParameters, - consumer: Processor + consumer: Processor, ): Boolean { if (queryParameters.psiClass != null) { return true // Not entirely sure what this is used for diff --git a/src/main/kotlin/platform/mixin/util/AsmDfaUtil.kt b/src/main/kotlin/platform/mixin/util/AsmDfaUtil.kt index b13b791d3..45b3121cb 100644 --- a/src/main/kotlin/platform/mixin/util/AsmDfaUtil.kt +++ b/src/main/kotlin/platform/mixin/util/AsmDfaUtil.kt @@ -39,8 +39,8 @@ object AsmDfaUtil { Type.getObjectType(clazz.name), clazz.superName?.let { Type.getObjectType(it) }, clazz.interfaces?.map { Type.getObjectType(it) } ?: emptyList(), - clazz.hasAccess(Opcodes.ACC_INTERFACE) - ) + clazz.hasAccess(Opcodes.ACC_INTERFACE), + ), ).analyze(clazz.name, method) } catch (e: AnalyzerException) { LOGGER.warn("AsmDfaUtil.analyzeMethod failed", e) @@ -54,7 +54,7 @@ object AsmDfaUtil { clazz: ClassNode, method: MethodNode, insn: AbstractInsnNode, - slot: Int + slot: Int, ): Type? { val insns = method.instructions ?: return null val frames = analyzeMethod(project, clazz, method) ?: return null @@ -67,7 +67,7 @@ object AsmDfaUtil { project: Project, clazz: ClassNode, method: MethodNode, - insn: AbstractInsnNode + insn: AbstractInsnNode, ): Array? { val insns = method.instructions ?: return null val frames = analyzeMethod(project, clazz, method) ?: return null @@ -80,7 +80,7 @@ object AsmDfaUtil { clazz: ClassNode, method: MethodNode, insn: AbstractInsnNode, - depth: Int + depth: Int, ): Type? { val insns = method.instructions ?: return null val frames = analyzeMethod(project, clazz, method) ?: return null @@ -93,7 +93,7 @@ object AsmDfaUtil { project: Project, clazz: ClassNode, method: MethodNode, - insn: AbstractInsnNode + insn: AbstractInsnNode, ): Array? { val insns = method.instructions ?: return null val frames = analyzeMethod(project, clazz, method) ?: return null @@ -106,7 +106,7 @@ object AsmDfaUtil { private val currentClass: Type, private val currentSuperClass: Type?, currentClassInterfaces: List, - private val isInterface: Boolean + private val isInterface: Boolean, ) : SimpleVerifier(Opcodes.ASM7, currentClass, currentSuperClass, currentClassInterfaces, isInterface) { override fun getClass(type: Type?): Class<*> { // should never be called given we have overridden the other methods diff --git a/src/main/kotlin/platform/mixin/util/AsmUtil.kt b/src/main/kotlin/platform/mixin/util/AsmUtil.kt index 5f054415e..582900234 100644 --- a/src/main/kotlin/platform/mixin/util/AsmUtil.kt +++ b/src/main/kotlin/platform/mixin/util/AsmUtil.kt @@ -280,7 +280,7 @@ private fun ClassNode.constructClass(project: Project, body: String): PsiClass? val file = PsiFileFactory.getInstance(project).createFileFromText( "$outerClassSimpleName.java", JavaFileType.INSTANCE, - text + text, ) as? PsiJavaFile ?: return null var clazz = file.classes.firstOrNull() ?: return null @@ -289,7 +289,7 @@ private fun ClassNode.constructClass(project: Project, body: String): PsiClass? ( JavaPsiFacade.getInstance(project).findClass( outerClassName.replace('/', '.'), - GlobalSearchScope.allScope(project) + GlobalSearchScope.allScope(project), ) as? PsiCompiledElement )?.let { originalClass -> clazz.putUserData(ClsElementImpl.COMPILED_ELEMENT, originalClass) @@ -440,7 +440,7 @@ val FieldNode.memberReference fun FieldNode.getGenericType( clazz: ClassNode, - project: Project + project: Project, ): PsiType { if (this.signature != null) { return findOrConstructSourceField(clazz, project, canDecompile = false).type @@ -453,7 +453,7 @@ inline fun FieldNode.cached( clazz: ClassNode, project: Project, vararg dependencies: Any, - crossinline compute: () -> T + crossinline compute: () -> T, ): T { return findStubField(clazz, project)?.cached(*dependencies, compute = compute) ?: compute() } @@ -471,7 +471,7 @@ fun FieldNode.findOrConstructSourceField( clazz: ClassNode?, project: Project, scope: GlobalSearchScope = GlobalSearchScope.allScope(project), - canDecompile: Boolean = false + canDecompile: Boolean = false, ): PsiField { clazz?.let { findSourceField(it, project, scope, canDecompile = canDecompile) }?.let { return it } @@ -489,7 +489,7 @@ fun FieldNode.findOrConstructSourceField( } val psiField = elementFactory.createField( this.name.toJavaIdentifier(), - type + type, ) psiField.realName = this.name val modifierList = psiField.modifierList!! @@ -510,7 +510,7 @@ fun FieldNode.findSourceField( clazz: ClassNode, project: Project, scope: GlobalSearchScope, - canDecompile: Boolean = false + canDecompile: Boolean = false, ): PsiField? { return clazz.findSourceClass(project, scope, canDecompile)?.findField(memberReference) } @@ -659,7 +659,7 @@ private fun findAssociatedLambda(psiClass: PsiClass, clazz: ClassNode, lambdaMet } } } - } + }, ) result } @@ -669,7 +669,7 @@ inline fun MethodNode.cached( clazz: ClassNode, project: Project, vararg dependencies: Array, - crossinline compute: () -> T + crossinline compute: () -> T, ): T { return findStubMethod(clazz, project)?.cached(*dependencies, compute = compute) ?: compute() } @@ -705,7 +705,7 @@ fun MethodNode.findOrConstructSourceMethod( clazz: ClassNode?, project: Project, scope: GlobalSearchScope = GlobalSearchScope.allScope(project), - canDecompile: Boolean = false + canDecompile: Boolean = false, ): PsiMethod { val sourceElement = clazz?.let { findSourceElement(it, project, scope, canDecompile = canDecompile) } if (sourceElement is PsiMethod) { @@ -839,8 +839,8 @@ fun MethodNode.findOrConstructSourceMethod( if (exceptions != null) { psiMethod.throwsList.replace( elementFactory.createReferenceList( - exceptions.mapToArray { elementFactory.createReferenceFromText(it.replace('/', '.'), null) } - ) + exceptions.mapToArray { elementFactory.createReferenceFromText(it.replace('/', '.'), null) }, + ), ) } @@ -870,7 +870,7 @@ fun MethodNode.findSourceElement( clazz: ClassNode, project: Project, scope: GlobalSearchScope, - canDecompile: Boolean = false + canDecompile: Boolean = false, ): PsiElement? { val psiClass = clazz.findSourceClass(project, scope, canDecompile) ?: return null if (isClinit) { diff --git a/src/main/kotlin/platform/mixin/util/LocalVariables.kt b/src/main/kotlin/platform/mixin/util/LocalVariables.kt index 3b26f5877..1194481cc 100644 --- a/src/main/kotlin/platform/mixin/util/LocalVariables.kt +++ b/src/main/kotlin/platform/mixin/util/LocalVariables.kt @@ -122,7 +122,7 @@ object LocalVariables { val controlFlow = ControlFlowFactory.getControlFlow( body, LocalsControlFlowPolicy(body), - ControlFlowOptions.NO_CONST_EVALUATE + ControlFlowOptions.NO_CONST_EVALUATE, ) val allLocalVariables = guessAllLocalVariables(argsIndex, body, controlFlow) @@ -133,7 +133,7 @@ object LocalVariables { private fun guessAllLocalVariables( argsSize: Int, body: PsiElement, - controlFlow: ControlFlow + controlFlow: ControlFlow, ): Array> { return body.cached(PsiModificationTracker.MODIFICATION_COUNT) { guessAllLocalVariablesUncached(argsSize, body, controlFlow) @@ -143,7 +143,7 @@ object LocalVariables { private fun guessAllLocalVariablesUncached( argsSize: Int, body: PsiElement, - controlFlow: ControlFlow + controlFlow: ControlFlow, ): Array> { val method = body.parent val allLocalVariables = getAllLocalVariables(body) @@ -156,7 +156,7 @@ object LocalVariables { true }, variable, - method + method, ) // add on other implicit declarations in scope for (parent in generateSequence(variable.parent, PsiElement::getParent).takeWhile { it != method }) { @@ -185,7 +185,7 @@ object LocalVariables { override fun visitWriteVariableInstruction( instruction: WriteVariableInstruction, offset: Int, - nextOffset: Int + nextOffset: Int, ) { if (instruction.variable in allLocalVariables) { val localIndex = instruction.variable.getUserData(LOCAL_INDEX_KEY)!! @@ -227,6 +227,7 @@ object LocalVariables { val localsHere = this.locals[offset] ?: emptyArray() var changed = false val nextLocals = this.locals[nextOffset] + @Suppress("KotlinConstantConditions") // kotlin is wrong if (nextLocals == null) { this.locals[nextOffset] = localsHere.clone() changed = true @@ -246,6 +247,7 @@ object LocalVariables { } } } + @Suppress("KotlinConstantConditions") // kotlin is wrong if (changed) { instructionQueue.add(nextOffset) } @@ -289,7 +291,7 @@ object LocalVariables { override fun visitLambdaExpression(expression: PsiLambdaExpression) { // don't recurse into lambdas } - } + }, ) return locals } @@ -319,7 +321,7 @@ object LocalVariables { type, localIndex, implicitLoadCountBefore = 1, - implicitStoreCountBefore = 1 + implicitStoreCountBefore = 1, ), // length SourceLocalVariable( @@ -327,7 +329,7 @@ object LocalVariables { PsiType.INT, localIndex + 1, implicitStoreCountBefore = 1, - implicitLoadCountAfter = 1 + implicitLoadCountAfter = 1, ), // index SourceLocalVariable( @@ -336,14 +338,14 @@ object LocalVariables { localIndex + 2, implicitStoreCountBefore = 1, implicitLoadCountBefore = 1, - implicitLoadCountAfter = 1 - ) + implicitLoadCountAfter = 1, + ), ) } else { val iteratorType = JavaPsiFacade.getElementFactory(project) .createTypeByFQClassName( CommonClassNames.JAVA_UTIL_ITERATOR, - resolveScope + resolveScope, ) return listOf( // iterator @@ -352,8 +354,8 @@ object LocalVariables { iteratorType, localIndex, implicitStoreCountBefore = 1, - implicitLoadCountBefore = 1 - ) + implicitLoadCountBefore = 1, + ), ) } } @@ -362,7 +364,7 @@ object LocalVariables { module: Module, classNode: ClassNode, method: MethodNode, - node: AbstractInsnNode + node: AbstractInsnNode, ): Array? { return getLocals(module.project, classNode, method, node, detectCurrentSettings(module)) } @@ -372,7 +374,7 @@ object LocalVariables { classNode: ClassNode, method: MethodNode, nodeArg: AbstractInsnNode, - settings: Settings + settings: Settings, ): Array? { return try { doGetLocals(project, classNode, method, nodeArg, settings) @@ -397,7 +399,7 @@ object LocalVariables { classNode: ClassNode, method: MethodNode, nodeArg: AbstractInsnNode, - settings: Settings + settings: Settings, ): Array { var node = nodeArg for (i in 0 until 3) { @@ -479,7 +481,7 @@ object LocalVariables { frameSize, frameData.type, frameData.computeFrameSize(initialFrameSize), - initialFrameSize + initialFrameSize, ) } } else { @@ -488,7 +490,7 @@ object LocalVariables { frameSize, insn.type, frameNodeSize, - initialFrameSize + initialFrameSize, ) } @@ -498,7 +500,7 @@ object LocalVariables { "Locals entered an invalid state evaluating " + "${classNode.name}::${method.name}${method.desc} at instruction " + "${method.instructions.indexOf(insn)}. Initial frame size is" + - " $initialFrameSize, calculated a frame size of $frameSize" + " $initialFrameSize, calculated a frame size of $frameSize", ) } if (( @@ -528,7 +530,7 @@ object LocalVariables { classNode, method, method.instructions.indexOf(insn), - framePos + framePos, ) } else if (localType is Int) { // Integer refers to a primitive type or other marker val isMarkerType = localType == Opcodes.UNINITIALIZED_THIS || localType == Opcodes.NULL @@ -552,7 +554,7 @@ object LocalVariables { classNode, method, method.instructions.indexOf(insn), - framePos + framePos, ) if (is64bitValue) { framePos++ @@ -561,7 +563,7 @@ object LocalVariables { } else { throw IllegalStateException( "Unrecognised locals opcode $localType in locals array at position" + - " $localPos in ${classNode.name}.${method.name}${method.desc}" + " $localPos in ${classNode.name}.${method.name}${method.desc}", ) } } else if (localType == null) { @@ -572,7 +574,7 @@ object LocalVariables { classNode, method, insn, - framePos + framePos, ) } else { frame[framePos] = ZombieLocalVariable.of(frame[framePos], ZombieLocalVariable.TRIM) @@ -583,7 +585,7 @@ object LocalVariables { } else { throw IllegalStateException( "Invalid value $localType in locals array at position" + - " $localPos in ${classNode.name}.${method.name}${method.desc}" + " $localPos in ${classNode.name}.${method.name}${method.desc}", ) } framePos++ @@ -669,7 +671,7 @@ object LocalVariables { classNode: ClassNode, method: MethodNode, pos: AbstractInsnNode, - index: Int + index: Int, ): LocalVariable? { return getLocalVariableAt(project, classNode, method, method.instructions.indexOf(pos), index) } @@ -679,7 +681,7 @@ object LocalVariables { classNode: ClassNode, method: MethodNode, pos: Int, - index: Int + index: Int, ): LocalVariable? { var localVariableNode: LocalVariable? = null var fallbackNode: LocalVariable? = null @@ -722,7 +724,7 @@ object LocalVariables { it.signature, instructions.indexOf(it.start), instructions.indexOf(it.end), - it.index + it.index, ) } } @@ -730,7 +732,7 @@ object LocalVariables { private fun getGeneratedLocalVariableTable( project: Project, classNode: ClassNode, - method: MethodNode + method: MethodNode, ): List { val frames = AsmDfaUtil.analyzeMethod(project, classNode, method) ?: throw LocalAnalysisFailedException() @@ -808,7 +810,7 @@ object LocalVariables { val trimmedFrameThreshold: Int, val resurrectExposedOnLoad: Boolean, val resurrectExposedOnStore: Boolean, - val resurrectForBogusTop: Boolean + val resurrectForBogusTop: Boolean, ) { companion object { val NO_RESURRECT = Settings( @@ -818,7 +820,7 @@ object LocalVariables { trimmedFrameThreshold = 0, resurrectExposedOnLoad = false, resurrectExposedOnStore = false, - resurrectForBogusTop = false + resurrectForBogusTop = false, ) val DEFAULT = Settings( @@ -828,7 +830,7 @@ object LocalVariables { trimmedFrameThreshold = -1, resurrectExposedOnLoad = true, resurrectExposedOnStore = true, - resurrectForBogusTop = true + resurrectForBogusTop = true, ) } } @@ -841,7 +843,7 @@ object LocalVariables { val implicitLoadCountBefore: Int = 0, val implicitLoadCountAfter: Int = 0, val implicitStoreCountBefore: Int = 0, - val implicitStoreCountAfter: Int = 0 + val implicitStoreCountAfter: Int = 0, ) open class LocalVariable( @@ -850,7 +852,7 @@ object LocalVariables { val signature: String?, val start: Int?, var end: Int?, - val index: Int + val index: Int, ) { fun isInRange(index: Int): Boolean { val end = this.end @@ -866,14 +868,14 @@ object LocalVariables { private class ZombieLocalVariable private constructor( val ancestor: LocalVariable, - val type: Char + val type: Char, ) : LocalVariable( ancestor.name, ancestor.desc, ancestor.signature, ancestor.start, ancestor.end, - ancestor.index + ancestor.index, ) { var lifetime = 0 var frames = 0 diff --git a/src/main/kotlin/platform/mixin/util/Mixin.kt b/src/main/kotlin/platform/mixin/util/Mixin.kt index 15ba86773..f29909818 100644 --- a/src/main/kotlin/platform/mixin/util/Mixin.kt +++ b/src/main/kotlin/platform/mixin/util/Mixin.kt @@ -11,10 +11,10 @@ package com.demonwav.mcdev.platform.mixin.util import com.demonwav.mcdev.platform.mixin.action.FindMixinsAction +import com.demonwav.mcdev.platform.mixin.handlers.MixinAnnotationHandler import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Annotations.ACCESSOR import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Annotations.INVOKER import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Annotations.MIXIN -import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Classes.ARGS import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Classes.CALLBACK_INFO import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Classes.CALLBACK_INFO_RETURNABLE import com.demonwav.mcdev.util.cached @@ -30,6 +30,8 @@ import com.intellij.psi.PsiClassType import com.intellij.psi.PsiDisjunctionType import com.intellij.psi.PsiElement import com.intellij.psi.PsiIntersectionType +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiParameter import com.intellij.psi.PsiPrimitiveType import com.intellij.psi.PsiType import com.intellij.psi.search.GlobalSearchScope @@ -80,7 +82,7 @@ val PsiClass.mixinTargets: List findClassNodeByQualifiedName( project, findModule(), - name.replace('/', '.') + name.replace('/', '.'), ) } classTargets @@ -121,6 +123,11 @@ val PsiClass.isAccessorMixin: Boolean return targets.isNotEmpty() && !targets.any { it.hasAccess(Opcodes.ACC_INTERFACE) } } +val PsiParameter.isMixinExtrasSugar: Boolean + get() { + return annotations.any { it.qualifiedName?.contains(".mixinextras.sugar.") == true } + } + fun callbackInfoType(project: Project): PsiType = PsiType.getTypeByName(CALLBACK_INFO, project, GlobalSearchScope.allScope(project)) @@ -138,9 +145,6 @@ fun callbackInfoReturnableType(project: Project, context: PsiElement, returnType return JavaPsiFacade.getElementFactory(project).createType(psiClass, boxedType) } -fun argsType(project: Project): PsiType = - PsiType.getTypeByName(ARGS, project, GlobalSearchScope.allScope(project)) - fun isAssignable(left: PsiType, right: PsiType): Boolean { return when { left is PsiIntersectionType -> left.conjuncts.all { isAssignable(it, right) } @@ -181,3 +185,18 @@ private fun isClassAssignable(leftClass: PsiClass, rightClass: PsiClass): Boolea } return result } + +fun isMixinEntryPoint(element: PsiElement?): Boolean { + if (element !is PsiMethod) { + return false + } + val project = element.project + for (annotation in element.annotations) { + val qName = annotation.qualifiedName ?: continue + val handler = MixinAnnotationHandler.forMixinAnnotation(qName, project) + if (handler != null && handler.isEntryPoint) { + return true + } + } + return false +} diff --git a/src/main/kotlin/platform/mixin/util/SignatureToPsi.kt b/src/main/kotlin/platform/mixin/util/SignatureToPsi.kt index 6013bdafc..841ed87e4 100644 --- a/src/main/kotlin/platform/mixin/util/SignatureToPsi.kt +++ b/src/main/kotlin/platform/mixin/util/SignatureToPsi.kt @@ -21,7 +21,7 @@ import org.objectweb.asm.signature.SignatureVisitor class SignatureToPsi( private val elementFactory: PsiElementFactory, private val context: PsiElement?, - private val typeCompletedCallback: ((PsiType) -> Unit)? = null + private val typeCompletedCallback: ((PsiType) -> Unit)? = null, ) : SignatureVisitor(Opcodes.ASM7) { private val text = StringBuilder() diff --git a/src/main/kotlin/platform/mixin/util/TargetClass.kt b/src/main/kotlin/platform/mixin/util/TargetClass.kt index 3082b3e66..273d229f4 100644 --- a/src/main/kotlin/platform/mixin/util/TargetClass.kt +++ b/src/main/kotlin/platform/mixin/util/TargetClass.kt @@ -123,16 +123,20 @@ class MethodTargetMember(val classAndMethod: ClassAndMethodNode, mixin: PsiClass private fun Sequence.filterAccessible( psiClass: PsiClass, - target: PsiClass + target: PsiClass, ): Sequence { - return if (psiClass equivalentTo target) this else filter { - (it.access and (Opcodes.ACC_PUBLIC or Opcodes.ACC_PROTECTED)) != 0 + return if (psiClass equivalentTo target) { + this + } else { + filter { + (it.access and (Opcodes.ACC_PUBLIC or Opcodes.ACC_PROTECTED)) != 0 + } } } private fun PsiClass.streamMixinHierarchy(): Sequence { return generateSequence(this) { - it.superClass?.takeIf { it.isMixin } + it.superClass?.takeIf { superClass -> superClass.isMixin } } } diff --git a/src/main/kotlin/platform/sponge/SpongeModule.kt b/src/main/kotlin/platform/sponge/SpongeModule.kt index 44910ce20..177c66925 100644 --- a/src/main/kotlin/platform/sponge/SpongeModule.kt +++ b/src/main/kotlin/platform/sponge/SpongeModule.kt @@ -18,18 +18,16 @@ import com.demonwav.mcdev.platform.AbstractModule import com.demonwav.mcdev.platform.PlatformType import com.demonwav.mcdev.platform.sponge.generation.SpongeGenerationData import com.demonwav.mcdev.platform.sponge.util.SpongeConstants +import com.demonwav.mcdev.util.createVoidMethodWithParameterType import com.demonwav.mcdev.util.extendsOrImplements import com.demonwav.mcdev.util.findContainingMethod import com.intellij.lang.jvm.JvmModifier import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiAnnotationMemberValue import com.intellij.psi.PsiClass -import com.intellij.psi.PsiClassType import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod import com.intellij.psi.PsiMethodCallExpression -import com.intellij.psi.PsiType -import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.uast.UClass import org.jetbrains.uast.UIdentifier import org.jetbrains.uast.toUElementOfType @@ -51,19 +49,9 @@ class SpongeModule(facet: MinecraftFacet) : AbstractModule(facet) { containingClass: PsiClass, chosenClass: PsiClass, chosenName: String, - data: GenerationData? + data: GenerationData?, ): PsiMethod? { - val method = JavaPsiFacade.getElementFactory(project).createMethod(chosenName, PsiType.VOID) - val parameterList = method.parameterList - - val qName = chosenClass.qualifiedName ?: return null - val parameter = JavaPsiFacade.getElementFactory(project) - .createParameter( - "event", - PsiClassType.getTypeByName(qName, project, GlobalSearchScope.allScope(project)) - ) - - parameterList.add(parameter) + val method = createVoidMethodWithParameterType(project, chosenName, chosenClass) ?: return null val modifierList = method.modifierList val listenerAnnotation = modifierList.addAnnotation("org.spongepowered.api.event.Listener") @@ -82,7 +70,7 @@ class SpongeModule(facet: MinecraftFacet) : AbstractModule(facet) { val value = JavaPsiFacade.getElementFactory(project) .createExpressionFromText( "org.spongepowered.api.event.Order." + generationData.eventOrder, - listenerAnnotation + listenerAnnotation, ) listenerAnnotation.setDeclaredAttributeValue("order", value) @@ -95,10 +83,9 @@ class SpongeModule(facet: MinecraftFacet) : AbstractModule(facet) { val identifier = element?.toUElementOfType() ?: return false - val psiClass = identifier.uastParent as? UClass - ?: return false + val psiClass = identifier.uastParent as? UClass ?: return false - if (psiClass.hasModifier(JvmModifier.ABSTRACT)) { + if (psiClass.javaPsi.hasModifier(JvmModifier.ABSTRACT)) { return false } @@ -122,8 +109,7 @@ class SpongeModule(facet: MinecraftFacet) : AbstractModule(facet) { return null } - val sub = text.substring(text.lastIndexOf('.') + 1) - when (sub) { + when (text.substring(text.lastIndexOf('.') + 1)) { "TRUE" -> true "FALSE" -> false else -> return null @@ -154,9 +140,9 @@ class SpongeModule(facet: MinecraftFacet) : AbstractModule(facet) { fix = { expression.replace( JavaPsiFacade.getElementFactory(project) - .createExpressionFromText(if (isCancelled) "true" else "false", expression) + .createExpressionFromText(if (isCancelled) "true" else "false", expression), ) - } + }, ) } } diff --git a/src/main/kotlin/platform/sponge/SpongeModuleType.kt b/src/main/kotlin/platform/sponge/SpongeModuleType.kt index b6d47bb4c..33cabaa98 100644 --- a/src/main/kotlin/platform/sponge/SpongeModuleType.kt +++ b/src/main/kotlin/platform/sponge/SpongeModuleType.kt @@ -26,7 +26,7 @@ object SpongeModuleType : AbstractModuleType("org.spongepowered", private val IGNORED_ANNOTATIONS = listOf( SpongeConstants.LISTENER_ANNOTATION, SpongeConstants.PLUGIN_ANNOTATION, - SpongeConstants.JVM_PLUGIN_ANNOTATION + SpongeConstants.JVM_PLUGIN_ANNOTATION, ) private val LISTENER_ANNOTATIONS = listOf(SpongeConstants.LISTENER_ANNOTATION) diff --git a/src/main/kotlin/platform/sponge/color/SpongeColorUtil.kt b/src/main/kotlin/platform/sponge/color/SpongeColorUtil.kt index df5009733..66eff347d 100644 --- a/src/main/kotlin/platform/sponge/color/SpongeColorUtil.kt +++ b/src/main/kotlin/platform/sponge/color/SpongeColorUtil.kt @@ -25,6 +25,6 @@ fun PsiElement.findSpongeColor(): Pair? = arrayOf( "com.flowpowered.math.vector.Vector3d", "com.flowpowered.math.vector.Vector3f", - "com.flowpowered.math.vector.Vector3i" - ) + "com.flowpowered.math.vector.Vector3i", + ), ) diff --git a/src/main/kotlin/platform/sponge/creator/Sponge8ProjectCreator.kt b/src/main/kotlin/platform/sponge/creator/Sponge8ProjectCreator.kt deleted file mode 100644 index 2711d8ee6..000000000 --- a/src/main/kotlin/platform/sponge/creator/Sponge8ProjectCreator.kt +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.sponge.creator - -import com.demonwav.mcdev.creator.BaseProjectCreator -import com.demonwav.mcdev.creator.BasicJavaClassStep -import com.demonwav.mcdev.creator.CreateDirectoriesStep -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.BasicGradleFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleFiles -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleGitignoreStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleSetupStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleWrapperStep -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenStep -import com.demonwav.mcdev.creator.buildsystem.maven.MavenBuildSystem -import com.demonwav.mcdev.creator.buildsystem.maven.MavenGitignoreStep -import com.intellij.openapi.module.Module -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.project.Project -import java.nio.file.Path - -sealed class Sponge8ProjectCreator( - protected val rootDirectory: Path, - protected val rootModule: Module, - protected val buildSystem: T, - protected val config: SpongeProjectConfig -) : BaseProjectCreator(rootModule, buildSystem) { - - protected fun setupDependencyStep(): SpongeDependenciesSetup { - val spongeApiVersion = config.spongeApiVersion - return SpongeDependenciesSetup(buildSystem, spongeApiVersion, false) - } - - protected fun setupMainClassStep(): BasicJavaClassStep { - return createJavaClassStep(config.mainClass) { packageName, className -> - val pluginId = (buildSystem.parent ?: buildSystem).artifactId - Sponge8Template.applyMainClass(project, pluginId, packageName, className) - } - } -} - -class Sponge8MavenCreator( - rootDirectory: Path, - rootModule: Module, - buildSystem: MavenBuildSystem, - config: SpongeProjectConfig -) : Sponge8ProjectCreator(rootDirectory, rootModule, buildSystem, config) { - - override fun getSteps(): Iterable { - val mainClassStep = setupMainClassStep() - val pluginsJsonStep = CreatePluginsJsonStep(project, buildSystem, config) - - val pomText = SpongeTemplate.applyPom(project, config) - - return listOf( - setupDependencyStep(), - BasicMavenStep(project, rootDirectory, buildSystem, config, pomText), - mainClassStep, - pluginsJsonStep, - MavenGitignoreStep(project, rootDirectory), - BasicMavenFinalizerStep(rootModule, rootDirectory), - ) - } -} - -class CreatePluginsJsonStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val config: SpongeProjectConfig -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val pluginsJsonPath = buildSystem.dirsOrError.resourceDirectory.resolve("META-INF") - val pluginsJsonText = Sponge8Template.applyPluginsJson(project, buildSystem, config) - CreatorStep.writeTextToFile(project, pluginsJsonPath, "sponge_plugins.json", pluginsJsonText) - } -} - -class Sponge8GradleCreator( - rootDirectory: Path, - rootModule: Module, - buildSystem: GradleBuildSystem, - config: SpongeProjectConfig -) : Sponge8ProjectCreator(rootDirectory, rootModule, buildSystem, config) { - - override fun getSteps(): Iterable { - val mainClassStep = setupMainClassStep() - - val buildText = Sponge8Template.applyBuildGradle( - project, - buildSystem, - config - ) - val propText = Sponge8Template.applyGradleProp(project) - val settingsText = Sponge8Template.applySettingsGradle(project, buildSystem.artifactId) - val files = GradleFiles(buildText, propText, settingsText) - - return listOf( - CreateDirectoriesStep(buildSystem, rootDirectory), - GradleSetupStep(project, rootDirectory, buildSystem, files, true), - mainClassStep, - GradleWrapperStep(project, rootDirectory, buildSystem), - GradleGitignoreStep(project, rootDirectory), - BasicGradleFinalizerStep(rootModule, rootDirectory, buildSystem, "runServer") - ) - } -} diff --git a/src/main/kotlin/platform/sponge/creator/Sponge8Template.kt b/src/main/kotlin/platform/sponge/creator/Sponge8Template.kt deleted file mode 100644 index 5bb825c71..000000000 --- a/src/main/kotlin/platform/sponge/creator/Sponge8Template.kt +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.sponge.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.platform.BaseTemplate -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.SPONGE8_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.SPONGE8_GRADLE_PROPERTIES_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.SPONGE8_MAIN_CLASS_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.SPONGE8_PLUGINS_JSON_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.SPONGE8_SETTINGS_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.SPONGE8_SUBMODULE_BUILD_GRADLE_TEMPLATE -import com.intellij.openapi.project.Project - -object Sponge8Template : BaseTemplate() { - - fun applyMainClass( - project: Project, - pluginId: String, - packageName: String, - className: String - ): String { - val props = mutableMapOf( - "PLUGIN_ID" to pluginId, - "PACKAGE" to packageName, - "CLASS_NAME" to className - ) - - return project.applyTemplate(SPONGE8_MAIN_CLASS_TEMPLATE, props) - } - - fun applyPluginsJson( - project: Project, - buildSystem: BuildSystem, - config: SpongeProjectConfig - ): String { - val props = mutableMapOf( - "PLUGIN_ID" to buildSystem.artifactId, - "VERSION_PLACEHOLDER" to "\${version}", - "SPONGEAPI_VERSION" to config.spongeApiVersion, - "LICENSE" to config.license, - "PLUGIN_NAME" to config.pluginName, - "MAIN_CLASS" to config.mainClass, - "DESCRIPTION" to config.description, - "WEBSITE" to config.website, - "AUTHORS" to config.authors, - "DEPENDENCIES" to config.dependencies - ) - - return project.applyTemplate(SPONGE8_PLUGINS_JSON_TEMPLATE, props) - } - - fun applyBuildGradle( - project: Project, - buildSystem: BuildSystem, - config: SpongeProjectConfig - ): String { - val props = mutableMapOf( - "JAVA_VERSION" to config.javaVersion.feature, - "GROUP_ID" to buildSystem.groupId, - "PLUGIN_ID" to buildSystem.artifactId, - "PLUGIN_VERSION" to buildSystem.version, - "SPONGEAPI_VERSION" to config.spongeApiVersion, - "LICENSE" to config.license, - "PLUGIN_NAME" to config.pluginName, - "MAIN_CLASS" to config.mainClass, - "DESCRIPTION" to config.description, - "WEBSITE" to config.website, - "AUTHORS" to config.authors, - "DEPENDENCIES" to config.dependencies - ) - - return project.applyTemplate(SPONGE8_BUILD_GRADLE_TEMPLATE, props) - } - - fun applyGradleProp(project: Project): String { - return project.applyTemplate(SPONGE8_GRADLE_PROPERTIES_TEMPLATE) - } - - fun applySettingsGradle(project: Project, artifactId: String): String { - val props = mapOf( - "ARTIFACT_ID" to artifactId - ) - - return project.applyTemplate(SPONGE8_SETTINGS_GRADLE_TEMPLATE, props) - } - - fun applySubBuildGradle( - project: Project, - buildSystem: BuildSystem, - config: SpongeProjectConfig - ): String { - val props = mutableMapOf( - "JAVA_VERSION" to config.javaVersion.feature, - "PLUGIN_ID" to buildSystem.parentOrError.artifactId, - "SPONGEAPI_VERSION" to config.spongeApiVersion, - "LICENSE" to config.license, - "PLUGIN_NAME" to config.pluginName, - "MAIN_CLASS" to config.mainClass, - "DESCRIPTION" to config.description, - "WEBSITE" to config.website, - "AUTHORS" to config.authors, - "DEPENDENCIES" to config.dependencies, - "COMMON_PROJECT_NAME" to buildSystem.commonModuleName - ) - - return project.applyTemplate(SPONGE8_SUBMODULE_BUILD_GRADLE_TEMPLATE, props) - } -} diff --git a/src/main/kotlin/platform/sponge/creator/SpongeProjectConfig.kt b/src/main/kotlin/platform/sponge/creator/SpongeProjectConfig.kt deleted file mode 100644 index 8c3a41868..000000000 --- a/src/main/kotlin/platform/sponge/creator/SpongeProjectConfig.kt +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.sponge.creator - -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.ProjectCreator -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleCreator -import com.demonwav.mcdev.creator.buildsystem.maven.MavenBuildSystem -import com.demonwav.mcdev.creator.buildsystem.maven.MavenCreator -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.platform.sponge.util.SpongeConstants -import com.demonwav.mcdev.util.License -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.VersionRange -import com.demonwav.mcdev.util.until -import com.intellij.openapi.module.Module -import com.intellij.util.lang.JavaVersion -import java.nio.file.Path - -class SpongeProjectConfig : ProjectConfig(), MavenCreator, GradleCreator { - - lateinit var mainClass: String - - var spongeApiVersion = "" - val apiVersion: SemanticVersion - get() = if (spongeApiVersion.isBlank()) SemanticVersion.release() else SemanticVersion.parse(spongeApiVersion) - - override var type = PlatformType.SPONGE - - init { - type = PlatformType.SPONGE - } - - val dependencies = mutableListOf() - fun hasDependencies() = listContainsAtLeastOne(dependencies) - fun setDependencies(string: String) { - dependencies.clear() - dependencies.addAll(commaSplit(string)) - } - - var license = License.ALL_RIGHTS_RESERVED - - override val preferredBuildSystem = BuildSystemType.GRADLE - - override val javaVersion: JavaVersion - get() = when { - apiVersion >= SpongeConstants.API9 -> JavaVersion.compose(17) - else -> JavaVersion.compose(8) - } - - override fun buildMavenCreator( - rootDirectory: Path, - module: Module, - buildSystem: MavenBuildSystem - ): ProjectCreator { - val apiVersion = SemanticVersion.parse(spongeApiVersion) - return if (apiVersion < SpongeConstants.API8) { - SpongeMavenCreator(rootDirectory, module, buildSystem, this) - } else { - Sponge8MavenCreator(rootDirectory, module, buildSystem, this) - } - } - - override val compatibleGradleVersions: VersionRange - get() = when { - apiVersion >= SpongeConstants.API8 -> SemanticVersion.release(7, 4, 2) until null - else -> SemanticVersion.release(6, 0) until SemanticVersion.release(7) - } - - override fun buildGradleCreator( - rootDirectory: Path, - module: Module, - buildSystem: GradleBuildSystem - ): ProjectCreator { - val apiVersion = SemanticVersion.parse(spongeApiVersion) - return if (apiVersion < SpongeConstants.API8) { - SpongeGradleCreator(rootDirectory, module, buildSystem, this) - } else { - Sponge8GradleCreator(rootDirectory, module, buildSystem, this) - } - } - - override fun configureRootGradle(rootDirectory: Path, buildSystem: GradleBuildSystem) { - buildSystem.gradleVersion = compatibleGradleVersions.lower - } -} diff --git a/src/main/kotlin/platform/sponge/creator/SpongeProjectCreator.kt b/src/main/kotlin/platform/sponge/creator/SpongeProjectCreator.kt deleted file mode 100644 index eaa977db0..000000000 --- a/src/main/kotlin/platform/sponge/creator/SpongeProjectCreator.kt +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.sponge.creator - -import com.demonwav.mcdev.creator.BaseProjectCreator -import com.demonwav.mcdev.creator.CreateDirectoriesStep -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.LicenseStep -import com.demonwav.mcdev.creator.buildsystem.BuildDependency -import com.demonwav.mcdev.creator.buildsystem.BuildRepository -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.BuildSystemType -import com.demonwav.mcdev.creator.buildsystem.gradle.BasicGradleFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleFiles -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleGitignoreStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleSetupStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleWrapperStep -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenStep -import com.demonwav.mcdev.creator.buildsystem.maven.MavenBuildSystem -import com.demonwav.mcdev.creator.buildsystem.maven.MavenGitignoreStep -import com.demonwav.mcdev.util.runWriteAction -import com.demonwav.mcdev.util.runWriteTaskInSmartMode -import com.demonwav.mcdev.util.virtualFileOrError -import com.intellij.openapi.module.Module -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.project.Project -import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiJavaFile -import com.intellij.psi.PsiManager -import com.intellij.psi.codeStyle.CodeStyleManager -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.Paths -import java.util.EnumSet -import java.util.Locale - -sealed class SpongeProjectCreator( - protected val rootDirectory: Path, - protected val rootModule: Module, - protected val buildSystem: T, - protected val config: SpongeProjectConfig -) : BaseProjectCreator(rootModule, buildSystem) { - - protected fun setupDependencyStep(): SpongeDependenciesSetup { - val spongeApiVersion = config.spongeApiVersion - return SpongeDependenciesSetup(buildSystem, spongeApiVersion, true) - } - - protected fun setupMainClassSteps(): Pair { - val mainClassStep = createJavaClassStep(config.mainClass) { packageName, className -> - SpongeTemplate.applyMainClass(project, packageName, className, config.hasDependencies()) - } - - val (packageName, className) = splitPackage(config.mainClass) - return mainClassStep to SpongeMainClassModifyStep(project, buildSystem, packageName, className, config) - } -} - -class SpongeMavenCreator( - rootDirectory: Path, - rootModule: Module, - buildSystem: MavenBuildSystem, - config: SpongeProjectConfig -) : SpongeProjectCreator(rootDirectory, rootModule, buildSystem, config) { - - override fun getSteps(): Iterable { - val (mainClassStep, modifyStep) = setupMainClassSteps() - - val pomText = SpongeTemplate.applyPom(project, config) - - return listOf( - setupDependencyStep(), - BasicMavenStep(project, rootDirectory, buildSystem, config, pomText), - mainClassStep, - modifyStep, - MavenGitignoreStep(project, rootDirectory), - LicenseStep(project, rootDirectory, config.license, config.authors.joinToString(", ")), - BasicMavenFinalizerStep(rootModule, rootDirectory) - ) - } -} - -class SpongeGradleCreator( - rootDirectory: Path, - rootModule: Module, - buildSystem: GradleBuildSystem, - config: SpongeProjectConfig -) : SpongeProjectCreator(rootDirectory, rootModule, buildSystem, config) { - - override fun getSteps(): Iterable { - val (mainClassStep, modifyStep) = setupMainClassSteps() - - val buildText = SpongeTemplate.applyBuildGradle(project, buildSystem) - val propText = SpongeTemplate.applyGradleProp(project) - val settingsText = SpongeTemplate.applySettingsGradle(project, buildSystem.artifactId) - val files = GradleFiles(buildText, propText, settingsText) - - return listOf( - setupDependencyStep(), - CreateDirectoriesStep(buildSystem, rootDirectory), - GradleSetupStep(project, rootDirectory, buildSystem, files), - mainClassStep, - modifyStep, - GradleWrapperStep(project, rootDirectory, buildSystem), - GradleGitignoreStep(project, rootDirectory), - LicenseStep(project, rootDirectory, config.license, config.authors.joinToString(", ")), - BasicGradleFinalizerStep(rootModule, rootDirectory, buildSystem) - ) - } -} - -class SpongeMainClassModifyStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val packageName: String, - private val className: String, - private val config: SpongeProjectConfig -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val dirs = buildSystem.dirsOrError - - project.runWriteTaskInSmartMode { - val targetDir = dirs.sourceDirectory.resolve(Paths.get(packageName.replace('.', '/'))) - if (!Files.isDirectory(targetDir)) { - throw IllegalStateException("$targetDir is not an existing directory") - } - val javaFile = targetDir.resolve("$className.java") - if (!Files.isRegularFile(javaFile)) { - throw IllegalStateException("$javaFile is not an existing file") - } - - val psiFile = PsiManager.getInstance(project).findFile(javaFile.virtualFileOrError) as? PsiJavaFile - ?: throw IllegalStateException("Failed to resolve PsiJavaFile for $javaFile") - val psiClass = psiFile.classes[0] - - val annotationString = StringBuilder("@Plugin(") - annotationString + "\nid = ${escape(buildSystem.artifactId.lowercase(Locale.ENGLISH))}" - annotationString + ",\nname = ${escape(config.pluginName)}" - if (buildSystem.type != BuildSystemType.GRADLE) { - // SpongeGradle will automatically set the Gradle version as plugin version - annotationString + ",\nversion = ${escape(buildSystem.version)}" - } - - if (config.hasDescription()) { - annotationString + ",\ndescription = ${escape(config.description)}" - } - - if (config.hasWebsite()) { - annotationString + ",\nurl = ${escape(config.website)}" - } - - if (config.hasAuthors()) { - annotationString + ",\nauthors = {\n${config.authors.joinToString(",\n", transform = ::escape)}\n}" - } - - if (config.hasDependencies()) { - val dep = config.dependencies.joinToString(",\n") { "@Dependency(id = ${escape(it)})" } - annotationString + ",\ndependencies = {\n$dep\n}" - } - - annotationString + "\n)" - val factory = JavaPsiFacade.getElementFactory(project) - val annotation = factory.createAnnotationFromText(annotationString.toString(), null) - - psiFile.runWriteAction { - psiClass.modifierList?.let { modifierList -> - modifierList.addBefore(annotation, modifierList.firstChild) - } - CodeStyleManager.getInstance(project).reformat(psiClass) - } - } - } - - private fun escape(text: String?): String { - if (text == null) { - return "\"\"" - } - return "\"" + text.replace("\\", "\\\\").replace("\"", "\\\"") + "\"" - } - - private operator fun StringBuilder.plus(text: String) = this.append(text) -} - -class SpongeDependenciesSetup( - private val buildSystem: BuildSystem, - private val spongeApiVersion: String, - private val addAnnotationProcessor: Boolean -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - buildSystem.repositories.add( - BuildRepository( - "spongepowered-repo", - "https://repo.spongepowered.org/maven/", - buildSystems = EnumSet.of(BuildSystemType.MAVEN) - ) - ) - buildSystem.dependencies.add( - BuildDependency( - "org.spongepowered", - "spongeapi", - spongeApiVersion, - mavenScope = "provided", - gradleConfiguration = "compileOnly" - ) - ) - if (addAnnotationProcessor) { - buildSystem.dependencies.add( - BuildDependency( - "org.spongepowered", - "spongeapi", - spongeApiVersion, - gradleConfiguration = "annotationProcessor" - ) - ) - } - } -} diff --git a/src/main/kotlin/platform/sponge/creator/SpongeProjectSettingsWizard.form b/src/main/kotlin/platform/sponge/creator/SpongeProjectSettingsWizard.form deleted file mode 100644 index c807ca748..000000000 --- a/src/main/kotlin/platform/sponge/creator/SpongeProjectSettingsWizard.form +++ /dev/null @@ -1,226 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/main/kotlin/platform/sponge/creator/SpongeProjectSettingsWizard.kt b/src/main/kotlin/platform/sponge/creator/SpongeProjectSettingsWizard.kt deleted file mode 100644 index 1d7f4477f..000000000 --- a/src/main/kotlin/platform/sponge/creator/SpongeProjectSettingsWizard.kt +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.sponge.creator - -import com.demonwav.mcdev.asset.PlatformAssets -import com.demonwav.mcdev.creator.MinecraftModuleWizardStep -import com.demonwav.mcdev.creator.MinecraftProjectCreator -import com.demonwav.mcdev.creator.ValidatedField -import com.demonwav.mcdev.creator.ValidatedFieldType.CLASS_NAME -import com.demonwav.mcdev.creator.ValidatedFieldType.LIST -import com.demonwav.mcdev.creator.ValidatedFieldType.NON_BLANK -import com.demonwav.mcdev.platform.sponge.SpongeVersion -import com.demonwav.mcdev.platform.sponge.util.SpongeConstants -import com.demonwav.mcdev.util.License -import com.demonwav.mcdev.util.SemanticVersion -import com.intellij.ui.EnumComboBoxModel -import com.intellij.util.text.nullize -import com.intellij.util.ui.UIUtil -import javax.swing.JComboBox -import javax.swing.JComponent -import javax.swing.JLabel -import javax.swing.JPanel -import javax.swing.JTextField -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.swing.Swing -import kotlinx.coroutines.withContext - -class SpongeProjectSettingsWizard(private val creator: MinecraftProjectCreator) : MinecraftModuleWizardStep() { - - @ValidatedField(NON_BLANK) - private lateinit var pluginNameField: JTextField - - @ValidatedField(NON_BLANK, CLASS_NAME) - private lateinit var mainClassField: JTextField - private lateinit var panel: JPanel - private lateinit var title: JLabel - private lateinit var descriptionField: JTextField - - @ValidatedField(LIST) - private lateinit var authorsField: JTextField - private lateinit var websiteField: JTextField - - @ValidatedField(LIST) - private lateinit var dependField: JTextField - private lateinit var licenseBox: JComboBox - private lateinit var spongeApiVersionBox: JComboBox - private lateinit var errorLabel: JLabel - - private var config: SpongeProjectConfig? = null - - private var versionsLoaded: Boolean = false - - init { - spongeApiVersionBox.addActionListener { - val stringVersion = spongeApiVersionBox.selectedItem as? String - licenseBox.isEnabled = stringVersion == null || SemanticVersion.parse(stringVersion) >= SpongeConstants.API8 - } - } - - override fun getComponent(): JComponent { - return panel - } - - override fun validate(): Boolean { - return super.validate() && spongeApiVersionBox.selectedItem != null - } - - override fun updateStep() { - config = creator.config as? SpongeProjectConfig - if (config == null) { - return - } - - basicUpdateStep(creator, pluginNameField, mainClassField) - - if (UIUtil.isUnderDarcula()) { - title.icon = PlatformAssets.SPONGE_ICON_2X_DARK - } else { - title.icon = PlatformAssets.SPONGE_ICON_2X - } - - licenseBox.model = EnumComboBoxModel(License::class.java) - licenseBox.selectedItem = License.ALL_RIGHTS_RESERVED - - if (versionsLoaded) { - return - } - - versionsLoaded = true - CoroutineScope(Dispatchers.Swing).launch { - try { - withContext(Dispatchers.IO) { SpongeVersion.downloadData() }?.set(spongeApiVersionBox) - } catch (e: Exception) { - errorLabel.isVisible = true - } - } - } - - override fun isStepVisible(): Boolean { - return creator.config is SpongeProjectConfig - } - - override fun updateDataModel() { - val conf = this.config ?: return - - conf.pluginName = this.pluginNameField.text - conf.mainClass = this.mainClassField.text - conf.description = this.descriptionField.text?.nullize(true) - conf.website = this.websiteField.text?.nullize(true) - conf.spongeApiVersion = this.spongeApiVersionBox.selectedItem as String - - conf.setAuthors(this.authorsField.text) - conf.setDependencies(this.dependField.text) - conf.license = this.licenseBox.selectedItem as License - } -} diff --git a/src/main/kotlin/platform/sponge/creator/SpongeTemplate.kt b/src/main/kotlin/platform/sponge/creator/SpongeTemplate.kt deleted file mode 100644 index ea0afa1de..000000000 --- a/src/main/kotlin/platform/sponge/creator/SpongeTemplate.kt +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.sponge.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenStep -import com.demonwav.mcdev.platform.BaseTemplate -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.SPONGE_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.SPONGE_GRADLE_PROPERTIES_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.SPONGE_MAIN_CLASS_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.SPONGE_POM_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.SPONGE_SETTINGS_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.SPONGE_SUBMODULE_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.SPONGE_SUBMODULE_POM_TEMPLATE -import com.intellij.openapi.project.Project - -object SpongeTemplate : BaseTemplate() { - - fun applyPom(project: Project, config: SpongeProjectConfig): String { - val props = BasicMavenStep.pluginVersions.toMutableMap() - props["JAVA_VERSION"] = config.javaVersion.toString() - - return project.applyTemplate(SPONGE_POM_TEMPLATE, props) - } - - fun applySubPom(project: Project, config: SpongeProjectConfig): String { - val props = BasicMavenStep.pluginVersions.toMutableMap() - props["JAVA_VERSION"] = config.javaVersion.toString() - - return project.applyTemplate(SPONGE_SUBMODULE_POM_TEMPLATE, props) - } - - fun applyMainClass( - project: Project, - packageName: String, - className: String, - hasDependencies: Boolean - ): String { - val props = mutableMapOf( - "PACKAGE" to packageName, - "CLASS_NAME" to className - ) - - if (hasDependencies) { - props["HAS_DEPENDENCIES"] = "true" - } - - return project.applyTemplate(SPONGE_MAIN_CLASS_TEMPLATE, props) - } - - fun applyBuildGradle(project: Project, buildSystem: BuildSystem): String { - val props = mapOf( - "GROUP_ID" to buildSystem.groupId, - "PLUGIN_ID" to buildSystem.artifactId, - "PLUGIN_VERSION" to buildSystem.version - ) - - return project.applyTemplate(SPONGE_BUILD_GRADLE_TEMPLATE, props) - } - - fun applyGradleProp(project: Project): String { - return project.applyTemplate(SPONGE_GRADLE_PROPERTIES_TEMPLATE) - } - - fun applySettingsGradle(project: Project, artifactId: String): String { - val props = mapOf( - "ARTIFACT_ID" to artifactId - ) - - return project.applyTemplate(SPONGE_SETTINGS_GRADLE_TEMPLATE, props) - } - - fun applySubBuildGradle(project: Project, buildSystem: BuildSystem): String { - val props = mapOf( - "COMMON_PROJECT_NAME" to buildSystem.commonModuleName, - "PLUGIN_ID" to buildSystem.artifactId - ) - - return project.applyTemplate(SPONGE_SUBMODULE_BUILD_GRADLE_TEMPLATE, props) - } -} diff --git a/src/main/kotlin/platform/sponge/creator/asset-steps.kt b/src/main/kotlin/platform/sponge/creator/asset-steps.kt new file mode 100644 index 000000000..334b2f899 --- /dev/null +++ b/src/main/kotlin/platform/sponge/creator/asset-steps.kt @@ -0,0 +1,56 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.sponge.creator + +import com.demonwav.mcdev.creator.addLicense +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.AbstractRunBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.splitPackage +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.MainClassStep +import com.demonwav.mcdev.util.MinecraftTemplates +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.project.Project + +class SpongeProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating project files" + + override fun setupAssets(project: Project) { + val buildSystemProps = findStep>() + val (packageName, className) = splitPackage(data.getUserData(MainClassStep.KEY) ?: return) + + assets.addTemplateProperties( + "PLUGIN_ID" to buildSystemProps.artifactId, + "PACKAGE" to packageName, + "CLASS_NAME" to className, + ) + val mainClassFile = "src/main/java/${packageName.replace('.', '/')}/$className.java" + assets.addTemplates( + project, + mainClassFile to MinecraftTemplates.SPONGE8_MAIN_CLASS_TEMPLATE, + ) + assets.addLicense(project) + } +} + +class SpongeBuildSystemStep(parent: NewProjectWizardStep) : AbstractBuildSystemStep(parent) { + override val platformName = "Sponge" +} + +class SpongePostBuildSystemStep( + parent: NewProjectWizardStep, +) : AbstractRunBuildSystemStep(parent, SpongeBuildSystemStep::class.java) { + override val step = BuildSystemSupport.POST_STEP +} diff --git a/src/main/kotlin/platform/sponge/creator/gradle-steps.kt b/src/main/kotlin/platform/sponge/creator/gradle-steps.kt new file mode 100644 index 000000000..e1d834e0c --- /dev/null +++ b/src/main/kotlin/platform/sponge/creator/gradle-steps.kt @@ -0,0 +1,117 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.sponge.creator + +import com.demonwav.mcdev.creator.EmptyStep +import com.demonwav.mcdev.creator.JdkProjectSetupFinalizer +import com.demonwav.mcdev.creator.addGradleGitignore +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.buildsystem.GRADLE_VERSION_KEY +import com.demonwav.mcdev.creator.buildsystem.GradleImportStep +import com.demonwav.mcdev.creator.buildsystem.GradleWrapperStep +import com.demonwav.mcdev.creator.buildsystem.ReformatBuildGradleStep +import com.demonwav.mcdev.creator.buildsystem.addGradleWrapperProperties +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.gitEnabled +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModNameStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DependStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.LicenseStep +import com.demonwav.mcdev.creator.step.MainClassStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.util.MinecraftTemplates +import com.demonwav.mcdev.util.SemanticVersion +import com.intellij.ide.starters.local.GeneratorEmptyDirectory +import com.intellij.ide.wizard.NewProjectWizardBaseData +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.project.Project + +class SpongeGradleSupport : BuildSystemSupport { + override val preferred = true + + override fun createStep(step: String, parent: NewProjectWizardStep): NewProjectWizardStep { + return when (step) { + BuildSystemSupport.PRE_STEP -> SpongeGradleFilesStep(parent).chain(::GradleWrapperStep) + BuildSystemSupport.POST_STEP -> SpongeGradleImportStep(parent).chain(::ReformatBuildGradleStep) + else -> EmptyStep(parent) + } + } +} + +class SpongeGradleFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating Gradle files" + + override fun setupAssets(project: Project) { + data.putUserData(GRADLE_VERSION_KEY, SemanticVersion.release(7, 4, 2)) + + val buildSystemProps = findStep>() + val javaVersion = findStep().preferredJdk.ordinal + val spongeVersion = data.getUserData(SpongeApiVersionStep.KEY) ?: return + val license = data.getUserData(LicenseStep.KEY) ?: return + val pluginName = data.getUserData(AbstractModNameStep.KEY) ?: return + val mainClass = data.getUserData(MainClassStep.KEY) ?: return + val description = data.getUserData(DescriptionStep.KEY) ?: "" + val website = data.getUserData(WebsiteStep.KEY) ?: "" + val authors = data.getUserData(AuthorsStep.KEY) ?: emptyList() + val dependencies = data.getUserData(DependStep.KEY) ?: emptyList() + val baseData = data.getUserData(NewProjectWizardBaseData.KEY) ?: return + + assets.addTemplateProperties( + "GROUP_ID" to buildSystemProps.groupId, + "ARTIFACT_ID" to buildSystemProps.artifactId, + "PLUGIN_ID" to buildSystemProps.artifactId, + "PLUGIN_VERSION" to buildSystemProps.version, + "JAVA_VERSION" to javaVersion, + "SPONGEAPI_VERSION" to spongeVersion, + "LICENSE" to license.id, + "PLUGIN_NAME" to pluginName, + "MAIN_CLASS" to mainClass, + "AUTHORS" to authors, + "DEPENDENCIES" to dependencies, + "PROJECT_NAME" to baseData.name, + ) + + if (description.isNotBlank()) { + assets.addTemplateProperties("DESCRIPTION" to description) + } + + if (website.isNotBlank()) { + assets.addTemplateProperties("WEBSITE" to website) + } + + assets.addTemplates( + project, + "build.gradle.kts" to MinecraftTemplates.SPONGE8_BUILD_GRADLE_TEMPLATE, + "settings.gradle.kts" to MinecraftTemplates.SPONGE8_SETTINGS_GRADLE_TEMPLATE, + "gradle.properties" to MinecraftTemplates.SPONGE8_GRADLE_PROPERTIES_TEMPLATE, + ) + + assets.addGradleWrapperProperties(project) + + assets.addAssets( + GeneratorEmptyDirectory("src/main/java"), + GeneratorEmptyDirectory("src/main/resources"), + ) + + if (gitEnabled) { + assets.addGradleGitignore(project) + } + } +} + +class SpongeGradleImportStep(parent: NewProjectWizardStep) : GradleImportStep(parent) { + override val additionalRunTasks = listOf("runServer") +} diff --git a/src/main/kotlin/platform/sponge/creator/maven-steps.kt b/src/main/kotlin/platform/sponge/creator/maven-steps.kt new file mode 100644 index 000000000..281fe8bc5 --- /dev/null +++ b/src/main/kotlin/platform/sponge/creator/maven-steps.kt @@ -0,0 +1,129 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.sponge.creator + +import com.demonwav.mcdev.creator.EmptyStep +import com.demonwav.mcdev.creator.JdkProjectSetupFinalizer +import com.demonwav.mcdev.creator.addLicense +import com.demonwav.mcdev.creator.addMavenGitignore +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractPatchPomStep +import com.demonwav.mcdev.creator.buildsystem.BuildDependency +import com.demonwav.mcdev.creator.buildsystem.BuildRepository +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.buildsystem.BuildSystemType +import com.demonwav.mcdev.creator.buildsystem.MavenImportStep +import com.demonwav.mcdev.creator.buildsystem.ReformatPomStep +import com.demonwav.mcdev.creator.buildsystem.addDefaultMavenProperties +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.gitEnabled +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModNameStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DependStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.LicenseStep +import com.demonwav.mcdev.creator.step.MainClassStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.util.MinecraftTemplates +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.project.Project +import com.intellij.psi.xml.XmlTag +import java.util.EnumSet +import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel + +class SpongeMavenSupport : BuildSystemSupport { + override fun createStep(step: String, parent: NewProjectWizardStep): NewProjectWizardStep { + return when (step) { + BuildSystemSupport.PRE_STEP -> SpongeMavenFilesStep(parent).chain(::SpongePatchPomStep) + BuildSystemSupport.POST_STEP -> SpongeMavenProjectFilesStep(parent).chain( + ::MavenImportStep, + ::ReformatPomStep, + ) + else -> EmptyStep(parent) + } + } +} + +class SpongeMavenFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating Maven files" + + override fun setupAssets(project: Project) { + assets.addDefaultMavenProperties() + val javaVersion = findStep().preferredJdk.ordinal + assets.addTemplateProperties("JAVA_VERSION" to javaVersion) + assets.addTemplates(project, "pom.xml" to MinecraftTemplates.SPONGE_POM_TEMPLATE) + if (gitEnabled) { + assets.addMavenGitignore(project) + } + } +} + +class SpongeMavenProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating Maven project files" + + override fun setupAssets(project: Project) { + val buildSystemProps = findStep>() + val mainClass = data.getUserData(MainClassStep.KEY) ?: return + val spongeApiVersion = data.getUserData(SpongeApiVersionStep.KEY) ?: return + val license = data.getUserData(LicenseStep.KEY) ?: return + val pluginName = data.getUserData(AbstractModNameStep.KEY) ?: return + val description = data.getUserData(DescriptionStep.KEY) ?: "" + val website = data.getUserData(WebsiteStep.KEY) ?: "" + val authors = data.getUserData(AuthorsStep.KEY) ?: emptyList() + val dependencies = data.getUserData(DependStep.KEY) ?: emptyList() + + assets.addTemplateProperties( + "PLUGIN_ID" to buildSystemProps.artifactId, + "VERSION_PLACEHOLDER" to "\${version}", + "SPONGEAPI_VERSION" to spongeApiVersion, + "LICENSE" to license.id, + "PLUGIN_NAME" to pluginName, + "MAIN_CLASS" to mainClass, + "DESCRIPTION" to description, + "WEBSITE" to website, + "AUTHORS" to authors, + "DEPENDENCIES" to dependencies, + ) + assets.addTemplates( + project, + "src/main/resources/META-INF/sponge_plugins.json" to MinecraftTemplates.SPONGE8_PLUGINS_JSON_TEMPLATE, + ) + assets.addLicense(project) + } +} + +class SpongePatchPomStep(parent: NewProjectWizardStep) : AbstractPatchPomStep(parent) { + override fun patchPom(model: MavenDomProjectModel, root: XmlTag) { + super.patchPom(model, root) + val spongeApiVersion = data.getUserData(SpongeApiVersionStep.KEY) ?: return + setupDependencies( + model, + listOf( + BuildRepository( + "spongepowered-repo", + "https://repo.spongepowered.org/maven/", + buildSystems = EnumSet.of(BuildSystemType.MAVEN), + ), + ), + listOf( + BuildDependency( + "org.spongepowered", + "spongeapi", + spongeApiVersion.toString(), + mavenScope = "provided", + ), + ), + ) + } +} diff --git a/src/main/kotlin/platform/sponge/creator/ui-steps.kt b/src/main/kotlin/platform/sponge/creator/ui-steps.kt new file mode 100644 index 000000000..910fff2c2 --- /dev/null +++ b/src/main/kotlin/platform/sponge/creator/ui-steps.kt @@ -0,0 +1,109 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.sponge.creator + +import com.demonwav.mcdev.creator.JdkProjectSetupFinalizer +import com.demonwav.mcdev.creator.chain +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.platformtype.PluginPlatformStep +import com.demonwav.mcdev.creator.step.AbstractCollapsibleStep +import com.demonwav.mcdev.creator.step.AbstractLatentStep +import com.demonwav.mcdev.creator.step.AbstractSelectVersionStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DependStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.LicenseStep +import com.demonwav.mcdev.creator.step.MainClassStep +import com.demonwav.mcdev.creator.step.PluginNameStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.platform.sponge.SpongeVersion +import com.demonwav.mcdev.platform.sponge.util.SpongeConstants +import com.demonwav.mcdev.util.SemanticVersion +import com.demonwav.mcdev.util.onShown +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.project.Project +import com.intellij.openapi.projectRoots.JavaSdkVersion +import com.intellij.openapi.util.Key +import com.intellij.ui.dsl.builder.Panel + +private val MIN_SPONGE_VERSION = SpongeConstants.API8 + +class SpongePlatformStep(parent: PluginPlatformStep) : AbstractLatentStep(parent) { + override val description = "download Sponge versions" + + override suspend fun computeData() = SpongeVersion.downloadData() + + override fun createStep(data: SpongeVersion) = SpongeApiVersionStep(this, data).chain( + ::PluginNameStep, + ::MainClassStep, + ::LicenseStep, + ::SpongeOptionalSettingsStep, + ::SpongeBuildSystemStep, + ::SpongeProjectFilesStep, + ::SpongePostBuildSystemStep, + ) + + class Factory : PluginPlatformStep.Factory { + override val name = "Sponge" + + override fun createStep(parent: PluginPlatformStep) = SpongePlatformStep(parent) + } +} + +class SpongeApiVersionStep( + parent: NewProjectWizardStep, + data: SpongeVersion, +) : AbstractSelectVersionStep( + parent, + data.versions.keys.mapNotNull(SemanticVersion::tryParse).filter { it >= MIN_SPONGE_VERSION }, +) { + override val label = "Sponge API Version:" + + override fun setupUI(builder: Panel) { + super.setupUI(builder) + versionProperty.afterChange { + applyJdkVersion() + } + versionBox.onShown { + applyJdkVersion() + } + } + + override fun setupProject(project: Project) { + data.putUserData(KEY, SemanticVersion.tryParse(version)) + applyJdkVersion() + } + + private fun applyJdkVersion() { + SemanticVersion.tryParse(version)?.let { version -> + val preferredJdk = when { + version >= SpongeConstants.API9 -> JavaSdkVersion.JDK_17 + else -> JavaSdkVersion.JDK_1_8 + } + findStep().setPreferredJdk(preferredJdk, "Sponge $version") + } + } + + companion object { + val KEY = Key.create("${SpongeApiVersionStep::class.java.name}.version") + } +} + +class SpongeOptionalSettingsStep(parent: NewProjectWizardStep) : AbstractCollapsibleStep(parent) { + override val title = "Optional Settings" + + override fun createStep() = DescriptionStep(this).chain( + ::AuthorsStep, + ::WebsiteStep, + ::DependStep, + ) +} diff --git a/src/main/kotlin/platform/sponge/generation/SpongeEventGenerationPanel.kt b/src/main/kotlin/platform/sponge/generation/SpongeEventGenerationPanel.kt index 13815b87e..d12ba5b3a 100644 --- a/src/main/kotlin/platform/sponge/generation/SpongeEventGenerationPanel.kt +++ b/src/main/kotlin/platform/sponge/generation/SpongeEventGenerationPanel.kt @@ -23,7 +23,7 @@ class SpongeEventGenerationPanel(chosenClass: PsiClass) : EventGenerationPanel(c private lateinit var eventOrderComboBox: JComboBox private lateinit var ignoreCanceledCheckBox: JCheckBox - override val panel: JPanel? + override val panel: JPanel get() { ignoreCanceledCheckBox.isSelected = true @@ -43,7 +43,7 @@ class SpongeEventGenerationPanel(chosenClass: PsiClass) : EventGenerationPanel(c return parentPanel } - override fun gatherData(): GenerationData? { + override fun gatherData(): GenerationData { return SpongeGenerationData(ignoreCanceledCheckBox.isSelected, eventOrderComboBox.selectedItem as String) } } diff --git a/src/main/kotlin/platform/sponge/inspection/SpongeInjectionInspection.kt b/src/main/kotlin/platform/sponge/inspection/SpongeInjectionInspection.kt index dd73bf751..16d327785 100644 --- a/src/main/kotlin/platform/sponge/inspection/SpongeInjectionInspection.kt +++ b/src/main/kotlin/platform/sponge/inspection/SpongeInjectionInspection.kt @@ -101,7 +101,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { annotation.parameterList, "Constructor injection cannot be optional.", ProblemHighlightType.GENERIC_ERROR, - RemoveAnnotationParameters(annotation, "Remove 'optional' parameter") + RemoveAnnotationParameters(annotation, "Remove 'optional' parameter"), ) } } @@ -115,7 +115,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { holder.registerProblem( typeElement, "Primitive types cannot be injected by Sponge.", - ProblemHighlightType.GENERIC_ERROR + ProblemHighlightType.GENERIC_ERROR, ) return } @@ -129,7 +129,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { typeElement, "${classType.presentableText} cannot be injected by Sponge.", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - AddToKnownInjectableTypes(name) + AddToKnownInjectableTypes(name), ) return } @@ -143,7 +143,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { private fun checkAssetId( name: String, variable: PsiVariable, - annotationsOwner: PsiModifierListOwner + annotationsOwner: PsiModifierListOwner, ) { if (name != "org.spongepowered.api.asset.Asset") { return @@ -155,7 +155,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { variable.nameIdentifier ?: variable, "Injected Assets must be annotated with @AssetId.", ProblemHighlightType.GENERIC_ERROR, - AddAnnotationFix(SpongeConstants.ASSET_ID_ANNOTATION, annotationsOwner) + AddAnnotationFix(SpongeConstants.ASSET_ID_ANNOTATION, annotationsOwner), ) } else { variable.findModule()?.let { module -> @@ -173,7 +173,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { holder.registerProblem( assetPathAttributeValue, "AssetId must reference a file.", - ProblemHighlightType.GENERIC_ERROR + ProblemHighlightType.GENERIC_ERROR, ) return@let } @@ -189,7 +189,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { assetPathAttributeValue, "Asset '$assetPath' does not exist.", ProblemHighlightType.GENERIC_ERROR, - fix + fix, ) } } @@ -200,7 +200,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { variable: PsiVariable, name: String, classType: PsiClassReferenceType, - annotationsOwner: PsiModifierListOwner + annotationsOwner: PsiModifierListOwner, ) { val configDir = variable.getAnnotation(SpongeConstants.CONFIG_DIR_ANNOTATION) val defaultConfig = variable.getAnnotation(SpongeConstants.DEFAULT_CONFIG_ANNOTATION) @@ -214,7 +214,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { "@ConfigDir and @DefaultConfig cannot be used on the same field.", ProblemHighlightType.GENERIC_ERROR, quickFixFactory.createDeleteFix(configDir, "Remove @ConfigDir"), - quickFixFactory.createDeleteFix(defaultConfig, "Remove @DefaultConfig") + quickFixFactory.createDeleteFix(defaultConfig, "Remove @DefaultConfig"), ) } else if (configDir == null && defaultConfig == null) { holder.registerProblem( @@ -222,7 +222,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { "An injected ${classType.name} must be annotated with either @ConfigDir or @DefaultConfig.", ProblemHighlightType.GENERIC_ERROR, AddAnnotationFix(SpongeConstants.CONFIG_DIR_ANNOTATION, annotationsOwner), - AddAnnotationFix(SpongeConstants.DEFAULT_CONFIG_ANNOTATION, annotationsOwner) + AddAnnotationFix(SpongeConstants.DEFAULT_CONFIG_ANNOTATION, annotationsOwner), ) } } @@ -232,7 +232,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { variable.nameIdentifier ?: variable, "Injected ConfigurationLoader must be annotated with @DefaultConfig.", ProblemHighlightType.GENERIC_ERROR, - AddAnnotationFix(SpongeConstants.DEFAULT_CONFIG_ANNOTATION, annotationsOwner) + AddAnnotationFix(SpongeConstants.DEFAULT_CONFIG_ANNOTATION, annotationsOwner), ) } @@ -241,7 +241,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { configDir, "Injected ConfigurationLoader cannot be annotated with @ConfigDir.", ProblemHighlightType.GENERIC_ERROR, - QuickFixFactory.getInstance().createDeleteFix(configDir, "Remove @ConfigDir") + QuickFixFactory.getInstance().createDeleteFix(configDir, "Remove @ConfigDir"), ) } @@ -251,7 +251,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { ref, "Injected ConfigurationLoader must have a generic parameter.", ProblemHighlightType.GENERIC_ERROR, - MissingConfLoaderTypeParamFix(ref) + MissingConfLoaderTypeParamFix(ref), ) } else { classType.parameters.firstOrNull()?.let { param -> @@ -264,7 +264,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { "Injected ConfigurationLoader generic parameter must be " + "CommentedConfigurationNode.", ProblemHighlightType.GENERIC_ERROR, - WrongConfLoaderTypeParamFix(ref) + WrongConfLoaderTypeParamFix(ref), ) } } @@ -277,7 +277,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { configDir, "${classType.name} cannot be annotated with @ConfigDir.", ProblemHighlightType.GENERIC_ERROR, - quickFixFactory.createDeleteFix(configDir, "Remove @ConfigDir") + quickFixFactory.createDeleteFix(configDir, "Remove @ConfigDir"), ) } @@ -286,7 +286,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { defaultConfig, "${classType.name} cannot be annotated with @DefaultConfig.", ProblemHighlightType.GENERIC_ERROR, - quickFixFactory.createDeleteFix(defaultConfig, "Remove @DefaultConfig") + quickFixFactory.createDeleteFix(defaultConfig, "Remove @DefaultConfig"), ) } } @@ -333,7 +333,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { "org.spongepowered.api.asset.Asset", "org.bstats.sponge.MetricsLite2.Factory", - "org.bstats.sponge.Metrics2.Factory" + "org.bstats.sponge.Metrics2.Factory", ) val serializedDefaultInjectableTypes: String = formatString(defaultInjectableTypes) @@ -362,7 +362,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { override fun invoke(project: Project, file: PsiFile, startElement: PsiElement, endElement: PsiElement) { val newRef = JavaPsiFacade.getElementFactory(project).createReferenceFromText( "ninja.leaping.configurate.commented.CommentedConfigurationNode", - startElement + startElement, ) startElement.replace(newRef) } @@ -378,7 +378,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { val newRef = JavaPsiFacade.getElementFactory(project).createReferenceFromText( "ninja.leaping.configurate.loader.ConfigurationLoader" + "", - startElement + startElement, ) startElement.replace(newRef) } @@ -388,7 +388,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { private val assetPath: String, private val module: Module, private val pluginId: String, - directory: PsiDirectory + directory: PsiDirectory, ) : LocalQuickFix { private val dirPointer = directory.createSmartPointer() @@ -409,7 +409,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { module, "assets.$pluginId$assetDir", dirPointer.element, - false + false, ) val createdFile = runWriteAction { createdDir?.createFile(fileName) @@ -432,7 +432,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { val chooserList = UiUtils.createTreeClassChooserList( injectableTypesList, "Injectable types", - "Choose injectable type" + "Choose injectable type", ) UiUtils.setComponentSize(chooserList, 7, 25) return chooserList diff --git a/src/main/kotlin/platform/sponge/inspection/SpongeInvalidGetterTargetInspection.kt b/src/main/kotlin/platform/sponge/inspection/SpongeInvalidGetterTargetInspection.kt index b50fe933a..5677a1d32 100644 --- a/src/main/kotlin/platform/sponge/inspection/SpongeInvalidGetterTargetInspection.kt +++ b/src/main/kotlin/platform/sponge/inspection/SpongeInvalidGetterTargetInspection.kt @@ -29,7 +29,7 @@ class SpongeInvalidGetterTargetInspection : AbstractBaseUastLocalInspectionTool( override fun checkMethod( method: UMethod, manager: InspectionManager, - isOnTheFly: Boolean + isOnTheFly: Boolean, ): Array? { if (!method.isValidSpongeListener()) { return null @@ -45,7 +45,7 @@ class SpongeInvalidGetterTargetInspection : AbstractBaseUastLocalInspectionTool( this.staticDescription, isOnTheFly, null, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, ) } } diff --git a/src/main/kotlin/platform/sponge/inspection/SpongeLoggingInspection.kt b/src/main/kotlin/platform/sponge/inspection/SpongeLoggingInspection.kt index fc8c6cdb4..a4930588f 100644 --- a/src/main/kotlin/platform/sponge/inspection/SpongeLoggingInspection.kt +++ b/src/main/kotlin/platform/sponge/inspection/SpongeLoggingInspection.kt @@ -59,7 +59,7 @@ class SpongeLoggingInspection : AbstractBaseJavaLocalInspectionTool() { holder.registerProblem( element, "Sponge plugins should use ${Constants.SLF4J_LOGGER} rather than ${Constants.JAVA_UTIL_LOGGER}.", - ProblemHighlightType.GENERIC_ERROR_OR_WARNING + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, ) } } diff --git a/src/main/kotlin/platform/sponge/inspection/SpongePluginClassInspection.kt b/src/main/kotlin/platform/sponge/inspection/SpongePluginClassInspection.kt index 106ef3704..0729f6107 100644 --- a/src/main/kotlin/platform/sponge/inspection/SpongePluginClassInspection.kt +++ b/src/main/kotlin/platform/sponge/inspection/SpongePluginClassInspection.kt @@ -66,7 +66,7 @@ class SpongePluginClassInspection : AbstractBaseJavaLocalInspectionTool() { injectAnno, "There can only be one injected constructor.", quickFixFactory.createDeleteFix(injectAnno, "Remove this @Inject"), - quickFixFactory.createDeleteFix(injectedMethod, "Remove this injected constructor") + quickFixFactory.createDeleteFix(injectedMethod, "Remove this injected constructor"), ) } } @@ -80,7 +80,7 @@ class SpongePluginClassInspection : AbstractBaseJavaLocalInspectionTool() { classIdentifier, "Plugin class must have an empty constructor or an @Inject constructor.", ProblemHighlightType.GENERIC_ERROR, - AddDefaultConstructorFix(aClass) + AddDefaultConstructorFix(aClass), ) } } @@ -94,7 +94,7 @@ class SpongePluginClassInspection : AbstractBaseJavaLocalInspectionTool() { ProblemHighlightType.GENERIC_ERROR, ModifierFix(emptyCtor, PsiModifier.PACKAGE_LOCAL, true, false), ModifierFix(emptyCtor, PsiModifier.PROTECTED, true, false), - ModifierFix(emptyCtor, PsiModifier.PUBLIC, true, false) + ModifierFix(emptyCtor, PsiModifier.PUBLIC, true, false), ) } } @@ -108,7 +108,7 @@ class SpongePluginClassInspection : AbstractBaseJavaLocalInspectionTool() { holder.registerProblem( pluginIdValue, "Plugin IDs should be lowercase, and only contain characters from a-z, dashes or underscores," + - " start with a lowercase letter, and not exceed 64 characters." + " start with a lowercase letter, and not exceed 64 characters.", ) } } diff --git a/src/main/kotlin/platform/sponge/inspection/SpongeWrongGetterTypeInspection.kt b/src/main/kotlin/platform/sponge/inspection/SpongeWrongGetterTypeInspection.kt index 6ca40ff88..98852799e 100644 --- a/src/main/kotlin/platform/sponge/inspection/SpongeWrongGetterTypeInspection.kt +++ b/src/main/kotlin/platform/sponge/inspection/SpongeWrongGetterTypeInspection.kt @@ -48,7 +48,7 @@ class SpongeWrongGetterTypeInspection : AbstractBaseUastLocalInspectionTool() { override fun checkMethod( method: UMethod, manager: InspectionManager, - isOnTheFly: Boolean + isOnTheFly: Boolean, ): Array? { val parameters = method.uastParameters if (parameters.size < 2 || !method.isValidSpongeListener()) { @@ -73,7 +73,7 @@ class SpongeWrongGetterTypeInspection : AbstractBaseUastLocalInspectionTool() { val getterSubst = TypeConversionUtil.getSuperClassSubstitutor( getterClass.javaPsi, eventClass, - eventTypeSubstitutor + eventTypeSubstitutor, ) val getterReturnType = getterMethod.returnType?.let(getterSubst::substitute) ?: continue val parameterType = parameter.type @@ -105,7 +105,7 @@ class SpongeWrongGetterTypeInspection : AbstractBaseUastLocalInspectionTool() { this.staticDescription, isOnTheFly, fixes, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, ) } return problems.toTypedArray() @@ -126,7 +126,7 @@ class SpongeWrongGetterTypeInspection : AbstractBaseUastLocalInspectionTool() { method: JvmMethod, expectedType: PsiType, paramIndex: Int, - project: Project + project: Project, ): Array { if (expectedType is PsiPrimitiveType || expectedType is PsiClassType && !isOptional(expectedType) @@ -155,7 +155,7 @@ class SpongeWrongGetterTypeInspection : AbstractBaseUastLocalInspectionTool() { // Suggest a non-Optional version too return arrayOf( Fix(method, paramIndex, expectedType), - Fix(method, paramIndex, fixedClassType) + Fix(method, paramIndex, fixedClassType), ) } @@ -174,7 +174,7 @@ class SpongeWrongGetterTypeInspection : AbstractBaseUastLocalInspectionTool() { val newParam = expectedParameter( expectedType, existingParam.semanticNames.first(), - existingParam.expectedAnnotations + existingParam.expectedAnnotations, ) actualParams.toMutableList().also { it[paramIndex] = newParam } } diff --git a/src/main/kotlin/platform/sponge/reference/SpongeReferenceContributor.kt b/src/main/kotlin/platform/sponge/reference/SpongeReferenceContributor.kt index ef12fa1a0..032cc4b31 100644 --- a/src/main/kotlin/platform/sponge/reference/SpongeReferenceContributor.kt +++ b/src/main/kotlin/platform/sponge/reference/SpongeReferenceContributor.kt @@ -46,7 +46,7 @@ class SpongeReferenceContributor : PsiReferenceContributor() { PlatformPatterns.psiElement(PsiLanguageInjectionHost::class.java) .and(FilterPattern(GetterAnnotationFilter)), UastGetterEventListenerReferenceResolver, - PsiReferenceRegistrar.HIGHER_PRIORITY + PsiReferenceRegistrar.HIGHER_PRIORITY, ) } } diff --git a/src/main/kotlin/platform/sponge/util/SpongeConstants.kt b/src/main/kotlin/platform/sponge/util/SpongeConstants.kt index 50f90bb2c..65acef428 100644 --- a/src/main/kotlin/platform/sponge/util/SpongeConstants.kt +++ b/src/main/kotlin/platform/sponge/util/SpongeConstants.kt @@ -31,8 +31,8 @@ object SpongeConstants { const val INJECT_ANNOTATION = "com.google.inject.Inject" // Taken from https://github.com/SpongePowered/plugin-meta/blob/185f5c2/src/main/java/org/spongepowered/plugin/meta/PluginMetadata.java#L60 - val ID_PATTERN_STRING = "^[a-z][a-z0-9-_]{1,63}$" - val ID_PATTERN = Pattern.compile(ID_PATTERN_STRING) + private const val ID_PATTERN_STRING = "^[a-z][a-z0-9-_]{1,63}$" + val ID_PATTERN: Pattern = Pattern.compile(ID_PATTERN_STRING) val API8 = SemanticVersion.release(8) val API9 = SemanticVersion.release(9) diff --git a/src/main/kotlin/platform/velocity/VelocityModule.kt b/src/main/kotlin/platform/velocity/VelocityModule.kt index d5e758165..44998d163 100644 --- a/src/main/kotlin/platform/velocity/VelocityModule.kt +++ b/src/main/kotlin/platform/velocity/VelocityModule.kt @@ -18,14 +18,12 @@ import com.demonwav.mcdev.platform.PlatformType import com.demonwav.mcdev.platform.velocity.generation.VelocityGenerationData import com.demonwav.mcdev.platform.velocity.util.VelocityConstants import com.demonwav.mcdev.platform.velocity.util.VelocityConstants.SUBSCRIBE_ANNOTATION +import com.demonwav.mcdev.util.createVoidMethodWithParameterType import com.intellij.lang.jvm.JvmModifier import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiClass -import com.intellij.psi.PsiClassType import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiType -import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.uast.UClass import org.jetbrains.uast.UIdentifier import org.jetbrains.uast.toUElementOfType @@ -41,19 +39,9 @@ class VelocityModule(facet: MinecraftFacet) : AbstractModule(facet) { containingClass: PsiClass, chosenClass: PsiClass, chosenName: String, - data: GenerationData? + data: GenerationData?, ): PsiMethod? { - val method = JavaPsiFacade.getElementFactory(project).createMethod(chosenName, PsiType.VOID) - val parameterList = method.parameterList - - val qName = chosenClass.qualifiedName ?: return null - val parameter = JavaPsiFacade.getElementFactory(project) - .createParameter( - "event", - PsiClassType.getTypeByName(qName, project, GlobalSearchScope.allScope(project)) - ) - - parameterList.add(parameter) + val method = createVoidMethodWithParameterType(project, chosenName, chosenClass) ?: return null val modifierList = method.modifierList val subscribeAnnotation = modifierList.addAnnotation(SUBSCRIBE_ANNOTATION) @@ -64,7 +52,7 @@ class VelocityModule(facet: MinecraftFacet) : AbstractModule(facet) { val value = JavaPsiFacade.getElementFactory(project) .createExpressionFromText( "com.velocitypowered.api.event.PostOrder." + generationData.eventOrder, - subscribeAnnotation + subscribeAnnotation, ) subscribeAnnotation.setDeclaredAttributeValue("order", value) diff --git a/src/main/kotlin/platform/velocity/creator/VelocityProjectConfig.kt b/src/main/kotlin/platform/velocity/creator/VelocityProjectConfig.kt deleted file mode 100644 index fe7567d5f..000000000 --- a/src/main/kotlin/platform/velocity/creator/VelocityProjectConfig.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.velocity.creator - -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.ProjectCreator -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleCreator -import com.demonwav.mcdev.creator.buildsystem.maven.MavenBuildSystem -import com.demonwav.mcdev.creator.buildsystem.maven.MavenCreator -import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.VersionRange -import com.intellij.openapi.module.Module -import com.intellij.util.lang.JavaVersion -import java.nio.file.Path - -class VelocityProjectConfig : ProjectConfig(), MavenCreator, GradleCreator { - - lateinit var mainClass: String - - var velocityApiVersion = "" - val apiVersion: SemanticVersion - get() = - if (velocityApiVersion.isBlank()) SemanticVersion.release() else SemanticVersion.parse(velocityApiVersion) - - override var type: PlatformType = PlatformType.VELOCITY - - val dependencies = mutableListOf() - fun hasDependencies() = listContainsAtLeastOne(dependencies) - fun setDependencies(string: String) { - dependencies.clear() - dependencies.addAll(commaSplit(string)) - } - - override val javaVersion: JavaVersion - get() = when { - apiVersion >= SemanticVersion.release(3) -> JavaVersion.compose(11) - else -> JavaVersion.compose(8) - } - - override fun buildMavenCreator( - rootDirectory: Path, - module: Module, - buildSystem: MavenBuildSystem - ): ProjectCreator { - return VelocityMavenCreator(rootDirectory, module, buildSystem, this) - } - - override val compatibleGradleVersions: VersionRange? = null - - override fun buildGradleCreator( - rootDirectory: Path, - module: Module, - buildSystem: GradleBuildSystem - ): ProjectCreator { - return VelocityGradleCreator(rootDirectory, module, buildSystem, this) - } -} diff --git a/src/main/kotlin/platform/velocity/creator/VelocityProjectCreator.kt b/src/main/kotlin/platform/velocity/creator/VelocityProjectCreator.kt deleted file mode 100644 index 7a7f93845..000000000 --- a/src/main/kotlin/platform/velocity/creator/VelocityProjectCreator.kt +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.velocity.creator - -import com.demonwav.mcdev.creator.BaseProjectCreator -import com.demonwav.mcdev.creator.BasicJavaClassStep -import com.demonwav.mcdev.creator.CreateDirectoriesStep -import com.demonwav.mcdev.creator.CreatorStep -import com.demonwav.mcdev.creator.buildsystem.BuildDependency -import com.demonwav.mcdev.creator.buildsystem.BuildRepository -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.AddGradlePluginStep -import com.demonwav.mcdev.creator.buildsystem.gradle.BasicGradleFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleBuildSystem -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleFiles -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleGitignoreStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradlePlugin -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleSetupStep -import com.demonwav.mcdev.creator.buildsystem.gradle.GradleWrapperStep -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenFinalizerStep -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenStep -import com.demonwav.mcdev.creator.buildsystem.maven.MavenBuildSystem -import com.demonwav.mcdev.creator.buildsystem.maven.MavenGitignoreStep -import com.demonwav.mcdev.platform.velocity.util.VelocityConstants -import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.runWriteAction -import com.demonwav.mcdev.util.runWriteTaskInSmartMode -import com.demonwav.mcdev.util.virtualFileOrError -import com.intellij.openapi.module.Module -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.project.Project -import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiJavaFile -import com.intellij.psi.PsiManager -import com.intellij.psi.codeStyle.CodeStyleManager -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.Paths - -sealed class VelocityProjectCreator( - protected val rootDirectory: Path, - protected val rootModule: Module, - protected val buildSystem: T, - protected val config: VelocityProjectConfig -) : BaseProjectCreator(rootModule, buildSystem) { - - protected fun setupDependencyStep(): VelocityDependenciesSetup { - val velocityApiVersion = config.velocityApiVersion - return VelocityDependenciesSetup(buildSystem, velocityApiVersion) - } - - protected fun setupMainClassSteps(): Pair { - val mainClassStep = createJavaClassStep(config.mainClass) { packageName, className -> - val version = config.apiVersion - VelocityTemplate.applyMainClass(project, packageName, className, config.hasDependencies(), version) - } - - return mainClassStep to VelocityMainClassModifyStep(project, buildSystem, config.mainClass, config) - } -} - -class VelocityMavenCreator( - rootDirectory: Path, - rootModule: Module, - buildSystem: MavenBuildSystem, - config: VelocityProjectConfig -) : VelocityProjectCreator(rootDirectory, rootModule, buildSystem, config) { - override fun getSteps(): Iterable { - val (mainClassStep, modifyStep) = setupMainClassSteps() - - val pomText = VelocityTemplate.applyPom(project, config) - - return listOf( - setupDependencyStep(), - BasicMavenStep(project, rootDirectory, buildSystem, config, pomText), - mainClassStep, - modifyStep, - MavenGitignoreStep(project, rootDirectory), - BasicMavenFinalizerStep(rootModule, rootDirectory) - ) - } -} - -class VelocityGradleCreator( - rootDirectory: Path, - rootModule: Module, - buildSystem: GradleBuildSystem, - config: VelocityProjectConfig -) : VelocityProjectCreator(rootDirectory, rootModule, buildSystem, config) { - - private val ideaExtPlugin = GradlePlugin("org.jetbrains.gradle.plugin.idea-ext", "1.0.1") - - override fun getSteps(): Iterable { - val (mainClassStep, modifyStep) = setupMainClassSteps() - - val buildText = VelocityTemplate.applyBuildGradle(project, buildSystem, config) - val propText = VelocityTemplate.applyGradleProp(project, null) - val settingsText = VelocityTemplate.applySettingsGradle(project, buildSystem.artifactId) - val files = GradleFiles(buildText, propText, settingsText) - - return listOf( - setupDependencyStep(), - CreateDirectoriesStep(buildSystem, rootDirectory), - GradleSetupStep(project, rootDirectory, buildSystem, files), - AddGradlePluginStep(project, rootDirectory, listOf(ideaExtPlugin)), - mainClassStep, - modifyStep, - buildConstantsStep(), - GradleWrapperStep(project, rootDirectory, buildSystem), - GradleGitignoreStep(project, rootDirectory), - BasicGradleFinalizerStep(rootModule, rootDirectory, buildSystem) - ) - } - - private fun buildConstantsStep(): BasicJavaClassStep { - return BasicJavaClassStep( - project, - buildSystem, - config.mainClass.replaceAfterLast('.', "BuildConstants"), - VelocityTemplate.applyBuildConstants(project, config.mainClass.substringBeforeLast('.')), - false - ) { it.dirsOrError.sourceDirectory.resolveSibling("templates") } - } -} - -class VelocityMainClassModifyStep( - private val project: Project, - private val buildSystem: BuildSystem, - private val classFullName: String, - private val config: VelocityProjectConfig -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - val dirs = buildSystem.dirsOrError - - project.runWriteTaskInSmartMode { - val classFile = dirs.sourceDirectory.resolve(Paths.get(classFullName.replace('.', '/') + ".java")) - if (!Files.isRegularFile(classFile)) { - throw IllegalStateException("$classFile is not an existing file") - } - - val psiFile = PsiManager.getInstance(project).findFile(classFile.virtualFileOrError) as? PsiJavaFile - ?: throw IllegalStateException("Failed to resolve PsiJavaFile for $classFile") - val psiClass = psiFile.classes[0] - val annotationBuilder = StringBuilder("@Plugin(") - annotationBuilder + "\nid = ${literal(buildSystem.artifactId)}" - annotationBuilder + ",\nname = ${literal(config.pluginName)}" - - if (buildSystem is GradleBuildSystem) { - annotationBuilder + ",\nversion = BuildConstants.VERSION" - } else { - annotationBuilder + ",\nversion = \"${buildSystem.version}\"" - } - - if (config.hasDescription()) { - annotationBuilder + ",\ndescription = ${literal(config.description)}" - } - - if (config.hasWebsite()) { - annotationBuilder + ",\nurl = ${literal(config.website)}" - } - - if (config.hasAuthors()) { - annotationBuilder + ",\nauthors = {${config.authors.joinToString(", ", transform = ::literal)}}" - } - - if (config.hasDependencies()) { - val deps = config.dependencies.joinToString(",\n") { "@Dependency(id = ${literal(it)})" } - annotationBuilder + ",\ndependencies = {\n$deps\n}" - } - - annotationBuilder + "\n)" - val factory = JavaPsiFacade.getElementFactory(project) - val pluginAnnotation = factory.createAnnotationFromText(annotationBuilder.toString(), null) - - psiFile.runWriteAction { - psiClass.modifierList?.let { it.addBefore(pluginAnnotation, it.firstChild) } - CodeStyleManager.getInstance(project).reformat(psiClass) - } - } - } - - private fun literal(text: String?): String { - if (text == null) { - return "\"\"" - } - return '"' + text.replace("\\", "\\\\").replace("\"", "\\\"") + '"' - } - - private operator fun StringBuilder.plus(text: String) = this.append(text) -} - -class VelocityDependenciesSetup( - private val buildSystem: BuildSystem, - private val velocityApiVersion: String -) : CreatorStep { - override fun runStep(indicator: ProgressIndicator) { - buildSystem.repositories.add( - BuildRepository( - "papermc-repo", - "https://repo.papermc.io/repository/maven-public/" - ) - ) - - buildSystem.dependencies.add( - BuildDependency( - "com.velocitypowered", - "velocity-api", - velocityApiVersion, - mavenScope = "provided", - gradleConfiguration = "compileOnly" - ) - ) - val semanticApiVersion = SemanticVersion.parse(velocityApiVersion) - buildSystem.dependencies.add( - BuildDependency( - "com.velocitypowered", - if (semanticApiVersion >= VelocityConstants.API_4) "velocity-annotation-processor" else "velocity-api", - velocityApiVersion, - mavenScope = if (semanticApiVersion >= VelocityConstants.API_4) "provided" else null, - gradleConfiguration = "annotationProcessor" - ) - ) - } -} diff --git a/src/main/kotlin/platform/velocity/creator/VelocityProjectSettingsWizard.form b/src/main/kotlin/platform/velocity/creator/VelocityProjectSettingsWizard.form deleted file mode 100644 index 2d9f5963d..000000000 --- a/src/main/kotlin/platform/velocity/creator/VelocityProjectSettingsWizard.form +++ /dev/null @@ -1,212 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/main/kotlin/platform/velocity/creator/VelocityProjectSettingsWizard.kt b/src/main/kotlin/platform/velocity/creator/VelocityProjectSettingsWizard.kt deleted file mode 100644 index 70311cec2..000000000 --- a/src/main/kotlin/platform/velocity/creator/VelocityProjectSettingsWizard.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.velocity.creator - -import com.demonwav.mcdev.creator.MinecraftModuleWizardStep -import com.demonwav.mcdev.creator.MinecraftProjectCreator -import com.demonwav.mcdev.creator.ValidatedField -import com.demonwav.mcdev.creator.ValidatedFieldType.CLASS_NAME -import com.demonwav.mcdev.creator.ValidatedFieldType.LIST -import com.demonwav.mcdev.creator.ValidatedFieldType.NON_BLANK -import com.demonwav.mcdev.creator.getVersionSelector -import javax.swing.JComboBox -import javax.swing.JComponent -import javax.swing.JLabel -import javax.swing.JPanel -import javax.swing.JTextField -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.swing.Swing -import kotlinx.coroutines.withContext - -class VelocityProjectSettingsWizard(private val creator: MinecraftProjectCreator) : MinecraftModuleWizardStep() { - - @ValidatedField(NON_BLANK) - private lateinit var pluginNameField: JTextField - - @ValidatedField(NON_BLANK, CLASS_NAME) - private lateinit var mainClassField: JTextField - private lateinit var panel: JPanel - private lateinit var title: JLabel - private lateinit var descriptionField: JTextField - - @ValidatedField(LIST) - private lateinit var authorsField: JTextField - private lateinit var websiteField: JTextField - - @ValidatedField(LIST) - private lateinit var dependField: JTextField - private lateinit var velocityApiVersionBox: JComboBox - private lateinit var errorLabel: JLabel - - private var config: VelocityProjectConfig? = null - - private var versionsLoaded: Boolean = false - - override fun getComponent(): JComponent { - return panel - } - - override fun validate(): Boolean { - return super.validate() && velocityApiVersionBox.selectedItem != null - } - - override fun updateStep() { - config = creator.config as? VelocityProjectConfig - if (config == null) { - return - } - val conf = config ?: return - - basicUpdateStep(creator, pluginNameField, mainClassField) - - if (versionsLoaded) { - return - } - - versionsLoaded = true - CoroutineScope(Dispatchers.Swing).launch { - try { - withContext(Dispatchers.IO) { getVersionSelector(conf.type) }.set(velocityApiVersionBox) - } catch (e: Exception) { - errorLabel.isVisible = true - } - } - } - - override fun isStepVisible(): Boolean { - return creator.config is VelocityProjectConfig - } - - override fun updateDataModel() { - val conf = this.config ?: return - - conf.pluginName = this.pluginNameField.text - conf.mainClass = this.mainClassField.text - conf.description = this.descriptionField.text - conf.website = this.websiteField.text - conf.velocityApiVersion = this.velocityApiVersionBox.selectedItem as String - - conf.setAuthors(this.authorsField.text) - conf.setDependencies(this.dependField.text) - } -} diff --git a/src/main/kotlin/platform/velocity/creator/VelocityTemplate.kt b/src/main/kotlin/platform/velocity/creator/VelocityTemplate.kt deleted file mode 100644 index be2756abc..000000000 --- a/src/main/kotlin/platform/velocity/creator/VelocityTemplate.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.platform.velocity.creator - -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import com.demonwav.mcdev.creator.buildsystem.maven.BasicMavenStep -import com.demonwav.mcdev.platform.BaseTemplate -import com.demonwav.mcdev.platform.velocity.util.VelocityConstants -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.VELOCITY_BUILD_CONSTANTS_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.VELOCITY_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.VELOCITY_GRADLE_PROPERTIES_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.VELOCITY_MAIN_CLASS_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.VELOCITY_MAIN_CLASS_V2_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.VELOCITY_POM_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.VELOCITY_SETTINGS_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.VELOCITY_SUBMODULE_BUILD_GRADLE_TEMPLATE -import com.demonwav.mcdev.util.MinecraftTemplates.Companion.VELOCITY_SUBMODULE_POM_TEMPLATE -import com.demonwav.mcdev.util.SemanticVersion -import com.intellij.openapi.project.Project - -object VelocityTemplate : BaseTemplate() { - - fun applyPom(project: Project, config: VelocityProjectConfig): String { - val props = BasicMavenStep.pluginVersions + ("JAVA_VERSION" to config.javaVersion.toFeatureString()) - return project.applyTemplate(VELOCITY_POM_TEMPLATE, props) - } - - fun applySubPom(project: Project, config: VelocityProjectConfig): String { - val props = BasicMavenStep.pluginVersions + ("JAVA_VERSION" to config.javaVersion.toFeatureString()) - return project.applyTemplate(VELOCITY_SUBMODULE_POM_TEMPLATE, props) - } - - fun applyMainClass( - project: Project, - packageName: String, - className: String, - hasDependencies: Boolean, - version: SemanticVersion - ): String { - val props = mutableMapOf( - "PACKAGE" to packageName, - "CLASS_NAME" to className - ) - - if (hasDependencies) { - props["HAS_DEPENDENCIES"] = "true" - } - - val template = if (version < VelocityConstants.API_2 || - (version >= VelocityConstants.API_3 && version < VelocityConstants.API_4) - ) { - VELOCITY_MAIN_CLASS_TEMPLATE // API 1 and 3 - } else { - VELOCITY_MAIN_CLASS_V2_TEMPLATE // API 2 and 4 (4+ maybe ?) - } - - return project.applyTemplate(template, props) - } - - fun applyBuildConstants(project: Project, packageName: String): String { - val props = mapOf( - "PACKAGE" to packageName - ) - - return project.applyTemplate(VELOCITY_BUILD_CONSTANTS_TEMPLATE, props) - } - - fun applyBuildGradle(project: Project, buildSystem: BuildSystem, config: VelocityProjectConfig): String { - val javaVersion = config.javaVersion.feature - val props = mapOf( - "GROUP_ID" to buildSystem.groupId, - "PLUGIN_ID" to buildSystem.artifactId, - "PLUGIN_VERSION" to buildSystem.version, - "JAVA_VERSION" to javaVersion - ) - - return project.applyTemplate(VELOCITY_BUILD_GRADLE_TEMPLATE, props) - } - - fun applyGradleProp(project: Project, javaVersion: Int?): String = - project.applyTemplate(VELOCITY_GRADLE_PROPERTIES_TEMPLATE, mapOf("JAVA_VERSION" to javaVersion)) - - fun applySettingsGradle(project: Project, artifactId: String): String { - val props = mapOf("ARTIFACT_ID" to artifactId) - - return project.applyTemplate(VELOCITY_SETTINGS_GRADLE_TEMPLATE, props) - } - - fun applySubBuildGradle(project: Project, buildSystem: BuildSystem): String { - val props = mapOf( - "COMMON_PROJECT_NAME" to buildSystem.commonModuleName, - "PLUGIN_ID" to buildSystem.artifactId - ) - - return project.applyTemplate(VELOCITY_SUBMODULE_BUILD_GRADLE_TEMPLATE, props) - } -} diff --git a/src/main/kotlin/platform/velocity/creator/asset-steps.kt b/src/main/kotlin/platform/velocity/creator/asset-steps.kt new file mode 100644 index 000000000..dc63c61a0 --- /dev/null +++ b/src/main/kotlin/platform/velocity/creator/asset-steps.kt @@ -0,0 +1,158 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.velocity.creator + +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.AbstractRunBuildSystemStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.splitPackage +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractLongRunningStep +import com.demonwav.mcdev.creator.step.AbstractModNameStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DependStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.MainClassStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.platform.velocity.util.VelocityConstants +import com.demonwav.mcdev.util.MinecraftTemplates +import com.demonwav.mcdev.util.runWriteAction +import com.demonwav.mcdev.util.runWriteTaskInSmartMode +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.text.StringUtil +import com.intellij.openapi.vfs.VfsUtil +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiJavaFile +import com.intellij.psi.PsiManager +import com.intellij.psi.codeStyle.CodeStyleManager +import java.nio.file.Path + +class VelocityProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating project files" + + override fun setupAssets(project: Project) { + val mainClass = data.getUserData(MainClassStep.KEY) ?: return + val dependencies = data.getUserData(DependStep.KEY) ?: emptyList() + val (packageName, className) = splitPackage(mainClass) + val version = data.getUserData(VelocityVersionStep.KEY) ?: return + + assets.addTemplateProperties( + "PACKAGE" to packageName, + "CLASS_NAME" to className, + ) + + if (dependencies.isNotEmpty()) { + assets.addTemplateProperties( + "HAS_DEPENDENCIES" to "true", + ) + } + + val template = if (version < VelocityConstants.API_2 || + (version >= VelocityConstants.API_3 && version < VelocityConstants.API_4) + ) { + MinecraftTemplates.VELOCITY_MAIN_CLASS_TEMPLATE // API 1 and 3 + } else { + MinecraftTemplates.VELOCITY_MAIN_CLASS_V2_TEMPLATE // API 2 and 4 (4+ maybe ?) + } + + assets.addTemplates( + project, + "src/main/java/${mainClass.replace('.', '/')}.java" to template, + ) + } +} + +class VelocityModifyMainClassStep( + parent: NewProjectWizardStep, + private val isGradle: Boolean, +) : AbstractLongRunningStep(parent) { + override val description = "Patching main class" + + override fun perform(project: Project) { + val buildSystemProps = findStep>() + val pluginName = data.getUserData(AbstractModNameStep.KEY) ?: return + val mainClassName = data.getUserData(MainClassStep.KEY) ?: return + val mainClassFile = "${context.projectFileDirectory}/src/main/java/${mainClassName.replace('.', '/')}.java" + val description = data.getUserData(DescriptionStep.KEY) ?: "" + val website = data.getUserData(WebsiteStep.KEY) ?: "" + val authors = data.getUserData(AuthorsStep.KEY) ?: emptyList() + val dependencies = data.getUserData(DependStep.KEY) ?: emptyList() + + project.runWriteTaskInSmartMode { + val mainClassVirtualFile = VfsUtil.findFile(Path.of(mainClassFile), true) + ?: return@runWriteTaskInSmartMode + val mainClassPsi = PsiManager.getInstance(project).findFile(mainClassVirtualFile) as? PsiJavaFile + ?: return@runWriteTaskInSmartMode + + val psiClass = mainClassPsi.classes[0] + val annotation = buildString { + append("@Plugin(") + append("\nid = ${literal(buildSystemProps.artifactId)}") + append(",\nname = ${literal(pluginName)}") + + if (isGradle) { + append(",\nversion = BuildConstants.VERSION") + } else { + append(",\nversion = \"${buildSystemProps.version}\"") + } + + if (description.isNotBlank()) { + append(",\ndescription = ${literal(description)}") + } + + if (website.isNotBlank()) { + append(",\nurl = ${literal(website)}") + } + + if (authors.isNotEmpty()) { + append(",\nauthors = {${authors.joinToString(", ", transform = ::literal)}}") + } + + if (dependencies.isNotEmpty()) { + val deps = dependencies.joinToString(",\n") { "@Dependency(id = ${literal(it)})" } + append(",\ndependencies = {\n$deps\n}") + } + + append("\n)") + } + + val factory = JavaPsiFacade.getElementFactory(project) + val pluginAnnotation = factory.createAnnotationFromText(annotation, null) + + mainClassPsi.runWriteAction { + psiClass.modifierList?.let { it.addBefore(pluginAnnotation, it.firstChild) } + CodeStyleManager.getInstance(project).reformat(psiClass) + } + } + } + + private fun literal(text: String?): String { + if (text == null) { + return "\"\"" + } + return '"' + StringUtil.escapeStringCharacters(text) + '"' + } +} + +class VelocityBuildSystemStep(parent: NewProjectWizardStep) : AbstractBuildSystemStep(parent) { + override val platformName = "Velocity" +} + +class VelocityPostBuildSystemStep(parent: NewProjectWizardStep) : AbstractRunBuildSystemStep( + parent, + VelocityBuildSystemStep::class.java, +) { + override val step = BuildSystemSupport.POST_STEP +} diff --git a/src/main/kotlin/platform/velocity/creator/gradle-steps.kt b/src/main/kotlin/platform/velocity/creator/gradle-steps.kt new file mode 100644 index 000000000..7d9f9981c --- /dev/null +++ b/src/main/kotlin/platform/velocity/creator/gradle-steps.kt @@ -0,0 +1,132 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.velocity.creator + +import com.demonwav.mcdev.creator.EmptyStep +import com.demonwav.mcdev.creator.JdkProjectSetupFinalizer +import com.demonwav.mcdev.creator.addGradleGitignore +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractPatchGradleFilesStep +import com.demonwav.mcdev.creator.buildsystem.BuildDependency +import com.demonwav.mcdev.creator.buildsystem.BuildRepository +import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.buildsystem.GradleImportStep +import com.demonwav.mcdev.creator.buildsystem.GradlePlugin +import com.demonwav.mcdev.creator.buildsystem.GradleWrapperStep +import com.demonwav.mcdev.creator.buildsystem.ReformatBuildGradleStep +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.gitEnabled +import com.demonwav.mcdev.creator.splitPackage +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.MainClassStep +import com.demonwav.mcdev.platform.velocity.util.VelocityConstants +import com.demonwav.mcdev.util.MinecraftTemplates +import com.intellij.ide.wizard.NewProjectWizardBaseData.Companion.baseData +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.project.Project + +class VelocityGradleSupport : BuildSystemSupport { + @Suppress("MoveLambdaOutsideParentheses") + override fun createStep(step: String, parent: NewProjectWizardStep): NewProjectWizardStep { + return when (step) { + BuildSystemSupport.PRE_STEP -> VelocityGradleFilesStep(parent).chain( + ::VelocityPatchGradleFilesStep, + ::GradleWrapperStep, + ) + BuildSystemSupport.POST_STEP -> GradleImportStep(parent).chain( + ::ReformatBuildGradleStep, + { VelocityModifyMainClassStep(it, true) }, + ) + else -> EmptyStep(parent) + } + } +} + +class VelocityGradleFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating Gradle files" + + override fun setupAssets(project: Project) { + val projectName = baseData.name + val buildSystemProps = findStep>() + val javaVersion = findStep().preferredJdk.ordinal + val mainClass = data.getUserData(MainClassStep.KEY) ?: return + val (mainPackage, _) = splitPackage(mainClass) + + assets.addTemplateProperties( + "GROUP_ID" to buildSystemProps.groupId, + "ARTIFACT_ID" to buildSystemProps.artifactId, + "PLUGIN_ID" to buildSystemProps.artifactId, + "PLUGIN_VERSION" to buildSystemProps.version, + "JAVA_VERSION" to javaVersion, + "PROJECT_NAME" to projectName, + "PACKAGE" to mainPackage, + ) + + val buildConstantsJava = "src/main/java/${mainPackage.replace('.', '/')}/BuildConstants.java" + assets.addTemplates( + project, + "build.gradle" to MinecraftTemplates.VELOCITY_BUILD_GRADLE_TEMPLATE, + "gradle.properties" to MinecraftTemplates.VELOCITY_GRADLE_PROPERTIES_TEMPLATE, + "settings.gradle" to MinecraftTemplates.VELOCITY_SETTINGS_GRADLE_TEMPLATE, + buildConstantsJava to MinecraftTemplates.VELOCITY_BUILD_CONSTANTS_TEMPLATE, + ) + + if (gitEnabled) { + assets.addGradleGitignore(project) + } + } +} + +class VelocityPatchGradleFilesStep(parent: NewProjectWizardStep) : AbstractPatchGradleFilesStep(parent) { + override fun patch(project: Project, gradleFiles: GradleFiles) { + val velocityApiVersion = data.getUserData(VelocityVersionStep.KEY) ?: return + + addPlugins( + project, + gradleFiles.buildGradle, + listOf( + GradlePlugin("org.jetbrains.gradle.plugin.idea-ext", "1.0.1"), + ), + ) + addRepositories( + project, + gradleFiles.buildGradle, + listOf( + BuildRepository( + "papermc-repo", + "https://repo.papermc.io/repository/maven-public/", + ), + ), + ) + val annotationArtifactId = + if (velocityApiVersion >= VelocityConstants.API_4) "velocity-annotation-processor" else "velocity-api" + addDependencies( + project, + gradleFiles.buildGradle, + listOf( + BuildDependency( + "com.velocitypowered", + "velocity-api", + velocityApiVersion.toString(), + gradleConfiguration = "compileOnly", + ), + BuildDependency( + "com.velocitypowered", + annotationArtifactId, + velocityApiVersion.toString(), + gradleConfiguration = "annotationProcessor", + ), + ), + ) + } +} diff --git a/src/main/kotlin/platform/velocity/creator/maven-steps.kt b/src/main/kotlin/platform/velocity/creator/maven-steps.kt new file mode 100644 index 000000000..399011bc7 --- /dev/null +++ b/src/main/kotlin/platform/velocity/creator/maven-steps.kt @@ -0,0 +1,97 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.velocity.creator + +import com.demonwav.mcdev.creator.EmptyStep +import com.demonwav.mcdev.creator.JdkProjectSetupFinalizer +import com.demonwav.mcdev.creator.addMavenGitignore +import com.demonwav.mcdev.creator.addTemplates +import com.demonwav.mcdev.creator.buildsystem.AbstractPatchPomStep +import com.demonwav.mcdev.creator.buildsystem.BuildDependency +import com.demonwav.mcdev.creator.buildsystem.BuildRepository +import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport +import com.demonwav.mcdev.creator.buildsystem.MavenImportStep +import com.demonwav.mcdev.creator.buildsystem.ReformatPomStep +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.gitEnabled +import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.platform.velocity.util.VelocityConstants +import com.demonwav.mcdev.util.MinecraftTemplates +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.project.Project +import com.intellij.psi.xml.XmlTag +import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel + +class VelocityMavenSupport : BuildSystemSupport { + override fun createStep(step: String, parent: NewProjectWizardStep): NewProjectWizardStep { + return when (step) { + BuildSystemSupport.PRE_STEP -> VelocityMavenFilesStep(parent).chain(::VelocityPatchPomStep) + BuildSystemSupport.POST_STEP -> MavenImportStep(parent).chain( + ::ReformatPomStep, + { VelocityModifyMainClassStep(it, false) }, + ) + else -> EmptyStep(parent) + } + } +} + +class VelocityMavenFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { + override val description = "Creating Maven files" + + override fun setupAssets(project: Project) { + val javaVersion = findStep().preferredJdk.ordinal + assets.addTemplateProperties( + "JAVA_VERSION" to javaVersion, + ) + assets.addTemplates( + project, + "pom.xml" to MinecraftTemplates.VELOCITY_POM_TEMPLATE, + ) + if (gitEnabled) { + assets.addMavenGitignore(project) + } + } +} + +class VelocityPatchPomStep(parent: NewProjectWizardStep) : AbstractPatchPomStep(parent) { + override fun patchPom(model: MavenDomProjectModel, root: XmlTag) { + super.patchPom(model, root) + + val velocityApiVersion = data.getUserData(VelocityVersionStep.KEY) ?: return + + val annotationArtifactId = + if (velocityApiVersion >= VelocityConstants.API_4) "velocity-annotation-processor" else "velocity-api" + setupDependencies( + model, + listOf( + BuildRepository( + "papermc-repo", + "https://repo.papermc.io/repository/maven-public/", + ), + ), + listOf( + BuildDependency( + "com.velocitypowered", + "velocity-api", + velocityApiVersion.toString(), + mavenScope = "provided", + ), + BuildDependency( + "com.velocitypowered", + annotationArtifactId, + velocityApiVersion.toString(), + mavenScope = if (velocityApiVersion >= VelocityConstants.API_4) "provided" else null, + ), + ), + ) + } +} diff --git a/src/main/kotlin/platform/velocity/creator/ui-steps.kt b/src/main/kotlin/platform/velocity/creator/ui-steps.kt new file mode 100644 index 000000000..dc68fc883 --- /dev/null +++ b/src/main/kotlin/platform/velocity/creator/ui-steps.kt @@ -0,0 +1,112 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.platform.velocity.creator + +import com.demonwav.mcdev.creator.JdkProjectSetupFinalizer +import com.demonwav.mcdev.creator.PlatformVersion +import com.demonwav.mcdev.creator.chain +import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.getVersionSelector +import com.demonwav.mcdev.creator.platformtype.PluginPlatformStep +import com.demonwav.mcdev.creator.step.AbstractCollapsibleStep +import com.demonwav.mcdev.creator.step.AbstractLatentStep +import com.demonwav.mcdev.creator.step.AbstractSelectVersionStep +import com.demonwav.mcdev.creator.step.AuthorsStep +import com.demonwav.mcdev.creator.step.DependStep +import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.MainClassStep +import com.demonwav.mcdev.creator.step.PluginNameStep +import com.demonwav.mcdev.creator.step.WebsiteStep +import com.demonwav.mcdev.platform.PlatformType +import com.demonwav.mcdev.util.SemanticVersion +import com.demonwav.mcdev.util.asyncIO +import com.demonwav.mcdev.util.onShown +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.ide.wizard.chain +import com.intellij.openapi.project.Project +import com.intellij.openapi.projectRoots.JavaSdkVersion +import com.intellij.openapi.util.Key +import com.intellij.ui.dsl.builder.Panel +import kotlinx.coroutines.coroutineScope + +class VelocityPlatformStep(parent: PluginPlatformStep) : AbstractLatentStep(parent) { + override val description = "download Velocity versions" + + override suspend fun computeData() = coroutineScope { + try { + asyncIO { getVersionSelector(PlatformType.VELOCITY) }.await() + } catch (e: Throwable) { + null + } + } + + override fun createStep(data: PlatformVersion) = + VelocityVersionStep(this, data.versions.mapNotNull(SemanticVersion::tryParse)).chain( + ::PluginNameStep, + ::MainClassStep, + ::VelocityOptionalSettingsStep, + ::VelocityBuildSystemStep, + ::VelocityProjectFilesStep, + ::VelocityPostBuildSystemStep, + ) + + class Factory : PluginPlatformStep.Factory { + override val name = "Velocity" + + override fun createStep(parent: PluginPlatformStep) = VelocityPlatformStep(parent) + } +} + +class VelocityVersionStep( + parent: NewProjectWizardStep, + versions: List, +) : AbstractSelectVersionStep(parent, versions) { + override val label = "Velocity Version:" + + override fun setupUI(builder: Panel) { + super.setupUI(builder) + versionProperty.afterChange { + applyJdkVersion() + } + versionBox.onShown { + applyJdkVersion() + } + } + + override fun setupProject(project: Project) { + data.putUserData(KEY, SemanticVersion.tryParse(version)) + applyJdkVersion() + } + + private fun applyJdkVersion() { + SemanticVersion.tryParse(version)?.let { version -> + val preferredJdk = when { + version >= SemanticVersion.release(3) -> JavaSdkVersion.JDK_11 + else -> JavaSdkVersion.JDK_1_8 + } + findStep().setPreferredJdk(preferredJdk, "Velocity $version") + } + } + + companion object { + val KEY = Key.create("${VelocityVersionStep::class.java.name}.version") + } +} + +class VelocityOptionalSettingsStep(parent: NewProjectWizardStep) : AbstractCollapsibleStep(parent) { + override val title = "Optional Settings" + + override fun createStep() = DescriptionStep(this).chain( + ::AuthorsStep, + ::WebsiteStep, + ::DependStep, + ) +} diff --git a/src/main/kotlin/platform/velocity/generation/VelocityEventGenerationPanel.kt b/src/main/kotlin/platform/velocity/generation/VelocityEventGenerationPanel.kt index 2fa0de1e5..5c9568cd3 100644 --- a/src/main/kotlin/platform/velocity/generation/VelocityEventGenerationPanel.kt +++ b/src/main/kotlin/platform/velocity/generation/VelocityEventGenerationPanel.kt @@ -21,7 +21,7 @@ class VelocityEventGenerationPanel(chosenClass: PsiClass) : EventGenerationPanel private lateinit var parentPanel: JPanel private lateinit var eventOrderComboBox: JComboBox - override val panel: JPanel? + override val panel: JPanel get() { // Not static because the form builder is not reliable eventOrderComboBox.addItem("FIRST") @@ -35,7 +35,7 @@ class VelocityEventGenerationPanel(chosenClass: PsiClass) : EventGenerationPanel return parentPanel } - override fun gatherData(): GenerationData? { + override fun gatherData(): GenerationData { return VelocityGenerationData(eventOrderComboBox.selectedItem as String) } } diff --git a/src/main/kotlin/toml/TomlSchema.kt b/src/main/kotlin/toml/TomlSchema.kt index 8ebd7c64c..c4963fe6d 100644 --- a/src/main/kotlin/toml/TomlSchema.kt +++ b/src/main/kotlin/toml/TomlSchema.kt @@ -26,7 +26,7 @@ import org.toml.lang.psi.TomlTable // https://github.com/intellij-rust/intellij-rust/blob/42d0981d45e8830aa5efe82c45688bab8223201c/toml/src/main/kotlin/org/rust/toml/completion/RsTomlKeysCompletionProvider.kt class TomlSchema private constructor( val topLevelEntries: Set, - private val tables: List + private val tables: List, ) { fun topLevelKeys(isArray: Boolean): Set = @@ -88,12 +88,12 @@ private fun TomlElement.getComments(): List { data class TomlSchemaEntry( val key: String, val description: List, - val type: TomlValueType? + val type: TomlValueType?, ) class TomlTableSchema( val name: String, val isArray: Boolean, val entries: Set, - val description: List + val description: List, ) diff --git a/src/main/kotlin/toml/platform/forge/ModsTomlDocumentationProvider.kt b/src/main/kotlin/toml/platform/forge/ModsTomlDocumentationProvider.kt index 3859f9923..5de9b4215 100644 --- a/src/main/kotlin/toml/platform/forge/ModsTomlDocumentationProvider.kt +++ b/src/main/kotlin/toml/platform/forge/ModsTomlDocumentationProvider.kt @@ -30,7 +30,7 @@ class ModsTomlDocumentationProvider : DocumentationProvider { editor: Editor, file: PsiFile, contextElement: PsiElement?, - targetOffset: Int + targetOffset: Int, ): PsiElement? { if (!isModsToml(contextElement)) { return null diff --git a/src/main/kotlin/toml/platform/forge/completion/ModsTomlCompletionContributor.kt b/src/main/kotlin/toml/platform/forge/completion/ModsTomlCompletionContributor.kt index 25c033b43..e8548810a 100644 --- a/src/main/kotlin/toml/platform/forge/completion/ModsTomlCompletionContributor.kt +++ b/src/main/kotlin/toml/platform/forge/completion/ModsTomlCompletionContributor.kt @@ -54,9 +54,10 @@ class ModsTomlCompletionContributor : CompletionContributor() { extend( CompletionType.BASIC, inModsTomlValueWithKey(key), - ModsTomlKnownStringValuesCompletionProvider(values) + ModsTomlKnownStringValuesCompletionProvider(values), ) + @Suppress("SameParameterValue") private fun extendKnownValues(key: String, vararg values: String) = extendKnownValues(key, values.toSet()) @@ -69,7 +70,7 @@ object ModsTomlKeyCompletionProvider : CompletionProvider( override fun addCompletions( parameters: CompletionParameters, context: ProcessingContext, - result: CompletionResultSet + result: CompletionResultSet, ) { val schema = ModsTomlSchema.get(parameters.position.project) @@ -86,16 +87,16 @@ object ModsTomlKeyCompletionProvider : CompletionProvider( is TomlTable -> false else -> return } - schema.topLevelKeys(isArray) - table.entries.map { it.key.text } + schema.topLevelKeys(isArray) - table.entries.mapTo(HashSet()) { it.key.text } } is TomlKeyValue -> when (table) { null -> { schema.topLevelEntries.map { it.key } - - key.containingFile.children.filterIsInstance().map { it.key.text } + key.containingFile.children.filterIsInstance().mapTo(HashSet()) { it.key.text } } is TomlHeaderOwner -> { val tableName = table.header.key?.segments?.firstOrNull()?.text ?: return - schema.keysForTable(tableName) - table.entries.map { it.key.text } + schema.keysForTable(tableName) - table.entries.mapTo(HashSet()) { it.key.text } } else -> return } @@ -110,13 +111,13 @@ class ModsTomlKnownStringValuesCompletionProvider(private val knownValues: Set() .filter { it.header.key?.name == "mods" } - .any { it.entries.find { it.key.text == "modId" }?.value?.stringValue() == targetId } + .any { it.entries.find { entry -> entry.key.text == "modId" }?.value?.stringValue() == targetId } if (!isDeclaredId) { holder.registerProblem(keySegment, "Mod $targetId is not declared in this file") } diff --git a/src/main/kotlin/toml/platform/forge/reference/ModsTomlReferenceContributor.kt b/src/main/kotlin/toml/platform/forge/reference/ModsTomlReferenceContributor.kt index 8d03ff418..955d816d0 100644 --- a/src/main/kotlin/toml/platform/forge/reference/ModsTomlReferenceContributor.kt +++ b/src/main/kotlin/toml/platform/forge/reference/ModsTomlReferenceContributor.kt @@ -85,13 +85,11 @@ class ModsTomlDependencyIdReference(keySegment: TomlKeySegment) : PsiReferenceBa override fun resolve(): PsiElement? { val referencedId = element.text return element.containingFile.childrenOfType() - .filter { it.header.key?.segments?.firstOrNull()?.text == "mods" } - .mapNotNull { table -> + .filter { it.header.key?.segments?.firstOrNull()?.text == "mods" }.firstNotNullOfOrNull { table -> table.entries.find { it.key.text == "modId" && it.value?.stringValue() == referencedId }?.value } - .firstOrNull() } override fun getVariants(): Array = diff --git a/src/main/kotlin/toml/toml-patterns.kt b/src/main/kotlin/toml/toml-patterns.kt index 708c09828..b7da65a49 100644 --- a/src/main/kotlin/toml/toml-patterns.kt +++ b/src/main/kotlin/toml/toml-patterns.kt @@ -25,13 +25,17 @@ inline fun inModsToml(): PsiElementPattern.Capture = fun inModsToml(clazz: Class): PsiElementPattern.Capture = PlatformPatterns.psiElement(clazz).inVirtualFile(VirtualFilePattern().withName(ForgeConstants.MODS_TOML)) -fun inModsTomlKey() = inModsToml().withParent(TomlKeySegment::class.java) +fun inModsTomlKey(): PsiElementPattern.Capture = + inModsToml().withParent(TomlKeySegment::class.java) -fun tomlKeyValue(key: String) = PlatformPatterns.psiElement(TomlKeyValue::class.java) - .withChild(PlatformPatterns.psiElement(TomlKey::class.java).withText(key)) +fun tomlKeyValue(key: String): PsiElementPattern.Capture = + PlatformPatterns.psiElement(TomlKeyValue::class.java) + .withChild(PlatformPatterns.psiElement(TomlKey::class.java).withText(key)) -fun inModsTomlValueWithKey(key: String) = inModsToml().inside(tomlKeyValue(key)) +fun inModsTomlValueWithKey(key: String): PsiElementPattern.Capture = + inModsToml().inside(tomlKeyValue(key)) -fun inDependenciesHeaderId() = inModsToml().inside(PlatformPatterns.psiElement(TomlTableHeader::class.java)) - // [[dependencies.]] - .afterLeaf(PlatformPatterns.psiElement().withText(".").afterLeaf("dependencies")) +fun inDependenciesHeaderId(): PsiElementPattern.Capture = + inModsToml().inside(PlatformPatterns.psiElement(TomlTableHeader::class.java)) + // [[dependencies.]] + .afterLeaf(PlatformPatterns.psiElement().withText(".").afterLeaf("dependencies")) diff --git a/src/main/kotlin/toml/toml-psi.kt b/src/main/kotlin/toml/toml-psi.kt index d963935e2..1b2a76f56 100644 --- a/src/main/kotlin/toml/toml-psi.kt +++ b/src/main/kotlin/toml/toml-psi.kt @@ -30,7 +30,8 @@ val TomlValue.tomlType: TomlValueType? TomlElementTypes.BOOLEAN -> TomlValueType.BooleanType TomlElementTypes.NUMBER -> TomlValueType.NumberType TomlElementTypes.BASIC_STRING, TomlElementTypes.LITERAL_STRING, - TomlElementTypes.MULTILINE_BASIC_STRING, TomlElementTypes.MULTILINE_LITERAL_STRING -> TomlValueType.StringType + TomlElementTypes.MULTILINE_BASIC_STRING, TomlElementTypes.MULTILINE_LITERAL_STRING, + -> TomlValueType.StringType TomlElementTypes.DATE_TIME -> TomlValueType.DateType else -> null } diff --git a/src/main/kotlin/translations/TranslationEditorNotificationProvider.kt b/src/main/kotlin/translations/TranslationEditorNotificationProvider.kt index 45ec0fa76..b27030742 100644 --- a/src/main/kotlin/translations/TranslationEditorNotificationProvider.kt +++ b/src/main/kotlin/translations/TranslationEditorNotificationProvider.kt @@ -36,7 +36,7 @@ class TranslationEditorNotificationProvider : EditorNotificationProvider { override fun collectNotificationData( project: Project, - file: VirtualFile + file: VirtualFile, ): Function = Function { createNotificationPanel(file, project) } private fun createNotificationPanel(file: VirtualFile, project: Project): InfoPanel? { @@ -48,9 +48,9 @@ class TranslationEditorNotificationProvider : EditorNotificationProvider { val missingTranslations = getMissingTranslations(project, file) if (missingTranslations.any()) { val panel = InfoPanel() - panel.setText("Translation file doesn't match default one (${TranslationConstants.DEFAULT_LOCALE} locale).") + panel.text = "Translation file doesn't match default one (${TranslationConstants.DEFAULT_LOCALE} locale)." panel.createActionLabel( - "Add missing default entries (won't reflect changes in original English localization)" + "Add missing default entries (won't reflect changes in original English localization)", ) { val psi = PsiManager.getInstance(project).findFile(file) ?: return@createActionLabel psi.applyWriteAction { @@ -70,7 +70,7 @@ class TranslationEditorNotificationProvider : EditorNotificationProvider { project, "Would you like to sort all translations now?", "Sort Translations", - Messages.getQuestionIcon() + Messages.getQuestionIcon(), ) if (sort == Messages.YES) { TranslationSorter.query(project, psi, Ordering.LIKE_DEFAULT) diff --git a/src/main/kotlin/translations/TranslationFiles.kt b/src/main/kotlin/translations/TranslationFiles.kt index 442cf38f7..15ab1dd7c 100644 --- a/src/main/kotlin/translations/TranslationFiles.kt +++ b/src/main/kotlin/translations/TranslationFiles.kt @@ -72,7 +72,7 @@ object TranslationFiles { when { element is JsonProperty && element.value is JsonStringLiteral -> Translation( element.name, - (element.value as JsonStringLiteral).value + (element.value as JsonStringLiteral).value, ) element is LangEntry -> Translation(element.key, element.value) else -> null @@ -120,7 +120,7 @@ object TranslationFiles { val files = FileTypeIndex.getFiles( if (jsonVersion) JsonFileType.INSTANCE else LangFileType, - GlobalSearchScope.moduleScope(module) + GlobalSearchScope.moduleScope(module), ).filter { getLocale(it) == TranslationConstants.DEFAULT_LOCALE } val domains = files.asSequence().mapNotNull { it.mcDomain }.distinct().sorted().toList() if (domains.size > 1) { @@ -129,7 +129,7 @@ object TranslationFiles { .createPopupChooserBuilder(domains) .setTitle("Choose Resource Domain") .setAdText( - "There are multiple resource domains with localization files, choose one for this translation." + "There are multiple resource domains with localization files, choose one for this translation.", ) .setItemChosenCallback { domain -> write(files.filter { f -> f.mcDomain == domain }) @@ -166,7 +166,7 @@ object TranslationFiles { doc.setText("{\n$content\n}") } else -> throw IllegalArgumentException( - "Cannot replace translations in file '${file.name}' of unknown type!" + "Cannot replace translations in file '${file.name}' of unknown type!", ) } } @@ -175,7 +175,7 @@ object TranslationFiles { val doc = FileDocumentManager.getInstance().getDocument(this.virtualFile) ?: return val content = generateLangFile( this.lastChild != null && this.lastChild.node.elementType != LangTypes.LINE_ENDING, - entries + entries, ) doc.insertString(this.lastChild?.textOffset ?: 0, content) } @@ -213,7 +213,7 @@ object TranslationFiles { private fun generateJsonFile( leadingComma: Boolean, indent: CharSequence, - entries: Iterable + entries: Iterable, ): CharSequence { val result = StringBuilder() @@ -238,13 +238,13 @@ object TranslationFiles { return result.removeSuffix("\n").removeSuffix(",") } - fun buildFileEntries(project: Project, locale: String, entries: Sequence, keepComments: Int) = + fun buildFileEntries(project: Project, locale: String, entries: Iterable, keepComments: Int) = sequence { for (entry in entries) { val langElement = TranslationInverseIndex.findElements( entry.key, GlobalSearchScope.allScope(project), - locale + locale, ) .asSequence() .mapNotNull { it as? LangEntry } @@ -259,7 +259,7 @@ object TranslationFiles { element: PsiElement, maxDepth: Int, acc: MutableList = mutableListOf(), - depth: Int = 0 + depth: Int = 0, ): List { if (maxDepth != 0 && depth >= maxDepth) { return acc @@ -287,7 +287,7 @@ object TranslationFiles { .getContainingFiles( TranslationIndex.NAME, TranslationConstants.DEFAULT_LOCALE, - GlobalSearchScope.moduleScope(module) + GlobalSearchScope.moduleScope(module), ) .asSequence() .filter { domain == null || it.mcDomain == domain } diff --git a/src/main/kotlin/translations/actions/TranslationSortOrderDialog.kt b/src/main/kotlin/translations/actions/TranslationSortOrderDialog.kt index 85feee077..f511b9c7c 100644 --- a/src/main/kotlin/translations/actions/TranslationSortOrderDialog.kt +++ b/src/main/kotlin/translations/actions/TranslationSortOrderDialog.kt @@ -56,14 +56,14 @@ class TranslationSortOrderDialog(excludeDefaultOption: Boolean, defaultSelection override fun windowClosing(e: WindowEvent?) { onCancel() } - } + }, ) // call onCancel() on ESCAPE contentPane.registerKeyboardAction( { onCancel() }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), - JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, ) } @@ -82,7 +82,7 @@ class TranslationSortOrderDialog(excludeDefaultOption: Boolean, defaultSelection value: Any?, index: Int, isSelected: Boolean, - cellHasFocus: Boolean + cellHasFocus: Boolean, ): Component { val displayValue = (value as? Ordering)?.text return super.getListCellRendererComponent(list, displayValue, index, isSelected, cellHasFocus) diff --git a/src/main/kotlin/translations/folding.kt b/src/main/kotlin/translations/folding.kt index 42f0cf9ff..367bc33b1 100644 --- a/src/main/kotlin/translations/folding.kt +++ b/src/main/kotlin/translations/folding.kt @@ -33,7 +33,7 @@ class TranslationCodeFoldingOptionsProvider : title = "Minecraft" checkBox( "Translation Strings", - TranslationFoldingSettings.instance::shouldFoldTranslations + TranslationFoldingSettings.instance::shouldFoldTranslations, ) { TranslationFoldingSettings.instance.shouldFoldTranslations = it } @@ -44,7 +44,7 @@ class TranslationCodeFoldingOptionsProvider : class TranslationFoldingSettings : PersistentStateComponent { data class State( - var shouldFoldTranslations: Boolean = true + var shouldFoldTranslations: Boolean = true, ) private var state = State() @@ -98,8 +98,8 @@ class TranslationFoldingBuilder : FoldingBuilderEx() { "\"Insufficient parameters for formatting '${translation.text}'\"" } else { "\"${translation.text}\"" - } - ) + }, + ), ) } } diff --git a/src/main/kotlin/translations/identification/LiteralTranslationIdentifier.kt b/src/main/kotlin/translations/identification/LiteralTranslationIdentifier.kt index c2f042659..d17d14aa9 100644 --- a/src/main/kotlin/translations/identification/LiteralTranslationIdentifier.kt +++ b/src/main/kotlin/translations/identification/LiteralTranslationIdentifier.kt @@ -22,9 +22,9 @@ class LiteralTranslationIdentifier : TranslationIdentifier key = result.key.copy( infix = result.key.infix.replace( CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED, - "" - ) - ) + "", + ), + ), ) } return null diff --git a/src/main/kotlin/translations/identification/ReferenceTranslationIdentifier.kt b/src/main/kotlin/translations/identification/ReferenceTranslationIdentifier.kt index bbdeed954..7977240b8 100644 --- a/src/main/kotlin/translations/identification/ReferenceTranslationIdentifier.kt +++ b/src/main/kotlin/translations/identification/ReferenceTranslationIdentifier.kt @@ -40,9 +40,9 @@ class ReferenceTranslationIdentifier : TranslationIdentifier { project: Project, element: PsiExpression, container: PsiElement, - referenceElement: PsiElement + referenceElement: PsiElement, ): TranslationInstance? { if (container is PsiExpressionList && container.parent is PsiCallExpression) { val call = container.parent as PsiCallExpression @@ -64,7 +64,7 @@ abstract class TranslationIdentifier { translationKey, formatted, if (superfluousParams >= 0) FormattingError.SUPERFLUOUS else null, - superfluousParams + superfluousParams, ) } catch (ignored: MissingFormatArgumentException) { return TranslationInstance( @@ -73,7 +73,7 @@ abstract class TranslationIdentifier { referenceElement, translationKey, translation, - FormattingError.MISSING + FormattingError.MISSING, ) } } else { @@ -82,7 +82,7 @@ abstract class TranslationIdentifier { function.matchedIndex, referenceElement, translationKey, - null + null, ) } } diff --git a/src/main/kotlin/translations/identification/TranslationInstance.kt b/src/main/kotlin/translations/identification/TranslationInstance.kt index 08dec8942..0d96a3642 100644 --- a/src/main/kotlin/translations/identification/TranslationInstance.kt +++ b/src/main/kotlin/translations/identification/TranslationInstance.kt @@ -22,7 +22,7 @@ data class TranslationInstance( val key: Key, val text: String?, val formattingError: FormattingError? = null, - val superfluousVarargStart: Int = -1 + val superfluousVarargStart: Int = -1, ) { data class Key(val prefix: String, val infix: String, val suffix: String) { val full = (prefix + infix + suffix).trim() @@ -38,68 +38,68 @@ data class TranslationInstance( MemberReference( TranslationConstants.FORMAT, "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;", - TranslationConstants.I18N_CLIENT_CLASS + TranslationConstants.I18N_CLIENT_CLASS, ), 0, formatting = true, - obfuscatedName = true + obfuscatedName = true, ), TranslationFunction( MemberReference( TranslationConstants.GET, "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;", - TranslationConstants.I18N_CLIENT_LANG_CLASS + TranslationConstants.I18N_CLIENT_LANG_CLASS, ), 0, formatting = true, - obfuscatedName = true + obfuscatedName = true, ), TranslationFunction( MemberReference( TranslationConstants.EXISTS, "(Ljava/lang/String;)Z", - TranslationConstants.I18N_CLIENT_LANG_CLASS + TranslationConstants.I18N_CLIENT_LANG_CLASS, ), 0, formatting = false, obfuscatedName = true, - foldParameters = TranslationFunction.FoldingScope.PARAMETERS + foldParameters = TranslationFunction.FoldingScope.PARAMETERS, ), TranslationFunction( MemberReference( TranslationConstants.TRANSLATE_TO_LOCAL, "(Ljava/lang/String;)Ljava/lang/String;", - TranslationConstants.I18N_COMMON_CLASS + TranslationConstants.I18N_COMMON_CLASS, ), 0, formatting = false, - obfuscatedName = true + obfuscatedName = true, ), TranslationFunction( MemberReference( TranslationConstants.TRANSLATE_TO_LOCAL_FORMATTED, "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;", - TranslationConstants.I18N_COMMON_CLASS + TranslationConstants.I18N_COMMON_CLASS, ), 0, formatting = true, - obfuscatedName = true + obfuscatedName = true, ), TranslationFunction( MemberReference( TranslationConstants.CONSTRUCTOR, "(Ljava/lang/String;[Ljava/lang/Object;)V", - TranslationConstants.TRANSLATION_COMPONENT_CLASS + TranslationConstants.TRANSLATION_COMPONENT_CLASS, ), 0, formatting = true, - foldParameters = TranslationFunction.FoldingScope.PARAMETERS + foldParameters = TranslationFunction.FoldingScope.PARAMETERS, ), TranslationFunction( MemberReference( TranslationConstants.CONSTRUCTOR, "(Ljava/lang/String;)V", - TranslationConstants.TRANSLATABLE_COMPONENT + TranslationConstants.TRANSLATABLE_COMPONENT, ), 0, formatting = false, @@ -108,7 +108,7 @@ data class TranslationInstance( MemberReference( TranslationConstants.CONSTRUCTOR, "(Ljava/lang/String;[Ljava/lang/Object;)V", - TranslationConstants.TRANSLATABLE_COMPONENT + TranslationConstants.TRANSLATABLE_COMPONENT, ), 0, formatting = true, @@ -118,7 +118,7 @@ data class TranslationInstance( TranslationConstants.CREATE_COMPONENT_TRANSLATION, "(Lnet/minecraft/commands/CommandSource;Ljava/lang/String;" + "[Ljava/lang/Object;)Lnet/minecraft/network/chat/BaseComponent;", - TranslationConstants.TEXT_COMPONENT_HELPER + TranslationConstants.TEXT_COMPONENT_HELPER, ), 1, formatting = true, @@ -128,17 +128,17 @@ data class TranslationInstance( MemberReference( TranslationConstants.CONSTRUCTOR, "(Ljava/lang/String;[Ljava/lang/Object;)V", - TranslationConstants.COMMAND_EXCEPTION_CLASS + TranslationConstants.COMMAND_EXCEPTION_CLASS, ), 0, formatting = true, - foldParameters = TranslationFunction.FoldingScope.PARAMETERS + foldParameters = TranslationFunction.FoldingScope.PARAMETERS, ), TranslationFunction( MemberReference( TranslationConstants.SET_BLOCK_NAME, "(Ljava/lang/String;)Lnet/minecraft/block/Block;", - McpConstants.BLOCK + McpConstants.BLOCK, ), 0, formatting = false, @@ -146,13 +146,13 @@ data class TranslationInstance( foldParameters = TranslationFunction.FoldingScope.PARAMETERS, prefix = "tile.", suffix = ".name", - obfuscatedName = true + obfuscatedName = true, ), TranslationFunction( MemberReference( TranslationConstants.SET_ITEM_NAME, "(Ljava/lang/String;)Lnet/minecraft/item/Item;", - McpConstants.ITEM + McpConstants.ITEM, ), 0, formatting = false, @@ -160,91 +160,91 @@ data class TranslationInstance( foldParameters = TranslationFunction.FoldingScope.PARAMETERS, prefix = "item.", suffix = ".name", - obfuscatedName = true + obfuscatedName = true, ), TranslationFunction( MemberReference( TranslationConstants.CONSTRUCTOR, "(Ljava/lang/String;ILjava/lang/String;)V", - TranslationConstants.KEY_MAPPING + TranslationConstants.KEY_MAPPING, ), 0, formatting = false, - foldParameters = TranslationFunction.FoldingScope.PARAMETER + foldParameters = TranslationFunction.FoldingScope.PARAMETER, ), TranslationFunction( MemberReference( TranslationConstants.CONSTRUCTOR, "(Ljava/lang/String;ILjava/lang/String;)V", - TranslationConstants.KEY_MAPPING + TranslationConstants.KEY_MAPPING, ), 2, formatting = false, - foldParameters = TranslationFunction.FoldingScope.PARAMETER + foldParameters = TranslationFunction.FoldingScope.PARAMETER, ), TranslationFunction( MemberReference( TranslationConstants.CONSTRUCTOR, "(Ljava/lang/String;Lcom/mojang/blaze3d/platform/InputConstants\$Type;ILjava/lang/String;)V", - TranslationConstants.KEY_MAPPING + TranslationConstants.KEY_MAPPING, ), 0, formatting = false, - foldParameters = TranslationFunction.FoldingScope.PARAMETER + foldParameters = TranslationFunction.FoldingScope.PARAMETER, ), TranslationFunction( MemberReference( TranslationConstants.CONSTRUCTOR, "(Ljava/lang/String;Lcom/mojang/blaze3d/platform/InputConstants\$Type;ILjava/lang/String;)V", - TranslationConstants.KEY_MAPPING + TranslationConstants.KEY_MAPPING, ), 3, formatting = false, - foldParameters = TranslationFunction.FoldingScope.PARAMETER + foldParameters = TranslationFunction.FoldingScope.PARAMETER, ), TranslationFunction( MemberReference( TranslationConstants.CONSTRUCTOR, "(Ljava/lang/String;Lnet/minecraftforge/client/settings/IKeyConflictContext;" + "Lcom/mojang/blaze3d/platform/InputConstants\$Type;ILjava/lang/String;)V", - TranslationConstants.KEY_MAPPING + TranslationConstants.KEY_MAPPING, ), 0, formatting = false, - foldParameters = TranslationFunction.FoldingScope.PARAMETER + foldParameters = TranslationFunction.FoldingScope.PARAMETER, ), TranslationFunction( MemberReference( TranslationConstants.CONSTRUCTOR, "(Ljava/lang/String;Lnet/minecraftforge/client/settings/IKeyConflictContext;" + "Lcom/mojang/blaze3d/platform/InputConstants\$Type;ILjava/lang/String;)V", - TranslationConstants.KEY_MAPPING + TranslationConstants.KEY_MAPPING, ), 4, formatting = false, - foldParameters = TranslationFunction.FoldingScope.PARAMETER + foldParameters = TranslationFunction.FoldingScope.PARAMETER, ), TranslationFunction( MemberReference( TranslationConstants.CONSTRUCTOR, "(Ljava/lang/String;Lnet/minecraftforge/client/settings/IKeyConflictContext;" + "Lcom/mojang/blaze3d/platform/InputConstants\$Key;Ljava/lang/String;)V", - TranslationConstants.KEY_MAPPING + TranslationConstants.KEY_MAPPING, ), 0, formatting = false, - foldParameters = TranslationFunction.FoldingScope.PARAMETER + foldParameters = TranslationFunction.FoldingScope.PARAMETER, ), TranslationFunction( MemberReference( TranslationConstants.CONSTRUCTOR, "(Ljava/lang/String;Lnet/minecraftforge/client/settings/IKeyConflictContext;" + "Lcom/mojang/blaze3d/platform/InputConstants\$Key;Ljava/lang/String;)V", - TranslationConstants.KEY_MAPPING + TranslationConstants.KEY_MAPPING, ), 3, formatting = false, - foldParameters = TranslationFunction.FoldingScope.PARAMETER + foldParameters = TranslationFunction.FoldingScope.PARAMETER, ), TranslationFunction( MemberReference( @@ -252,11 +252,11 @@ data class TranslationInstance( "(Ljava/lang/String;Lnet/minecraftforge/client/settings/IKeyConflictContext;" + "Lnet/minecraftforge/client/settings/KeyModifier;" + "Lcom/mojang/blaze3d/platform/InputConstants\$Type;ILjava/lang/String;)V", - TranslationConstants.KEY_MAPPING + TranslationConstants.KEY_MAPPING, ), 0, formatting = false, - foldParameters = TranslationFunction.FoldingScope.PARAMETER + foldParameters = TranslationFunction.FoldingScope.PARAMETER, ), TranslationFunction( MemberReference( @@ -264,11 +264,11 @@ data class TranslationInstance( "(Ljava/lang/String;Lnet/minecraftforge/client/settings/IKeyConflictContext;" + "Lnet/minecraftforge/client/settings/KeyModifier;" + "Lcom/mojang/blaze3d/platform/InputConstants\$Type;ILjava/lang/String;)V", - TranslationConstants.KEY_MAPPING + TranslationConstants.KEY_MAPPING, ), 5, formatting = false, - foldParameters = TranslationFunction.FoldingScope.PARAMETER + foldParameters = TranslationFunction.FoldingScope.PARAMETER, ), TranslationFunction( MemberReference( @@ -276,11 +276,11 @@ data class TranslationInstance( "(Ljava/lang/String;Lnet/minecraftforge/client/settings/IKeyConflictContext;" + "Lnet/minecraftforge/client/settings/KeyModifier;" + "Lcom/mojang/blaze3d/platform/InputConstants\$Key;Ljava/lang/String;)V", - TranslationConstants.KEY_MAPPING + TranslationConstants.KEY_MAPPING, ), 0, formatting = false, - foldParameters = TranslationFunction.FoldingScope.PARAMETER + foldParameters = TranslationFunction.FoldingScope.PARAMETER, ), TranslationFunction( MemberReference( @@ -288,22 +288,22 @@ data class TranslationInstance( "(Ljava/lang/String;Lnet/minecraftforge/client/settings/IKeyConflictContext;" + "Lnet/minecraftforge/client/settings/KeyModifier;" + "Lcom/mojang/blaze3d/platform/InputConstants\$Key;Ljava/lang/String;)V", - TranslationConstants.KEY_MAPPING + TranslationConstants.KEY_MAPPING, ), 4, formatting = false, - foldParameters = TranslationFunction.FoldingScope.PARAMETER + foldParameters = TranslationFunction.FoldingScope.PARAMETER, ), TranslationFunction( MemberReference( TranslationConstants.INPUT_CONSTANTS_KEY_GET_KEY, "(Ljava/lang/String;)Lcom/mojang/blaze3d/platform/InputConstants\$Key;", - TranslationConstants.INPUT_CONSTANTS_KEY + TranslationConstants.INPUT_CONSTANTS_KEY, ), 0, formatting = false, foldParameters = TranslationFunction.FoldingScope.PARAMETER, - obfuscatedName = true + obfuscatedName = true, ), ) diff --git a/src/main/kotlin/translations/index/TranslationIndex.kt b/src/main/kotlin/translations/index/TranslationIndex.kt index e1e116f05..b068b8ff4 100644 --- a/src/main/kotlin/translations/index/TranslationIndex.kt +++ b/src/main/kotlin/translations/index/TranslationIndex.kt @@ -57,7 +57,7 @@ class TranslationIndex : FileBasedIndexExtension( return getEntries( GlobalSearchScope.fileScope(project, file), TranslationFiles.getLocale(file) ?: return emptySequence(), - file.mcDomain + file.mcDomain, ).flatten() } @@ -66,22 +66,18 @@ class TranslationIndex : FileBasedIndexExtension( return getEntries( GlobalSearchScope.fileScope(file), TranslationFiles.getLocale(virtualFile) ?: return emptySequence(), - virtualFile.mcDomain + virtualFile.mcDomain, ).flatten() } fun getAllDefaultEntries(project: Project, domain: String? = null) = getEntries(GlobalSearchScope.allScope(project), TranslationConstants.DEFAULT_LOCALE, domain) - fun getProjectDefaultEntries(project: Project, domain: String? = null) = + private fun getProjectDefaultEntries(project: Project, domain: String? = null) = getEntries(GlobalSearchScope.projectScope(project), TranslationConstants.DEFAULT_LOCALE, domain) fun getEntries(scope: GlobalSearchScope, locale: String, domain: String? = null) = - FileBasedIndex.getInstance().getValues( - TranslationIndex.NAME, - locale, - scope - ).asSequence() + FileBasedIndex.getInstance().getValues(NAME, locale, scope,).asSequence() .filter { domain == null || it.sourceDomain == domain } private fun Sequence.flatten() = this.flatMap { it.translations.asSequence() } @@ -108,7 +104,7 @@ class TranslationIndex : FileBasedIndexExtension( private object Indexer : DataIndexer { override fun map(inputData: FileContent): MutableMap { val domain = inputData.file.mcDomain ?: return mutableMapOf() - val entry = TranslationProvider.INSTANCES[inputData.fileType]?.map(domain, inputData) + val entry = TranslationProvider.INSTANCES[inputData.fileType.name]?.map(domain, inputData) ?: return mutableMapOf() val locale = TranslationFiles.getLocale(inputData.file) ?: return mutableMapOf() return mutableMapOf(locale to entry) diff --git a/src/main/kotlin/translations/index/TranslationInputFilter.kt b/src/main/kotlin/translations/index/TranslationInputFilter.kt index 02e5da630..8c7375208 100644 --- a/src/main/kotlin/translations/index/TranslationInputFilter.kt +++ b/src/main/kotlin/translations/index/TranslationInputFilter.kt @@ -12,6 +12,7 @@ package com.demonwav.mcdev.translations.index import com.demonwav.mcdev.translations.TranslationFiles import com.intellij.openapi.fileTypes.FileType +import com.intellij.openapi.fileTypes.FileTypeManager import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.Consumer import com.intellij.util.indexing.FileBasedIndex @@ -19,7 +20,7 @@ import com.intellij.util.indexing.FileBasedIndex object TranslationInputFilter : FileBasedIndex.FileTypeSpecificInputFilter { override fun registerFileTypesUsedForIndexing(fileTypeSink: Consumer) { for (fileType in TranslationProvider.INSTANCES.keys) { - fileTypeSink.consume(fileType) + fileTypeSink.consume(FileTypeManager.getInstance().findFileTypeByName(fileType)) } } diff --git a/src/main/kotlin/translations/index/TranslationInverseIndex.kt b/src/main/kotlin/translations/index/TranslationInverseIndex.kt index 32934f26b..3943953bb 100644 --- a/src/main/kotlin/translations/index/TranslationInverseIndex.kt +++ b/src/main/kotlin/translations/index/TranslationInverseIndex.kt @@ -54,7 +54,7 @@ class TranslationInverseIndex : FileBasedIndexExtension() { locale == null || TranslationFiles.getLocale(it) == locale } .flatMap { - TranslationProvider.INSTANCES[it.fileType]?.findElements(project, it, key) ?: emptyList() + TranslationProvider.INSTANCES[it.fileType.name]?.findElements(project, it, key) ?: emptyList() } } } @@ -62,7 +62,7 @@ class TranslationInverseIndex : FileBasedIndexExtension() { private object Indexer : DataIndexer { override fun map(inputData: FileContent): MutableMap { val domain = inputData.file.mcDomain ?: return mutableMapOf() - val entry = TranslationProvider.INSTANCES[inputData.fileType]?.map(domain, inputData) + val entry = TranslationProvider.INSTANCES[inputData.fileType.name]?.map(domain, inputData) ?: return mutableMapOf() return entry.translations.associateTo(mutableMapOf()) { it.key to null } } diff --git a/src/main/kotlin/translations/index/providers.kt b/src/main/kotlin/translations/index/providers.kt index dd8a58fc7..c9fec446c 100644 --- a/src/main/kotlin/translations/index/providers.kt +++ b/src/main/kotlin/translations/index/providers.kt @@ -38,9 +38,11 @@ interface TranslationProvider { fun findElements(project: Project, file: VirtualFile, key: String): List companion object { + // Use name, using FileType as map keys can leak and cause problems with plugin unloading + // name is unique among all file types val INSTANCES = mapOf( - JsonFileType.INSTANCE to JsonTranslationProvider, - LangFileType to LangTranslationProvider + JsonFileType.INSTANCE.name to JsonTranslationProvider, + LangFileType.name to LangTranslationProvider, ) } } @@ -67,19 +69,19 @@ object JsonTranslationProvider : TranslationProvider { val psiFile = PsiManager.getInstance(project).findFile(file) as? JsonFile ?: return emptyList() return CachedValuesManager.getCachedValue( psiFile, - Key>>("translation_lookup.$key") + Key>>("translation_lookup.$key"), ) { val value = psiFile.topLevelValue as? JsonObject CachedValueProvider.Result.create( value?.propertyList?.filter { it.name == key } ?: emptyList(), - PsiModificationTracker.MODIFICATION_COUNT + PsiModificationTracker.MODIFICATION_COUNT, ) } } } object LangTranslationProvider : TranslationProvider { - override fun map(domain: String, input: FileContent): TranslationIndexEntry? { + override fun map(domain: String, input: FileContent): TranslationIndexEntry { val translations = input.contentAsText .lineSequence() .filter { !it.startsWith("#") && it.isNotEmpty() } @@ -94,11 +96,11 @@ object LangTranslationProvider : TranslationProvider { val psiFile = PsiManager.getInstance(project).findFile(file) as? LangFile ?: return emptyList() return CachedValuesManager.getCachedValue( psiFile, - Key("translation_lookup.$key") + Key("translation_lookup.$key"), ) { CachedValueProvider.Result.create( psiFile.childrenOfType().filter { it.key == key }, - PsiModificationTracker.MODIFICATION_COUNT + PsiModificationTracker.MODIFICATION_COUNT, ) } } diff --git a/src/main/kotlin/translations/inspections/ChangeTranslationQuickFix.kt b/src/main/kotlin/translations/inspections/ChangeTranslationQuickFix.kt index 97936e1b5..d9db718eb 100644 --- a/src/main/kotlin/translations/inspections/ChangeTranslationQuickFix.kt +++ b/src/main/kotlin/translations/inspections/ChangeTranslationQuickFix.kt @@ -34,7 +34,7 @@ class ChangeTranslationQuickFix(private val name: String) : LocalQuickFix { val popup = ChooseByNamePopup.createPopup( project, TranslationGotoModel(project, key.prefix, key.suffix), - null + null, ) popup.invoke( object : ChooseByNamePopupComponent.Callback() { @@ -43,19 +43,19 @@ class ChangeTranslationQuickFix(private val name: String) : LocalQuickFix { literal.containingFile.runWriteAction { val insertion = selectedKey.substring( key.prefix.length, - selectedKey.length - key.suffix.length + selectedKey.length - key.suffix.length, ) literal.replace( JavaPsiFacade.getInstance(project).elementFactory.createExpressionFromText( "\"$insertion\"", - literal.context - ) + literal.context, + ), ) } } }, ModalityState.current(), - false + false, ) } catch (ignored: IncorrectOperationException) { } diff --git a/src/main/kotlin/translations/inspections/MissingFormatInspection.kt b/src/main/kotlin/translations/inspections/MissingFormatInspection.kt index d8006a396..d936bb1fb 100644 --- a/src/main/kotlin/translations/inspections/MissingFormatInspection.kt +++ b/src/main/kotlin/translations/inspections/MissingFormatInspection.kt @@ -42,7 +42,7 @@ class MissingFormatInspection : TranslationInspection() { expression, "There are missing formatting arguments to satisfy '${result.text}'", ProblemHighlightType.GENERIC_ERROR, - *quickFixes + *quickFixes, ) } } diff --git a/src/main/kotlin/translations/inspections/NoTranslationInspection.kt b/src/main/kotlin/translations/inspections/NoTranslationInspection.kt index b540956ad..aa5b0edd3 100644 --- a/src/main/kotlin/translations/inspections/NoTranslationInspection.kt +++ b/src/main/kotlin/translations/inspections/NoTranslationInspection.kt @@ -39,7 +39,7 @@ class NoTranslationInspection : TranslationInspection() { "The given translation key does not exist", ProblemHighlightType.GENERIC_ERROR, CreateTranslationQuickFix, - ChangeTranslationQuickFix("Use existing translation") + ChangeTranslationQuickFix("Use existing translation"), ) } } @@ -57,7 +57,7 @@ class NoTranslationInspection : TranslationInspection() { val result = Messages.showInputDialog( "Enter default value for \"$key\":", "Create Translation", - Messages.getQuestionIcon() + Messages.getQuestionIcon(), ) if (result != null) { TranslationFiles.add(literal, key, result) diff --git a/src/main/kotlin/translations/inspections/SuperfluousFormatInspection.kt b/src/main/kotlin/translations/inspections/SuperfluousFormatInspection.kt index 57e193721..e4011da82 100644 --- a/src/main/kotlin/translations/inspections/SuperfluousFormatInspection.kt +++ b/src/main/kotlin/translations/inspections/SuperfluousFormatInspection.kt @@ -56,9 +56,9 @@ class SuperfluousFormatInspection : TranslationInspection() { RemoveArgumentsQuickFix( SmartPointerManager.getInstance(holder.project) .createSmartPsiElementPointer(result.foldingElement), - result.superfluousVarargStart + result.superfluousVarargStart, ), - ChangeTranslationQuickFix("Use a different translation") + ChangeTranslationQuickFix("Use a different translation"), ) } } @@ -66,20 +66,20 @@ class SuperfluousFormatInspection : TranslationInspection() { private fun registerProblem( expression: PsiExpression, result: TranslationInstance, - vararg quickFixes: LocalQuickFix + vararg quickFixes: LocalQuickFix, ) { holder.registerProblem( expression, "There are missing formatting arguments to satisfy '${result.text}'", ProblemHighlightType.GENERIC_ERROR, - *quickFixes + *quickFixes, ) } } private class RemoveArgumentsQuickFix( private val call: SmartPsiElementPointer, - private val position: Int + private val position: Int, ) : LocalQuickFix { override fun getName() = "Remove superfluous arguments" diff --git a/src/main/kotlin/translations/intentions/ConvertToTranslationIntention.kt b/src/main/kotlin/translations/intentions/ConvertToTranslationIntention.kt index 956deb80f..418a5c6bf 100644 --- a/src/main/kotlin/translations/intentions/ConvertToTranslationIntention.kt +++ b/src/main/kotlin/translations/intentions/ConvertToTranslationIntention.kt @@ -50,13 +50,13 @@ class ConvertToTranslationIntention : PsiElementBaseIntentionAction() { } override fun checkInput(inputString: String): Boolean { - return !inputString.isEmpty() && !inputString.contains('=') + return inputString.isNotEmpty() && !inputString.contains('=') } override fun canClose(inputString: String): Boolean { - return !inputString.isEmpty() && !inputString.contains('=') + return inputString.isNotEmpty() && !inputString.contains('=') } - } + }, ) val key = result.first val replaceLiteral = result.second @@ -67,7 +67,7 @@ class ConvertToTranslationIntention : PsiElementBaseIntentionAction() { psi.runWriteAction { val expression = JavaPsiFacade.getElementFactory(project).createExpressionFromText( "net.minecraft.client.resources.I18n.format(\"$key\")", - element.context + element.context, ) if (psi.language === JavaLanguage.INSTANCE) { JavaCodeStyleManager.getInstance(project) diff --git a/src/main/kotlin/translations/intentions/RemoveDuplicatesIntention.kt b/src/main/kotlin/translations/intentions/RemoveDuplicatesIntention.kt index 4fe1b75dd..6b8d15c6d 100644 --- a/src/main/kotlin/translations/intentions/RemoveDuplicatesIntention.kt +++ b/src/main/kotlin/translations/intentions/RemoveDuplicatesIntention.kt @@ -30,7 +30,7 @@ class RemoveDuplicatesIntention(private val translation: Translation) : PsiEleme val keep = TranslationFiles.seekTranslation(element) ?: return val entries = TranslationInverseIndex.findElements( translation.key, - GlobalSearchScope.fileScope(element.containingFile) + GlobalSearchScope.fileScope(element.containingFile), ) for (other in entries) { if (other !== keep) { diff --git a/src/main/kotlin/translations/intentions/TrimKeyIntention.kt b/src/main/kotlin/translations/intentions/TrimKeyIntention.kt index c8ac5137a..fa611b30e 100644 --- a/src/main/kotlin/translations/intentions/TrimKeyIntention.kt +++ b/src/main/kotlin/translations/intentions/TrimKeyIntention.kt @@ -25,7 +25,7 @@ class TrimKeyIntention : PsiElementBaseIntentionAction() { override fun isAvailable(project: Project, editor: Editor, element: PsiElement): Boolean { val translation = TranslationFiles.toTranslation( - TranslationFiles.seekTranslation(element) ?: return false + TranslationFiles.seekTranslation(element) ?: return false, ) ?: return false return translation.key != translation.trimmedKey diff --git a/src/main/kotlin/translations/lang/LangCommenter.kt b/src/main/kotlin/translations/lang/LangCommenter.kt index a51aef9df..3ea8a704e 100644 --- a/src/main/kotlin/translations/lang/LangCommenter.kt +++ b/src/main/kotlin/translations/lang/LangCommenter.kt @@ -13,7 +13,7 @@ package com.demonwav.mcdev.translations.lang import com.intellij.lang.Commenter class LangCommenter : Commenter { - override fun getLineCommentPrefix(): String? = "#" + override fun getLineCommentPrefix(): String = "#" override fun getBlockCommentPrefix(): String? = null override fun getBlockCommentSuffix(): String? = null override fun getCommentedBlockCommentPrefix(): String? = null diff --git a/src/main/kotlin/translations/lang/colors/LangColorSettingsPage.kt b/src/main/kotlin/translations/lang/colors/LangColorSettingsPage.kt index 4111c7104..c28a0ad90 100644 --- a/src/main/kotlin/translations/lang/colors/LangColorSettingsPage.kt +++ b/src/main/kotlin/translations/lang/colors/LangColorSettingsPage.kt @@ -35,7 +35,7 @@ class LangColorSettingsPage : ColorSettingsPage { AttributesDescriptor("Key", LangSyntaxHighlighter.KEY), AttributesDescriptor("Separator", LangSyntaxHighlighter.EQUALS), AttributesDescriptor("Value", LangSyntaxHighlighter.VALUE), - AttributesDescriptor("Comments", LangSyntaxHighlighter.COMMENT) + AttributesDescriptor("Comments", LangSyntaxHighlighter.COMMENT), ) } } diff --git a/src/main/kotlin/translations/lang/formatting/LangBlock.kt b/src/main/kotlin/translations/lang/formatting/LangBlock.kt index cd4371b3e..994f2f8de 100644 --- a/src/main/kotlin/translations/lang/formatting/LangBlock.kt +++ b/src/main/kotlin/translations/lang/formatting/LangBlock.kt @@ -40,7 +40,7 @@ class LangBlock(node: ASTNode, wrap: Wrap?, alignment: Alignment?, private val s child, Wrap.createWrap(WrapType.NONE, false), Alignment.createAlignment(), - spacingBuilder + spacingBuilder, ) blocks.add(block) } @@ -50,7 +50,7 @@ class LangBlock(node: ASTNode, wrap: Wrap?, alignment: Alignment?, private val s return blocks } - override fun getIndent() = Indent.getNoneIndent() + override fun getIndent(): Indent = Indent.getNoneIndent() override fun getSpacing(child1: Block?, child2: Block) = spacingBuilder.getSpacing(this, child1, child2) diff --git a/src/main/kotlin/translations/lang/formatting/LangFormattingModelBuilder.kt b/src/main/kotlin/translations/lang/formatting/LangFormattingModelBuilder.kt index 292d074a3..19925bbc6 100644 --- a/src/main/kotlin/translations/lang/formatting/LangFormattingModelBuilder.kt +++ b/src/main/kotlin/translations/lang/formatting/LangFormattingModelBuilder.kt @@ -30,9 +30,9 @@ class LangFormattingModelBuilder : FormattingModelBuilder { formattingContext.node, Wrap.createWrap(WrapType.NONE, false), Alignment.createAlignment(), - createSpaceBuilder(formattingContext.codeStyleSettings) + createSpaceBuilder(formattingContext.codeStyleSettings), ), - formattingContext.codeStyleSettings + formattingContext.codeStyleSettings, ) } diff --git a/src/main/kotlin/translations/lang/structure/LangStructureViewFactory.kt b/src/main/kotlin/translations/lang/structure/LangStructureViewFactory.kt index 1c9936c83..93a3cc592 100644 --- a/src/main/kotlin/translations/lang/structure/LangStructureViewFactory.kt +++ b/src/main/kotlin/translations/lang/structure/LangStructureViewFactory.kt @@ -17,7 +17,7 @@ import com.intellij.openapi.editor.Editor import com.intellij.psi.PsiFile class LangStructureViewFactory : PsiStructureViewFactory { - override fun getStructureViewBuilder(psiFile: PsiFile): StructureViewBuilder? { + override fun getStructureViewBuilder(psiFile: PsiFile): StructureViewBuilder { return object : TreeBasedStructureViewBuilder() { override fun createStructureViewModel(editor: Editor?) = LangStructureViewModel(psiFile) } diff --git a/src/main/kotlin/translations/reference/TranslationGotoModel.kt b/src/main/kotlin/translations/reference/TranslationGotoModel.kt index 19cc5f125..131b226f2 100644 --- a/src/main/kotlin/translations/reference/TranslationGotoModel.kt +++ b/src/main/kotlin/translations/reference/TranslationGotoModel.kt @@ -26,19 +26,19 @@ class TranslationGotoModel(project: Project, private val prefix: String, private ContributorsBasedGotoByModel( project, arrayOf( - ChooseByNameContributor.SYMBOL_EP_NAME.findExtensionOrFail(TranslationGotoSymbolContributor::class.java) - ) + ChooseByNameContributor.SYMBOL_EP_NAME.findExtensionOrFail(TranslationGotoSymbolContributor::class.java), + ), ) { override fun acceptItem(item: NavigationItem?): Boolean { return TranslationFiles.getLocale( - (item as PsiElement).containingFile?.virtualFile + (item as PsiElement).containingFile?.virtualFile, ) == TranslationConstants.DEFAULT_LOCALE } override fun getElementsByName( name: String, parameters: FindSymbolParameters, - canceled: ProgressIndicator + canceled: ProgressIndicator, ): Array { val superResult = super.getElementsByName(name, parameters, canceled).asSequence() val result = TreeSet { o1, o2 -> @@ -48,7 +48,7 @@ class TranslationGotoModel(project: Project, private val prefix: String, private superResult.map { it as PsiNamedElement }.filter { val key = it.name ?: return@filter false key.startsWith(prefix) && key.endsWith(suffix) - } + }, ) return result.toArray() } diff --git a/src/main/kotlin/translations/reference/TranslationGotoSymbolContributor.kt b/src/main/kotlin/translations/reference/TranslationGotoSymbolContributor.kt index fa829d7b9..c54f1c8ad 100644 --- a/src/main/kotlin/translations/reference/TranslationGotoSymbolContributor.kt +++ b/src/main/kotlin/translations/reference/TranslationGotoSymbolContributor.kt @@ -40,7 +40,7 @@ class TranslationGotoSymbolContributor : ChooseByNameContributor { name: String, pattern: String, project: Project, - includeNonProjectItems: Boolean + includeNonProjectItems: Boolean, ): Array { val scope = if (includeNonProjectItems) { GlobalSearchScope.allScope(project) diff --git a/src/main/kotlin/translations/reference/TranslationReference.kt b/src/main/kotlin/translations/reference/TranslationReference.kt index 086804431..dbe66a055 100644 --- a/src/main/kotlin/translations/reference/TranslationReference.kt +++ b/src/main/kotlin/translations/reference/TranslationReference.kt @@ -38,14 +38,14 @@ class TranslationReference( private val renameHandler: (element: PsiElement, range: TextRange, newName: String) -> PsiElement = { elem, range, newName -> ElementManipulators.getManipulator(elem).handleContentChange(elem, range, newName)!! - } + }, ) : PsiReferenceBase.Poly(element, textRange, false), PsiPolyVariantReference { override fun multiResolve(incompleteCode: Boolean): Array { val project = myElement.project val entries = TranslationInverseIndex.findElements( key.full, GlobalSearchScope.allScope(project), - TranslationConstants.DEFAULT_LOCALE + TranslationConstants.DEFAULT_LOCALE, ) return entries.mapToArray(::PsiElementResolveResult) } diff --git a/src/main/kotlin/translations/reference/TranslationReferenceSearch.kt b/src/main/kotlin/translations/reference/TranslationReferenceSearch.kt index 1b289a6b3..5d2e30809 100644 --- a/src/main/kotlin/translations/reference/TranslationReferenceSearch.kt +++ b/src/main/kotlin/translations/reference/TranslationReferenceSearch.kt @@ -63,7 +63,7 @@ class TranslationReferenceSearch : QueryExecutor { val result = identifier.identifyUnsafe(element) if (result != null) { @@ -43,13 +43,13 @@ class JavaReferenceContributor : PsiReferenceContributor() { TranslationReference( referenceElement, TextRange(1, referenceElement.textLength - 1), - result.key - ) + result.key, + ), ) } return emptyArray() } - } + }, ) } } @@ -62,7 +62,7 @@ class JsonReferenceContributor : PsiReferenceContributor() { object : PsiReferenceProvider() { override fun getReferencesByElement( element: PsiElement, - context: ProcessingContext + context: ProcessingContext, ): Array { if (!TranslationFiles.isTranslationFile(element.containingFile?.virtualFile)) { return arrayOf() @@ -76,13 +76,13 @@ class JsonReferenceContributor : PsiReferenceContributor() { TranslationReference( element, nameTextRange.shiftRight(1).grown(-2), - TranslationInstance.Key("", entry.name, "") + TranslationInstance.Key("", entry.name, ""), ) { elem, _, newName -> (elem as JsonProperty).setName(newName) - } + }, ) } - } + }, ) } } @@ -94,18 +94,18 @@ class LangReferenceContributor : PsiReferenceContributor() { object : PsiReferenceProvider() { override fun getReferencesByElement( element: PsiElement, - context: ProcessingContext + context: ProcessingContext, ): Array { val entry = element as LangEntry return arrayOf( TranslationReference( element, TextRange(0, entry.key.length), - TranslationInstance.Key("", entry.key, "") - ) + TranslationInstance.Key("", entry.key, ""), + ), ) } - } + }, ) } } diff --git a/src/main/kotlin/translations/reference/usages.kt b/src/main/kotlin/translations/reference/usages.kt index 3bd31e8b1..5ea18510d 100644 --- a/src/main/kotlin/translations/reference/usages.kt +++ b/src/main/kotlin/translations/reference/usages.kt @@ -42,21 +42,37 @@ sealed class TranslationFindUsagesProvider : FindUsagesProvider { } class JsonFindUsagesProvider : TranslationFindUsagesProvider() { - override fun getWordsScanner(): WordsScanner? = + override fun getWordsScanner(): WordsScanner = DefaultWordsScanner( JsonLexer(), TokenSet.create(JsonElementTypes.DOUBLE_QUOTED_STRING, JsonElementTypes.SINGLE_QUOTED_STRING), TokenSet.create(JsonElementTypes.BLOCK_COMMENT, JsonElementTypes.LINE_COMMENT), - TokenSet.EMPTY + TokenSet.EMPTY, ) + + override fun equals(other: Any?): Boolean { + return this === other + } + + override fun hashCode(): Int { + return System.identityHashCode(this) + } } class LangFindUsagesProvider : TranslationFindUsagesProvider() { - override fun getWordsScanner(): WordsScanner? = + override fun getWordsScanner(): WordsScanner = DefaultWordsScanner( LangLexerAdapter(), TokenSet.create(LangTypes.KEY), TokenSet.create(LangTypes.COMMENT), - TokenSet.EMPTY + TokenSet.EMPTY, ) + + override fun equals(other: Any?): Boolean { + return this === other + } + + override fun hashCode(): Int { + return System.identityHashCode(this) + } } diff --git a/src/main/kotlin/translations/sorting/Ordering.kt b/src/main/kotlin/translations/sorting/Ordering.kt index a520ce143..544a608de 100644 --- a/src/main/kotlin/translations/sorting/Ordering.kt +++ b/src/main/kotlin/translations/sorting/Ordering.kt @@ -16,5 +16,5 @@ enum class Ordering(val text: String) { ASCENDING("Ascending"), DESCENDING("Descending"), LIKE_DEFAULT("Like default (${TranslationConstants.DEFAULT_LOCALE})"), - TEMPLATE("Use Project Template") + TEMPLATE("Use Project Template"), } diff --git a/src/main/kotlin/translations/sorting/TranslationSorter.kt b/src/main/kotlin/translations/sorting/TranslationSorter.kt index 4807e6656..0e230c6a6 100644 --- a/src/main/kotlin/translations/sorting/TranslationSorter.kt +++ b/src/main/kotlin/translations/sorting/TranslationSorter.kt @@ -20,10 +20,11 @@ import com.demonwav.mcdev.util.mcDomain import com.demonwav.mcdev.util.runWriteAction import com.intellij.openapi.project.Project import com.intellij.psi.PsiFile +import java.util.TreeSet object TranslationSorter { private val ascendingComparator = compareBy>( - naturalOrder().lexicographical() + naturalOrder().lexicographical(), ) { it.key.split('.') } private val descendingComparator = ascendingComparator.reversed() @@ -51,21 +52,21 @@ object TranslationSorter { Ordering.ASCENDING -> TranslationFiles.buildFileEntries( project, locale, - it.sortedWith(ascendingComparator), - keepComments + it.sortedWith(ascendingComparator).asIterable(), + keepComments, ) Ordering.DESCENDING -> TranslationFiles.buildFileEntries( project, locale, - it.sortedWith(descendingComparator), - keepComments + it.sortedWith(descendingComparator).asIterable(), + keepComments, ) Ordering.TEMPLATE -> sortByTemplate( project, locale, TemplateManager.getProjectTemplate(project), it, - keepComments + keepComments, ) else -> sortByTemplate( project, @@ -73,7 +74,7 @@ object TranslationSorter { TranslationFiles.buildSortingTemplateFromDefault(file, domain) ?: throw IllegalStateException("Could not generate template from default translation file"), it, - keepComments + keepComments, ) } } @@ -88,7 +89,7 @@ object TranslationSorter { locale: String, template: Template, entries: Sequence, - keepComments: Int + keepComments: Int, ) = sequence { val tmp = entries.toMutableList() @@ -97,14 +98,14 @@ object TranslationSorter { is Comment -> yield(TranslationFiles.FileEntry.Comment(elem.text)) EmptyLine -> yield(TranslationFiles.FileEntry.EmptyLine) is Key -> { - val toWrite = tmp.asSequence().filter { elem.matcher.matches(it.key) } + val toWrite = tmp.filterTo(TreeSet(ascendingComparator)) { elem.matcher.matches(it.key) } yieldAll( TranslationFiles.buildFileEntries( project, locale, - toWrite.sortedWith(ascendingComparator), - keepComments - ) + toWrite, + keepComments, + ), ) tmp.removeAll(toWrite) } @@ -116,9 +117,9 @@ object TranslationSorter { TranslationFiles.buildFileEntries( project, locale, - tmp.sortedWith(ascendingComparator).asSequence(), - keepComments - ) + tmp.sortedWith(ascendingComparator), + keepComments, + ), ) } } diff --git a/src/main/kotlin/translations/sorting/TranslationTemplateConfigurable.kt b/src/main/kotlin/translations/sorting/TranslationTemplateConfigurable.kt index 832e2c167..d0335460d 100644 --- a/src/main/kotlin/translations/sorting/TranslationTemplateConfigurable.kt +++ b/src/main/kotlin/translations/sorting/TranslationTemplateConfigurable.kt @@ -69,7 +69,7 @@ class TranslationTemplateConfigurable(private val project: Project) : Configurab val editorColorsScheme = EditorColorsManager.getInstance().globalScheme val highlighter = LexerEditorHighlighter( LangSyntaxHighlighter(TranslationTemplateLexerAdapter()), - editorColorsScheme + editorColorsScheme, ) (templateEditor as EditorEx).highlighter = highlighter templateEditor.settings.isLineNumbersShown = true diff --git a/src/main/kotlin/translations/sorting/template.kt b/src/main/kotlin/translations/sorting/template.kt index cb43a23fb..e4645c978 100644 --- a/src/main/kotlin/translations/sorting/template.kt +++ b/src/main/kotlin/translations/sorting/template.kt @@ -37,7 +37,7 @@ data class Template(val elements: List) { } } else { listOf() - } + }, ) private val keyRegex = Regex("([?!]?[+*]?)([^+*!?]*)([?!]?[+*]?)") diff --git a/src/main/kotlin/update/Channels.kt b/src/main/kotlin/update/Channels.kt index 90c1d49cb..ff1faa05c 100644 --- a/src/main/kotlin/update/Channels.kt +++ b/src/main/kotlin/update/Channels.kt @@ -13,7 +13,8 @@ package com.demonwav.mcdev.update import com.intellij.openapi.updateSettings.impl.UpdateSettings enum class Channels(val title: String, val url: String) { - NIGHTLY("Nightly", "https://plugins.jetbrains.com/plugins/Nightly/8327"); + NIGHTLY("Nightly", "https://plugins.jetbrains.com/plugins/Nightly/8327"), + ; fun hasChannel(): Boolean { return UpdateSettings.getInstance().pluginHosts.contains(url) diff --git a/src/main/kotlin/update/PluginUpdateStatus.kt b/src/main/kotlin/update/PluginUpdateStatus.kt index bdcab1858..6e2f9a450 100644 --- a/src/main/kotlin/update/PluginUpdateStatus.kt +++ b/src/main/kotlin/update/PluginUpdateStatus.kt @@ -26,7 +26,7 @@ sealed class PluginUpdateStatus : Comparable { } object LatestVersionInstalled : PluginUpdateStatus() { - override fun getVersionString(): String? = PluginUtil.pluginVersion + override fun getVersionString(): String = PluginUtil.pluginVersion } class Update(val pluginDescriptor: IdeaPluginDescriptor, val hostToInstallFrom: String?) : PluginUpdateStatus() { diff --git a/src/main/kotlin/update/PluginUpdater.kt b/src/main/kotlin/update/PluginUpdater.kt index 923e6eab9..5c4c78374 100644 --- a/src/main/kotlin/update/PluginUpdater.kt +++ b/src/main/kotlin/update/PluginUpdater.kt @@ -138,7 +138,7 @@ object PluginUpdater { e.printStackTrace() } } - } + }, ) } } diff --git a/src/main/kotlin/util/ActionData.kt b/src/main/kotlin/util/ActionData.kt index 2164319cf..e0d6f7366 100644 --- a/src/main/kotlin/util/ActionData.kt +++ b/src/main/kotlin/util/ActionData.kt @@ -23,5 +23,5 @@ class ActionData( val file: PsiFile, val element: PsiElement, val caret: Caret, - val instance: MinecraftFacet + val instance: MinecraftFacet, ) diff --git a/src/main/kotlin/util/License.kt b/src/main/kotlin/util/License.kt index eb9056214..4e5a2be7a 100644 --- a/src/main/kotlin/util/License.kt +++ b/src/main/kotlin/util/License.kt @@ -22,7 +22,13 @@ enum class License(private val displayName: String, val id: String) { GPL_3("GNU GPL 3.0", "GPL-3.0"), AGPL_3("GNU AGPL 3.0", "AGPL-3.0"), UNLICENSE("Unlicense", "unlicense"), + ; override fun toString() = displayName + + companion object { + private val byId = values().associateBy { it.id } + fun byId(id: String) = byId[id] + } } diff --git a/src/main/kotlin/util/MemberReference.kt b/src/main/kotlin/util/MemberReference.kt index 2b665f2af..935e24c2a 100644 --- a/src/main/kotlin/util/MemberReference.kt +++ b/src/main/kotlin/util/MemberReference.kt @@ -30,7 +30,7 @@ data class MemberReference( val descriptor: String? = null, override val owner: String? = null, val matchAllNames: Boolean = false, - val matchAllDescs: Boolean = false + val matchAllDescs: Boolean = false, ) : Serializable, MixinSelector { init { diff --git a/src/main/kotlin/util/MinecraftTemplates.kt b/src/main/kotlin/util/MinecraftTemplates.kt index 291bc0fea..11b69efa7 100644 --- a/src/main/kotlin/util/MinecraftTemplates.kt +++ b/src/main/kotlin/util/MinecraftTemplates.kt @@ -26,11 +26,9 @@ class MinecraftTemplates : FileTemplateGroupDescriptorFactory { bukkitGroup.addTemplate(FileTemplateDescriptor(BUKKIT_MAIN_CLASS_TEMPLATE)) bukkitGroup.addTemplate(FileTemplateDescriptor(BUKKIT_PLUGIN_YML_TEMPLATE)) bukkitGroup.addTemplate(FileTemplateDescriptor(BUKKIT_BUILD_GRADLE_TEMPLATE)) - bukkitGroup.addTemplate(FileTemplateDescriptor(BUKKIT_SUBMODULE_BUILD_GRADLE_TEMPLATE)) bukkitGroup.addTemplate(FileTemplateDescriptor(BUKKIT_GRADLE_PROPERTIES_TEMPLATE)) bukkitGroup.addTemplate(FileTemplateDescriptor(BUKKIT_SETTINGS_GRADLE_TEMPLATE)) bukkitGroup.addTemplate(FileTemplateDescriptor(BUKKIT_POM_TEMPLATE)) - bukkitGroup.addTemplate(FileTemplateDescriptor(BUKKIT_SUBMODULE_POM_TEMPLATE)) } FileTemplateGroupDescriptor("BungeeCord", PlatformAssets.BUNGEECORD_ICON).let { bungeeGroup -> @@ -38,11 +36,9 @@ class MinecraftTemplates : FileTemplateGroupDescriptorFactory { bungeeGroup.addTemplate(FileTemplateDescriptor(BUNGEECORD_MAIN_CLASS_TEMPLATE)) bungeeGroup.addTemplate(FileTemplateDescriptor(BUNGEECORD_PLUGIN_YML_TEMPLATE)) bungeeGroup.addTemplate(FileTemplateDescriptor(BUNGEECORD_BUILD_GRADLE_TEMPLATE)) - bungeeGroup.addTemplate(FileTemplateDescriptor(BUNGEECORD_SUBMODULE_BUILD_GRADLE_TEMPLATE)) bungeeGroup.addTemplate(FileTemplateDescriptor(BUNGEECORD_GRADLE_PROPERTIES_TEMPLATE)) bungeeGroup.addTemplate(FileTemplateDescriptor(BUNGEECORD_SETTINGS_GRADLE_TEMPLATE)) bungeeGroup.addTemplate(FileTemplateDescriptor(BUNGEECORD_POM_TEMPLATE)) - bungeeGroup.addTemplate(FileTemplateDescriptor(BUNGEECORD_SUBMODULE_POM_TEMPLATE)) } FileTemplateGroupDescriptor("Velocity", PlatformAssets.VELOCITY_ICON).let { velocityGroup -> @@ -51,41 +47,24 @@ class MinecraftTemplates : FileTemplateGroupDescriptorFactory { velocityGroup.addTemplate(FileTemplateDescriptor(VELOCITY_BUILD_CONSTANTS_TEMPLATE)) velocityGroup.addTemplate(FileTemplateDescriptor(VELOCITY_MAIN_CLASS_V2_TEMPLATE)) velocityGroup.addTemplate(FileTemplateDescriptor(VELOCITY_BUILD_GRADLE_TEMPLATE)) - velocityGroup.addTemplate(FileTemplateDescriptor(VELOCITY_SUBMODULE_BUILD_GRADLE_TEMPLATE)) velocityGroup.addTemplate(FileTemplateDescriptor(VELOCITY_GRADLE_PROPERTIES_TEMPLATE)) velocityGroup.addTemplate(FileTemplateDescriptor(VELOCITY_SETTINGS_GRADLE_TEMPLATE)) velocityGroup.addTemplate(FileTemplateDescriptor(VELOCITY_POM_TEMPLATE)) - velocityGroup.addTemplate(FileTemplateDescriptor(VELOCITY_SUBMODULE_POM_TEMPLATE)) } FileTemplateGroupDescriptor("Sponge", PlatformAssets.SPONGE_ICON).let { spongeGroup -> group.addTemplate(spongeGroup) - FileTemplateGroupDescriptor("Legacy", null).let { legacyGroup -> - spongeGroup.addTemplate(legacyGroup) - legacyGroup.addTemplate(template(SPONGE_MAIN_CLASS_TEMPLATE)) - legacyGroup.addTemplate(template(SPONGE_BUILD_GRADLE_TEMPLATE)) - legacyGroup.addTemplate(template(SPONGE_SUBMODULE_BUILD_GRADLE_TEMPLATE)) - legacyGroup.addTemplate(template(SPONGE_GRADLE_PROPERTIES_TEMPLATE)) - legacyGroup.addTemplate(template(SPONGE_SETTINGS_GRADLE_TEMPLATE)) - } fun sponge8Template(fileName: String) = template(fileName, fileName.replace("8+ ", "")) spongeGroup.addTemplate(sponge8Template(SPONGE8_MAIN_CLASS_TEMPLATE)) spongeGroup.addTemplate(sponge8Template(SPONGE8_PLUGINS_JSON_TEMPLATE)) spongeGroup.addTemplate(sponge8Template(SPONGE8_BUILD_GRADLE_TEMPLATE)) - spongeGroup.addTemplate(sponge8Template(SPONGE8_SUBMODULE_BUILD_GRADLE_TEMPLATE)) spongeGroup.addTemplate(sponge8Template(SPONGE8_GRADLE_PROPERTIES_TEMPLATE)) spongeGroup.addTemplate(sponge8Template(SPONGE8_SETTINGS_GRADLE_TEMPLATE)) spongeGroup.addTemplate(template(SPONGE_POM_TEMPLATE)) - spongeGroup.addTemplate(template(SPONGE_SUBMODULE_POM_TEMPLATE)) } FileTemplateGroupDescriptor("Forge", PlatformAssets.FORGE_ICON).let { forgeGroup -> group.addTemplate(forgeGroup) - forgeGroup.addTemplate(FileTemplateDescriptor(FORGE_MAIN_CLASS_TEMPLATE)) - forgeGroup.addTemplate(FileTemplateDescriptor(FORGE_BUILD_GRADLE_TEMPLATE)) - forgeGroup.addTemplate(FileTemplateDescriptor(FORGE_SUBMODULE_BUILD_GRADLE_TEMPLATE)) - forgeGroup.addTemplate(FileTemplateDescriptor(FORGE_GRADLE_PROPERTIES_TEMPLATE)) - forgeGroup.addTemplate(FileTemplateDescriptor(FORGE_SETTINGS_GRADLE_TEMPLATE)) forgeGroup.addTemplate(FileTemplateDescriptor(FORGE_MIXINS_JSON_TEMPLATE, PlatformAssets.FORGE_ICON)) forgeGroup.addTemplate(FileTemplateDescriptor(FG3_MAIN_CLASS_TEMPLATE)) forgeGroup.addTemplate(FileTemplateDescriptor(FG3_1_17_MAIN_CLASS_TEMPLATE)) @@ -93,10 +72,8 @@ class MinecraftTemplates : FileTemplateGroupDescriptorFactory { forgeGroup.addTemplate(FileTemplateDescriptor(FG3_1_19_MAIN_CLASS_TEMPLATE)) forgeGroup.addTemplate(FileTemplateDescriptor(FG3_1_19_3_MAIN_CLASS_TEMPLATE)) forgeGroup.addTemplate(FileTemplateDescriptor(FG3_BUILD_GRADLE_TEMPLATE)) - forgeGroup.addTemplate(FileTemplateDescriptor(FG3_SUBMODULE_BUILD_GRADLE_TEMPLATE)) forgeGroup.addTemplate(FileTemplateDescriptor(FG3_GRADLE_PROPERTIES_TEMPLATE)) forgeGroup.addTemplate(FileTemplateDescriptor(FG3_SETTINGS_GRADLE_TEMPLATE)) - forgeGroup.addTemplate(FileTemplateDescriptor(MCMOD_INFO_TEMPLATE)) forgeGroup.addTemplate(FileTemplateDescriptor(MODS_TOML_TEMPLATE)) forgeGroup.addTemplate(FileTemplateDescriptor(PACK_MCMETA_TEMPLATE)) } @@ -105,24 +82,17 @@ class MinecraftTemplates : FileTemplateGroupDescriptorFactory { group.addTemplate(fabricGroup) fabricGroup.addTemplate(FileTemplateDescriptor(FABRIC_BUILD_GRADLE_TEMPLATE, PlatformAssets.FABRIC_ICON)) fabricGroup.addTemplate( - FileTemplateDescriptor(FABRIC_GRADLE_PROPERTIES_TEMPLATE, PlatformAssets.FABRIC_ICON) + FileTemplateDescriptor(FABRIC_GRADLE_PROPERTIES_TEMPLATE, PlatformAssets.FABRIC_ICON), ) fabricGroup.addTemplate(FileTemplateDescriptor(FABRIC_MIXINS_JSON_TEMPLATE, PlatformAssets.FABRIC_ICON)) fabricGroup.addTemplate(FileTemplateDescriptor(FABRIC_MOD_JSON_TEMPLATE, PlatformAssets.FABRIC_ICON)) fabricGroup.addTemplate(FileTemplateDescriptor(FABRIC_SETTINGS_GRADLE_TEMPLATE, PlatformAssets.FABRIC_ICON)) - fabricGroup.addTemplate( - FileTemplateDescriptor(FABRIC_SUBMODULE_BUILD_GRADLE_TEMPLATE, PlatformAssets.FABRIC_ICON) - ) - fabricGroup.addTemplate( - FileTemplateDescriptor(FABRIC_SUBMODULE_GRADLE_PROPERTIES_TEMPLATE, PlatformAssets.FABRIC_ICON) - ) } FileTemplateGroupDescriptor("LiteLoader", PlatformAssets.LITELOADER_ICON).let { liteGroup -> group.addTemplate(liteGroup) liteGroup.addTemplate(FileTemplateDescriptor(LITELOADER_MAIN_CLASS_TEMPLATE)) liteGroup.addTemplate(FileTemplateDescriptor(LITELOADER_BUILD_GRADLE_TEMPLATE)) - liteGroup.addTemplate(FileTemplateDescriptor(LITELOADER_SUBMODULE_BUILD_GRADLE_TEMPLATE)) liteGroup.addTemplate(FileTemplateDescriptor(LITELOADER_GRADLE_PROPERTIES_TEMPLATE)) liteGroup.addTemplate(FileTemplateDescriptor(LITELOADER_SETTINGS_GRADLE_TEMPLATE)) } @@ -145,6 +115,7 @@ class MinecraftTemplates : FileTemplateGroupDescriptorFactory { group.addTemplate(commonGroup) commonGroup.addTemplate(FileTemplateDescriptor(GRADLE_GITIGNORE_TEMPLATE)) commonGroup.addTemplate(FileTemplateDescriptor(MAVEN_GITIGNORE_TEMPLATE)) + commonGroup.addTemplate(FileTemplateDescriptor(GRADLE_WRAPPER_PROPERTIES)) } FileTemplateGroupDescriptor("Skeletons", GeneralAssets.MC_TEMPLATE).let { skeletonGroup -> @@ -189,62 +160,41 @@ class MinecraftTemplates : FileTemplateGroupDescriptorFactory { const val BUKKIT_MAIN_CLASS_TEMPLATE = "Bukkit Main Class.java" const val BUKKIT_PLUGIN_YML_TEMPLATE = "Bukkit plugin.yml" const val BUKKIT_BUILD_GRADLE_TEMPLATE = "Bukkit build.gradle" - const val BUKKIT_SUBMODULE_BUILD_GRADLE_TEMPLATE = "Bukkit Submodule build.gradle" const val BUKKIT_GRADLE_PROPERTIES_TEMPLATE = "Bukkit gradle.properties" const val BUKKIT_SETTINGS_GRADLE_TEMPLATE = "Bukkit settings.gradle" const val BUKKIT_POM_TEMPLATE = "Bukkit pom.xml" - const val BUKKIT_SUBMODULE_POM_TEMPLATE = "Bukkit Submodule pom.xml" const val BUNGEECORD_MAIN_CLASS_TEMPLATE = "BungeeCord Main Class.java" const val BUNGEECORD_PLUGIN_YML_TEMPLATE = "BungeeCord bungee.yml" const val BUNGEECORD_BUILD_GRADLE_TEMPLATE = "BungeeCord build.gradle" - const val BUNGEECORD_SUBMODULE_BUILD_GRADLE_TEMPLATE = "BungeeCord Submodule build.gradle" const val BUNGEECORD_GRADLE_PROPERTIES_TEMPLATE = "BungeeCord gradle.properties" const val BUNGEECORD_SETTINGS_GRADLE_TEMPLATE = "BungeeCord settings.gradle" const val BUNGEECORD_POM_TEMPLATE = "BungeeCord pom.xml" - const val BUNGEECORD_SUBMODULE_POM_TEMPLATE = "BungeeCord Submodule pom.xml" const val VELOCITY_MAIN_CLASS_TEMPLATE = "Velocity Main Class.java" const val VELOCITY_MAIN_CLASS_V2_TEMPLATE = "Velocity Main Class V2.java" const val VELOCITY_BUILD_CONSTANTS_TEMPLATE = "Velocity Build Constants.java" const val VELOCITY_BUILD_GRADLE_TEMPLATE = "Velocity build.gradle" - const val VELOCITY_SUBMODULE_BUILD_GRADLE_TEMPLATE = "Velocity Submodule build.gradle" const val VELOCITY_GRADLE_PROPERTIES_TEMPLATE = "Velocity gradle.properties" const val VELOCITY_SETTINGS_GRADLE_TEMPLATE = "Velocity settings.gradle" const val VELOCITY_POM_TEMPLATE = "Velocity pom.xml" - const val VELOCITY_SUBMODULE_POM_TEMPLATE = "Velocity Submodule pom.xml" - const val SPONGE_MAIN_CLASS_TEMPLATE = "Sponge Main Class.java" - const val SPONGE_BUILD_GRADLE_TEMPLATE = "Sponge build.gradle" - const val SPONGE_SUBMODULE_BUILD_GRADLE_TEMPLATE = "Sponge Submodule build.gradle" - const val SPONGE_GRADLE_PROPERTIES_TEMPLATE = "Sponge gradle.properties" - const val SPONGE_SETTINGS_GRADLE_TEMPLATE = "Sponge settings.gradle" const val SPONGE_POM_TEMPLATE = "Sponge pom.xml" - const val SPONGE_SUBMODULE_POM_TEMPLATE = "Sponge Submodule pom.xml" - const val SPONGE8_MAIN_CLASS_TEMPLATE = "Sponge 8+ Main Class.java" const val SPONGE8_PLUGINS_JSON_TEMPLATE = "Sponge 8+ sponge_plugins.json" const val SPONGE8_BUILD_GRADLE_TEMPLATE = "Sponge 8+ build.gradle.kts" - const val SPONGE8_SUBMODULE_BUILD_GRADLE_TEMPLATE = "Sponge 8+ Submodule build.gradle.kts" const val SPONGE8_GRADLE_PROPERTIES_TEMPLATE = "Sponge 8+ gradle.properties" const val SPONGE8_SETTINGS_GRADLE_TEMPLATE = "Sponge 8+ settings.gradle.kts" - const val FORGE_MAIN_CLASS_TEMPLATE = "Forge Main Class.java" - const val FORGE_BUILD_GRADLE_TEMPLATE = "Forge build.gradle" - const val FORGE_SUBMODULE_BUILD_GRADLE_TEMPLATE = "Forge Submodule build.gradle" - const val FORGE_GRADLE_PROPERTIES_TEMPLATE = "Forge gradle.properties" const val FORGE_MIXINS_JSON_TEMPLATE = "Forge Mixins Config.json" - const val FORGE_SETTINGS_GRADLE_TEMPLATE = "Forge settings.gradle" const val FG3_MAIN_CLASS_TEMPLATE = "Forge (1.13+) Main Class.java" const val FG3_1_17_MAIN_CLASS_TEMPLATE = "Forge (1.17+) Main Class.java" const val FG3_1_18_MAIN_CLASS_TEMPLATE = "Forge (1.18+) Main Class.java" const val FG3_1_19_MAIN_CLASS_TEMPLATE = "Forge (1.19+) Main Class.java" const val FG3_1_19_3_MAIN_CLASS_TEMPLATE = "Forge (1.19.3+) Main Class.java" const val FG3_BUILD_GRADLE_TEMPLATE = "Forge (1.13+) build.gradle" - const val FG3_SUBMODULE_BUILD_GRADLE_TEMPLATE = "Forge (1.13+) Submodule build.gradle" const val FG3_GRADLE_PROPERTIES_TEMPLATE = "Forge (1.13+) gradle.properties" const val FG3_SETTINGS_GRADLE_TEMPLATE = "Forge (1.13+) settings.gradle" - const val MCMOD_INFO_TEMPLATE = "mcmod.info" const val MODS_TOML_TEMPLATE = "mods.toml" const val PACK_MCMETA_TEMPLATE = "pack.mcmeta" @@ -253,13 +203,9 @@ class MinecraftTemplates : FileTemplateGroupDescriptorFactory { const val FABRIC_MIXINS_JSON_TEMPLATE = "fabric_mixins.json" const val FABRIC_MOD_JSON_TEMPLATE = "fabric_mod.json" const val FABRIC_SETTINGS_GRADLE_TEMPLATE = "fabric_settings.gradle" - const val FABRIC_SUBMODULE_BUILD_GRADLE_TEMPLATE = "fabric_submodule_build.gradle" - const val FABRIC_SUBMODULE_GRADLE_PROPERTIES_TEMPLATE = "fabric_submodule_gradle.properties" const val ARCHITECTURY_BUILD_GRADLE_TEMPLATE = "architectury_build.gradle" const val ARCHITECTURY_GRADLE_PROPERTIES_TEMPLATE = "architectury_gradle.properties" - const val ARCHITECTURY_SUBMODULE_BUILD_GRADLE_TEMPLATE = "architectury_submodule_build.gradle" - const val ARCHITECTURY_SUBMODULE_GRADLE_PROPERTIES_TEMPLATE = "architectury_submodule_gradle.properties" const val ARCHITECTURY_SETTINGS_GRADLE_TEMPLATE = "architectury_settings.gradle" const val ARCHITECTURY_COMMON_BUILD_GRADLE_TEMPLATE = "architectury_common_build.gradle" const val ARCHITECTURY_COMMON_MAIN_CLASS_TEMPLATE = "architectury_common_main_class.java" @@ -277,7 +223,6 @@ class MinecraftTemplates : FileTemplateGroupDescriptorFactory { const val LITELOADER_MAIN_CLASS_TEMPLATE = "LiteLoader Main Class.java" const val LITELOADER_BUILD_GRADLE_TEMPLATE = "LiteLoader build.gradle" - const val LITELOADER_SUBMODULE_BUILD_GRADLE_TEMPLATE = "LiteLoader Submodule build.gradle" const val LITELOADER_GRADLE_PROPERTIES_TEMPLATE = "LiteLoader gradle.properties" const val LITELOADER_SETTINGS_GRADLE_TEMPLATE = "LiteLoader settings.gradle" @@ -289,6 +234,7 @@ class MinecraftTemplates : FileTemplateGroupDescriptorFactory { const val MIXIN_OVERWRITE_FALLBACK = "Mixin Overwrite Fallback.java" + const val GRADLE_WRAPPER_PROPERTIES = "MinecraftDev gradle-wrapper.properties" const val GRADLE_GITIGNORE_TEMPLATE = "Gradle.gitignore" const val MAVEN_GITIGNORE_TEMPLATE = "Maven.gitignore" diff --git a/src/main/kotlin/util/MinecraftVersions.kt b/src/main/kotlin/util/MinecraftVersions.kt index 269058a46..237afcedf 100644 --- a/src/main/kotlin/util/MinecraftVersions.kt +++ b/src/main/kotlin/util/MinecraftVersions.kt @@ -10,20 +10,22 @@ package com.demonwav.mcdev.util -import com.intellij.util.lang.JavaVersion +import com.intellij.openapi.projectRoots.JavaSdkVersion object MinecraftVersions { val MC1_12_2 = SemanticVersion.release(1, 12, 2) val MC1_14_4 = SemanticVersion.release(1, 14, 4) val MC1_16_1 = SemanticVersion.release(1, 16, 1) + val MC1_16_5 = SemanticVersion.release(1, 16, 5) val MC1_17 = SemanticVersion.release(1, 17) + val MC1_17_1 = SemanticVersion.release(1, 17, 1) val MC1_18 = SemanticVersion.release(1, 18) val MC1_19 = SemanticVersion.release(1, 19) val MC1_19_3 = SemanticVersion.release(1, 19, 3) fun requiredJavaVersion(minecraftVersion: SemanticVersion) = when { - minecraftVersion >= MC1_18 -> JavaVersion.compose(17) - minecraftVersion >= MC1_17 -> JavaVersion.compose(16) - else -> JavaVersion.compose(8) + minecraftVersion <= MC1_16_5 -> JavaSdkVersion.JDK_1_8 + minecraftVersion <= MC1_17_1 -> JavaSdkVersion.JDK_16 + else -> JavaSdkVersion.JDK_17 } } diff --git a/src/main/kotlin/util/ModuleDebugRunConfigurationExtension.kt b/src/main/kotlin/util/ModuleDebugRunConfigurationExtension.kt index 76acffe18..d5128735b 100644 --- a/src/main/kotlin/util/ModuleDebugRunConfigurationExtension.kt +++ b/src/main/kotlin/util/ModuleDebugRunConfigurationExtension.kt @@ -30,7 +30,7 @@ abstract class ModuleDebugRunConfigurationExtension : RunConfigurationExtension( override fun > updateJavaParameters( configuration: T, params: JavaParameters, - runnerSettings: RunnerSettings? + runnerSettings: RunnerSettings?, ) { } @@ -39,7 +39,7 @@ abstract class ModuleDebugRunConfigurationExtension : RunConfigurationExtension( override fun attachToProcess( configuration: RunConfigurationBase<*>, handler: ProcessHandler, - runnerSettings: RunnerSettings? + runnerSettings: RunnerSettings?, ) { // Check if we are in a debug run if (runnerSettings !is DebuggingRunnerData) { diff --git a/src/main/kotlin/util/SemanticVersion.kt b/src/main/kotlin/util/SemanticVersion.kt index e9042e65b..ed71c8d57 100644 --- a/src/main/kotlin/util/SemanticVersion.kt +++ b/src/main/kotlin/util/SemanticVersion.kt @@ -22,7 +22,7 @@ import java.net.URLDecoder */ class SemanticVersion( val parts: List, - private val buildMetadata: String = "" + private val buildMetadata: String = "", ) : Comparable { private fun createVersionString(): String { @@ -73,7 +73,7 @@ class SemanticVersion( val TEXT_PRIORITIES = mapOf( "snapshot" to 0, "rc" to 1, - "pre" to 1 + "pre" to 1, ) /** @@ -86,6 +86,14 @@ class SemanticVersion( */ fun release(vararg parts: Int) = SemanticVersion(parts.map { ReleasePart(it, it.toString()) }) + fun tryParse(value: String): SemanticVersion? { + return try { + parse(value) + } catch (e: IllegalArgumentException) { + null + } + } + /** * Parses a version string into a comparable representation. * @throws IllegalArgumentException if any part of the version string cannot be parsed as integer or split into text parts. @@ -97,7 +105,7 @@ class SemanticVersion( } else { throw IllegalArgumentException( "Failed to parse version part as integer: $part " + - "(whole version text: $value)" + "(whole version text: $value)", ) } @@ -106,7 +114,7 @@ class SemanticVersion( versionPart: String, preReleasePart: String, separator: Char, - versionString: String + versionString: String, ): VersionPart { val version = parseInt(versionPart) if (!preReleasePart.contains('.')) { @@ -196,7 +204,7 @@ class SemanticVersion( val version: Int, val separator: Char, val subParts: List, - override val versionString: String + override val versionString: String, ) : VersionPart() { override fun compareTo(other: VersionPart): Int = diff --git a/src/main/kotlin/util/SourceType.kt b/src/main/kotlin/util/SourceType.kt index 669c30232..6fdee3ba1 100644 --- a/src/main/kotlin/util/SourceType.kt +++ b/src/main/kotlin/util/SourceType.kt @@ -14,5 +14,5 @@ enum class SourceType { SOURCE, RESOURCE, TEST_SOURCE, - TEST_RESOURCE + TEST_RESOURCE, } diff --git a/src/main/kotlin/util/bytecode-utils.kt b/src/main/kotlin/util/bytecode-utils.kt index a0cf1dbd9..5f9f0c214 100644 --- a/src/main/kotlin/util/bytecode-utils.kt +++ b/src/main/kotlin/util/bytecode-utils.kt @@ -17,10 +17,12 @@ import com.intellij.psi.PsiClass import com.intellij.psi.PsiClassType import com.intellij.psi.PsiField import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiModifier import com.intellij.psi.PsiPrimitiveType import com.intellij.psi.PsiType import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.util.TypeConversionUtil +import org.jetbrains.plugins.groovy.lang.resolve.processors.inference.type private const val INTERNAL_CONSTRUCTOR_NAME = "" @@ -149,6 +151,13 @@ val PsiMethod.descriptor: String? @Throws(ClassNameResolutionFailedException::class) private fun PsiMethod.appendDescriptor(builder: StringBuilder): StringBuilder { builder.append('(') + if (isConstructor) { + containingClass?.let { containingClass -> + if (containingClass.hasModifierProperty(PsiModifier.STATIC)) return@let + val outerClass = containingClass.containingClass + outerClass?.type()?.appendDescriptor(builder) + } + } for (parameter in parameterList.parameters) { parameter.type.appendDescriptor(builder) } diff --git a/src/main/kotlin/util/call-utils.kt b/src/main/kotlin/util/call-utils.kt index 26669663d..2898d7364 100644 --- a/src/main/kotlin/util/call-utils.kt +++ b/src/main/kotlin/util/call-utils.kt @@ -45,7 +45,7 @@ private fun extractVarArgs( type: PsiType, elements: List, allowReferences: Boolean, - allowTranslations: Boolean + allowTranslations: Boolean, ): Array { tailrec fun resolveReference(expression: PsiExpression): Array { if (expression is PsiTypeCastExpression && expression.operand != null) { diff --git a/src/main/kotlin/util/class-utils.kt b/src/main/kotlin/util/class-utils.kt index d11fd9a0e..00f34e232 100644 --- a/src/main/kotlin/util/class-utils.kt +++ b/src/main/kotlin/util/class-utils.kt @@ -117,7 +117,7 @@ fun findQualifiedClass(fullQualifiedName: String, context: PsiElement): PsiClass fun findQualifiedClass( project: Project, fullQualifiedName: String, - scope: GlobalSearchScope = GlobalSearchScope.allScope(project) + scope: GlobalSearchScope = GlobalSearchScope.allScope(project), ): PsiClass? { return findQualifiedClass(fullQualifiedName) { name -> JavaPsiFacade.getInstance(project).findClass(name, scope) @@ -126,7 +126,7 @@ fun findQualifiedClass( fun findQualifiedClass( fullQualifiedName: String, - outerResolver: (String) -> PsiClass? + outerResolver: (String) -> PsiClass?, ): PsiClass? { var innerPos = fullQualifiedName.indexOf('$') if (innerPos == -1) { @@ -163,7 +163,7 @@ private fun PsiClass.findInnerClass(name: String): PsiClass? { } @Throws(ClassNameResolutionFailedException::class) -fun PsiElement.getAnonymousIndex(anonymousElement: PsiElement): Int? { +fun PsiElement.getAnonymousIndex(anonymousElement: PsiElement): Int { // Attempt to find name for anonymous class for ((i, element) in anonymousElements.withIndex()) { if (element equivalentTo anonymousElement) { @@ -232,7 +232,7 @@ fun PsiClass.findMatchingMethod( pattern: PsiMethod, checkBases: Boolean, name: String = pattern.name, - constructor: Boolean = pattern.isConstructor + constructor: Boolean = pattern.isConstructor, ): PsiMethod? { return findMethodsByName(name, checkBases).firstOrNull { it.isMatchingMethod(pattern, constructor) } } @@ -241,7 +241,7 @@ fun PsiClass.findMatchingMethods( pattern: PsiMethod, checkBases: Boolean, name: String = pattern.name, - constructor: Boolean = pattern.isConstructor + constructor: Boolean = pattern.isConstructor, ): List { return findMethodsByName(name, checkBases).filter { it.isMatchingMethod(pattern, constructor) } } @@ -250,7 +250,7 @@ inline fun PsiClass.findMatchingMethods( pattern: PsiMethod, checkBases: Boolean, name: String, - func: (PsiMethod) -> Unit + func: (PsiMethod) -> Unit, ) { for (method in findMethodsByName(name, checkBases)) { if (method.isMatchingMethod(pattern)) { @@ -279,7 +279,7 @@ fun PsiField.isMatchingField(pattern: PsiField): Boolean { private fun areReallyOnlyParametersErasureEqual( parameterList1: PsiParameterList, - parameterList2: PsiParameterList + parameterList2: PsiParameterList, ): Boolean { // Similar to MethodSignatureUtil.areParametersErasureEqual, but doesn't check method name if (parameterList1.parametersCount != parameterList2.parametersCount) { diff --git a/src/main/kotlin/util/code-gen.kt b/src/main/kotlin/util/code-gen.kt new file mode 100644 index 000000000..87d04ff5e --- /dev/null +++ b/src/main/kotlin/util/code-gen.kt @@ -0,0 +1,51 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.util + +import com.intellij.codeInsight.generation.PsiGenerationInfo +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.text.StringUtil +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiAnnotation +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiClassType +import com.intellij.psi.PsiMember +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiType +import com.intellij.psi.search.GlobalSearchScope + +fun createVoidMethodWithParameterType(project: Project, name: String, paramType: PsiClass): PsiMethod? { + val newMethod = JavaPsiFacade.getElementFactory(project).createMethod(name, PsiType.VOID) + + val list = newMethod.parameterList + val qName = paramType.qualifiedName ?: return null + val parameter = JavaPsiFacade.getElementFactory(project) + .createParameter( + "event", + PsiClassType.getTypeByName(qName, project, GlobalSearchScope.allScope(project)), + ) + list.add(parameter) + + return newMethod +} + +fun generationInfoFromMethod(method: T, annotation: PsiAnnotation, newMethod: T): PsiGenerationInfo { + val realName = method.realName + if (realName != null && realName != method.name) { + val elementFactory = JavaPsiFacade.getElementFactory(method.project) + val value = elementFactory.createExpressionFromText( + "\"${StringUtil.escapeStringCharacters(realName)}\"", + annotation, + ) + annotation.setDeclaredAttributeValue("aliases", value) + } + return PsiGenerationInfo(newMethod) +} diff --git a/src/main/kotlin/util/coroutine-utils.kt b/src/main/kotlin/util/coroutine-utils.kt index a67532648..c11507b7e 100644 --- a/src/main/kotlin/util/coroutine-utils.kt +++ b/src/main/kotlin/util/coroutine-utils.kt @@ -18,5 +18,5 @@ import kotlinx.coroutines.async fun CoroutineScope.asyncIO( start: CoroutineStart = CoroutineStart.DEFAULT, - block: suspend CoroutineScope.() -> T + block: suspend CoroutineScope.() -> T, ): Deferred = async(Dispatchers.IO, start, block) diff --git a/src/main/kotlin/util/gradle-util.kt b/src/main/kotlin/util/gradle-util.kt index f5a93d375..1a9a84a18 100644 --- a/src/main/kotlin/util/gradle-util.kt +++ b/src/main/kotlin/util/gradle-util.kt @@ -36,7 +36,7 @@ fun runGradleTaskWithCallback( project: Project, dir: Path, func: (ExternalSystemTaskExecutionSettings) -> Unit, - callback: TaskCallback + callback: TaskCallback, ) { val settings = ExternalSystemTaskExecutionSettings().apply { externalSystemIdString = GradleConstants.SYSTEM_ID.id @@ -52,7 +52,7 @@ fun runGradleTaskWithCallback( GradleConstants.SYSTEM_ID, callback, ProgressExecutionMode.IN_BACKGROUND_ASYNC, - false + false, ) } diff --git a/src/main/kotlin/util/json-patterns.kt b/src/main/kotlin/util/json-patterns.kt index 5ab53f1cd..bd9b34479 100644 --- a/src/main/kotlin/util/json-patterns.kt +++ b/src/main/kotlin/util/json-patterns.kt @@ -26,7 +26,7 @@ fun PsiElementPattern.Capture.isPropertyValue(property: String) = val parent = t.parent as? JsonProperty ?: return false return parent.value == t && parent.name == property } - } + }, ) private object PropertyKeyCondition : PatternCondition("isPropertyKey") { diff --git a/src/main/kotlin/util/mod-creator.kt b/src/main/kotlin/util/mod-creator.kt deleted file mode 100644 index da01decd4..000000000 --- a/src/main/kotlin/util/mod-creator.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Minecraft Dev for IntelliJ - * - * https://minecraftdev.org - * - * Copyright (c) 2023 minecraft-dev - * - * MIT License - */ - -package com.demonwav.mcdev.util - -import com.demonwav.mcdev.creator.MinecraftProjectCreator -import com.demonwav.mcdev.creator.ProjectConfig -import com.demonwav.mcdev.creator.buildsystem.BuildSystem -import javax.swing.JTextField -import org.apache.commons.lang.WordUtils - -inline fun modUpdateStep( - creator: MinecraftProjectCreator, - modNameField: JTextField -): Pair? { - val buildSystem = creator.buildSystem ?: return null - - modNameField.text = WordUtils.capitalize(buildSystem.artifactId.replace('-', ' ')) - - val config = creator.config as? T ?: return null - return config to buildSystem -} diff --git a/src/main/kotlin/util/patterns.kt b/src/main/kotlin/util/patterns.kt index 3f0f345bb..95ddbdccb 100644 --- a/src/main/kotlin/util/patterns.kt +++ b/src/main/kotlin/util/patterns.kt @@ -24,22 +24,22 @@ private val ANNOTATION_ATTRIBUTE_STOP = // It can be more if the value is for example enclosed in parentheses fun > PsiJavaElementPattern.insideAnnotationAttribute( annotation: PsiAnnotationPattern, - attribute: String + attribute: String, ): Self { return inside( true, PsiJavaPatterns.psiNameValuePair().withName(attribute) .withParent( PlatformPatterns.psiElement(PsiAnnotationParameterList::class.java) - .withParent(annotation) + .withParent(annotation), ), - ANNOTATION_ATTRIBUTE_STOP + ANNOTATION_ATTRIBUTE_STOP, ) } fun > PsiJavaElementPattern.insideAnnotationAttribute( annotation: String, - attribute: String = "value" + attribute: String = "value", ): Self { return insideAnnotationAttribute(PsiJavaPatterns.psiAnnotation().qName(annotation), attribute) } diff --git a/src/main/kotlin/util/psi-utils.kt b/src/main/kotlin/util/psi-utils.kt index dde24d63f..bb1bb0b47 100644 --- a/src/main/kotlin/util/psi-utils.kt +++ b/src/main/kotlin/util/psi-utils.kt @@ -230,7 +230,9 @@ fun PsiElement.findMcpModule() = this.cached { ?: return@cached null ModuleManager.getInstance(project).modules.asSequence() .filter { OrderEntryUtil.findLibraryOrderEntry(ModuleRootManager.getInstance(it), library) != null } - } else sequenceOf(this.findModule()) + } else { + sequenceOf(this.findModule()) + } modules.mapNotNull { it?.findMcpModule() }.firstOrNull() } diff --git a/src/main/kotlin/util/reference/ClassNameReferenceProvider.kt b/src/main/kotlin/util/reference/ClassNameReferenceProvider.kt index 97fff45b6..360e50278 100644 --- a/src/main/kotlin/util/reference/ClassNameReferenceProvider.kt +++ b/src/main/kotlin/util/reference/ClassNameReferenceProvider.kt @@ -86,7 +86,9 @@ abstract class ClassNameReferenceProvider : PackageNameReferenceProvider() { } basePackage.length + 1 - } else 0 + } else { + 0 + } val end = packageName.indexOf('.', start) return if (end == -1) { diff --git a/src/main/kotlin/util/reference/PackageNameReferenceProvider.kt b/src/main/kotlin/util/reference/PackageNameReferenceProvider.kt index 1ba512ad1..a044edf32 100644 --- a/src/main/kotlin/util/reference/PackageNameReferenceProvider.kt +++ b/src/main/kotlin/util/reference/PackageNameReferenceProvider.kt @@ -40,7 +40,7 @@ abstract class PackageNameReferenceProvider : PsiReferenceProvider() { protected open fun resolve( qualifiedName: String, element: PsiElement, - facade: JavaPsiFacade + facade: JavaPsiFacade, ): Array { facade.findPackage(qualifiedName)?.let { return arrayOf(PsiElementResolveResult(it)) } return ResolveResult.EMPTY_ARRAY @@ -55,7 +55,7 @@ abstract class PackageNameReferenceProvider : PsiReferenceProvider() { protected inline fun collectPackageChildren( context: PsiPackage, classes: Iterable, - classFunc: (PsiClass) -> Any? + classFunc: (PsiClass) -> Any?, ): Array { val parentPackage = context.qualifiedName val subPackageStart = parentPackage.length + 1 @@ -137,7 +137,7 @@ abstract class PackageNameReferenceProvider : PsiReferenceProvider() { private val qualifiedName: String get() { val name = qualifiedRange.substring(element.text) - return getBasePackage(element)?.let { it + '.' + name } ?: name + return getBasePackage(element)?.let { "$it.$name" } ?: name } override val unresolved: Boolean @@ -153,7 +153,7 @@ abstract class PackageNameReferenceProvider : PsiReferenceProvider() { private fun getNewName(newTarget: PsiQualifiedNamedElement): String { val newName = newTarget.qualifiedName!! - return getBasePackage(element)?.let { newName.removePrefix(it + '.') } ?: newName + return getBasePackage(element)?.let { newName.removePrefix("$it.") } ?: newName } override fun bindToElement(newTarget: PsiElement): PsiElement? { diff --git a/src/main/kotlin/util/reference/ReferenceResolver.kt b/src/main/kotlin/util/reference/ReferenceResolver.kt index 6354f43de..4450f9c94 100644 --- a/src/main/kotlin/util/reference/ReferenceResolver.kt +++ b/src/main/kotlin/util/reference/ReferenceResolver.kt @@ -99,6 +99,7 @@ private fun PsiElement.findContextElement(): PsiElement { var current: PsiElement var parent = this + @Suppress("KotlinConstantConditions") // kotlin is wrong do { current = parent parent = current.parent @@ -131,7 +132,7 @@ fun LookupElementBuilder.completeToLiteral(context: PsiElement): LookupElementBu private class ReplaceElementWithLiteral( private val editor: Editor, private val file: PsiFile, - private val text: String + private val text: String, ) : Runnable { override fun run() { @@ -145,8 +146,8 @@ private class ReplaceElementWithLiteral( element.replace( JavaPsiFacade.getElementFactory(element.project).createExpressionFromText( "\"$text\"", - element.parent - ) + element.parent, + ), ) } } diff --git a/src/main/kotlin/util/reflection-utils.kt b/src/main/kotlin/util/reflection-utils.kt index 53fb9fb04..0151fc473 100644 --- a/src/main/kotlin/util/reflection-utils.kt +++ b/src/main/kotlin/util/reflection-utils.kt @@ -27,7 +27,7 @@ fun Any.invokeDeclaredMethod( name: String, params: Array>, args: Array, - owner: Class<*> = javaClass + owner: Class<*> = javaClass, ): Any? { return runCatching { val method = owner.getDeclaredMethod(name, *params) diff --git a/src/main/kotlin/util/swing-utils.kt b/src/main/kotlin/util/swing-utils.kt new file mode 100644 index 000000000..111083f6c --- /dev/null +++ b/src/main/kotlin/util/swing-utils.kt @@ -0,0 +1,41 @@ +/* + * Minecraft Dev for IntelliJ + * + * https://minecraftdev.org + * + * Copyright (c) 2023 minecraft-dev + * + * MIT License + */ + +package com.demonwav.mcdev.util + +import com.intellij.openapi.observable.properties.ObservableProperty +import com.intellij.openapi.observable.util.bindEnabled +import com.intellij.ui.dsl.builder.Cell +import java.awt.Component +import java.awt.event.HierarchyEvent +import javax.swing.JComponent + +fun Component.onShown(func: (HierarchyEvent) -> Unit) { + addHierarchyListener { event -> + if ((event.changeFlags and HierarchyEvent.SHOWING_CHANGED.toLong()) != 0L && isShowing) { + func(event) + } + } +} + +fun Component.onHidden(func: (HierarchyEvent) -> Unit) { + addHierarchyListener { event -> + if ((event.changeFlags and HierarchyEvent.SHOWING_CHANGED.toLong()) != 0L && !isShowing) { + func(event) + } + } +} + +fun Cell.bindEnabled(property: ObservableProperty): Cell { + applyToComponent { + bindEnabled(property) + } + return this +} diff --git a/src/main/kotlin/util/utils.kt b/src/main/kotlin/util/utils.kt index f6bbd3be8..26a1c69e1 100644 --- a/src/main/kotlin/util/utils.kt +++ b/src/main/kotlin/util/utils.kt @@ -30,6 +30,7 @@ import com.intellij.openapi.roots.libraries.LibraryKindRegistry import com.intellij.openapi.util.Computable import com.intellij.openapi.util.Condition import com.intellij.openapi.util.Ref +import com.intellij.openapi.util.text.StringUtil import com.intellij.pom.java.LanguageLevel import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiFile @@ -52,30 +53,25 @@ fun runWriteTaskLater(func: () -> Unit) { } } -inline fun Project.runWriteTaskInSmartMode(crossinline func: () -> T): T { - if (ApplicationManager.getApplication().isReadAccessAllowed) { - return runWriteTask { func() } - } - +inline fun Project.runWriteTaskInSmartMode(crossinline func: () -> Unit) { val dumbService = DumbService.getInstance(this) - val ref = Ref() - while (true) { - dumbService.waitForSmartMode() - val success = runWriteTask { + lateinit var runnable: Runnable + runnable = Runnable { + if (isDisposed) { + throw ProcessCanceledException() + } + runWriteTask { if (isDisposed) { throw ProcessCanceledException() } if (dumbService.isDumb) { - return@runWriteTask false + dumbService.runWhenSmart(runnable) + } else { + func() } - ref.set(func()) - return@runWriteTask true - } - if (success) { - break } } - return ref.get() + dumbService.runWhenSmart(runnable) } fun invokeAndWait(func: () -> T): T { @@ -306,6 +302,9 @@ fun String.toJavaIdentifier(allowDollars: Boolean = true): String { .joinToString("") } +fun String.toJavaClassName() = StringUtil.capitalizeWords(this, true) + .replace(" ", "").toJavaIdentifier(allowDollars = false) + fun String.toPackageName(): String { if (this.isEmpty()) { return "_" diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 7fc506cfc..27640f1ab 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -13,7 +13,9 @@ com.intellij.modules.java org.jetbrains.idea.maven com.intellij.gradle + org.jetbrains.kotlin org.intellij.groovy + com.intellij.properties ByteCodeViewer org.toml.lang @@ -22,8 +24,7 @@ eigenraven messages.MinecraftDevelopment @@ -34,6 +35,18 @@ + + + + + + + + + + + + @@ -44,6 +57,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -82,7 +130,6 @@ * Sponge * Forge * Fabric - * LiteLoader * MCP * Mixin * Velocity @@ -269,14 +316,6 @@ - - - - - - - - diff --git a/src/main/resources/fileTemplates/j2ee/architectury/architectury_submodule_build.gradle.ft b/src/main/resources/fileTemplates/j2ee/architectury/architectury_submodule_build.gradle.ft deleted file mode 100644 index fd9553791..000000000 --- a/src/main/resources/fileTemplates/j2ee/architectury/architectury_submodule_build.gradle.ft +++ /dev/null @@ -1,49 +0,0 @@ -plugins { - id "architectury-plugin" version "3.4-SNAPSHOT" - id "dev.architectury.loom" version "0.+" apply false -} - -architectury { - minecraft = project.minecraft_version -} - -subprojects { - apply plugin: "dev.architectury.loom" - - loom { - silentMojangMappingsLicense() - } - - dependencies { - minecraft "com.mojang:minecraft:${project.minecraft_version}" - // The following line declares the mojmap mappings, you may use other mappings as well - mappings loom.officialMojangMappings() - // The following line declares the yarn mappings you may select this one as well. - // mappings "net.fabricmc:yarn:@YARN_MAPPINGS@:v2" - } -} - -allprojects { - apply plugin: "java" - apply plugin: "architectury-plugin" - apply plugin: "maven-publish" - - archivesBaseName = project.archives_base_name - - repositories { - // Add repositories to retrieve artifacts from in here. - // You should only use this when depending on other mods because - // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html - // for more information about repositories. - } - - tasks.withType(JavaCompile) { - options.encoding = "UTF-8" - options.release = ${JAVA_VERSION} - } - - java { - withSourcesJar() - } -} diff --git a/src/main/resources/fileTemplates/j2ee/architectury/architectury_submodule_build.gradle.html b/src/main/resources/fileTemplates/j2ee/architectury/architectury_submodule_build.gradle.html deleted file mode 100644 index 1b1796f1e..000000000 --- a/src/main/resources/fileTemplates/j2ee/architectury/architectury_submodule_build.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new build.gradle file for multi-module Architectury projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/architectury/architectury_submodule_gradle.properties.ft b/src/main/resources/fileTemplates/j2ee/architectury/architectury_submodule_gradle.properties.ft deleted file mode 100644 index 9232bdfad..000000000 --- a/src/main/resources/fileTemplates/j2ee/architectury/architectury_submodule_gradle.properties.ft +++ /dev/null @@ -1,12 +0,0 @@ -org.gradle.jvmargs=-Xmx1G - -minecraft_version=${MC_VERSION} - -archives_base_name=${ARTIFACT_ID} - -architectury_version=${ARCHITECTURY_API_VERSION} - -fabric_loader_version=${FABRIC_LOADER_VERSION} -fabric_api_version=${FABRIC_API_VERSION} - -forge_version=${FORGE_VERSION} diff --git a/src/main/resources/fileTemplates/j2ee/architectury/architectury_submodule_gradle.properties.html b/src/main/resources/fileTemplates/j2ee/architectury/architectury_submodule_gradle.properties.html deleted file mode 100644 index 8d9eca498..000000000 --- a/src/main/resources/fileTemplates/j2ee/architectury/architectury_submodule_gradle.properties.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new gradle.properties file for multi-module Architectury projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/bukkit/Bukkit Submodule build.gradle.ft b/src/main/resources/fileTemplates/j2ee/bukkit/Bukkit Submodule build.gradle.ft deleted file mode 100644 index 947d4c087..000000000 --- a/src/main/resources/fileTemplates/j2ee/bukkit/Bukkit Submodule build.gradle.ft +++ /dev/null @@ -1,28 +0,0 @@ -plugins { - id 'com.github.johnrengelman.shadow' -} - -repositories { -} - -dependencies { - api project(':${COMMON_PROJECT_NAME}') -} - -processResources { - def props = [version: project.version] - inputs.properties props - expand props - filteringCharset 'UTF-8' - filesMatching('plugin.yml') { - expand props - } -} - -shadowJar { - dependencies { - include(dependency(':${COMMON_PROJECT_NAME}')) - } -} - -tasks.build.dependsOn tasks.shadowJar diff --git a/src/main/resources/fileTemplates/j2ee/bukkit/Bukkit Submodule build.gradle.html b/src/main/resources/fileTemplates/j2ee/bukkit/Bukkit Submodule build.gradle.html deleted file mode 100644 index c04af1ad6..000000000 --- a/src/main/resources/fileTemplates/j2ee/bukkit/Bukkit Submodule build.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new build.gradle for the multi-module projects' Bukkit submodule.

- - diff --git a/src/main/resources/fileTemplates/j2ee/bukkit/Bukkit Submodule pom.xml.ft b/src/main/resources/fileTemplates/j2ee/bukkit/Bukkit Submodule pom.xml.ft deleted file mode 100644 index 65f9715ad..000000000 --- a/src/main/resources/fileTemplates/j2ee/bukkit/Bukkit Submodule pom.xml.ft +++ /dev/null @@ -1,42 +0,0 @@ - - - 4.0.0 - - - - - - - - - jar - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-shade-plugin - - - - - src/main/resources - true - - - - - - - - - - diff --git a/src/main/resources/fileTemplates/j2ee/bukkit/Bukkit Submodule pom.xml.html b/src/main/resources/fileTemplates/j2ee/bukkit/Bukkit Submodule pom.xml.html deleted file mode 100644 index 2111ec480..000000000 --- a/src/main/resources/fileTemplates/j2ee/bukkit/Bukkit Submodule pom.xml.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new pom.xml for the multi-module projects' Bukkit submodule.

- - diff --git a/src/main/resources/fileTemplates/j2ee/bungeecord/BungeeCord Submodule build.gradle.ft b/src/main/resources/fileTemplates/j2ee/bungeecord/BungeeCord Submodule build.gradle.ft deleted file mode 100644 index 927bd2386..000000000 --- a/src/main/resources/fileTemplates/j2ee/bungeecord/BungeeCord Submodule build.gradle.ft +++ /dev/null @@ -1,28 +0,0 @@ -plugins { - id 'com.github.johnrengelman.shadow' -} - -repositories { -} - -dependencies { - api project(':${COMMON_PROJECT_NAME}') -} - -processResources { - def props = [version: project.version] - inputs.properties props - expand props - filteringCharset 'UTF-8' - filesMatching('bungee.yml') { - expand props - } -} - -shadowJar { - dependencies { - include(dependency(':${COMMON_PROJECT_NAME}')) - } -} - -tasks.build.dependsOn tasks.shadowJar diff --git a/src/main/resources/fileTemplates/j2ee/bungeecord/BungeeCord Submodule build.gradle.html b/src/main/resources/fileTemplates/j2ee/bungeecord/BungeeCord Submodule build.gradle.html deleted file mode 100644 index 67991a014..000000000 --- a/src/main/resources/fileTemplates/j2ee/bungeecord/BungeeCord Submodule build.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new build.gradle for the multi-module projects' BungeeCord submodule.

- - diff --git a/src/main/resources/fileTemplates/j2ee/bungeecord/BungeeCord Submodule pom.xml.ft b/src/main/resources/fileTemplates/j2ee/bungeecord/BungeeCord Submodule pom.xml.ft deleted file mode 100644 index 65f9715ad..000000000 --- a/src/main/resources/fileTemplates/j2ee/bungeecord/BungeeCord Submodule pom.xml.ft +++ /dev/null @@ -1,42 +0,0 @@ - - - 4.0.0 - - - - - - - - - jar - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-shade-plugin - - - - - src/main/resources - true - - - - - - - - - - diff --git a/src/main/resources/fileTemplates/j2ee/bungeecord/BungeeCord Submodule pom.xml.html b/src/main/resources/fileTemplates/j2ee/bungeecord/BungeeCord Submodule pom.xml.html deleted file mode 100644 index b80a2607d..000000000 --- a/src/main/resources/fileTemplates/j2ee/bungeecord/BungeeCord Submodule pom.xml.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new pom.xml for the multi-module projects' BungeeCord submodule.

- - diff --git a/src/main/resources/fileTemplates/j2ee/common/MinecraftDev gradle-wrapper.properties.ft b/src/main/resources/fileTemplates/j2ee/common/MinecraftDev gradle-wrapper.properties.ft new file mode 100644 index 000000000..6177dd6c5 --- /dev/null +++ b/src/main/resources/fileTemplates/j2ee/common/MinecraftDev gradle-wrapper.properties.ft @@ -0,0 +1 @@ +distributionUrl=https\://services.gradle.org/distributions/gradle-${GRADLE_WRAPPER_VERSION}-bin.zip diff --git a/src/main/resources/fileTemplates/j2ee/forge/mcmod.info.html b/src/main/resources/fileTemplates/j2ee/common/MinecraftDev gradle-wrapper.properties.html similarity index 57% rename from src/main/resources/fileTemplates/j2ee/forge/mcmod.info.html rename to src/main/resources/fileTemplates/j2ee/common/MinecraftDev gradle-wrapper.properties.html index 1df4ae98a..9893a1041 100644 --- a/src/main/resources/fileTemplates/j2ee/forge/mcmod.info.html +++ b/src/main/resources/fileTemplates/j2ee/common/MinecraftDev gradle-wrapper.properties.html @@ -10,6 +10,6 @@ -

This is a built-in file template used to create a new mcmod.info for Forge projects 1.12 and below.

+

This is a built-in file template used to create a new gradle-wrapper.properties file for Minecraft projects.

diff --git a/src/main/resources/fileTemplates/j2ee/fabric/fabric_submodule_build.gradle.ft b/src/main/resources/fileTemplates/j2ee/fabric/fabric_submodule_build.gradle.ft deleted file mode 100644 index 293a749d7..000000000 --- a/src/main/resources/fileTemplates/j2ee/fabric/fabric_submodule_build.gradle.ft +++ /dev/null @@ -1,80 +0,0 @@ -plugins { - id 'fabric-loom' version '${LOOM_VERSION}' - id 'maven-publish' -} - -repositories { - // Add repositories to retrieve artifacts from in here. - // You should only use this when depending on other mods because - // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html - // for more information about repositories. -} - -dependencies { - // To change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - - #if (${API_VERSION}) - // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - #end -} - -processResources { - inputs.property "version", project.version - filteringCharset "UTF-8" - - filesMatching("fabric.mod.json") { - expand "version": project.version - } -} - -def targetJavaVersion = ${JAVA_VERSION} -tasks.withType(JavaCompile).configureEach { - // ensure that the encoding is set to UTF-8, no matter what the system default is - // this fixes some edge cases with special characters not displaying correctly - // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html - // If Javadoc is generated, this must be specified in that task too. - it.options.encoding = "UTF-8" - if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { - it.options.release = targetJavaVersion - } -} - -java { - def javaVersion = JavaVersion.toVersion(targetJavaVersion) - if (JavaVersion.current() < javaVersion) { - toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) - } - archivesBaseName = project.archives_base_name - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() -} - -jar { - from("LICENSE") { - rename { "${it}_${project.archivesBaseName}"} - } -} - -// configure the maven publication -publishing { - publications { - mavenJava(MavenPublication) { - from components.java - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. - } -} diff --git a/src/main/resources/fileTemplates/j2ee/fabric/fabric_submodule_build.gradle.html b/src/main/resources/fileTemplates/j2ee/fabric/fabric_submodule_build.gradle.html deleted file mode 100644 index f96b4feac..000000000 --- a/src/main/resources/fileTemplates/j2ee/fabric/fabric_submodule_build.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new build.gradle file for multi-module Fabric projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/fabric/fabric_submodule_gradle.properties.ft b/src/main/resources/fileTemplates/j2ee/fabric/fabric_submodule_gradle.properties.ft deleted file mode 100644 index da97f5695..000000000 --- a/src/main/resources/fileTemplates/j2ee/fabric/fabric_submodule_gradle.properties.ft +++ /dev/null @@ -1,17 +0,0 @@ -# Done to increase the memory available to gradle. -org.gradle.jvmargs=-Xmx1G - -# Fabric Properties - # check these on https://modmuss50.me/fabric.html - minecraft_version=${MC_VERSION} - yarn_mappings=${YARN_MAPPINGS} - loader_version=${LOADER_VERSION} - -# Mod Properties - archives_base_name = ${ARTIFACT_ID} - -#if (${API_VERSION}) -# Dependencies - # check this on https://modmuss50.me/fabric.html - fabric_version=${API_VERSION} -#end diff --git a/src/main/resources/fileTemplates/j2ee/fabric/fabric_submodule_gradle.properties.html b/src/main/resources/fileTemplates/j2ee/fabric/fabric_submodule_gradle.properties.html deleted file mode 100644 index 5e1251648..000000000 --- a/src/main/resources/fileTemplates/j2ee/fabric/fabric_submodule_gradle.properties.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new gradle.properties file for multi-module Fabric projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/forge/Forge Submodule build.gradle.ft b/src/main/resources/fileTemplates/j2ee/forge/Forge Submodule build.gradle.ft deleted file mode 100644 index e26a3179c..000000000 --- a/src/main/resources/fileTemplates/j2ee/forge/Forge Submodule build.gradle.ft +++ /dev/null @@ -1,56 +0,0 @@ -buildscript { - repositories { - mavenCentral() - maven { - name = "forge" - url = "https://files.minecraftforge.net/maven" - } - } - dependencies { - classpath "net.minecraftforge.gradle:ForgeGradle:${FORGEGRADLE_VERSION}-SNAPSHOT" - } -} - -apply plugin: "net.minecraftforge.gradle.forge" - -archivesBaseName = '${ARTIFACT_ID}' - -minecraft { - version = project.forgeVersion - runDir = "run" - - // the mappings can be changed at any time, and must be in the following format. - // snapshot_YYYYMMDD snapshot are built nightly. - // stable_# stables are built at the discretion of the MCP team. - // Use non-default mappings at your own risk. they may not always work. - // simply re-run your setup task after changing the mappings to update your workspace. - mappings = project.mcpVersion - // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. -} - -repositories { - mavenCentral() -} - -dependencies { - compile project(":${COMMON_PROJECT_NAME}") -} - -processResources { - // this will ensure that this task is redone when the versions change. - inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.version - - // replace stuff in mcmod.info, nothing else - from(sourceSets.main.resources.srcDirs) { - include "mcmod.info" - - // replace version and mcversion - expand "version": project.version, "mcversion": project.minecraft.version - } - - // copy everything else, thats not the mcmod.info - from(sourceSets.main.resources.srcDirs) { - exclude "mcmod.info" - } -} diff --git a/src/main/resources/fileTemplates/j2ee/forge/Forge Submodule build.gradle.html b/src/main/resources/fileTemplates/j2ee/forge/Forge Submodule build.gradle.html deleted file mode 100644 index 2bd55638c..000000000 --- a/src/main/resources/fileTemplates/j2ee/forge/Forge Submodule build.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new build.gradle for the multi-module projects' Forge submodule for 1.12 and below.

- - diff --git a/src/main/resources/fileTemplates/j2ee/forge/mcmod.info.ft b/src/main/resources/fileTemplates/j2ee/forge/mcmod.info.ft deleted file mode 100644 index e87320e3d..000000000 --- a/src/main/resources/fileTemplates/j2ee/forge/mcmod.info.ft +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "modid": "${ARTIFACT_ID}", - "name": "${MOD_NAME}", - "description": "${DESCRIPTION}", - "version": "${version}", - "mcversion": "${mcversion}", -#if (${URL}) - "url": "${URL}", -#else - "url": "", -#end -#if (${UPDATE_URL}) - "updateUrl": "${UPDATE_URL}", -#else - "updateUrl": "", -#end -#if (${AUTHOR_LIST}) - "authorList": [${AUTHOR_LIST}], -#else - "authorList": [], -#end - "credits": "", - "logoFile": "", - "screenshots": [], - "dependencies": [] - } -] diff --git a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader Main Class.java.ft b/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader Main Class.java.ft deleted file mode 100644 index 967732e10..000000000 --- a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader Main Class.java.ft +++ /dev/null @@ -1,55 +0,0 @@ -package ${PACKAGE_NAME}; - -import com.mumfrey.liteloader.LiteMod; -import java.io.File; - -public class ${CLASS_NAME} implements LiteMod { - - /** - * Default constructor. All LiteMods must have a default constructor. In general you should do very little - * in the mod constructor EXCEPT for initialising any non-game-interfacing components or performing - * sanity checking prior to initialisation - */ - public ${CLASS_NAME}() { - } - - /** - * getName() should be used to return the display name of your mod and MUST NOT return null - * - * @see com.mumfrey.liteloader.LiteMod#getName() - */ - @Override - public String getName() { - return "${MOD_NAME}"; - } - - /** - * getVersion() should return the same version string present in the mod metadata, although this is - * not a strict requirement. - * - * @see com.mumfrey.liteloader.LiteMod#getVersion() - */ - @Override - public String getVersion() { - return "${MOD_VERSION}"; - } - - /** - * init() is called very early in the initialisation cycle, before the game is fully initialised, this - * means that it is important that your mod does not interact with the game in any way at this point. - * - * @see com.mumfrey.liteloader.LiteMod#init(File) - */ - @Override - public void init(File configPath) { - } - - /** - * upgradeSettings is used to notify a mod that its version-specific settings are being migrated - * - * @see com.mumfrey.liteloader.LiteMod#upgradeSettings(String, File, File) - */ - @Override - public void upgradeSettings(String version, File configPath, File oldConfigPath) { - } -} \ No newline at end of file diff --git a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader Main Class.java.html b/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader Main Class.java.html deleted file mode 100644 index df6b6ef0b..000000000 --- a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader Main Class.java.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new main class for LiteLoader projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader Submodule build.gradle.ft b/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader Submodule build.gradle.ft deleted file mode 100644 index 4a0a08391..000000000 --- a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader Submodule build.gradle.ft +++ /dev/null @@ -1,52 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - maven { - name = "sonatype" - url = "https://oss.sonatype.org/content/repositories/snapshots/" - } - maven { - name = "forge" - url = "https://files.minecraftforge.net/maven" - } - maven { - name = 'sponge' - url = 'https://repo.spongepowered.org/maven' - } - } - dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:${FORGEGRADLE_VERSION}-SNAPSHOT' - classpath 'org.spongepowered:mixingradle:0.4-SNAPSHOT' - } -} - -apply plugin: 'com.github.johnrengelman.shadow' -apply plugin: 'net.minecraftforge.gradle.liteloader' -apply plugin: 'org.spongepowered.mixin' - -archivesBaseName = '${ARTIFACT_ID}' - -minecraft { - version = project.mcVersion - mappings = project.mcpMappings - runDir = "run" -} - -dependencies { - compile project(":${COMMON_PROJECT_NAME}") -} - -mixin { - defaultObfuscationEnv notch -} - -jar { - from litemod.outputs -} - -shadowJar { - dependencies { - include(dependency(":${COMMON_PROJECT_NAME}")) - } -} diff --git a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader Submodule build.gradle.html b/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader Submodule build.gradle.html deleted file mode 100644 index 4fce93126..000000000 --- a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader Submodule build.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new build.gradle for the multi-module projects' LiteLoader submodule.

- - diff --git a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader build.gradle.ft b/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader build.gradle.ft deleted file mode 100644 index 7ca73caed..000000000 --- a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader build.gradle.ft +++ /dev/null @@ -1,43 +0,0 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - maven { - name = "sonatype" - url = "https://oss.sonatype.org/content/repositories/snapshots/" - } - maven { - name = "forge" - url = "https://files.minecraftforge.net/maven" - } - maven { - name = 'sponge' - url = 'https://repo.spongepowered.org/maven' - } - } - dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:${FORGEGRADLE_VERSION}-SNAPSHOT' - classpath 'org.spongepowered:mixingradle:0.4-SNAPSHOT' - } -} - -apply plugin: 'net.minecraftforge.gradle.liteloader' -apply plugin: 'org.spongepowered.mixin' - -group = '${GROUP_ID}' -version = '${VERSION}' -archivesBaseName = '${ARTIFACT_ID}' - -minecraft { - version = project.mcVersion - mappings = project.mcpMappings - runDir = "run" -} - -mixin { - defaultObfuscationEnv notch -} - -jar { - from litemod.outputs -} diff --git a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader build.gradle.html b/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader build.gradle.html deleted file mode 100644 index 1cda5e69d..000000000 --- a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader build.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new build.gradle for LiteLoader projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader gradle.properties.ft b/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader gradle.properties.ft deleted file mode 100644 index 79c95aa85..000000000 --- a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader gradle.properties.ft +++ /dev/null @@ -1,2 +0,0 @@ -mcVersion = ${MC_VERSION} -mcpMappings = ${MCP_MAPPINGS} diff --git a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader gradle.properties.html b/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader gradle.properties.html deleted file mode 100644 index 16ad1e3d7..000000000 --- a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader gradle.properties.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new gradle.properties file for LiteLoader projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader settings.gradle.ft b/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader settings.gradle.ft deleted file mode 100644 index 9e1c33fcf..000000000 --- a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader settings.gradle.ft +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = '${PROJECT_NAME}' diff --git a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader settings.gradle.html b/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader settings.gradle.html deleted file mode 100644 index 8c0d6210d..000000000 --- a/src/main/resources/fileTemplates/j2ee/liteloader/LiteLoader settings.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new settings.gradle for LiteLoader projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base build.gradle.ft b/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base build.gradle.ft deleted file mode 100644 index 352b9ad2e..000000000 --- a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base build.gradle.ft +++ /dev/null @@ -1,34 +0,0 @@ -plugins { - id "com.github.johnrengelman.shadow" version "7.0.0" apply false -} - -group = '${GROUP_ID}' -version = '${PLUGIN_VERSION}' - -subprojects { - apply plugin: 'java-library' - apply plugin: 'maven-publish' - - group = parent.group - version = parent.version - - def targetJavaVersion = property('javaVersion') as int - java { - def javaVersion = JavaVersion.toVersion(targetJavaVersion) - sourceCompatibility = javaVersion - targetCompatibility = javaVersion - if (JavaVersion.current() < javaVersion) { - toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) - } - } - - tasks.withType(JavaCompile).configureEach { - if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { - options.release = targetJavaVersion - } - } - - repositories { - mavenCentral() - } -} diff --git a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base build.gradle.html b/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base build.gradle.html deleted file mode 100644 index 64cef9fe5..000000000 --- a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base build.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new build.gradle for multi-module Minecraft projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base gradle.properties.ft b/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base gradle.properties.ft deleted file mode 100644 index 752910940..000000000 --- a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base gradle.properties.ft +++ /dev/null @@ -1 +0,0 @@ -javaVersion=8 diff --git a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base gradle.properties.html b/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base gradle.properties.html deleted file mode 100644 index 085ba1330..000000000 --- a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base gradle.properties.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new gradle.properties file for Minecraft projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base pom.xml.ft b/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base pom.xml.ft deleted file mode 100644 index 29d9ef601..000000000 --- a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base pom.xml.ft +++ /dev/null @@ -1,51 +0,0 @@ - - - 4.0.0 - - - - - pom - - - 1.8 - UTF-8 - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin-version} - - ${java.version} - ${java.version} - - - - org.apache.maven.plugins - maven-shade-plugin - ${maven-shade-plugin-version} - - - package - - shade - - - false - - - - - - - - - - - diff --git a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base pom.xml.html b/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base pom.xml.html deleted file mode 100644 index 34409a508..000000000 --- a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base pom.xml.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new pom.xml for multi-module Minecraft projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base settings.gradle.ft b/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base settings.gradle.ft deleted file mode 100644 index 7526c6d93..000000000 --- a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base settings.gradle.ft +++ /dev/null @@ -1,3 +0,0 @@ -rootProject.name = '${ARTIFACT_ID}' - -include ${INCLUDES} diff --git a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base settings.gradle.html b/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base settings.gradle.html deleted file mode 100644 index 048ad65d8..000000000 --- a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Base settings.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new settings.gradle for multi-module Minecraft projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Common pom.xml.ft b/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Common pom.xml.ft deleted file mode 100644 index 69a87e31b..000000000 --- a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Common pom.xml.ft +++ /dev/null @@ -1,34 +0,0 @@ - - - 4.0.0 - - - - - - - - - jar - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-shade-plugin - - - - - src/main/resources - true - - - - diff --git a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Common pom.xml.html b/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Common pom.xml.html deleted file mode 100644 index 2e5f8a46d..000000000 --- a/src/main/resources/fileTemplates/j2ee/multi/Multi-Module Common pom.xml.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new pom.xml for the common module in multi-module Minecraft projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge 8+ Submodule build.gradle.kts.ft b/src/main/resources/fileTemplates/j2ee/sponge/Sponge 8+ Submodule build.gradle.kts.ft deleted file mode 100644 index 712be36d0..000000000 --- a/src/main/resources/fileTemplates/j2ee/sponge/Sponge 8+ Submodule build.gradle.kts.ft +++ /dev/null @@ -1,94 +0,0 @@ -import org.spongepowered.gradle.plugin.config.PluginLoaders -import org.spongepowered.plugin.metadata.model.PluginDependency - -plugins { - `java-library` - id("com.github.johnrengelman.shadow") - id("org.spongepowered.gradle.plugin") version "2.0.2" -} - -repositories { - mavenCentral() -} - -dependencies { - implementation(project(":${COMMON_PROJECT_NAME}")) -} - -sponge { - apiVersion("${SPONGEAPI_VERSION}") - license("${LICENSE}") - loader { - name(PluginLoaders.JAVA_PLAIN) - version("1.0") - } - plugin("${PLUGIN_ID}") { - displayName("${PLUGIN_NAME}") - entrypoint("${MAIN_CLASS}") - #if (${DESCRIPTION}) - description("${DESCRIPTION}") - #else - description("My plugin description") - #end - links { - #if (${WEBSITE}) - homepage("${WEBSITE}") - #else - // homepage("https://spongepowered.org") - #end - // source("https://spongepowered.org/source") - // issues("https://spongepowered.org/issues") - } - #foreach (${AUTHOR} in ${AUTHORS}) - contributor("${AUTHOR}") { - description("Author") - } - #end - dependency("spongeapi") { - loadOrder(PluginDependency.LoadOrder.AFTER) - optional(false) - } - #foreach (${DEPENDENCY} in ${DEPENDENCIES}) - dependency("${DEPEDENCY}") { - loadOrder(PluginDependency.LoadOrder.AFTER) - optional(false) - } - #end - } -} - -val javaTarget = ${JAVA_VERSION} // Sponge targets a minimum of Java ${JAVA_VERSION} -java { - sourceCompatibility = JavaVersion.toVersion(javaTarget) - targetCompatibility = JavaVersion.toVersion(javaTarget) - if (JavaVersion.current() < JavaVersion.toVersion(javaTarget)) { - toolchain.languageVersion.set(JavaLanguageVersion.of(javaTarget)) - } -} - -tasks.withType(JavaCompile::class).configureEach { - options.apply { - encoding = "utf-8" // Consistent source file encoding - if (JavaVersion.current().isJava10Compatible) { - release.set(javaTarget) - } - } -} - -// Make sure all tasks which produce archives (jar, sources jar, javadoc jar, etc) produce more consistent output -tasks.withType(AbstractArchiveTask::class).configureEach { - isReproducibleFileOrder = true - isPreserveFileTimestamps = false -} - -tasks { - shadowJar { - dependencies { - include(dependency(":${COMMON_PROJECT_NAME}")) - } - } - - build { - dependsOn(shadowJar) - } -} diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge 8+ Submodule build.gradle.kts.html b/src/main/resources/fileTemplates/j2ee/sponge/Sponge 8+ Submodule build.gradle.kts.html deleted file mode 100644 index f913b5546..000000000 --- a/src/main/resources/fileTemplates/j2ee/sponge/Sponge 8+ Submodule build.gradle.kts.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new build.gradle for the multi-module projects' SpongeAPI 8 submodule.

- - diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge Main Class.java.ft b/src/main/resources/fileTemplates/j2ee/sponge/Sponge Main Class.java.ft deleted file mode 100644 index 220ee0224..000000000 --- a/src/main/resources/fileTemplates/j2ee/sponge/Sponge Main Class.java.ft +++ /dev/null @@ -1,19 +0,0 @@ -package ${PACKAGE}; - -import com.google.inject.Inject; -import org.slf4j.Logger; -import org.spongepowered.api.event.game.state.GameStartedServerEvent; -import org.spongepowered.api.event.Listener; -#if(${HAS_DEPENDENCIES}) -import org.spongepowered.api.plugin.Dependency; -#end -import org.spongepowered.api.plugin.Plugin; - -public class ${CLASS_NAME} { - - @Inject private Logger logger; - - @Listener - public void onServerStart(GameStartedServerEvent event) { - } -} diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge Main Class.java.html b/src/main/resources/fileTemplates/j2ee/sponge/Sponge Main Class.java.html deleted file mode 100644 index d7ab0079b..000000000 --- a/src/main/resources/fileTemplates/j2ee/sponge/Sponge Main Class.java.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new main class for legacy Sponge (API 7).

- - diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge Submodule build.gradle.ft b/src/main/resources/fileTemplates/j2ee/sponge/Sponge Submodule build.gradle.ft deleted file mode 100644 index 20710bcf9..000000000 --- a/src/main/resources/fileTemplates/j2ee/sponge/Sponge Submodule build.gradle.ft +++ /dev/null @@ -1,23 +0,0 @@ -plugins { - id 'org.spongepowered.plugin' version '0.9.0' - id 'com.github.johnrengelman.shadow' -} - -java { - targetCompatibility = null - sourceCompatibility = null -} - -dependencies { - compile project(':${COMMON_PROJECT_NAME}') -} - -sponge.plugin.id = '${PLUGIN_ID}' - -shadowJar { - dependencies { - include(dependency(':${COMMON_PROJECT_NAME}')) - } -} - -tasks.build.dependsOn tasks.shadowJar diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge Submodule build.gradle.html b/src/main/resources/fileTemplates/j2ee/sponge/Sponge Submodule build.gradle.html deleted file mode 100644 index 1b093e727..000000000 --- a/src/main/resources/fileTemplates/j2ee/sponge/Sponge Submodule build.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new build.gradle for the multi-module projects' legacy Sponge (API 7) submodule.

- - diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge Submodule pom.xml.ft b/src/main/resources/fileTemplates/j2ee/sponge/Sponge Submodule pom.xml.ft deleted file mode 100644 index ebc5b3be3..000000000 --- a/src/main/resources/fileTemplates/j2ee/sponge/Sponge Submodule pom.xml.ft +++ /dev/null @@ -1,149 +0,0 @@ - - - 4.0.0 - - - - - - - - - jar - - - - - ${JAVA_VERSION} - UTF-8 - - - - - release - - - - org.apache.maven.plugins - maven-source-plugin - ${maven-source-plugin-version} - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - ${maven-javadoc-plugin-version} - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-gpg-plugin - ${maven-gpg-plugin-version} - - - sign-artifacts - verify - - sign - - - - - - - - src/main/resources - true - - - - - - - - - - ${project.basedir}/src/main/resources - true - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.codehaus.mojo - templating-maven-plugin - ${templating-maven-plugin-version} - - - filter-src - - filter-sources - - - - - - org.apache.maven.plugins - maven-site-plugin - ${maven-site-plugin-version} - - - net.trajano.wagon - wagon-git - ${wagon-git-version} - - - org.apache.maven.doxia - doxia-module-markdown - ${doxia-module-markdown-version} - - - - - org.apache.maven.plugins - maven-release-plugin - ${maven-release-plugin-version} - - true - @{project.version} - [RELEASE] - install deploy site-deploy - release - - - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - ${maven-javadoc-plugin-version} - - - - - - - - diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge Submodule pom.xml.html b/src/main/resources/fileTemplates/j2ee/sponge/Sponge Submodule pom.xml.html deleted file mode 100644 index 405d4ce61..000000000 --- a/src/main/resources/fileTemplates/j2ee/sponge/Sponge Submodule pom.xml.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new pom.xml for the multi-module projects' Sponge submodule.

- - diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge build.gradle.ft b/src/main/resources/fileTemplates/j2ee/sponge/Sponge build.gradle.ft deleted file mode 100644 index 07537bf6c..000000000 --- a/src/main/resources/fileTemplates/j2ee/sponge/Sponge build.gradle.ft +++ /dev/null @@ -1,27 +0,0 @@ -plugins { - id 'org.spongepowered.plugin' version '0.9.0' -} - -group = '${GROUP_ID}' -version = '${PLUGIN_VERSION}' - -dependencies { -} - -sponge.plugin.id = '${PLUGIN_ID}' - -def targetJavaVersion = 8 -java { - def javaVersion = JavaVersion.toVersion(targetJavaVersion) - sourceCompatibility = javaVersion - targetCompatibility = javaVersion - if (JavaVersion.current() < javaVersion) { - toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) - } -} - -tasks.withType(JavaCompile).configureEach { - if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { - options.release = targetJavaVersion - } -} diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge build.gradle.html b/src/main/resources/fileTemplates/j2ee/sponge/Sponge build.gradle.html deleted file mode 100644 index 635bd9be5..000000000 --- a/src/main/resources/fileTemplates/j2ee/sponge/Sponge build.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new build.gradle for legacy Sponge (API 7) projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge gradle.properties.ft b/src/main/resources/fileTemplates/j2ee/sponge/Sponge gradle.properties.ft deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge gradle.properties.html b/src/main/resources/fileTemplates/j2ee/sponge/Sponge gradle.properties.html deleted file mode 100644 index 60c270a7d..000000000 --- a/src/main/resources/fileTemplates/j2ee/sponge/Sponge gradle.properties.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new gradle.properties file for legacy Sponge (API 7) projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge settings.gradle.ft b/src/main/resources/fileTemplates/j2ee/sponge/Sponge settings.gradle.ft deleted file mode 100644 index 9e1c33fcf..000000000 --- a/src/main/resources/fileTemplates/j2ee/sponge/Sponge settings.gradle.ft +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = '${PROJECT_NAME}' diff --git a/src/main/resources/fileTemplates/j2ee/sponge/Sponge settings.gradle.html b/src/main/resources/fileTemplates/j2ee/sponge/Sponge settings.gradle.html deleted file mode 100644 index 1467466e6..000000000 --- a/src/main/resources/fileTemplates/j2ee/sponge/Sponge settings.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new settings.gradle for legacy Sponge (API 7) projects.

- - diff --git a/src/main/resources/fileTemplates/j2ee/velocity/Velocity Submodule build.gradle.ft b/src/main/resources/fileTemplates/j2ee/velocity/Velocity Submodule build.gradle.ft deleted file mode 100644 index f66478daa..000000000 --- a/src/main/resources/fileTemplates/j2ee/velocity/Velocity Submodule build.gradle.ft +++ /dev/null @@ -1,39 +0,0 @@ -plugins { - id 'java' - id 'eclipse' - id 'com.github.johnrengelman.shadow' -} - -repositories { - mavenCentral() -} - -dependencies { - api project(':${COMMON_PROJECT_NAME}') -} - -def templateSource = file('src/main/templates') -def templateDest = layout.buildDirectory.dir('generated/sources/templates') -def generateTemplates = tasks.register('generateTemplates', Copy) { task -> - def props = [ - 'version': project.version - ] - task.inputs.properties props - - task.from templateSource - task.into templateDest - task.expand props -} - -sourceSets.main.java.srcDir(generateTemplates.map { it.outputs }) - -rootProject.idea.project.settings.taskTriggers.afterSync generateTemplates -project.eclipse.synchronizationTasks(generateTemplates) - -shadowJar { - dependencies { - include(dependency(':${COMMON_PROJECT_NAME}')) - } -} - -tasks.build.dependsOn tasks.shadowJar diff --git a/src/main/resources/fileTemplates/j2ee/velocity/Velocity Submodule build.gradle.html b/src/main/resources/fileTemplates/j2ee/velocity/Velocity Submodule build.gradle.html deleted file mode 100644 index 90e99e05b..000000000 --- a/src/main/resources/fileTemplates/j2ee/velocity/Velocity Submodule build.gradle.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new build.gradle for the multi-module projects' Velocity submodule.

- - diff --git a/src/main/resources/fileTemplates/j2ee/velocity/Velocity Submodule pom.xml.ft b/src/main/resources/fileTemplates/j2ee/velocity/Velocity Submodule pom.xml.ft deleted file mode 100644 index ebc5b3be3..000000000 --- a/src/main/resources/fileTemplates/j2ee/velocity/Velocity Submodule pom.xml.ft +++ /dev/null @@ -1,149 +0,0 @@ - - - 4.0.0 - - - - - - - - - jar - - - - - ${JAVA_VERSION} - UTF-8 - - - - - release - - - - org.apache.maven.plugins - maven-source-plugin - ${maven-source-plugin-version} - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - ${maven-javadoc-plugin-version} - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-gpg-plugin - ${maven-gpg-plugin-version} - - - sign-artifacts - verify - - sign - - - - - - - - src/main/resources - true - - - - - - - - - - ${project.basedir}/src/main/resources - true - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.codehaus.mojo - templating-maven-plugin - ${templating-maven-plugin-version} - - - filter-src - - filter-sources - - - - - - org.apache.maven.plugins - maven-site-plugin - ${maven-site-plugin-version} - - - net.trajano.wagon - wagon-git - ${wagon-git-version} - - - org.apache.maven.doxia - doxia-module-markdown - ${doxia-module-markdown-version} - - - - - org.apache.maven.plugins - maven-release-plugin - ${maven-release-plugin-version} - - true - @{project.version} - [RELEASE] - install deploy site-deploy - release - - - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - ${maven-javadoc-plugin-version} - - - - - - - - diff --git a/src/main/resources/fileTemplates/j2ee/velocity/Velocity Submodule pom.xml.html b/src/main/resources/fileTemplates/j2ee/velocity/Velocity Submodule pom.xml.html deleted file mode 100644 index 6a3b659c0..000000000 --- a/src/main/resources/fileTemplates/j2ee/velocity/Velocity Submodule pom.xml.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -

This is a built-in file template used to create a new pom.xml for the multi-module projects' Velocity submodule.

- - diff --git a/src/test/kotlin/framework/BaseMinecraftTest.kt b/src/test/kotlin/framework/BaseMinecraftTest.kt index 2a0ed178c..f53d81d65 100644 --- a/src/test/kotlin/framework/BaseMinecraftTest.kt +++ b/src/test/kotlin/framework/BaseMinecraftTest.kt @@ -24,9 +24,9 @@ import com.intellij.testFramework.LightProjectDescriptor import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor abstract class BaseMinecraftTest( - vararg platformTypes: PlatformType + vararg platformTypes: PlatformType, ) : ProjectBuilderTest( - getProjectDescriptor(platformTypes) + getProjectDescriptor(platformTypes), ) { protected open val resourcePath = "src/test/resources" protected open val packagePath = "com/demonwav/mcdev" diff --git a/src/test/kotlin/framework/EdtInterceptor.kt b/src/test/kotlin/framework/EdtInterceptor.kt index e23aa89c8..95d56877c 100644 --- a/src/test/kotlin/framework/EdtInterceptor.kt +++ b/src/test/kotlin/framework/EdtInterceptor.kt @@ -20,7 +20,7 @@ class EdtInterceptor : InvocationInterceptor { override fun interceptBeforeEachMethod( invocation: InvocationInterceptor.Invocation, invocationContext: ReflectiveInvocationContext, - extensionContext: ExtensionContext + extensionContext: ExtensionContext, ) { exec(invocation, invocationContext) } @@ -28,7 +28,7 @@ class EdtInterceptor : InvocationInterceptor { override fun interceptAfterEachMethod( invocation: InvocationInterceptor.Invocation, invocationContext: ReflectiveInvocationContext, - extensionContext: ExtensionContext + extensionContext: ExtensionContext, ) { exec(invocation, invocationContext) } @@ -36,14 +36,14 @@ class EdtInterceptor : InvocationInterceptor { override fun interceptTestMethod( invocation: InvocationInterceptor.Invocation, invocationContext: ReflectiveInvocationContext, - extensionContext: ExtensionContext + extensionContext: ExtensionContext, ) { exec(invocation, invocationContext) } private fun exec( invocation: InvocationInterceptor.Invocation, - invocationContext: ReflectiveInvocationContext + invocationContext: ReflectiveInvocationContext, ) { if (invocationContext.executable.getAnnotation(NoEdt::class.java) != null) { invocation.proceed() diff --git a/src/test/kotlin/framework/MockJdk.kt b/src/test/kotlin/framework/MockJdk.kt index da5e00e7f..94ce5d134 100644 --- a/src/test/kotlin/framework/MockJdk.kt +++ b/src/test/kotlin/framework/MockJdk.kt @@ -55,7 +55,7 @@ class MockJdk(private val name: String, jar: VirtualFile, private val home: Virt override fun addRootSetChangedListener(listener: RootProvider.RootSetChangedListener) {} override fun addRootSetChangedListener( listener: RootProvider.RootSetChangedListener, - parentDisposable: Disposable + parentDisposable: Disposable, ) { } diff --git a/src/test/kotlin/framework/ProjectBuilder.kt b/src/test/kotlin/framework/ProjectBuilder.kt index 57f997811..64933b377 100644 --- a/src/test/kotlin/framework/ProjectBuilder.kt +++ b/src/test/kotlin/framework/ProjectBuilder.kt @@ -33,25 +33,25 @@ class ProjectBuilder(private val fixture: JavaCodeInsightTestFixture, private va path: String, @Language("JAVA") code: String, configure: Boolean = true, - allowAst: Boolean = false + allowAst: Boolean = false, ) = file(path, code, ".java", configure, allowAst) fun at( path: String, @Language("Access Transformers") code: String, configure: Boolean = true, - allowAst: Boolean = false + allowAst: Boolean = false, ) = file(path, code, "_at.cfg", configure, allowAst) fun lang( path: String, @Language("MCLang") code: String, configure: Boolean = true, - allowAst: Boolean = false + allowAst: Boolean = false, ) = file(path, code, ".lang", configure, allowAst) fun nbtt( path: String, @Language("NBTT") code: String, configure: Boolean = true, - allowAst: Boolean = false + allowAst: Boolean = false, ) = file(path, code, ".nbtt", configure, allowAst) inline fun dir(path: String, block: ProjectBuilder.() -> Unit) { diff --git a/src/test/kotlin/framework/test-util.kt b/src/test/kotlin/framework/test-util.kt index 2ff0a1c72..3250c7f7f 100644 --- a/src/test/kotlin/framework/test-util.kt +++ b/src/test/kotlin/framework/test-util.kt @@ -55,7 +55,7 @@ private fun findLibrary(name: String): VirtualFile? { it.children it.refresh(false, false) true - } + }, ) } return fsRoot diff --git a/src/test/kotlin/nbt/NbtParseTest.kt b/src/test/kotlin/nbt/NbtParseTest.kt index 0ea86b928..4cec10171 100644 --- a/src/test/kotlin/nbt/NbtParseTest.kt +++ b/src/test/kotlin/nbt/NbtParseTest.kt @@ -90,22 +90,22 @@ class NbtParseTest { listOf( TagCompound( mapOf( - "key" to TagString("value") - ) + "key" to TagString("value"), + ), ), TagCompound( mapOf( - "key" to TagString("value") - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) + "key" to TagString("value"), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), ) } diff --git a/src/test/kotlin/platform/forge/ModsTomlCompletionTest.kt b/src/test/kotlin/platform/forge/ModsTomlCompletionTest.kt index 4e05ef968..02e3e57d8 100644 --- a/src/test/kotlin/platform/forge/ModsTomlCompletionTest.kt +++ b/src/test/kotlin/platform/forge/ModsTomlCompletionTest.kt @@ -42,7 +42,7 @@ class ModsTomlCompletionTest : BasePlatformTestCase() { "loaderVersion", "license", "showAsResourcePack", - "issueTrackerURL" + "issueTrackerURL", ) } @@ -61,7 +61,7 @@ class ModsTomlCompletionTest : BasePlatformTestCase() { "credits", "authors", "displayTest", - "description" + "description", ) } @@ -74,7 +74,7 @@ class ModsTomlCompletionTest : BasePlatformTestCase() { "mandatory", "versionRange", "ordering", - "side" + "side", ) } @@ -98,7 +98,7 @@ class ModsTomlCompletionTest : BasePlatformTestCase() { "MATCH_VERSION", "IGNORE_SERVER_VERSION", "IGNORE_ALL_VERSION", - "NONE" + "NONE", ) } @@ -119,7 +119,7 @@ class ModsTomlCompletionTest : BasePlatformTestCase() { fun stringCompletionFromNothing() { myFixture.testCompletion( "stringCompletionFromNothing/mods.toml", - "stringCompletionFromNothing/mods.toml.after" + "stringCompletionFromNothing/mods.toml.after", ) } @@ -128,7 +128,7 @@ class ModsTomlCompletionTest : BasePlatformTestCase() { fun stringCompletion() { myFixture.testCompletion( "stringCompletion/mods.toml", - "stringCompletion/mods.toml.after" + "stringCompletion/mods.toml.after", ) } } diff --git a/src/test/kotlin/platform/forge/ModsTomlValidationInspectionTest.kt b/src/test/kotlin/platform/forge/ModsTomlValidationInspectionTest.kt index 5dc4d3797..190c84b02 100644 --- a/src/test/kotlin/platform/forge/ModsTomlValidationInspectionTest.kt +++ b/src/test/kotlin/platform/forge/ModsTomlValidationInspectionTest.kt @@ -44,7 +44,7 @@ class ModsTomlValidationInspectionTest : BasePlatformTestCase() { """ [[mods]] modId="invalid id" - """ + """, ) } @@ -63,7 +63,7 @@ logoBlur="true" modId="forge" versionRange=35 mandatory=true - """ + """, ) } @@ -82,7 +82,7 @@ side="CLIENT" modId="minecraft" ordering="NONE" side="UP" - """ + """, ) } @@ -96,7 +96,7 @@ modId="examplemod1" [[mods]] modId="examplemod2" [[dependencies.examplemod3]] - """ + """, ) } } diff --git a/src/test/kotlin/platform/mcp/at/AtCommenterTest.kt b/src/test/kotlin/platform/mcp/at/AtCommenterTest.kt index 2810414a5..d4b02f723 100644 --- a/src/test/kotlin/platform/mcp/at/AtCommenterTest.kt +++ b/src/test/kotlin/platform/mcp/at/AtCommenterTest.kt @@ -24,7 +24,7 @@ class AtCommenterTest : CommenterTest() { private fun doTest( @Language("Access Transformers") before: String, - @Language("Access Transformers") after: String + @Language("Access Transformers") after: String, ) { doTest(before, after, "_at.cfg", ProjectBuilder::at) } @@ -39,7 +39,7 @@ class AtCommenterTest : CommenterTest() { """ #public net.minecraft.entity.Entity field_190534_ay # fire public net.minecraft.entity.Entity field_70152_a # nextEntityID - """ + """, ) @Test @@ -54,7 +54,7 @@ class AtCommenterTest : CommenterTest() { #public net.minecraft.command.CommandHandler func_71559_a([Ljava/lang/String;)[Ljava/lang/String; # dropFirstString #public net.minecraft.command.CommandHandler func_82370_a(Lnet/minecraft/command/ICommand;[Ljava/lang/String;)I # getUsernameIndex public net.minecraft.command.EntitySelector func_82381_h(Ljava/lang/String;)Ljava/util/Map; # getArgumentMap - """ + """, ) @Test @@ -71,7 +71,7 @@ class AtCommenterTest : CommenterTest() { #public net.minecraft.entity.Entity func_190531_bD()I #public net.minecraft.entity.EntityHanging func_174859_a(Lnet/minecraft/util/EnumFacing;)V # updateFacingWithBoundingBox #public net.minecraft.entity.EntityList field_180126_g # stringToIDMapping - """ + """, ) @Test @@ -86,7 +86,7 @@ class AtCommenterTest : CommenterTest() { public net.minecraft.entity.EntityLivingBase field_70752_e # potionsNeedUpdate public net.minecraft.entity.EntityLivingBase field_70755_b # entityLivingToAttack public net.minecraft.entity.EntityLivingBase func_184583_d(Lnet/minecraft/util/DamageSource;)Z # canBlockDamageSource - """ + """, ) @Test @@ -105,6 +105,6 @@ class AtCommenterTest : CommenterTest() { #public net.minecraft.entity.EntityLivingBase field_184633_f # POTION_EFFECTS ##public net.minecraft.entity.EntityLivingBase field_184634_g # HIDE_PARTICLES ##public net.minecraft.entity.EntityLivingBase field_184635_h # ARROW_COUNT_IN_ENTITY - """ + """, ) } diff --git a/src/test/kotlin/platform/mixin/AccessorMixinTest.kt b/src/test/kotlin/platform/mixin/AccessorMixinTest.kt index 3c451390f..dd602d053 100644 --- a/src/test/kotlin/platform/mixin/AccessorMixinTest.kt +++ b/src/test/kotlin/platform/mixin/AccessorMixinTest.kt @@ -55,7 +55,7 @@ class AccessorMixinTest : BaseMixinTest() { @Invoker void invoke(); @Invoker double doThing(); } - """ + """, ) { psiClass -> Assertions.assertTrue(psiClass.isAccessorMixin) } @@ -79,7 +79,7 @@ class AccessorMixinTest : BaseMixinTest() { @Invoker void invoke(); double doThing(); } - """ + """, ) { psiClass -> Assertions.assertFalse(psiClass.isAccessorMixin) } @@ -103,7 +103,7 @@ class AccessorMixinTest : BaseMixinTest() { @Invoker void invoke(); @Invoker double doThing(); } - """ + """, ) { psiClass -> Assertions.assertFalse(psiClass.isAccessorMixin) } @@ -124,7 +124,7 @@ class AccessorMixinTest : BaseMixinTest() { @Accessor String getString(); @Accessor int getInt(); } - """ + """, ) { psiClass -> Assertions.assertTrue(psiClass.isAccessorMixin) } @@ -145,7 +145,7 @@ class AccessorMixinTest : BaseMixinTest() { @Invoker void invoke(); @Invoker double doThing(); } - """ + """, ) { psiClass -> Assertions.assertTrue(psiClass.isAccessorMixin) } @@ -167,7 +167,7 @@ class AccessorMixinTest : BaseMixinTest() { @Accessor String getString(); @Invoker void invoke(); } - """ + """, ) { psiClass -> Assertions.assertFalse(psiClass.isAccessorMixin) } @@ -189,7 +189,7 @@ class AccessorMixinTest : BaseMixinTest() { @Accessor String getString(); @Invoker void invoke(); } - """ + """, ) { psiClass -> Assertions.assertFalse(psiClass.isAccessorMixin) } @@ -218,7 +218,7 @@ class AccessorMixinTest : BaseMixinTest() { @Invoker String callPrivateMethod(); @Invoker static MixinBase createMixinBase() { return null; } } - """ + """, ) { fixture.enableInspections(MixinAnnotationTargetInspection::class.java) fixture.checkHighlighting(false, false, false) @@ -243,7 +243,7 @@ class AccessorMixinTest : BaseMixinTest() { @Invoker("privateMethod") String foo3(); @Invoker("") MixinBase foo4(); } - """ + """, ) { fixture.enableInspections(MixinAnnotationTargetInspection::class.java) fixture.checkHighlighting(false, false, false) @@ -264,7 +264,7 @@ class AccessorMixinTest : BaseMixinTest() { public interface AccessorMixinTargetMixin { @Accessor String getFoo(); } - """ + """, ) { fixture.enableInspections(MixinAnnotationTargetInspection::class.java) fixture.checkHighlighting(false, false, false) @@ -285,7 +285,7 @@ class AccessorMixinTest : BaseMixinTest() { public interface AccessorMixinTargetMixin { @Accessor("foo") String bar(); } - """ + """, ) { fixture.enableInspections(MixinAnnotationTargetInspection::class.java) fixture.checkHighlighting(false, false, false) @@ -306,7 +306,7 @@ class AccessorMixinTest : BaseMixinTest() { public interface AccessorMixinTargetMixin { @Invoker String callFoo(); } - """ + """, ) { fixture.enableInspections(MixinAnnotationTargetInspection::class.java) fixture.checkHighlighting(false, false, false) @@ -327,7 +327,7 @@ class AccessorMixinTest : BaseMixinTest() { public interface AccessorMixinTargetMixin { @Invoker("foo") String bar(); } - """ + """, ) { fixture.enableInspections(MixinAnnotationTargetInspection::class.java) fixture.checkHighlighting(false, false, false) @@ -348,7 +348,7 @@ class AccessorMixinTest : BaseMixinTest() { public interface AccessorMixinTargetMixin { @Invoker("") String construct(String invalidArg); } - """ + """, ) { fixture.enableInspections(MixinAnnotationTargetInspection::class.java) fixture.checkHighlighting(false, false, false) diff --git a/src/test/kotlin/platform/mixin/AmbiguousReferenceInspectionTest.kt b/src/test/kotlin/platform/mixin/AmbiguousReferenceInspectionTest.kt index 46663b6f8..ff08567f8 100644 --- a/src/test/kotlin/platform/mixin/AmbiguousReferenceInspectionTest.kt +++ b/src/test/kotlin/platform/mixin/AmbiguousReferenceInspectionTest.kt @@ -51,7 +51,7 @@ class AmbiguousReferenceInspectionTest : BaseMixinTest() { public void onMethod() { } } - """ + """, ) } @@ -74,7 +74,7 @@ class AmbiguousReferenceInspectionTest : BaseMixinTest() { public void onMethod() { } } - """ + """, ) } @@ -97,7 +97,7 @@ class AmbiguousReferenceInspectionTest : BaseMixinTest() { public void onMethod() { } } - """ + """, ) } @@ -120,7 +120,7 @@ class AmbiguousReferenceInspectionTest : BaseMixinTest() { public void onMethod() { } } - """ + """, ) } @@ -143,7 +143,7 @@ class AmbiguousReferenceInspectionTest : BaseMixinTest() { public void onMethod() { } } - """ + """, ) } } diff --git a/src/test/kotlin/platform/mixin/BaseMixinTest.kt b/src/test/kotlin/platform/mixin/BaseMixinTest.kt index 3849d0cec..7b6169d7d 100644 --- a/src/test/kotlin/platform/mixin/BaseMixinTest.kt +++ b/src/test/kotlin/platform/mixin/BaseMixinTest.kt @@ -47,7 +47,7 @@ abstract class BaseMixinTest : BaseMinecraftTest(PlatformType.MIXIN) { for (l in listOfNotNull(mixinLibrary, testDataLibrary)) { ModuleRootModificationUtil.updateModel(module) { model -> model.removeOrderEntry( - model.findLibraryOrderEntry(l) ?: throw IllegalStateException("Library not found") + model.findLibraryOrderEntry(l) ?: throw IllegalStateException("Library not found"), ) } diff --git a/src/test/kotlin/platform/mixin/InnerClassTest.kt b/src/test/kotlin/platform/mixin/InnerClassTest.kt index bee855330..3e1762dea 100644 --- a/src/test/kotlin/platform/mixin/InnerClassTest.kt +++ b/src/test/kotlin/platform/mixin/InnerClassTest.kt @@ -67,7 +67,7 @@ class InnerClassTest : BaseMixinTest() { } } - """ + """, ) } } diff --git a/src/test/kotlin/platform/mixin/InvalidInjectorMethodSignatureFixTest.kt b/src/test/kotlin/platform/mixin/InvalidInjectorMethodSignatureFixTest.kt index 4e2317c75..29ac302da 100644 --- a/src/test/kotlin/platform/mixin/InvalidInjectorMethodSignatureFixTest.kt +++ b/src/test/kotlin/platform/mixin/InvalidInjectorMethodSignatureFixTest.kt @@ -30,6 +30,10 @@ class InvalidInjectorMethodSignatureFixTest : BaseMixinTest() { @DisplayName("Simple case") fun simpleCase() = doTest("simpleCase") + @Test + @DisplayName("Simple case with MixinExtras Sugar") + fun simpleCaseWithMixinExtrasSugar() = doTest("simpleCaseWithMixinExtrasSugar") + @Test @DisplayName("With captured locals") fun withCapturedLocals() = doTest("withCapturedLocals") diff --git a/src/test/kotlin/platform/mixin/InvalidInjectorMethodSignatureInspectionTest.kt b/src/test/kotlin/platform/mixin/InvalidInjectorMethodSignatureInspectionTest.kt index e7d82fc2a..8c5243e4c 100644 --- a/src/test/kotlin/platform/mixin/InvalidInjectorMethodSignatureInspectionTest.kt +++ b/src/test/kotlin/platform/mixin/InvalidInjectorMethodSignatureInspectionTest.kt @@ -55,7 +55,7 @@ class InvalidInjectorMethodSignatureInspectionTest : BaseMixinTest() { private void redirectMethod2() { } } - """ + """, ) } @@ -91,7 +91,7 @@ class InvalidInjectorMethodSignatureInspectionTest : BaseMixinTest() { private void injectCtor(String string, CallbackInfo ci) { } } - """ + """, ) } @@ -127,7 +127,7 @@ class InvalidInjectorMethodSignatureInspectionTest : BaseMixinTest() { private void injectCtor(String string, CallbackInfo ci) { } } - """ + """, ) } } diff --git a/src/test/kotlin/platform/mixin/MultipleTargetTest.kt b/src/test/kotlin/platform/mixin/MultipleTargetTest.kt index f11e06b8c..4f898b08f 100644 --- a/src/test/kotlin/platform/mixin/MultipleTargetTest.kt +++ b/src/test/kotlin/platform/mixin/MultipleTargetTest.kt @@ -55,7 +55,7 @@ class MultipleTargetTest : BaseMixinTest() { public void onMethod() { } } - """ + """, ) } @@ -78,7 +78,7 @@ class MultipleTargetTest : BaseMixinTest() { public void onMethod() { } } - """ + """, ) } } diff --git a/src/test/kotlin/platform/mixin/SuperClassTest.kt b/src/test/kotlin/platform/mixin/SuperClassTest.kt index 2e2e3c423..8959359bb 100644 --- a/src/test/kotlin/platform/mixin/SuperClassTest.kt +++ b/src/test/kotlin/platform/mixin/SuperClassTest.kt @@ -23,7 +23,7 @@ class SuperClassTest : BaseMixinTest() { private fun doTest( @Language("JAVA") - mixinCode: String + mixinCode: String, ) { buildProject { dir("test") { @@ -49,7 +49,7 @@ class SuperClassTest : BaseMixinTest() { public class SuperClassMixin { } - """ + """, ) } @@ -68,7 +68,7 @@ class SuperClassTest : BaseMixinTest() { public class SuperClassMixin extends Entity { } - """ + """, ) } @@ -86,7 +86,7 @@ class SuperClassTest : BaseMixinTest() { public class SuperClassMixin extends DemonWav { } - """ + """, ) } @@ -105,7 +105,7 @@ class SuperClassTest : BaseMixinTest() { public class SuperClassMixin extends Minecrell { } - """ + """, ) } } diff --git a/src/test/kotlin/platform/mixin/UnnecessaryQualifiedMemberReferenceInspectionTest.kt b/src/test/kotlin/platform/mixin/UnnecessaryQualifiedMemberReferenceInspectionTest.kt index b044f05f5..640707f2c 100644 --- a/src/test/kotlin/platform/mixin/UnnecessaryQualifiedMemberReferenceInspectionTest.kt +++ b/src/test/kotlin/platform/mixin/UnnecessaryQualifiedMemberReferenceInspectionTest.kt @@ -51,7 +51,7 @@ class UnnecessaryQualifiedMemberReferenceInspectionTest : BaseMixinTest() { public void onMethod() { } } - """ + """, ) } @@ -74,7 +74,7 @@ class UnnecessaryQualifiedMemberReferenceInspectionTest : BaseMixinTest() { public void onMethod() { } } - """ + """, ) } @@ -97,7 +97,7 @@ class UnnecessaryQualifiedMemberReferenceInspectionTest : BaseMixinTest() { public void onMethod() { } } - """ + """, ) } @@ -120,7 +120,7 @@ class UnnecessaryQualifiedMemberReferenceInspectionTest : BaseMixinTest() { public void onMethod() { } } - """ + """, ) } } diff --git a/src/test/kotlin/platform/mixin/implements/DuplicateInterfaceInspectionTest.kt b/src/test/kotlin/platform/mixin/implements/DuplicateInterfaceInspectionTest.kt index 71f90fa99..4c993a582 100644 --- a/src/test/kotlin/platform/mixin/implements/DuplicateInterfaceInspectionTest.kt +++ b/src/test/kotlin/platform/mixin/implements/DuplicateInterfaceInspectionTest.kt @@ -36,7 +36,7 @@ class DuplicateInterfaceInspectionTest : BaseMixinTest() { } """, - configure = false + configure = false, ) java( @@ -48,7 +48,7 @@ class DuplicateInterfaceInspectionTest : BaseMixinTest() { } """, - configure = false + configure = false, ) } } @@ -84,7 +84,7 @@ class DuplicateInterfaceInspectionTest : BaseMixinTest() { class DuplicateInterfaceMixin { } - """ + """, ) } @@ -107,7 +107,7 @@ class DuplicateInterfaceInspectionTest : BaseMixinTest() { class DuplicateInterfaceMixin { } - """ + """, ) } } diff --git a/src/test/kotlin/platform/mixin/implements/DuplicateInterfacePrefixInspectionTest.kt b/src/test/kotlin/platform/mixin/implements/DuplicateInterfacePrefixInspectionTest.kt index 5521e45fa..a4cc18865 100644 --- a/src/test/kotlin/platform/mixin/implements/DuplicateInterfacePrefixInspectionTest.kt +++ b/src/test/kotlin/platform/mixin/implements/DuplicateInterfacePrefixInspectionTest.kt @@ -36,7 +36,7 @@ class DuplicateInterfacePrefixInspectionTest : BaseMixinTest() { } """, - configure = false + configure = false, ) java( @@ -48,7 +48,7 @@ class DuplicateInterfacePrefixInspectionTest : BaseMixinTest() { } """, - configure = false + configure = false, ) } } @@ -84,7 +84,7 @@ class DuplicateInterfacePrefixInspectionTest : BaseMixinTest() { class DuplicateInterfacePrefixMixin { } - """ + """, ) } @@ -107,7 +107,7 @@ class DuplicateInterfacePrefixInspectionTest : BaseMixinTest() { class DuplicateInterfacePrefixMixin { } - """ + """, ) } } diff --git a/src/test/kotlin/platform/mixin/implements/EmptyImplementsTest.kt b/src/test/kotlin/platform/mixin/implements/EmptyImplementsTest.kt index 01228e306..845316b88 100644 --- a/src/test/kotlin/platform/mixin/implements/EmptyImplementsTest.kt +++ b/src/test/kotlin/platform/mixin/implements/EmptyImplementsTest.kt @@ -36,7 +36,7 @@ class EmptyImplementsTest : BaseMixinTest() { } """, - configure = false + configure = false, ) } } @@ -69,7 +69,7 @@ class EmptyImplementsTest : BaseMixinTest() { class EmptyImplementsMixin { } - """ + """, ) } @@ -89,7 +89,7 @@ class EmptyImplementsTest : BaseMixinTest() { class EmptyImplementsMixin { } - """ + """, ) } @@ -112,7 +112,7 @@ class EmptyImplementsTest : BaseMixinTest() { class EmptyImplementsMixin { } - """ + """, ) } } diff --git a/src/test/kotlin/platform/mixin/implements/InterfaceIsInterfaceTest.kt b/src/test/kotlin/platform/mixin/implements/InterfaceIsInterfaceTest.kt index f8396ce5b..299c584ad 100644 --- a/src/test/kotlin/platform/mixin/implements/InterfaceIsInterfaceTest.kt +++ b/src/test/kotlin/platform/mixin/implements/InterfaceIsInterfaceTest.kt @@ -35,7 +35,7 @@ class InterfaceIsInterfaceTest : BaseMixinTest() { } """, - configure = false + configure = false, ) java( @@ -47,7 +47,7 @@ class InterfaceIsInterfaceTest : BaseMixinTest() { } """, - configure = false + configure = false, ) java( @@ -67,7 +67,7 @@ class InterfaceIsInterfaceTest : BaseMixinTest() { class InterfaceIsInterfaceMixin { } - """ + """, ) } } diff --git a/src/test/kotlin/platform/mixin/implements/InterfacePrefixTest.kt b/src/test/kotlin/platform/mixin/implements/InterfacePrefixTest.kt index 192c2732a..fd63346ae 100644 --- a/src/test/kotlin/platform/mixin/implements/InterfacePrefixTest.kt +++ b/src/test/kotlin/platform/mixin/implements/InterfacePrefixTest.kt @@ -35,7 +35,7 @@ class InterfacePrefixTest : BaseMixinTest() { } """, - configure = false + configure = false, ) java( @@ -55,7 +55,7 @@ class InterfacePrefixTest : BaseMixinTest() { class InterfacePrefixMixin { } - """ + """, ) } } diff --git a/src/test/kotlin/platform/mixin/implements/SoftImplementTest.kt b/src/test/kotlin/platform/mixin/implements/SoftImplementTest.kt index a4fdbee9c..a83ac2a0f 100644 --- a/src/test/kotlin/platform/mixin/implements/SoftImplementTest.kt +++ b/src/test/kotlin/platform/mixin/implements/SoftImplementTest.kt @@ -37,7 +37,7 @@ class SoftImplementTest : BaseMixinTest() { } """, - configure = false + configure = false, ) java( @@ -62,7 +62,7 @@ class SoftImplementTest : BaseMixinTest() { } } - """ + """, ) } } diff --git a/src/test/kotlin/platform/mixin/shadow/ShadowModifiersInspectionTest.kt b/src/test/kotlin/platform/mixin/shadow/ShadowModifiersInspectionTest.kt index b240ad79c..26d4aa630 100644 --- a/src/test/kotlin/platform/mixin/shadow/ShadowModifiersInspectionTest.kt +++ b/src/test/kotlin/platform/mixin/shadow/ShadowModifiersInspectionTest.kt @@ -56,7 +56,7 @@ class ShadowModifiersInspectionTest : BaseMixinTest() { @Shadow protected String twoIssues; } - """ + """, ) } diff --git a/src/test/kotlin/platform/mixin/shadow/ShadowTargetInspectionTest.kt b/src/test/kotlin/platform/mixin/shadow/ShadowTargetInspectionTest.kt index c5eebc33c..6a7899780 100644 --- a/src/test/kotlin/platform/mixin/shadow/ShadowTargetInspectionTest.kt +++ b/src/test/kotlin/platform/mixin/shadow/ShadowTargetInspectionTest.kt @@ -56,7 +56,7 @@ class ShadowTargetInspectionTest : BaseMixinTest() { @Shadow protected String twoIssues; } - """ + """, ) } diff --git a/src/test/kotlin/platform/sponge/BaseSpongeTest.kt b/src/test/kotlin/platform/sponge/BaseSpongeTest.kt index cdf2472de..44c2f80e1 100644 --- a/src/test/kotlin/platform/sponge/BaseSpongeTest.kt +++ b/src/test/kotlin/platform/sponge/BaseSpongeTest.kt @@ -45,7 +45,7 @@ abstract class BaseSpongeTest : BaseMinecraftTest(PlatformType.SPONGE) { library?.let { l -> ModuleRootModificationUtil.updateModel(module) { model -> model.removeOrderEntry( - model.findLibraryOrderEntry(l) ?: throw IllegalStateException("Library not found") + model.findLibraryOrderEntry(l) ?: throw IllegalStateException("Library not found"), ) } diff --git a/src/test/kotlin/platform/sponge/PluginClassInspectionTest.kt b/src/test/kotlin/platform/sponge/PluginClassInspectionTest.kt index 6920d649f..01b856915 100644 --- a/src/test/kotlin/platform/sponge/PluginClassInspectionTest.kt +++ b/src/test/kotlin/platform/sponge/PluginClassInspectionTest.kt @@ -46,7 +46,7 @@ class PluginClassInspectionTest : BaseSpongeTest() { ASpongePlugin() { } } - """ + """, ) } @@ -62,7 +62,7 @@ class PluginClassInspectionTest : BaseSpongeTest() { @Plugin(id = "a-plugin") public class ASpongePlugin { } - """ + """, ) } @@ -80,7 +80,7 @@ class PluginClassInspectionTest : BaseSpongeTest() { private ASpongePlugin() { } } - """ + """, ) } @@ -104,7 +104,7 @@ class PluginClassInspectionTest : BaseSpongeTest() { private ASpongePlugin(Logger logger) { } } - """ + """, ) } @@ -125,7 +125,7 @@ class PluginClassInspectionTest : BaseSpongeTest() { private ASpongePlugin(Logger logger) { } } - """ + """, ) } } diff --git a/src/test/kotlin/platform/sponge/SpongeInjectionInspectionTest.kt b/src/test/kotlin/platform/sponge/SpongeInjectionInspectionTest.kt index b475ab8ee..0e3966194 100644 --- a/src/test/kotlin/platform/sponge/SpongeInjectionInspectionTest.kt +++ b/src/test/kotlin/platform/sponge/SpongeInjectionInspectionTest.kt @@ -48,7 +48,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { @Inject private int number; } - """ + """, ) } @@ -67,7 +67,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { @Inject private String string; } - """ + """, ) } @@ -90,7 +90,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { this.string = string; } } - """ + """, ) } @@ -114,7 +114,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { this.logger = logger; } } - """ + """, ) } @@ -137,7 +137,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { this.string = string; } } - """ + """, ) } @@ -157,7 +157,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { @Inject private Asset asset; } - """ + """, ) } @@ -179,7 +179,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { @AssetId("absent_asset") private Asset asset; } - """ + """, ) } @@ -202,7 +202,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { private Asset asset; } """, - "assets/a-plugin/dir/an_asset.txt" + "assets/a-plugin/dir/an_asset.txt", ) } @@ -227,7 +227,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { @DefaultConfig(sharedRoot = false) private File file; } - """ + """, ) } @@ -248,7 +248,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { @Inject private File file; } - """ + """, ) } @@ -270,7 +270,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { @DefaultConfig(sharedRoot = false) private Logger logger; } - """ + """, ) } @@ -295,7 +295,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { @ConfigDir(sharedRoot = false) private ConfigurationLoader configurationLoader; } - """ + """, ) } @@ -317,7 +317,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { @Inject private ConfigurationLoader configurationLoader; } - """ + """, ) } @@ -340,7 +340,7 @@ class SpongeInjectionInspectionTest : BaseSpongeTest() { @DefaultConfig(sharedRoot = false) private ConfigurationLoader<ConfigurationNode> configurationLoader; } - """ + """, ) } } diff --git a/src/test/kotlin/translations/LangCommenterTest.kt b/src/test/kotlin/translations/LangCommenterTest.kt index 0911e3066..4878a536b 100644 --- a/src/test/kotlin/translations/LangCommenterTest.kt +++ b/src/test/kotlin/translations/LangCommenterTest.kt @@ -35,7 +35,7 @@ class LangCommenterTest : CommenterTest() { """ #test.key1=value1 test.key2=value2 - """ + """, ) @Test @@ -52,7 +52,7 @@ class LangCommenterTest : CommenterTest() { #test.key2=value2 #test.key3=value3 test.key4=value4 - """ + """, ) @Test @@ -69,7 +69,7 @@ class LangCommenterTest : CommenterTest() { test.key2=value2 test.key3=value3 #test.key4=value4 - """ + """, ) @Test @@ -86,6 +86,6 @@ class LangCommenterTest : CommenterTest() { test.key2=value2 #test.key3=value3 test.key4=value4 - """ + """, ) } diff --git a/src/test/kotlin/util/McPsiClassTest.kt b/src/test/kotlin/util/McPsiClassTest.kt index 3e5e41326..50824be91 100644 --- a/src/test/kotlin/util/McPsiClassTest.kt +++ b/src/test/kotlin/util/McPsiClassTest.kt @@ -64,7 +64,7 @@ class McPsiClassTest : OuterClassTest() { fun innerAnonymousInnerFullQualifiedNameTest() = Assertions.assertEquals( "com.example.test.OuterClass\$InnerClass$1\$AnonymousInnerClass", - innerAnonymousInnerClass.fullQualifiedName + innerAnonymousInnerClass.fullQualifiedName, ) @Test @@ -97,8 +97,8 @@ class McPsiClassTest : OuterClassTest() { assertEquivalent( innerAnonymousClass, findQualifiedClass( - "com.example.test.OuterClass\$InnerClass$1" - ) + "com.example.test.OuterClass\$InnerClass$1", + ), ) @Test @@ -106,7 +106,7 @@ class McPsiClassTest : OuterClassTest() { fun innerAnonymousInnerFindTest() = assertEquivalent( innerAnonymousInnerClass, - findQualifiedClass("com.example.test.OuterClass\$InnerClass$1\$AnonymousInnerClass") + findQualifiedClass("com.example.test.OuterClass\$InnerClass$1\$AnonymousInnerClass"), ) @Test @@ -114,7 +114,7 @@ class McPsiClassTest : OuterClassTest() { fun selfReferencingGenericFullQualifiedNameTest() = Assertions.assertEquals( "com.example.test.OuterClass\$SelfReferencingGeneric", - selfReferencingGeneric.fullQualifiedName + selfReferencingGeneric.fullQualifiedName, ) @Test diff --git a/src/test/kotlin/util/OuterClassTest.kt b/src/test/kotlin/util/OuterClassTest.kt index b774e962f..583f41304 100644 --- a/src/test/kotlin/util/OuterClassTest.kt +++ b/src/test/kotlin/util/OuterClassTest.kt @@ -54,7 +54,7 @@ abstract class OuterClassTest : ProjectBuilderTest() { public C doSomething() {} } } - """ + """, ).toPsiFile().classes.single() } diff --git a/src/test/kotlin/util/PsiBytecodeUtilTest.kt b/src/test/kotlin/util/PsiBytecodeUtilTest.kt index b5002915f..3d565db3e 100644 --- a/src/test/kotlin/util/PsiBytecodeUtilTest.kt +++ b/src/test/kotlin/util/PsiBytecodeUtilTest.kt @@ -44,6 +44,6 @@ class PsiBytecodeUtilTest : OuterClassTest() { fun innerAnonymousInnerInternalNameTest() = Assertions.assertEquals( "com/example/test/OuterClass\$InnerClass$1\$AnonymousInnerClass", - innerAnonymousInnerClass.internalName + innerAnonymousInnerClass.internalName, ) } diff --git a/src/test/resources/com/demonwav/mcdev/platform/mixin/invalidInjectorMethodSignature/simpleCaseWithMixinExtrasSugar.after.java b/src/test/resources/com/demonwav/mcdev/platform/mixin/invalidInjectorMethodSignature/simpleCaseWithMixinExtrasSugar.after.java new file mode 100644 index 000000000..50ac28b2d --- /dev/null +++ b/src/test/resources/com/demonwav/mcdev/platform/mixin/invalidInjectorMethodSignature/simpleCaseWithMixinExtrasSugar.after.java @@ -0,0 +1,16 @@ +package test; + +import com.demonwav.mcdev.mixintestdata.invalidInjectorMethodSignatureFix.MixedInSimple; +import com.llamalad7.mixinextras.sugar.Local; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MixedInSimple.class) +public class TestMixin { + + @Inject(method = "simpleMethod", at = @At("RETURN")) + private void injectCtor(String string, int i, CallbackInfo ci, @Local String str) { + } +} diff --git a/src/test/resources/com/demonwav/mcdev/platform/mixin/invalidInjectorMethodSignature/simpleCaseWithMixinExtrasSugar.java b/src/test/resources/com/demonwav/mcdev/platform/mixin/invalidInjectorMethodSignature/simpleCaseWithMixinExtrasSugar.java new file mode 100644 index 000000000..95c251a21 --- /dev/null +++ b/src/test/resources/com/demonwav/mcdev/platform/mixin/invalidInjectorMethodSignature/simpleCaseWithMixinExtrasSugar.java @@ -0,0 +1,16 @@ +package test; + +import com.demonwav.mcdev.mixintestdata.invalidInjectorMethodSignatureFix.MixedInSimple; +import com.llamalad7.mixinextras.sugar.Local; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MixedInSimple.class) +public class TestMixin { + + @Inject(method = "simpleMethod", at = @At("RETURN")) + private void injectCtor(String string, CallbackInfo ci, @Local String str) { + } +}