diff --git a/build.gradle.kts b/build.gradle.kts index 548b98b0c..993e58799 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,8 +18,7 @@ * along with this program. If not, see . */ -import io.sentry.android.gradle.extensions.SentryPluginExtension -import org.gradle.kotlin.dsl.configure +import org.gradle.internal.jvm.Jvm import org.jetbrains.changelog.Changelog import org.jetbrains.gradle.ext.settings import org.jetbrains.gradle.ext.taskTriggers @@ -33,7 +32,6 @@ plugins { `mcdev-core` `mcdev-parsing` `mcdev-publishing` - alias(libs.plugins.sentry) apply (System.getenv("CI") == "true" && System.getenv("NO_SENTRY") != "true") } val coreVersion: String by project @@ -45,32 +43,32 @@ val testLibs: Configuration by configurations.creating { group = "com.demonwav.mcdev" -val gradleToolingExtensionSourceSet: SourceSet = sourceSets.create("gradle-tooling-extension", Action { +val gradleToolingExtensionSourceSet: SourceSet = sourceSets.create("gradle-tooling-extension") { configurations.named(compileOnlyConfigurationName) { extendsFrom(gradleToolingExtension) } -}) +} val gradleToolingExtensionJar = tasks.register(gradleToolingExtensionSourceSet.jarTaskName) { from(gradleToolingExtensionSourceSet.output) archiveClassifier.set("gradle-tooling-extension") exclude("META-INF/plugin.xml") } -val templatesSourceSet: SourceSet = sourceSets.create("templates", Action { +val templatesSourceSet: SourceSet = sourceSets.create("templates") { resources { srcDir("templates") compileClasspath += sourceSets.main.get().output } -}) +} val templateSourceSets: List = (file("templates").listFiles() ?: emptyArray()).mapNotNull { file -> if (file.isDirectory() && (file.listFiles() ?: emptyArray()).any { it.name.endsWith(".mcdev.template.json") }) { - sourceSets.create("templates-${file.name}", Action { + sourceSets.create("templates-${file.name}") { resources { srcDir(file) compileClasspath += sourceSets.main.get().output } - }) + } } else { null } @@ -83,20 +81,22 @@ val externalAnnotationsJar = tasks.register("externalAnnotationsJar") { } dependencies { + // Add tools.jar for the JDI API + implementation(files(Jvm.current().toolsJar)) + implementation(files(gradleToolingExtensionJar)) implementation(libs.mixinExtras.expressions) { exclude(group = "org.ow2.asm", module = "asm-debug-all") } testLibs(libs.mixinExtras.common) - implementation(libs.jgraphx) implementation(libs.mappingIo) implementation(libs.bundles.asm) - implementation(libs.bundles.fuel) - implementation(libs.sentry) { - exclude(group = "org.slf4j") + implementation(libs.bundles.fuel) { + exclude(group = "org.jetbrains.kotlin") + exclude(group = "org.jetbrains.kotlinx") } intellijPlatform { @@ -120,11 +120,13 @@ dependencies { testFramework(TestFrameworkType.JUnit5) + testFramework(TestFrameworkType.Platform) testFramework(TestFrameworkType.Plugin.Java) pluginVerifier() } + testLibs(libs.test.mockJdk) testLibs(libs.test.mixin) testLibs(libs.test.spigotapi) testLibs(libs.test.bungeecord) @@ -142,7 +144,7 @@ dependencies { testLibs(projects.mixinTestData) // For non-SNAPSHOT versions (unless Jetbrains fixes this...) find the version with: - // afterEvaluate { println(intellij.ideaDependency.get().buildNumber.substring(intellij.type.get().length + 1)) } + // afterEvaluate { println(intellijPlatform.productInfo.buildNumber) } gradleToolingExtension(libs.groovy) gradleToolingExtension(libs.gradleToolingExtension) gradleToolingExtension(libs.annotations) @@ -169,20 +171,28 @@ tasks.patchPluginXml { changeNotes = changelog.render(Changelog.OutputType.HTML) } -// Compile classes to be loaded into the Gradle VM to Java 8 +// Compile classes to be loaded into the Gradle VM to Java 5 to match Groovy // This is for maximum compatibility, these classes will be loaded into every Gradle import on all // projects (not just Minecraft), so we don't want to break that with an incompatible class version. tasks.named(gradleToolingExtensionSourceSet.compileJavaTaskName, JavaCompile::class) { - options.release = 8 + val java7Compiler = javaToolchains.compilerFor { languageVersion.set(JavaLanguageVersion.of(11)) } + javaCompiler.set(java7Compiler) + options.release.set(6) + options.bootstrapClasspath = files(java7Compiler.map { it.metadata.installationPath.file("jre/lib/rt.jar") }) options.compilerArgs = listOf("-Xlint:-options") } tasks.withType().configureEach { options.compilerArgs = listOf("-proc:none") - sourceCompatibility = "1.8" - targetCompatibility = "1.8" + sourceCompatibility = "1.5" + targetCompatibility = "1.5" } tasks.processResources { + for (lang in arrayOf("", "_en")) { + from("src/main/resources/messages.MinecraftDevelopment_en_US.properties") { + rename { "messages.MinecraftDevelopment$lang.properties" } + } + } // These templates aren't allowed to be in a directory structure in the output jar // But we have a lot of templates that would get real hard to deal with if we didn't have some structure // So this just flattens out the fileTemplates/j2ee directory in the jar, while still letting us have directories @@ -216,7 +226,6 @@ idea { license { val endings = listOf("java", "kt", "kts", "groovy", "gradle.kts", "xml", "properties", "html", "flex", "bnf") exclude("META-INF/plugin.xml") // https://youtrack.jetbrains.com/issue/IDEA-345026 - exclude("sentry-debug-meta.properties", "sentry-external-modules.txt") include(endings.map { "**/*.$it" }) val projectDir = layout.projectDirectory.asFile @@ -263,8 +272,8 @@ license { val generateAtLexer by lexer("AtLexer", "com/demonwav/mcdev/platform/mcp/at/gen") val generateAtParser by parser("AtParser", "com/demonwav/mcdev/platform/mcp/at/gen") -val generateCtLexer by lexer("CtLexer", "com/demonwav/mcdev/platform/mcp/ct/gen") -val generateCtParser by parser("CtParser", "com/demonwav/mcdev/platform/mcp/ct/gen") +val generateAwLexer by lexer("AwLexer", "com/demonwav/mcdev/platform/mcp/aw/gen") +val generateAwParser by parser("AwParser", "com/demonwav/mcdev/platform/mcp/aw/gen") val generateNbttLexer by lexer("NbttLexer", "com/demonwav/mcdev/nbt/lang/gen") val generateNbttParser by parser("NbttParser", "com/demonwav/mcdev/nbt/lang/gen") @@ -287,8 +296,8 @@ val generate by tasks.registering { dependsOn( generateAtLexer, generateAtParser, - generateCtLexer, - generateCtParser, + generateAwLexer, + generateAwParser, generateNbttLexer, generateNbttParser, generateLangLexer, @@ -333,29 +342,3 @@ tasks.runIde { // systemProperty("user.language", "fr") // systemProperty("user.country", "FR") } - -if (System.getenv("CI") == "true" && System.getenv("NO_SENTRY") != "true") { - configure { - includeSourceContext = true - includeDependenciesReport = true - autoInstallation { - enabled = false - } - - url = "https://sentry.mcdev.io/" - org = "mcdev" - projectName = "mcdev" - authToken = providers.gradleProperty("mcdev.sentry.token") - } - - // Wire together some tasks to make Gradle happy - tasks.named("generateSentryBundleIdJava") { - dependsOn(generate) - } - tasks.named("sentryCollectSourcesJava") { - dependsOn(generate) - } - tasks.checkLicenseMain { - dependsOn(tasks.named("generateSentryDebugMetaPropertiesjava"), tasks.named("collectExternalDependenciesForSentry")) - } -} diff --git a/buildSrc/src/main/kotlin/mcdev-core.gradle.kts b/buildSrc/src/main/kotlin/mcdev-core.gradle.kts index 07883d518..bac0c7dca 100644 --- a/buildSrc/src/main/kotlin/mcdev-core.gradle.kts +++ b/buildSrc/src/main/kotlin/mcdev-core.gradle.kts @@ -105,10 +105,12 @@ repositories { val libs = the() dependencies { - implementation(libs.kotlin.stdlib) - implementation(libs.kotlin.reflect) + compileOnly(libs.kotlin.stdlib) + compileOnly(libs.kotlin.reflect) + compileOnly(libs.annotations) implementation(libs.bundles.coroutines) { exclude(module = "kotlinx-coroutines-core-jvm") + exclude(group = "org.jetbrains.kotlin") } testImplementation(libs.junit.api) diff --git a/gradle.properties b/gradle.properties index 24657aceb..e57b7157f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -23,7 +23,7 @@ org.gradle.jvmargs=-Xmx1g ideaVersionName = 2024.3 -coreVersion = 1.8.7 +coreVersion = 1.8.8 # Silences a build-time warning because we are bundling our own kotlin library kotlin.stdlib.default.dependency = false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 533afab9c..a525ec5b7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,25 +1,24 @@ [versions] -kotlin = "2.2.20" -coroutines = "1.9.0-RC.2" +kotlin = "2.1.21" +coroutines = "1.10.2" junit = "5.10.2" junit-platform = "1.10.2" asm = "9.6" fuel = "2.3.1" -licenser = "0.7.5" +licenser = "0.6.1" changelog = "2.2.0" -intellij-plugin = "2.5.0" +intellij-plugin = "2.6.0" intellij-plugin-repository-rest-client = "2.0.46" -intellij-ide = "2024.3.5" +intellij-ide = "2025.2" idea-ext = "1.1.10" -psiPlugin = "243.7768" +psiPlugin = "251.175" [plugins] kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } intellij-platform = { id = "org.jetbrains.intellij.platform", version.ref = "intellij-plugin" } idea-ext = { id = "org.jetbrains.gradle.plugin.idea-ext", version.ref = "idea-ext" } -licenser = { id = "net.neoforged.licenser", version.ref = "licenser" } +licenser = { id = "org.cadixdev.licenser", version.ref = "licenser" } changelog = { id = "org.jetbrains.changelog", version.ref = "changelog" } -sentry = "io.sentry.jvm.gradle:5.12.2" [libraries] intellij-plugin-repository-rest-client = { module = "org.jetbrains.intellij:plugin-repository-rest-client", version.ref = "intellij-plugin-repository-rest-client" } @@ -29,14 +28,13 @@ kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.re kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } intellij-plugin = { module = "org.jetbrains.intellij.platform:org.jetbrains.intellij.platform.gradle.plugin", version.ref = "intellij-plugin" } -licenser-plugin = { module = "net.neoforged.licenser:net.neoforged.licenser.gradle.plugin", version.ref = "licenser" } +licenser-plugin = { module = "org.cadixdev.licenser:org.cadixdev.licenser.gradle.plugin", version.ref = "licenser" } changelog-plugin = { module = "org.jetbrains.changelog:org.jetbrains.changelog.gradle.plugin", version.ref = "changelog" } coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "coroutines" } mappingIo = "net.fabricmc:mapping-io:0.2.1" -mixinExtras-expressions = "io.github.llamalad7:mixinextras-expressions:0.0.6" -jgraphx = "com.github.vlsi.mxgraph:jgraphx:4.2.2" +mixinExtras-expressions = "io.github.llamalad7:mixinextras-expressions:0.0.4" # GrammarKit jflex-lib = "org.jetbrains.idea:jflex:1.7.0-b7f882a" @@ -44,7 +42,7 @@ jflex-skeleton = "org.jetbrains.idea:jflex:1.7.0-c1fdf11" grammarKit = "org.jetbrains.idea:grammar-kit:1.5.1" # Gradle Tooling -gradleToolingExtension = "com.jetbrains.intellij.gradle:gradle-tooling-extension:243-EAP-SNAPSHOT" +gradleToolingExtension = { module = "com.jetbrains.intellij.gradle:gradle-tooling-extension", version = "252.23892.409" } annotations = "org.jetbrains:annotations:24.0.0" groovy = "org.codehaus.groovy:groovy:3.0.19" @@ -58,12 +56,11 @@ gson = "com.google.code.gson:gson:2.10.1" fuel = { module = "com.github.kittinunf.fuel:fuel", version.ref = "fuel" } fuel-coroutines = { module = "com.github.kittinunf.fuel:fuel-coroutines", version.ref = "fuel" } -sentry = "io.sentry:sentry:8.22.0" - # Testing +test-mockJdk = "org.jetbrains.idea:mock-jdk:1.7-4d76c50" test-mixin = "org.spongepowered:mixin:0.8.5" test-spigotapi = "org.spigotmc:spigot-api:1.21-R0.1-SNAPSHOT" -test-bungeecord = "net.md-5:bungeecord-api:1.21-R0.3" +test-bungeecord = "net.md-5:bungeecord-api:1.21-R0.3-SNAPSHOT" test-spongeapi = "org.spongepowered:spongeapi:7.4.0" test-fabricloader = "net.fabricmc:fabric-loader:0.15.11" test-nbt = "com.demonwav.mcdev:all-types-nbt:1.0" diff --git a/src/main/kotlin/creator/buildsystem/gradle-steps.kt b/src/main/kotlin/creator/buildsystem/gradle-steps.kt index f3302f6ef..48bc08e2e 100644 --- a/src/main/kotlin/creator/buildsystem/gradle-steps.kt +++ b/src/main/kotlin/creator/buildsystem/gradle-steps.kt @@ -56,10 +56,11 @@ import com.intellij.psi.PsiFile import com.intellij.psi.PsiManager import java.nio.file.Path import java.util.concurrent.CountDownLatch +import kotlinx.coroutines.runBlocking 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.gradle.service.project.open.linkAndSyncGradleProject val DEFAULT_GRADLE_VERSION = SemanticVersion.release(8, 7) val GRADLE_VERSION_KEY = Key.create("mcdev.gradleVersion") @@ -216,7 +217,9 @@ open class GradleImportStep(parent: NewProjectWizardStep) : AbstractLongRunningS invokeLater(project.disposed) { val path = rootDirectory.toAbsolutePath().toString() if (canLinkAndRefreshGradleProject(path, project, false)) { - linkAndRefreshGradleProject(path, project) + runBlocking { + linkAndSyncGradleProject(project, path) + } showProgress(project) } diff --git a/src/main/kotlin/creator/custom/providers/ZipTemplateProvider.kt b/src/main/kotlin/creator/custom/providers/ZipTemplateProvider.kt index 90d9f315c..7834ffb6e 100644 --- a/src/main/kotlin/creator/custom/providers/ZipTemplateProvider.kt +++ b/src/main/kotlin/creator/custom/providers/ZipTemplateProvider.kt @@ -67,7 +67,7 @@ class ZipTemplateProvider : TemplateProvider { return panel { row(MCDevBundle("creator.ui.custom.path.label")) { - val pathChooserDescriptor = FileChooserDescriptorFactory.createSingleLocalFileDescriptor() + val pathChooserDescriptor = FileChooserDescriptorFactory.singleFile() .withTitle(MCDevBundle("creator.ui.custom.archive.dialog.title")) .withFileFilter { it.extension == "zip" } .apply { description = MCDevBundle("creator.ui.custom.archive.dialog.description") } diff --git a/src/main/kotlin/creator/step/FixedAssetsNewProjectWizardStep.kt b/src/main/kotlin/creator/step/FixedAssetsNewProjectWizardStep.kt index c249c1df4..89bc3dc76 100644 --- a/src/main/kotlin/creator/step/FixedAssetsNewProjectWizardStep.kt +++ b/src/main/kotlin/creator/step/FixedAssetsNewProjectWizardStep.kt @@ -25,6 +25,7 @@ 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.GeneratorFile import com.intellij.ide.starters.local.GeneratorResourceFile import com.intellij.ide.starters.local.GeneratorTemplateFile import com.intellij.ide.wizard.AbstractNewProjectWizardStep @@ -50,20 +51,14 @@ import java.nio.file.Path */ abstract class FixedAssetsNewProjectWizardStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { lateinit var outputDirectory: String - private val assets = arrayListOf() + private val assets = arrayListOf() val templateProperties = hashMapOf() private val filesToOpen = hashSetOf() - fun addAssets(vararg assets: Any) = addAssets(assets.toList()) + fun addAssets(vararg assets: GeneratorAsset) = 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 addAssets(assets: Iterable) { + this.assets += assets } fun addTemplateProperties(vararg properties: Pair) = addTemplateProperties(properties.toMap()) @@ -107,13 +102,11 @@ abstract class FixedAssetsNewProjectWizardStep(parent: NewProjectWizardStep) : A } } - private fun generateFile(asset: FixedGeneratorAsset): VirtualFile? { + private fun generateFile(asset: GeneratorAsset): VirtualFile? { return when (asset) { - is GeneratorAssetDelegate -> when (val delegate = asset.delegate) { - is GeneratorTemplateFile -> generateFile(delegate) - is GeneratorResourceFile -> generateFile(delegate) - is GeneratorEmptyDirectory -> generateFile(delegate) - } + is GeneratorTemplateFile -> generateFile(asset) + is GeneratorResourceFile -> generateFile(asset) + is GeneratorEmptyDirectory -> generateFile(asset) is GeneratorFile -> generateFile(asset) } } @@ -152,7 +145,7 @@ abstract class FixedAssetsNewProjectWizardStep(parent: NewProjectWizardStep) : A } private fun generateFile(asset: GeneratorFile): VirtualFile? { - val pathStr = "$outputDirectory/${asset.targetFileName}" + val pathStr = "$outputDirectory/${asset.relativePath}" val path = Path.of(pathStr) path.parent?.let(NioFiles::createDirectories) Files.write(path, asset.content) @@ -177,18 +170,3 @@ abstract class FixedAssetsNewProjectWizardStep(parent: NewProjectWizardStep) : A } } -// 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.relativePath -} - -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/insight/generation/MinecraftClassCreateAction.kt b/src/main/kotlin/insight/generation/MinecraftClassCreateAction.kt index 70f659390..ace5810a7 100644 --- a/src/main/kotlin/insight/generation/MinecraftClassCreateAction.kt +++ b/src/main/kotlin/insight/generation/MinecraftClassCreateAction.kt @@ -33,7 +33,6 @@ import com.demonwav.mcdev.util.MinecraftVersions import com.demonwav.mcdev.util.SemanticVersion import com.demonwav.mcdev.util.findModule import com.intellij.codeInsight.daemon.JavaErrorBundle -import com.intellij.codeInsight.daemon.impl.analysis.HighlightClassUtil import com.intellij.ide.actions.CreateFileFromTemplateDialog import com.intellij.ide.actions.CreateTemplateInPackageAction import com.intellij.openapi.actionSystem.CommonDataKeys @@ -47,6 +46,7 @@ import com.intellij.psi.PsiClass import com.intellij.psi.PsiDirectory import com.intellij.psi.PsiElement import com.intellij.psi.PsiNameHelper +import com.intellij.psi.util.PsiTypesUtil import com.intellij.psi.util.PsiUtil import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes @@ -151,7 +151,7 @@ class MinecraftClassCreateAction : val shortName = StringUtil.getShortName(inputString) val languageLevel = PsiUtil.getLanguageLevel(directory) - return if (HighlightClassUtil.isRestrictedIdentifier(shortName, languageLevel)) { + return if (PsiTypesUtil.isRestrictedIdentifier(shortName, languageLevel)) { JavaErrorBundle.message("restricted.identifier", shortName) } else { null diff --git a/src/main/kotlin/inspection/IsCancelled.kt b/src/main/kotlin/inspection/IsCancelled.kt index 8994b646c..18dc6c570 100644 --- a/src/main/kotlin/inspection/IsCancelled.kt +++ b/src/main/kotlin/inspection/IsCancelled.kt @@ -21,21 +21,17 @@ package com.demonwav.mcdev.inspection import com.demonwav.mcdev.asset.MCDevBundle +import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemDescriptor import com.intellij.openapi.project.Project -import com.siyeh.ig.InspectionGadgetsFix class IsCancelled( fix: (ProblemDescriptor) -> Unit, val errorString: String, ) { - val buildFix: InspectionGadgetsFix - - init { - this.buildFix = object : InspectionGadgetsFix() { - override fun doFix(project: Project, descriptor: ProblemDescriptor) = fix(descriptor) - override fun getName() = "Simplify" - override fun getFamilyName() = MCDevBundle("inspection.is_cancelled.name") - } + val buildFix: LocalQuickFix = object : LocalQuickFix { + override fun applyFix(project: Project, descriptor: ProblemDescriptor) = fix(descriptor) + override fun getName() = "Simplify" + override fun getFamilyName() = MCDevBundle("inspection.is_cancelled.name") } } diff --git a/src/main/kotlin/inspection/IsCancelledInspection.kt b/src/main/kotlin/inspection/IsCancelledInspection.kt index 1492b025d..7be47214c 100644 --- a/src/main/kotlin/inspection/IsCancelledInspection.kt +++ b/src/main/kotlin/inspection/IsCancelledInspection.kt @@ -23,11 +23,11 @@ package com.demonwav.mcdev.inspection import com.demonwav.mcdev.asset.MCDevBundle import com.demonwav.mcdev.facet.MinecraftFacet import com.demonwav.mcdev.util.mapFirstNotNull +import com.intellij.codeInspection.LocalQuickFix import com.intellij.openapi.module.ModuleUtilCore import com.intellij.psi.PsiMethodCallExpression import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor -import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls class IsCancelledInspection : BaseInspection() { @@ -41,7 +41,7 @@ class IsCancelledInspection : BaseInspection() { return useless.errorString } - override fun buildFix(vararg infos: Any): InspectionGadgetsFix? { + override fun buildFix(vararg infos: Any): LocalQuickFix? { val useless = infos[0] as? IsCancelled return useless?.buildFix } diff --git a/src/main/kotlin/platform/bukkit/inspection/BukkitListenerImplementedInspection.kt b/src/main/kotlin/platform/bukkit/inspection/BukkitListenerImplementedInspection.kt index 676d286f0..d88fa69c5 100644 --- a/src/main/kotlin/platform/bukkit/inspection/BukkitListenerImplementedInspection.kt +++ b/src/main/kotlin/platform/bukkit/inspection/BukkitListenerImplementedInspection.kt @@ -23,13 +23,13 @@ package com.demonwav.mcdev.platform.bukkit.inspection import com.demonwav.mcdev.platform.bukkit.util.BukkitConstants import com.demonwav.mcdev.util.addImplements import com.demonwav.mcdev.util.extendsOrImplements +import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemDescriptor import com.intellij.openapi.project.Project import com.intellij.psi.PsiClass import com.intellij.psi.createSmartPointer import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor -import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls class BukkitListenerImplementedInspection : BaseInspection() { @@ -44,10 +44,10 @@ 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): LocalQuickFix { val classPointer = (infos[0] as PsiClass).createSmartPointer() - return object : InspectionGadgetsFix() { - override fun doFix(project: Project, descriptor: ProblemDescriptor) { + return object : LocalQuickFix { + override fun applyFix(project: Project, descriptor: ProblemDescriptor) { classPointer.element?.addImplements(BukkitConstants.LISTENER_CLASS) } diff --git a/src/main/kotlin/platform/bungeecord/inspection/BungeeCordListenerImplementedInspection.kt b/src/main/kotlin/platform/bungeecord/inspection/BungeeCordListenerImplementedInspection.kt index ff111eb93..9188f4163 100644 --- a/src/main/kotlin/platform/bungeecord/inspection/BungeeCordListenerImplementedInspection.kt +++ b/src/main/kotlin/platform/bungeecord/inspection/BungeeCordListenerImplementedInspection.kt @@ -23,13 +23,13 @@ package com.demonwav.mcdev.platform.bungeecord.inspection import com.demonwav.mcdev.platform.bungeecord.util.BungeeCordConstants import com.demonwav.mcdev.util.addImplements import com.demonwav.mcdev.util.extendsOrImplements +import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemDescriptor import com.intellij.openapi.project.Project import com.intellij.psi.PsiClass import com.intellij.psi.createSmartPointer import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor -import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls class BungeeCordListenerImplementedInspection : BaseInspection() { @@ -43,10 +43,10 @@ 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): LocalQuickFix { val classPointer = (infos[0] as PsiClass).createSmartPointer() - return object : InspectionGadgetsFix() { - override fun doFix(project: Project, descriptor: ProblemDescriptor) { + return object : LocalQuickFix { + override fun applyFix(project: Project, descriptor: ProblemDescriptor) { classPointer.element?.addImplements(BungeeCordConstants.LISTENER_CLASS) } diff --git a/src/main/kotlin/platform/forge/inspections/sideonly/FieldDeclarationSideOnlyInspection.kt b/src/main/kotlin/platform/forge/inspections/sideonly/FieldDeclarationSideOnlyInspection.kt index 51b9315d0..a7ab4fa70 100644 --- a/src/main/kotlin/platform/forge/inspections/sideonly/FieldDeclarationSideOnlyInspection.kt +++ b/src/main/kotlin/platform/forge/inspections/sideonly/FieldDeclarationSideOnlyInspection.kt @@ -20,12 +20,12 @@ package com.demonwav.mcdev.platform.forge.inspections.sideonly +import com.intellij.codeInspection.LocalQuickFix import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiClassType import com.intellij.psi.PsiField import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor -import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls class FieldDeclarationSideOnlyInspection : BaseInspection() { @@ -45,7 +45,7 @@ class FieldDeclarationSideOnlyInspection : BaseInspection() { "everything with it, @SideOnly annotated fields are usually useless" } - override fun buildFix(vararg infos: Any): InspectionGadgetsFix? { + override fun buildFix(vararg infos: Any): LocalQuickFix? { val annotation = infos[3] as PsiAnnotation return if (annotation.isWritable) { diff --git a/src/main/kotlin/platform/forge/inspections/sideonly/LocalVariableDeclarationSideOnlyInspection.kt b/src/main/kotlin/platform/forge/inspections/sideonly/LocalVariableDeclarationSideOnlyInspection.kt index 764eba244..55a9319a5 100644 --- a/src/main/kotlin/platform/forge/inspections/sideonly/LocalVariableDeclarationSideOnlyInspection.kt +++ b/src/main/kotlin/platform/forge/inspections/sideonly/LocalVariableDeclarationSideOnlyInspection.kt @@ -21,12 +21,12 @@ package com.demonwav.mcdev.platform.forge.inspections.sideonly import com.demonwav.mcdev.util.findContainingClass +import com.intellij.codeInspection.LocalQuickFix import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiClassType import com.intellij.psi.PsiLocalVariable import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor -import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls class LocalVariableDeclarationSideOnlyInspection : BaseInspection() { @@ -43,7 +43,7 @@ class LocalVariableDeclarationSideOnlyInspection : BaseInspection() { "A variable whose class declaration is annotated with @SideOnly for one side cannot be declared in a class" + " or method that does not match the same side." - override fun buildFix(vararg infos: Any): InspectionGadgetsFix? { + override fun buildFix(vararg infos: Any): LocalQuickFix? { val annotation = infos[3] as PsiAnnotation return if (annotation.isWritable) { diff --git a/src/main/kotlin/platform/forge/inspections/sideonly/MethodCallSideOnlyInspection.kt b/src/main/kotlin/platform/forge/inspections/sideonly/MethodCallSideOnlyInspection.kt index 567ec54c5..766a524ee 100644 --- a/src/main/kotlin/platform/forge/inspections/sideonly/MethodCallSideOnlyInspection.kt +++ b/src/main/kotlin/platform/forge/inspections/sideonly/MethodCallSideOnlyInspection.kt @@ -22,6 +22,7 @@ package com.demonwav.mcdev.platform.forge.inspections.sideonly import com.demonwav.mcdev.platform.forge.util.ForgeConstants import com.demonwav.mcdev.util.findContainingClass +import com.intellij.codeInspection.LocalQuickFix import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiField import com.intellij.psi.PsiMethod @@ -29,7 +30,6 @@ import com.intellij.psi.PsiMethodCallExpression import com.intellij.psi.PsiReferenceExpression import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor -import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls class MethodCallSideOnlyInspection : BaseInspection() { @@ -47,7 +47,7 @@ class MethodCallSideOnlyInspection : BaseInspection() { "Methods which are declared with a @SideOnly annotation can only be " + "used in matching @SideOnly classes and methods." - override fun buildFix(vararg infos: Any): InspectionGadgetsFix? { + override fun buildFix(vararg infos: Any): LocalQuickFix? { val annotation = infos[3] as PsiAnnotation return if (annotation.isWritable) { diff --git a/src/main/kotlin/platform/forge/inspections/sideonly/MethodSideOnlyInspection.kt b/src/main/kotlin/platform/forge/inspections/sideonly/MethodSideOnlyInspection.kt index 96caa3db2..d02375fb8 100644 --- a/src/main/kotlin/platform/forge/inspections/sideonly/MethodSideOnlyInspection.kt +++ b/src/main/kotlin/platform/forge/inspections/sideonly/MethodSideOnlyInspection.kt @@ -20,12 +20,12 @@ package com.demonwav.mcdev.platform.forge.inspections.sideonly +import com.intellij.codeInspection.LocalQuickFix import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiClassType import com.intellij.psi.PsiMethod import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor -import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls class MethodSideOnlyInspection : BaseInspection() { @@ -45,7 +45,7 @@ class MethodSideOnlyInspection : BaseInspection() { "everything with it, @SideOnly annotated methods are usually useless" } - override fun buildFix(vararg infos: Any): InspectionGadgetsFix? { + override fun buildFix(vararg infos: Any): LocalQuickFix? { val error = infos[0] as Error val annotation = infos[3] as PsiAnnotation diff --git a/src/main/kotlin/platform/forge/inspections/sideonly/NestedClassSideOnlyInspection.kt b/src/main/kotlin/platform/forge/inspections/sideonly/NestedClassSideOnlyInspection.kt index b2f45525e..f7809c512 100644 --- a/src/main/kotlin/platform/forge/inspections/sideonly/NestedClassSideOnlyInspection.kt +++ b/src/main/kotlin/platform/forge/inspections/sideonly/NestedClassSideOnlyInspection.kt @@ -20,11 +20,11 @@ package com.demonwav.mcdev.platform.forge.inspections.sideonly +import com.intellij.codeInspection.LocalQuickFix import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiClass import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor -import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls class NestedClassSideOnlyInspection : BaseInspection() { @@ -42,7 +42,7 @@ class NestedClassSideOnlyInspection : BaseInspection() { "brings everything with it, @SideOnly annotated nested classes are usually useless." } - override fun buildFix(vararg infos: Any): InspectionGadgetsFix? { + override fun buildFix(vararg infos: Any): LocalQuickFix? { val annotation = infos[0] as PsiAnnotation return if (annotation.isWritable) { diff --git a/src/main/kotlin/platform/forge/inspections/sideonly/NewExpressionSideOnlyInspection.kt b/src/main/kotlin/platform/forge/inspections/sideonly/NewExpressionSideOnlyInspection.kt index 06ce664cc..005e3af10 100644 --- a/src/main/kotlin/platform/forge/inspections/sideonly/NewExpressionSideOnlyInspection.kt +++ b/src/main/kotlin/platform/forge/inspections/sideonly/NewExpressionSideOnlyInspection.kt @@ -21,12 +21,12 @@ package com.demonwav.mcdev.platform.forge.inspections.sideonly import com.demonwav.mcdev.util.findContainingClass +import com.intellij.codeInspection.LocalQuickFix import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiClass import com.intellij.psi.PsiNewExpression import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor -import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls class NewExpressionSideOnlyInspection : BaseInspection() { @@ -44,7 +44,7 @@ class NewExpressionSideOnlyInspection : BaseInspection() { "use @SideOnly annotated classes either." } - override fun buildFix(vararg infos: Any?): InspectionGadgetsFix? { + override fun buildFix(vararg infos: Any?): LocalQuickFix? { val annotation = infos[0] as? PsiAnnotation ?: return null return if (annotation.isWritable) { diff --git a/src/main/kotlin/platform/forge/inspections/sideonly/RemoveAnnotationInspectionGadgetsFix.kt b/src/main/kotlin/platform/forge/inspections/sideonly/RemoveAnnotationInspectionGadgetsFix.kt index 9c3f55a09..03a93ddf8 100644 --- a/src/main/kotlin/platform/forge/inspections/sideonly/RemoveAnnotationInspectionGadgetsFix.kt +++ b/src/main/kotlin/platform/forge/inspections/sideonly/RemoveAnnotationInspectionGadgetsFix.kt @@ -21,19 +21,19 @@ package com.demonwav.mcdev.platform.forge.inspections.sideonly import com.demonwav.mcdev.util.findAnnotation +import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemDescriptor import com.intellij.openapi.project.Project import com.intellij.psi.PsiModifierListOwner import com.intellij.psi.util.findParentOfType -import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls class RemoveAnnotationInspectionGadgetsFix( private val annotationName: String, private val name: String -) : InspectionGadgetsFix() { +) : LocalQuickFix { - override fun doFix(project: Project, descriptor: ProblemDescriptor) { + override fun applyFix(project: Project, descriptor: ProblemDescriptor) { val decl = descriptor.psiElement.findParentOfType() ?: return decl.findAnnotation(annotationName)?.delete() } diff --git a/src/main/kotlin/platform/forge/inspections/simpleimpl/AddEmptyConstructorInspectionGadgetsFix.kt b/src/main/kotlin/platform/forge/inspections/simpleimpl/AddEmptyConstructorInspectionGadgetsFix.kt index 008859ce3..602e367b7 100644 --- a/src/main/kotlin/platform/forge/inspections/simpleimpl/AddEmptyConstructorInspectionGadgetsFix.kt +++ b/src/main/kotlin/platform/forge/inspections/simpleimpl/AddEmptyConstructorInspectionGadgetsFix.kt @@ -21,14 +21,14 @@ package com.demonwav.mcdev.platform.forge.inspections.simpleimpl import com.demonwav.mcdev.util.findContainingClass +import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemDescriptor import com.intellij.openapi.project.Project import com.intellij.psi.JavaPsiFacade -import com.siyeh.ig.InspectionGadgetsFix -object AddEmptyConstructorInspectionGadgetsFix : InspectionGadgetsFix() { +object AddEmptyConstructorInspectionGadgetsFix : LocalQuickFix { - override fun doFix(project: Project, descriptor: ProblemDescriptor) { + override fun applyFix(project: Project, descriptor: ProblemDescriptor) { val clazz = descriptor.psiElement.findContainingClass() ?: return clazz.addBefore(JavaPsiFacade.getElementFactory(project).createConstructor(), clazz.methods[0]) } diff --git a/src/main/kotlin/platform/forge/inspections/simpleimpl/MissingMessageConstructorInspection.kt b/src/main/kotlin/platform/forge/inspections/simpleimpl/MissingMessageConstructorInspection.kt index 0197c9450..07477191d 100644 --- a/src/main/kotlin/platform/forge/inspections/simpleimpl/MissingMessageConstructorInspection.kt +++ b/src/main/kotlin/platform/forge/inspections/simpleimpl/MissingMessageConstructorInspection.kt @@ -20,10 +20,10 @@ package com.demonwav.mcdev.platform.forge.inspections.simpleimpl +import com.intellij.codeInspection.LocalQuickFix import com.intellij.psi.PsiClass import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor -import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls class MissingMessageConstructorInspection : BaseInspection() { @@ -36,7 +36,7 @@ class MissingMessageConstructorInspection : BaseInspection() { override fun getStaticDescription() = "All implementations of IMessage and IMessageHandler must have an empty constructor" - override fun buildFix(vararg infos: Any?): InspectionGadgetsFix? { + override fun buildFix(vararg infos: Any?): LocalQuickFix? { val messageClass = infos[0] as PsiClass return if (messageClass.isWritable) { diff --git a/src/main/kotlin/platform/mcp/actions/platform/mcp/actions/CopyNeoAtAction.kt b/src/main/kotlin/platform/mcp/actions/platform/mcp/actions/CopyNeoAtAction.kt new file mode 100644 index 000000000..1b2637b5a --- /dev/null +++ b/src/main/kotlin/platform/mcp/actions/platform/mcp/actions/CopyNeoAtAction.kt @@ -0,0 +1,105 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2025 minecraft-dev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, version 3.0 only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.demonwav.mcdev.platform.mcp.actions.platform.mcp.actions + +import com.demonwav.mcdev.platform.mcp.actions.SrgActionBase.Companion.showBalloon +import com.demonwav.mcdev.platform.mcp.actions.SrgActionBase.Companion.showSuccessBalloon +import com.demonwav.mcdev.util.descriptor +import com.demonwav.mcdev.util.getDataFromActionEvent +import com.demonwav.mcdev.util.internalName +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.editor.Editor +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiField +import com.intellij.psi.PsiIdentifier +import com.intellij.psi.PsiMember +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiReference +import java.awt.Toolkit +import java.awt.datatransfer.StringSelection + +class CopyNeoAtAction : AnAction() { + + override fun actionPerformed(e: AnActionEvent) { + val data = getDataFromActionEvent(e) ?: return showBalloon("Unknown failure", e) + val editor = data.editor + + val element = data.element + if (element !is PsiIdentifier) { + showBalloon("Invalid element", e) + return + } + + val target = when (val parent = element.parent) { + is PsiMember -> parent + is PsiReference -> parent.resolve() + else -> null + } ?: return showBalloon("Invalid element", e) + + doCopy(target, element, editor, e) + } + + companion object { + + fun doCopy(target: PsiElement, element: PsiElement, editor: Editor?, e: AnActionEvent?) { + when (target) { + is PsiClass -> { + val text = "public ${target.internalName}" + val text2 = text.replace("/",".").replace(" (","(") + copyToClipboard(editor, element, text2) + } + is PsiField -> { + val containing = target.containingClass?.internalName + ?: return maybeShow("Could not get owner of field", e) + val text = "public $containing ${target.name}" + val text2 = text.replace("/",".").replace(" (","(") + copyToClipboard(editor, element, text2) + } + is PsiMethod -> { + 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 modifiedContaining = containing.replace("/","."); + val text = "public ${modifiedContaining} ${target.internalName}$desc" + copyToClipboard(editor, element, text) + } + else -> maybeShow("Invalid element", e) + } + } + + private fun copyToClipboard(editor: Editor?, element: PsiElement, text: String) { + val stringSelection = StringSelection(text) + val clpbrd = Toolkit.getDefaultToolkit().systemClipboard + clpbrd.setContents(stringSelection, null) + if (editor != null) { + showSuccessBalloon(editor, element, "Copied: \"$text\"") + } + } + + private fun maybeShow(text: String, e: AnActionEvent?) { + if (e != null) { + showBalloon(text, e) + } + } + } +} diff --git a/src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt b/src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt index ac7a25069..b7aa72d7e 100644 --- a/src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt +++ b/src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt @@ -25,6 +25,7 @@ import com.demonwav.mcdev.platform.mcp.mappings.getMappedField import com.demonwav.mcdev.platform.mcp.mappings.getMappedMethod import com.demonwav.mcdev.util.findModule import com.demonwav.mcdev.util.fullQualifiedName +import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemDescriptor import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project @@ -38,7 +39,6 @@ import com.intellij.psi.PsiReferenceExpression import com.intellij.psi.createSmartPointer import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor -import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls class StackEmptyInspection : BaseInspection() { @@ -59,13 +59,13 @@ 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): LocalQuickFix { val compareExpressionPointer = (infos[0] as PsiExpression).createSmartPointer() val binaryExpressionPointer = (infos[2] as PsiBinaryExpression).createSmartPointer() - return object : InspectionGadgetsFix() { + return object : LocalQuickFix { override fun getFamilyName() = "Replace with .isEmpty()" - override fun doFix(project: Project, descriptor: ProblemDescriptor) { + override fun applyFix(project: Project, descriptor: ProblemDescriptor) { val elementFactory = JavaPsiFacade.getElementFactory(project) val compareExpression = compareExpressionPointer.element ?: return diff --git a/src/main/kotlin/platform/mixin/action/GenerateAccessorHandler.kt b/src/main/kotlin/platform/mixin/action/GenerateAccessorHandler.kt index 96b3553b6..c7ca5dfd7 100644 --- a/src/main/kotlin/platform/mixin/action/GenerateAccessorHandler.kt +++ b/src/main/kotlin/platform/mixin/action/GenerateAccessorHandler.kt @@ -42,7 +42,7 @@ import com.intellij.codeInsight.generation.PsiElementClassMember import com.intellij.codeInsight.generation.PsiFieldMember import com.intellij.codeInsight.generation.PsiMethodMember import com.intellij.codeInsight.hint.HintManager -import com.intellij.codeInsight.intention.AddAnnotationFix +import com.intellij.codeInsight.intention.AddAnnotationPsiFix import com.intellij.codeInsight.intention.impl.CreateClassDialog import com.intellij.ide.util.ChooseElementsDialog import com.intellij.ide.util.EditorHelper @@ -310,8 +310,11 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In "@${MixinConstants.Annotations.MIXIN}(targets=\"${targetClass.fullQualifiedName}\")" } val annotation = factory.createAnnotationFromText(annotationText, clazz) - AddAnnotationFix(MixinConstants.Annotations.MIXIN, clazz, annotation.parameterList.attributes) - .applyFix() + AddAnnotationPsiFix.addPhysicalAnnotationTo( + MixinConstants.Annotations.MIXIN, + annotation.parameterList.attributes, + clazz.modifierList + ) val module = clazz.findModule() ?: return@compute null val configToWrite = MixinModule.getBestWritableConfigForMixinClass( @@ -427,7 +430,11 @@ class GenerateAccessorHandler : GenerateMembersHandlerBase("Generate Accessor/In ) target.typeElement?.let { method.parameterList.parameters[0].typeElement?.replace(it) } if (target.modifierList?.hasExplicitModifier(PsiModifier.FINAL) == true) { - AddAnnotationFix(MixinConstants.Annotations.MUTABLE, method).applyFix() + AddAnnotationPsiFix.addPhysicalAnnotationTo( + MixinConstants.Annotations.MUTABLE, + emptyArray(), + method.modifierList + ) } accessors.add(method) } diff --git a/src/main/kotlin/platform/mixin/config/reference/MixinPackage.kt b/src/main/kotlin/platform/mixin/config/reference/MixinPackage.kt index f38a1da45..44ec82cf6 100644 --- a/src/main/kotlin/platform/mixin/config/reference/MixinPackage.kt +++ b/src/main/kotlin/platform/mixin/config/reference/MixinPackage.kt @@ -32,6 +32,7 @@ import com.intellij.psi.search.PackageScope import com.intellij.psi.search.searches.AnnotatedElementsSearch import com.intellij.util.ArrayUtil import com.intellij.util.PlatformIcons +import com.intellij.util.Processor object MixinPackage : PackageNameReferenceProvider() { @@ -49,8 +50,8 @@ object MixinPackage : PackageNameReferenceProvider() { val packages = HashSet() val list = ArrayList() - for (mixin in AnnotatedElementsSearch.searchPsiClasses(mixinAnnotation, element.resolveScope)) { - val packageName = mixin.packageName ?: continue + AnnotatedElementsSearch.searchPsiClasses(mixinAnnotation, element.resolveScope).forEach(Processor { mixin -> + val packageName = mixin.packageName ?: return@Processor true if (packages.add(packageName)) { list.add(LookupElementBuilder.create(packageName).withIcon(PlatformIcons.PACKAGE_ICON)) } @@ -59,7 +60,8 @@ object MixinPackage : PackageNameReferenceProvider() { if (packages.add(topLevelPackage)) { list.add(LookupElementBuilder.create(topLevelPackage).withIcon(PlatformIcons.PACKAGE_ICON)) } - } + return@Processor true + }) return list.toArray() } diff --git a/src/main/kotlin/platform/mixin/expression/MEExpressionInjector.kt b/src/main/kotlin/platform/mixin/expression/MEExpressionInjector.kt index 6922536a6..96bb00934 100644 --- a/src/main/kotlin/platform/mixin/expression/MEExpressionInjector.kt +++ b/src/main/kotlin/platform/mixin/expression/MEExpressionInjector.kt @@ -23,8 +23,6 @@ package com.demonwav.mcdev.platform.mixin.expression import com.demonwav.mcdev.platform.mixin.util.MixinConstants import com.demonwav.mcdev.util.findContainingModifierList import com.demonwav.mcdev.util.findContainingNameValuePair -import com.demonwav.mcdev.util.parseArray -import com.intellij.lang.injection.InjectedLanguageManager import com.intellij.lang.injection.MultiHostInjector import com.intellij.lang.injection.MultiHostRegistrar import com.intellij.openapi.util.Key @@ -45,7 +43,6 @@ import com.intellij.psi.util.PsiModificationTracker import com.intellij.psi.util.PsiUtil import com.intellij.psi.util.parentOfType import com.intellij.util.SmartList -import org.intellij.plugins.intelliLang.inject.InjectorUtils class MEExpressionInjector : MultiHostInjector { companion object { @@ -118,44 +115,36 @@ class MEExpressionInjector : MultiHostInjector { } } } else if (annotation.hasQualifiedName(MixinConstants.MixinExtras.EXPRESSION)) { - for (valueExpr in annotation.findDeclaredAttributeValue("value")?.parseArray { it }.orEmpty()) { - val places = mutableListOf>() - iterateConcatenation(valueExpr) { op -> - if (op is PsiLanguageInjectionHost) { - for (textRange in getTextRanges(op)) { - places += op to textRange - } - } else { - isFrankenstein = true + val valueExpr = annotation.findDeclaredAttributeValue("value") ?: continue + val places = mutableListOf>() + iterateConcatenation(valueExpr) { op -> + if (op is PsiLanguageInjectionHost) { + for (textRange in getTextRanges(op)) { + places += op to textRange } + } else { + isFrankenstein = true } - if (places.isNotEmpty()) { - for ((i, place) in places.withIndex()) { - val (host, range) = place - val prefix = "\ndo { ".takeIf { i == 0 } - val suffix = " }".takeIf { i == places.size - 1 } - registrar.addPlace(prefix, suffix, host, range) - } + } + if (places.isNotEmpty()) { + for ((i, place) in places.withIndex()) { + val (host, range) = place + val prefix = "\ndo { ".takeIf { i == 0 } + val suffix = " }".takeIf { i == places.size - 1 } + registrar.addPlace(prefix, suffix, host, range) } } } } + registrar.frankensteinInjection(isFrankenstein) + registrar.doneInjecting() modifierList.putUserData( ME_EXPRESSION_INJECTION, MEExpressionInjection(modCount, METHOD_GET_INJECTED_RESULT.invoke(registrar)) ) - - if (isFrankenstein) { - InjectorUtils.putInjectedFileUserData( - context, - MEExpressionLanguage, - InjectedLanguageManager.FRANKENSTEIN_INJECTION, - true - ) - } } private fun iterateConcatenation(element: PsiElement, consumer: (PsiElement) -> Unit) { diff --git a/src/main/kotlin/platform/mixin/inspection/addedMembers/MissingUniqueAnnotationInspection.kt b/src/main/kotlin/platform/mixin/inspection/addedMembers/MissingUniqueAnnotationInspection.kt index 543f02ec5..e070c37cd 100644 --- a/src/main/kotlin/platform/mixin/inspection/addedMembers/MissingUniqueAnnotationInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/addedMembers/MissingUniqueAnnotationInspection.kt @@ -21,7 +21,8 @@ package com.demonwav.mcdev.platform.mixin.inspection.addedMembers import com.demonwav.mcdev.platform.mixin.util.MixinConstants -import com.intellij.codeInsight.intention.AddAnnotationFix +import com.intellij.codeInsight.intention.AddAnnotationModCommandAction +import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemsHolder import com.intellij.psi.PsiField import com.intellij.psi.PsiMethod @@ -34,7 +35,7 @@ class MissingUniqueAnnotationInspection : AbstractAddedMembersInspection() { holder.registerProblem( field.nameIdentifier, "Missing @Unique annotation", - AddAnnotationFix(MixinConstants.Annotations.UNIQUE, field) + LocalQuickFix.from(AddAnnotationModCommandAction(MixinConstants.Annotations.UNIQUE, field))!!, ) } } @@ -44,7 +45,7 @@ class MissingUniqueAnnotationInspection : AbstractAddedMembersInspection() { holder.registerProblem( method.nameIdentifier ?: return, "Missing @Unique annotation", - AddAnnotationFix(MixinConstants.Annotations.UNIQUE, method) + LocalQuickFix.from(AddAnnotationModCommandAction(MixinConstants.Annotations.UNIQUE, method))!! ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/injector/InjectCouldBeOverwriteInspection.kt b/src/main/kotlin/platform/mixin/inspection/injector/InjectCouldBeOverwriteInspection.kt index 52551598e..e3156ac36 100644 --- a/src/main/kotlin/platform/mixin/inspection/injector/InjectCouldBeOverwriteInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/injector/InjectCouldBeOverwriteInspection.kt @@ -34,7 +34,7 @@ import com.demonwav.mcdev.util.findAnnotation import com.demonwav.mcdev.util.findAnnotations import com.demonwav.mcdev.util.hasImplicitReturnStatement import com.intellij.analysis.AnalysisScope -import com.intellij.codeInsight.intention.AddAnnotationFix +import com.intellij.codeInsight.intention.AddAnnotationPsiFix import com.intellij.codeInsight.intention.FileModifier.SafeFieldForPreview import com.intellij.codeInspection.CleanupLocalInspectionTool import com.intellij.codeInspection.InspectionManager @@ -313,7 +313,11 @@ class InjectCouldBeOverwriteInspection : MixinInspection() { val newMethod = oldMethod.replace(templateMethod) as PsiMethod // add the @Overwrite annotation - AddAnnotationFix(MixinConstants.Annotations.OVERWRITE, newMethod).applyFix() + AddAnnotationPsiFix.addPhysicalAnnotationTo( + MixinConstants.Annotations.OVERWRITE, + emptyArray(), + newMethod.modifierList + ) // if the old method includes the parameters of the target method, use those if (!newParameterList.isEmpty) { diff --git a/src/main/kotlin/platform/mixin/inspection/injector/MixinCancellableInspection.kt b/src/main/kotlin/platform/mixin/inspection/injector/MixinCancellableInspection.kt index 5ae7d67d1..6483257af 100644 --- a/src/main/kotlin/platform/mixin/inspection/injector/MixinCancellableInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/injector/MixinCancellableInspection.kt @@ -18,9 +18,9 @@ * along with this program. If not, see . */ -package com.demonwav.mcdev.platform.mixin.inspection.injector +package com.demonwav.mcdev.platform.mixin.inspection -import com.demonwav.mcdev.platform.mixin.inspection.MixinInspection +import com.demonwav.mcdev.platform.mixin.inspection.injector.CancellableBeforeSuperCallInspection import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Annotations.INJECT import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Classes.CALLBACK_INFO import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Classes.CALLBACK_INFO_RETURNABLE @@ -44,6 +44,7 @@ import com.intellij.psi.PsiMethod import com.intellij.psi.PsiReferenceExpression import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.psi.util.PsiUtil +import com.intellij.util.Processor class MixinCancellableInspection : MixinInspection() { @@ -65,24 +66,26 @@ class MixinCancellableInspection : MixinInspection() { } ?: return val ciType = (ciParam.type as? PsiClassType)?.resolve() ?: return - val searchingFor = ciType.findMethodsByName("setReturnValue", false) + - ciType.findMethodsByName("cancel", true) - searchingFor.ifEmpty { return } + val searchingFor = ciType.findMethodsByName("setReturnValue", false).firstOrNull() + ?: ciType.findMethodsByName("cancel", false).firstOrNull() + ?: return var mayUseCancel = false var definitelyUsesCancel = false - for (ref in ReferencesSearch.search(ciParam)) { + ReferencesSearch.search(ciParam).forEach(Processor { ref -> val parent = PsiUtil.skipParenthesizedExprUp(ref.element.parent) if (parent is PsiExpressionList) { // method argument, we can't tell whether it uses cancel mayUseCancel = true } - val methodCall = parent as? PsiReferenceExpression ?: continue - if (methodCall.references.any { reference -> searchingFor.any(reference::isReferenceTo) }) { + val methodCall = parent as? PsiReferenceExpression ?: return@Processor true + if (methodCall.references.any { it.isReferenceTo(searchingFor) }) { definitelyUsesCancel = true - break + return@Processor false } - } + + return@Processor true + }) if (definitelyUsesCancel && !isCancellable) { val fixes = mutableListOf() diff --git a/src/main/kotlin/platform/mixin/inspection/mixinextras/UnnecessaryMutableLocalInspection.kt b/src/main/kotlin/platform/mixin/inspection/mixinextras/UnnecessaryMutableLocalInspection.kt index 97f172ccc..1127e6cc4 100644 --- a/src/main/kotlin/platform/mixin/inspection/mixinextras/UnnecessaryMutableLocalInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/mixinextras/UnnecessaryMutableLocalInspection.kt @@ -46,6 +46,7 @@ import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.psi.util.PsiTypesUtil import com.intellij.psi.util.PsiUtil import com.intellij.psi.util.parentOfType +import com.intellij.util.Processor import com.siyeh.ig.psiutils.MethodCallUtils class UnnecessaryMutableLocalInspection : MixinInspection() { @@ -97,16 +98,28 @@ class UnnecessaryMutableLocalInspection : MixinInspection() { for (method in OverridingMethodsSearch.search(originalMethod).findAll() + listOf(originalMethod)) { val param = method.parameterList.getParameter(paramIndex) ?: return val getMethod = paramType.findMethodsByName("get", false).firstOrNull() ?: return - for (ref in ReferencesSearch.search(param)) { + + var exitEarly = false + ReferencesSearch.search(param).forEach(Processor { ref -> if (isDelegationToSuper(ref.element, paramIndex)) { - continue + return@Processor true + } + val parent = PsiUtil.skipParenthesizedExprUp(ref.element.parent) as? PsiReferenceExpression ?: run { + exitEarly = true + return@Processor false } - val parent = PsiUtil.skipParenthesizedExprUp(ref.element.parent) as? PsiReferenceExpression ?: return if (parent.references.any { it.isReferenceTo(getMethod) }) { hasAnyGets = true } else { - return + exitEarly = true + return@Processor false } + + return@Processor true + }) + + if (exitEarly) { + return } } if (!hasAnyGets) { @@ -127,11 +140,9 @@ class UnnecessaryMutableLocalInspection : MixinInspection() { ?: return false // For some reason ref is sometimes the identifier rather than the reference expression. Get the reference expr - val actualRef = if (ref is PsiReferenceExpression) { - ref - } else { - PsiUtil.skipParenthesizedExprUp(ref.parent) as? PsiReferenceExpression ?: return false - } + val actualRef = ref as? PsiReferenceExpression + ?: PsiUtil.skipParenthesizedExprUp(ref.parent) as? PsiReferenceExpression + ?: return false val param = PsiUtil.skipParenthesizedExprUp(actualRef) val paramList = param.parent as? PsiExpressionList ?: return false val methodCall = paramList.parent as? PsiMethodCallExpression ?: return false @@ -172,12 +183,14 @@ class UnnecessaryMutableLocalInspection : MixinInspection() { val innerType = param.type.unwrapLocalRef() val factory = PsiElementFactory.getInstance(method.project) param.typeElement?.replace(factory.createTypeElement(innerType)) - for (ref in ReferencesSearch.search(param)) { + ReferencesSearch.search(param).forEach(Processor { ref -> val refExpression = PsiUtil.skipParenthesizedExprUp(ref.element.parent) as? PsiReferenceExpression - ?: continue - val call = refExpression.parent as? PsiMethodCallExpression ?: continue + ?: return@Processor true + val call = refExpression.parent as? PsiMethodCallExpression ?: return@Processor true call.replace(ref.element) - } + + return@Processor true + }) } } } diff --git a/src/main/kotlin/platform/mixin/inspection/overwrite/OverwriteModifiersInspection.kt b/src/main/kotlin/platform/mixin/inspection/overwrite/OverwriteModifiersInspection.kt index 8f2d168d8..0e514227c 100644 --- a/src/main/kotlin/platform/mixin/inspection/overwrite/OverwriteModifiersInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/overwrite/OverwriteModifiersInspection.kt @@ -30,8 +30,9 @@ import com.demonwav.mcdev.platform.mixin.util.internalNameToShortName import com.demonwav.mcdev.util.findAnnotation import com.demonwav.mcdev.util.findKeyword import com.demonwav.mcdev.util.isAccessModifier -import com.intellij.codeInsight.intention.AddAnnotationFix +import com.intellij.codeInsight.intention.AddAnnotationModCommandAction import com.intellij.codeInsight.intention.QuickFixFactory +import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemHighlightType import com.intellij.codeInspection.ProblemsHolder import com.intellij.psi.PsiAnnotation @@ -114,7 +115,7 @@ class OverwriteModifiersInspection : OverwriteInspection() { nameIdentifier, "Missing @${internalNameToShortName(internalName)} annotation", ProblemHighlightType.WARNING, - AddAnnotationFix(qualifiedName, method, targetAnnPsi.parameterList.attributes), + LocalQuickFix.from(AddAnnotationModCommandAction(qualifiedName, method, targetAnnPsi.parameterList.attributes))!!, ) } else { holder.registerProblem( diff --git a/src/main/kotlin/platform/mixin/inspection/shadow/ShadowFinalInspection.kt b/src/main/kotlin/platform/mixin/inspection/shadow/ShadowFinalInspection.kt index 3342811a3..f8faa04bf 100644 --- a/src/main/kotlin/platform/mixin/inspection/shadow/ShadowFinalInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/shadow/ShadowFinalInspection.kt @@ -24,7 +24,8 @@ import com.demonwav.mcdev.platform.mixin.inspection.MixinInspection import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Annotations.FINAL import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Annotations.MUTABLE import com.demonwav.mcdev.util.findContainingClass -import com.intellij.codeInsight.intention.AddAnnotationFix +import com.intellij.codeInsight.intention.AddAnnotationModCommandAction +import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemsHolder import com.intellij.psi.JavaElementVisitor import com.intellij.psi.PsiClass @@ -61,7 +62,7 @@ class ShadowFinalInspection : MixinInspection() { holder.registerProblem( expression, "@Final fields cannot be modified", - AddAnnotationFix(MUTABLE, field), + LocalQuickFix.from(AddAnnotationModCommandAction(MUTABLE, field))!!, ) } } diff --git a/src/main/kotlin/platform/mixin/inspection/shadow/ShadowModifiersInspection.kt b/src/main/kotlin/platform/mixin/inspection/shadow/ShadowModifiersInspection.kt index e29a0bd14..847bebc38 100644 --- a/src/main/kotlin/platform/mixin/inspection/shadow/ShadowModifiersInspection.kt +++ b/src/main/kotlin/platform/mixin/inspection/shadow/ShadowModifiersInspection.kt @@ -29,8 +29,9 @@ import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Annotations.FINAL import com.demonwav.mcdev.platform.mixin.util.MixinTargetMember import com.demonwav.mcdev.platform.mixin.util.accessLevel import com.demonwav.mcdev.util.findKeyword -import com.intellij.codeInsight.intention.AddAnnotationFix +import com.intellij.codeInsight.intention.AddAnnotationModCommandAction import com.intellij.codeInsight.intention.QuickFixFactory +import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemHighlightType import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.RemoveAnnotationQuickFix @@ -118,7 +119,7 @@ class ShadowModifiersInspection : MixinInspection() { holder.registerProblem( annotation, "@Shadow for final member should be annotated as @Final", - AddAnnotationFix(FINAL, member), + LocalQuickFix.from(AddAnnotationModCommandAction(FINAL, member))!!, ) } else { holder.registerProblem( diff --git a/src/main/kotlin/platform/mixin/util/AsmUtil.kt b/src/main/kotlin/platform/mixin/util/AsmUtil.kt index bdf8a15d4..3f18915e4 100644 --- a/src/main/kotlin/platform/mixin/util/AsmUtil.kt +++ b/src/main/kotlin/platform/mixin/util/AsmUtil.kt @@ -22,7 +22,7 @@ package com.demonwav.mcdev.platform.mixin.util import com.demonwav.mcdev.platform.mixin.reference.MixinSelector import com.demonwav.mcdev.util.MemberReference -import com.demonwav.mcdev.util.anonymousClasses +import com.demonwav.mcdev.util.anonymousElements import com.demonwav.mcdev.util.cached import com.demonwav.mcdev.util.childrenOfType import com.demonwav.mcdev.util.findField @@ -39,6 +39,7 @@ import com.demonwav.mcdev.util.loggerForTopLevel import com.demonwav.mcdev.util.mapToArray import com.demonwav.mcdev.util.realName import com.demonwav.mcdev.util.toJavaIdentifier +import com.intellij.byteCodeViewer.ByteCodeViewerManager import com.intellij.codeEditor.JavaEditorFileSwapper import com.intellij.ide.highlighter.JavaFileType import com.intellij.openapi.module.Module @@ -86,7 +87,6 @@ import com.llamalad7.mixinextras.expression.impl.utils.ExpressionASMUtils import java.io.PrintWriter import java.io.StringWriter import java.lang.reflect.InvocationTargetException -import java.lang.reflect.Method import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentMap import org.objectweb.asm.ClassReader @@ -183,18 +183,6 @@ fun internalNameToShortName(internalName: String) = internalName.substringAfterL val ClassNode.shortName get() = internalNameToShortName(name) -val Type.shortName get() = className.substringAfterLast('.').replace('$', '.') - -fun shortDescString(desc: String) = Type.getArgumentTypes(desc).joinToString(prefix = "(", postfix = ")") { - it.shortName -} - -private val LOAD_CLASS_FILE_BYTES: Method? = runCatching { - com.intellij.byteCodeViewer.ByteCodeViewerManager::class.java - .getDeclaredMethod("loadClassFileBytes", PsiClass::class.java) - .let { it.isAccessible = true; it } -}.getOrNull() - private val INNER_CLASS_NODES_KEY = Key.create>>("mcdev.innerClassNodes") /** @@ -230,7 +218,7 @@ private val NODE_BY_PSI_CLASS_KEY = Key.create>("mcdev.n fun findClassNodeByPsiClass(psiClass: PsiClass, module: Module? = psiClass.findModule()): ClassNode? { return psiClass.lockedCached(NODE_BY_PSI_CLASS_KEY) { try { - val bytes = LOAD_CLASS_FILE_BYTES?.invoke(null, psiClass) as? ByteArray + val bytes = ByteCodeViewerManager.loadClassFileBytes(psiClass) if (bytes == null) { // find compiler output if (module == null) return@lockedCached null @@ -395,7 +383,7 @@ private fun ClassNode.constructClass(project: Project, body: String): PsiClass? // find innermost PsiClass while (true) { clazz = clazz.innerClasses.firstOrNull() - ?: clazz.anonymousClasses.lastOrNull() + ?: clazz.anonymousElements.lastOrNull { it !== clazz && it is PsiClass } as? PsiClass ?: clazz.localClasses.lastOrNull() ?: break } @@ -788,7 +776,7 @@ private fun findAssociatedLambda(project: Project, scope: GlobalSearchScope, cla // walk inside the reference first, visits the qualifier first (it's first in the bytecode) super.visitMethodReferenceExpression(expression) - if (expression.hasSyntheticMethod(clazz.version)) { + if (expression.hasSyntheticMethod) { if (matcher.accept(expression)) { stopWalking() } @@ -1106,26 +1094,6 @@ fun MethodInsnNode.fakeResolve(): ClassAndMethodNode { return ClassAndMethodNode(clazz, method) } -// AbstractInsnNode - -val AbstractInsnNode.nextRealInsn: AbstractInsnNode? - get() { - var insn = next - while (insn != null && insn.opcode < 0) { - insn = insn.next - } - return insn - } - -val AbstractInsnNode.previousRealInsn: AbstractInsnNode? - get() { - var insn = previous - while (insn != null && insn.opcode < 0) { - insn = insn.previous - } - return insn - } - // Textifier fun ClassNode.textify(): String { diff --git a/src/main/kotlin/platform/sponge/inspection/SpongeInjectionInspection.kt b/src/main/kotlin/platform/sponge/inspection/SpongeInjectionInspection.kt index 8e0356738..b0fccfc05 100644 --- a/src/main/kotlin/platform/sponge/inspection/SpongeInjectionInspection.kt +++ b/src/main/kotlin/platform/sponge/inspection/SpongeInjectionInspection.kt @@ -29,7 +29,7 @@ import com.demonwav.mcdev.util.constantStringValue import com.demonwav.mcdev.util.findModule import com.demonwav.mcdev.util.fullQualifiedName import com.demonwav.mcdev.util.mapFirstNotNull -import com.intellij.codeInsight.intention.AddAnnotationFix +import com.intellij.codeInsight.intention.AddAnnotationModCommandAction import com.intellij.codeInsight.intention.QuickFixFactory import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool import com.intellij.codeInspection.InspectionManager @@ -165,7 +165,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { variable.nameIdentifier ?: variable, "Injected Assets must be annotated with @AssetId.", ProblemHighlightType.GENERIC_ERROR, - AddAnnotationFix(SpongeConstants.ASSET_ID_ANNOTATION, annotationsOwner), + LocalQuickFix.from(AddAnnotationModCommandAction(SpongeConstants.ASSET_ID_ANNOTATION, annotationsOwner))!!, ) } else { variable.findModule()?.let { module -> @@ -239,8 +239,8 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { variable.nameIdentifier ?: variable, "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), + LocalQuickFix.from(AddAnnotationModCommandAction(SpongeConstants.CONFIG_DIR_ANNOTATION, annotationsOwner))!!, + LocalQuickFix.from(AddAnnotationModCommandAction(SpongeConstants.DEFAULT_CONFIG_ANNOTATION, annotationsOwner))!!, ) } } @@ -252,7 +252,7 @@ class SpongeInjectionInspection : AbstractBaseJavaLocalInspectionTool() { variable.nameIdentifier ?: variable, "Injected ${classType.name} must be annotated with @DefaultConfig.", ProblemHighlightType.GENERIC_ERROR, - AddAnnotationFix(SpongeConstants.DEFAULT_CONFIG_ANNOTATION, annotationsOwner), + LocalQuickFix.from(AddAnnotationModCommandAction(SpongeConstants.DEFAULT_CONFIG_ANNOTATION, annotationsOwner))!!, ) } diff --git a/src/main/kotlin/platform/sponge/inspection/SpongeWrongGetterTypeInspection.kt b/src/main/kotlin/platform/sponge/inspection/SpongeWrongGetterTypeInspection.kt index 4a8e219da..2e0687c11 100644 --- a/src/main/kotlin/platform/sponge/inspection/SpongeWrongGetterTypeInspection.kt +++ b/src/main/kotlin/platform/sponge/inspection/SpongeWrongGetterTypeInspection.kt @@ -43,7 +43,6 @@ import com.intellij.psi.PsiPrimitiveType import com.intellij.psi.PsiSubstitutor import com.intellij.psi.PsiType import com.intellij.psi.util.TypeConversionUtil -import com.siyeh.ig.InspectionGadgetsFix import java.util.function.Supplier import org.jetbrains.uast.UMethod import org.jetbrains.uast.getContainingUClass @@ -148,17 +147,17 @@ class SpongeWrongGetterTypeInspection : AbstractBaseUastLocalInspectionTool() { val elementFactory = JavaPsiFacade.getElementFactory(project) val expectedClassType = expectedType as? PsiClassType - ?: return InspectionGadgetsFix.EMPTY_ARRAY + ?: return LocalQuickFix.EMPTY_ARRAY val fixedClassType = if (isOptional(expectedClassType)) { val wrappedType = expectedClassType.parameters.first() val resolveResult = (wrappedType as? PsiClassType)?.resolveGenerics() - ?: return InspectionGadgetsFix.EMPTY_ARRAY + ?: return LocalQuickFix.EMPTY_ARRAY val element = resolveResult.element - ?: return InspectionGadgetsFix.EMPTY_ARRAY + ?: return LocalQuickFix.EMPTY_ARRAY elementFactory.createType(element, resolveResult.substitutor) } else { val resolvedClass = expectedClassType.resolve() - ?: return InspectionGadgetsFix.EMPTY_ARRAY + ?: return LocalQuickFix.EMPTY_ARRAY elementFactory.createType(resolvedClass) } diff --git a/src/main/kotlin/util/analysis-utils.kt b/src/main/kotlin/util/analysis-utils.kt index 79c006b5f..5c6ec0088 100644 --- a/src/main/kotlin/util/analysis-utils.kt +++ b/src/main/kotlin/util/analysis-utils.kt @@ -20,13 +20,13 @@ package com.demonwav.mcdev.util -import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil import com.intellij.psi.PsiCodeBlock import com.intellij.psi.controlFlow.AnalysisCanceledException +import com.intellij.psi.controlFlow.ControlFlowFactory import com.intellij.psi.controlFlow.ControlFlowUtil @Throws(AnalysisCanceledException::class) fun hasImplicitReturnStatement(body: PsiCodeBlock): Boolean { - val controlFlow = HighlightControlFlowUtil.getControlFlowNoConstantEvaluate(body) + val controlFlow = ControlFlowFactory.getControlFlowNoConstantEvaluate(body) return ControlFlowUtil.canCompleteNormally(controlFlow, 0, controlFlow.size) } diff --git a/src/main/kotlin/util/psi-utils.kt b/src/main/kotlin/util/psi-utils.kt index 9945d191b..8ef6f1ecf 100644 --- a/src/main/kotlin/util/psi-utils.kt +++ b/src/main/kotlin/util/psi-utils.kt @@ -89,6 +89,7 @@ import com.intellij.psi.util.PsiUtil import com.intellij.psi.util.TypeConversionUtil import com.intellij.psi.util.parentOfType import com.intellij.refactoring.changeSignature.ChangeSignatureUtil +import com.intellij.util.CachedValueBase import com.intellij.util.IncorrectOperationException import com.siyeh.ig.psiutils.ImportUtils import java.util.concurrent.ConcurrentHashMap @@ -314,6 +315,7 @@ inline fun PsiElement.cached(vararg dependencies: Any, crossinline compute: @PublishedApi internal val CACHE_LOCKS_KEY = Key.create, ReentrantReadWriteLock>>("mcdev.cacheLock") +@Suppress("UNCHECKED_CAST") inline fun PsiElement.lockedCached( key: Key>, vararg dependencies: Any, @@ -323,14 +325,14 @@ inline fun PsiElement.lockedCached( val cacheLock = cacheLocks.computeIfAbsent(key) { ReentrantReadWriteLock() } cacheLock.read { - val value = getUserData(key)?.upToDateOrNull + val value = getUserData(key as Key>)?.upToDateOrNull if (value != null) { return value.get() } } cacheLock.write { - val value = getUserData(key)?.upToDateOrNull + val value = getUserData(key as Key>)?.upToDateOrNull if (value != null) { return value.get() } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 93479fed5..a8910455a 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -1652,10 +1652,15 @@ text="Minecraft Class" description="Create skeleton classes used in Minecraft Mods"> + + + - +