diff --git a/build.gradle.kts b/build.gradle.kts index 6208e61ac..35e6727d5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -29,12 +29,12 @@ import org.jlleitschuh.gradle.ktlint.tasks.BaseKtLintCheckTask import org.jlleitschuh.gradle.ktlint.tasks.KtLintFormatTask plugins { - kotlin("jvm") version "1.9.0" + kotlin("jvm") version "1.9.20" java mcdev groovy idea - id("org.jetbrains.intellij") version "1.15.0" + id("org.jetbrains.intellij") version "1.16.0" id("org.cadixdev.licenser") id("org.jlleitschuh.gradle.ktlint") version "10.3.0" } diff --git a/gradle.properties b/gradle.properties index 4c7f2b120..b4ce2f35a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,7 +24,7 @@ kotlin.code.style=official ideaVersion = 2023.1 ideaVersionName = 2023.1 -coreVersion = 1.6.10 +coreVersion = 1.6.11 downloadIdeaSources = true pluginTomlVersion = 231.8109.1 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 033e24c4c..7f93135c4 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 62f495dfe..3fa8f862f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index fcb6fca14..1aa94a426 100755 --- a/gradlew +++ b/gradlew @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -201,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/readme.md b/readme.md index 169d27f0d..ba6b529a0 100644 --- a/readme.md +++ b/readme.md @@ -35,7 +35,7 @@ Minecraft Development for IntelliJ -Info and Documentation [![Current Release](https://img.shields.io/badge/release-1.6.10-orange.svg?style=flat-square)](https://plugins.jetbrains.com/plugin/8327) +Info and Documentation [![Current Release](https://img.shields.io/badge/release-1.6.11-orange.svg?style=flat-square)](https://plugins.jetbrains.com/plugin/8327) ---------------------- diff --git a/src/main/kotlin/creator/PlatformVersion.kt b/src/main/kotlin/creator/PlatformVersion.kt index 4b17ee1ca..2e6be03b8 100644 --- a/src/main/kotlin/creator/PlatformVersion.kt +++ b/src/main/kotlin/creator/PlatformVersion.kt @@ -25,7 +25,6 @@ import com.demonwav.mcdev.update.PluginUtil import com.demonwav.mcdev.util.fromJson import com.demonwav.mcdev.util.mapFirstNotNull import com.demonwav.mcdev.util.withSuppressed -import com.github.kittinunf.fuel.core.FuelError import com.github.kittinunf.fuel.core.FuelManager import com.github.kittinunf.fuel.core.requests.suspendable import com.github.kittinunf.fuel.coroutines.awaitString @@ -77,11 +76,11 @@ suspend fun getVersionJson(path: String, type: KClass): T { } suspend fun getText(path: String): String { - var thrown: FuelError? = null + var thrown: Exception? = null return URLS.mapFirstNotNull { url -> try { doCall(url + path) - } catch (e: FuelError) { + } catch (e: Exception) { PLATFORM_VERSION_LOGGER.warn("Failed to reach URL $url$path") thrown = withSuppressed(thrown, e) null diff --git a/src/main/kotlin/facet/MinecraftFacet.kt b/src/main/kotlin/facet/MinecraftFacet.kt index 6c38fd206..5be0acd96 100644 --- a/src/main/kotlin/facet/MinecraftFacet.kt +++ b/src/main/kotlin/facet/MinecraftFacet.kt @@ -114,6 +114,7 @@ class MinecraftFacet( } newlyEnabled.forEach(AbstractModule::init) + modules.forEach(AbstractModule::refresh) ProjectView.getInstance(module.project).refresh() } diff --git a/src/main/kotlin/insight/ColorUtil.kt b/src/main/kotlin/insight/ColorUtil.kt index 2c9fe8ded..5c61bde1f 100644 --- a/src/main/kotlin/insight/ColorUtil.kt +++ b/src/main/kotlin/insight/ColorUtil.kt @@ -79,7 +79,7 @@ private fun findColorFromExpression( val facet = MinecraftFacet.getInstance(module) ?: return null val resolvedName = expression.resolvedName ?: return null for (abstractModuleType in facet.types) { - val map = abstractModuleType.classToColorMappings + val map = abstractModuleType.classToColorMappings(module) for (entry in map.entries) { // This is such a hack // Okay, type will be the fully-qualified class, but it will exclude the actual enum diff --git a/src/main/kotlin/platform/AbstractModule.kt b/src/main/kotlin/platform/AbstractModule.kt index f4ffe5eec..fdc77c22f 100644 --- a/src/main/kotlin/platform/AbstractModule.kt +++ b/src/main/kotlin/platform/AbstractModule.kt @@ -93,4 +93,5 @@ abstract class AbstractModule(protected val facet: MinecraftFacet) { open fun init() {} open fun dispose() {} + open fun refresh() {} } diff --git a/src/main/kotlin/platform/AbstractModuleType.kt b/src/main/kotlin/platform/AbstractModuleType.kt index d88258293..f27254eac 100644 --- a/src/main/kotlin/platform/AbstractModuleType.kt +++ b/src/main/kotlin/platform/AbstractModuleType.kt @@ -25,6 +25,7 @@ import com.demonwav.mcdev.insight.generation.ui.EventGenerationPanel import com.demonwav.mcdev.util.findContainingClass import com.intellij.codeInspection.ex.EntryPointsManager import com.intellij.codeInspection.ex.EntryPointsManagerBase +import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleUtilCore import com.intellij.openapi.project.Project import com.intellij.psi.PsiClass @@ -51,8 +52,7 @@ abstract class AbstractModuleType(val groupId: String, v abstract val listenerAnnotations: List - val classToColorMappings: Map - get() = this.colorMap + open fun classToColorMappings(module: Module): Map = this.colorMap abstract fun generateModule(facet: MinecraftFacet): T diff --git a/src/main/kotlin/platform/bukkit/inspection/BukkitListenerImplementedInspection.kt b/src/main/kotlin/platform/bukkit/inspection/BukkitListenerImplementedInspection.kt index 2e554b834..e0a86ff05 100644 --- a/src/main/kotlin/platform/bukkit/inspection/BukkitListenerImplementedInspection.kt +++ b/src/main/kotlin/platform/bukkit/inspection/BukkitListenerImplementedInspection.kt @@ -26,11 +26,11 @@ import com.demonwav.mcdev.util.extendsOrImplements import com.intellij.codeInspection.ProblemDescriptor import com.intellij.openapi.project.Project import com.intellij.psi.PsiClass +import com.intellij.psi.util.createSmartPointer import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls -import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer class BukkitListenerImplementedInspection : BaseInspection() { diff --git a/src/main/kotlin/platform/bungeecord/inspection/BungeeCordListenerImplementedInspection.kt b/src/main/kotlin/platform/bungeecord/inspection/BungeeCordListenerImplementedInspection.kt index f28946a05..2dbdfb843 100644 --- a/src/main/kotlin/platform/bungeecord/inspection/BungeeCordListenerImplementedInspection.kt +++ b/src/main/kotlin/platform/bungeecord/inspection/BungeeCordListenerImplementedInspection.kt @@ -26,11 +26,11 @@ import com.demonwav.mcdev.util.extendsOrImplements import com.intellij.codeInspection.ProblemDescriptor import com.intellij.openapi.project.Project import com.intellij.psi.PsiClass +import com.intellij.psi.util.createSmartPointer import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls -import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer class BungeeCordListenerImplementedInspection : BaseInspection() { diff --git a/src/main/kotlin/platform/fabric/FabricModule.kt b/src/main/kotlin/platform/fabric/FabricModule.kt index 6d02073a8..8ec555e48 100644 --- a/src/main/kotlin/platform/fabric/FabricModule.kt +++ b/src/main/kotlin/platform/fabric/FabricModule.kt @@ -26,6 +26,10 @@ import com.demonwav.mcdev.platform.AbstractModule import com.demonwav.mcdev.platform.PlatformType import com.demonwav.mcdev.platform.fabric.reference.EntryPointReference import com.demonwav.mcdev.platform.fabric.util.FabricConstants +import com.demonwav.mcdev.platform.mcp.fabricloom.FabricLoomData +import com.demonwav.mcdev.platform.mcp.mappings.HardcodedYarnToMojmap +import com.demonwav.mcdev.platform.mcp.mappings.HasCustomNamedMappings +import com.demonwav.mcdev.platform.mcp.mappings.MappingsManager import com.demonwav.mcdev.util.SourceType import com.demonwav.mcdev.util.nullable import com.demonwav.mcdev.util.runCatchingKtIdeaExceptions @@ -33,16 +37,25 @@ import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod import com.intellij.psi.search.searches.ReferencesSearch +import java.io.IOException +import net.fabricmc.mappingio.MappedElementKind +import net.fabricmc.mappingio.MappingReader +import net.fabricmc.mappingio.MappingVisitor +import org.jetbrains.plugins.gradle.util.GradleUtil import org.jetbrains.uast.UClass import org.jetbrains.uast.UIdentifier import org.jetbrains.uast.UMethod import org.jetbrains.uast.toUElementOfType -class FabricModule internal constructor(facet: MinecraftFacet) : AbstractModule(facet) { +class FabricModule internal constructor(facet: MinecraftFacet) : AbstractModule(facet), HasCustomNamedMappings { var fabricJson by nullable { facet.findFile(FabricConstants.FABRIC_MOD_JSON, SourceType.RESOURCE) } private set + private var namedToMojangManagerField: MappingsManager? = null + override val namedToMojangManager: MappingsManager? + get() = namedToMojangManagerField + override val moduleType = FabricModuleType override val type = PlatformType.FABRIC override val icon = PlatformAssets.FABRIC_ICON @@ -65,6 +78,59 @@ class FabricModule internal constructor(facet: MinecraftFacet) : AbstractModule( return ReferencesSearch.search(psiParent).anyMatch { EntryPointReference.isEntryPointReference(it) } } + override fun refresh() { + namedToMojangManagerField = if (detectYarn()) { + MappingsManager.Immediate(HardcodedYarnToMojmap.createMappings()) + } else { + null + } + } + + private fun detectYarn(): Boolean { + val gradleData = GradleUtil.findGradleModuleData(facet.module) ?: return false + val loomData = + gradleData.children.find { it.key == FabricLoomData.KEY }?.data as? FabricLoomData ?: return false + val mappingsFile = loomData.tinyMappings ?: return false + + var yarnDetected = false + val visitor = object : MappingVisitor { + private var namedIndex = -1 + + override fun visitNamespaces(srcNamespace: String?, dstNamespaces: List) { + namedIndex = dstNamespaces.indexOf("named") + } + + override fun visitContent() = namedIndex >= 0 + + override fun visitClass(srcName: String) = true + + override fun visitField(srcName: String?, srcDesc: String?) = false + + override fun visitMethod(srcName: String?, srcDesc: String?) = false + + override fun visitMethodArg(argPosition: Int, lvIndex: Int, srcName: String?) = false + + override fun visitMethodVar(lvtRowIndex: Int, lvIndex: Int, startOpIdx: Int, srcName: String?) = false + + override fun visitDstName(targetKind: MappedElementKind?, namespace: Int, name: String) { + if (namespace == namedIndex && name == "net/minecraft/client/MinecraftClient") { + yarnDetected = true + } + } + + override fun visitComment(targetKind: MappedElementKind?, comment: String?) { + } + } + + try { + MappingReader.read(mappingsFile.toPath(), visitor) + } catch (e: IOException) { + return false + } + + return yarnDetected + } + override fun dispose() { super.dispose() fabricJson = null diff --git a/src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt b/src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt index 90eb2f117..ffce39644 100644 --- a/src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt +++ b/src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt @@ -67,9 +67,9 @@ object ReflectedFieldReference : PsiReferenceProvider() { ?: return@withInsertHandler val srgManager = literal.findModule()?.let { MinecraftFacet.getInstance(it) } - ?.getModuleOfType(McpModuleType)?.srgManager - val srgMap = srgManager?.srgMapNow - val srgField = srgMap?.getSrgField(field.simpleQualifiedMemberReference) + ?.getModuleOfType(McpModuleType)?.mappingsManager + val srgMap = srgManager?.mappingsNow + val srgField = srgMap?.getIntermediaryField(field.simpleQualifiedMemberReference) ?: return@withInsertHandler context.setLaterRunnable { diff --git a/src/main/kotlin/platform/forge/reflection/reference/ReflectedMemberReferenceBasePoly.kt b/src/main/kotlin/platform/forge/reflection/reference/ReflectedMemberReferenceBasePoly.kt index e5709deca..84e57bf06 100644 --- a/src/main/kotlin/platform/forge/reflection/reference/ReflectedMemberReferenceBasePoly.kt +++ b/src/main/kotlin/platform/forge/reflection/reference/ReflectedMemberReferenceBasePoly.kt @@ -49,9 +49,9 @@ abstract class ReflectedMemberReferenceBasePoly(element: PsiLiteral) : PsiRefere val name = memberName val srgManager = element.findModule()?.let { MinecraftFacet.getInstance(it) } - ?.getModuleOfType(McpModuleType)?.srgManager - val srgMap = srgManager?.srgMapNow - val mcpName = srgMap?.mapMcpToSrgName(name) ?: name + ?.getModuleOfType(McpModuleType)?.mappingsManager + val srgMap = srgManager?.mappingsNow + val mcpName = srgMap?.mapIntermediaryToMapped(name) ?: name return typeClass.allFields.asSequence() .filter { it.name == mcpName } diff --git a/src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt b/src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt index e4e4a2ce9..cad7c8f94 100644 --- a/src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt +++ b/src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt @@ -74,8 +74,8 @@ object ReflectedMethodReference : PsiReferenceProvider() { ?: return@withInsertHandler val params = literal.parent as? PsiExpressionList ?: return@withInsertHandler val srgManager = literal.findModule()?.let { MinecraftFacet.getInstance(it) } - ?.getModuleOfType(McpModuleType)?.srgManager - val srgMap = srgManager?.srgMapNow + ?.getModuleOfType(McpModuleType)?.mappingsManager + val srgMap = srgManager?.mappingsNow val signature = method.getSignature(PsiSubstitutor.EMPTY) val returnType = method.returnType?.let { TypeConversionUtil.erasure(it).canonicalText } @@ -84,7 +84,7 @@ object ReflectedMethodReference : PsiReferenceProvider() { .map { it.canonicalText } val memberRef = method.qualifiedMemberReference - val srgMethod = srgMap?.getSrgMethod(memberRef) ?: memberRef + val srgMethod = srgMap?.getIntermediaryMethod(memberRef) ?: memberRef context.setLaterRunnable { // Commit changes made by code completion diff --git a/src/main/kotlin/platform/mcp/McpModule.kt b/src/main/kotlin/platform/mcp/McpModule.kt index e0816ff44..dcb1a7845 100644 --- a/src/main/kotlin/platform/mcp/McpModule.kt +++ b/src/main/kotlin/platform/mcp/McpModule.kt @@ -23,7 +23,7 @@ package com.demonwav.mcdev.platform.mcp import com.demonwav.mcdev.facet.MinecraftFacet import com.demonwav.mcdev.platform.AbstractModule import com.demonwav.mcdev.platform.PlatformType -import com.demonwav.mcdev.platform.mcp.srg.SrgManager +import com.demonwav.mcdev.platform.mcp.mappings.MappingsManager import com.demonwav.mcdev.platform.mcp.util.McpConstants import com.demonwav.mcdev.translations.TranslationFileListener import com.demonwav.mcdev.util.runWriteTaskLater @@ -43,7 +43,7 @@ class McpModule(facet: MinecraftFacet) : AbstractModule(facet) { private val settings: McpModuleSettings = McpModuleSettings.getInstance(module) val accessTransformers = mutableSetOf() - var srgManager: SrgManager? = null + var mappingsManager: MappingsManager? = null private set override fun init() { @@ -61,8 +61,8 @@ class McpModule(facet: MinecraftFacet) : AbstractModule(facet) { val file = settings.mappingFile ?: return val srgType = settings.srgType ?: return - srgManager = SrgManager.getInstance(file, srgType) - srgManager?.parse() + mappingsManager = MappingsManager.getInstance(file, srgType) + mappingsManager?.parse() } override val moduleType = McpModuleType @@ -78,8 +78,8 @@ class McpModule(facet: MinecraftFacet) : AbstractModule(facet) { val mappingFile = data.mappingFile ?: return val srgType = data.srgType ?: return - srgManager = SrgManager.getInstance(mappingFile, srgType) - srgManager?.parse() + mappingsManager = MappingsManager.getInstance(mappingFile, srgType) + mappingsManager?.parse() } fun addAccessTransformerFile(file: VirtualFile) { @@ -91,6 +91,6 @@ class McpModule(facet: MinecraftFacet) : AbstractModule(facet) { connection.disconnect() accessTransformers.clear() - srgManager = null + mappingsManager = null } } diff --git a/src/main/kotlin/platform/mcp/McpModuleType.kt b/src/main/kotlin/platform/mcp/McpModuleType.kt index 12d98b3a1..be617faf7 100644 --- a/src/main/kotlin/platform/mcp/McpModuleType.kt +++ b/src/main/kotlin/platform/mcp/McpModuleType.kt @@ -23,9 +23,12 @@ package com.demonwav.mcdev.platform.mcp import com.demonwav.mcdev.facet.MinecraftFacet import com.demonwav.mcdev.platform.AbstractModuleType import com.demonwav.mcdev.platform.PlatformType +import com.demonwav.mcdev.platform.mcp.mappings.getMappedClass +import com.demonwav.mcdev.platform.mcp.mappings.getMappedField import com.demonwav.mcdev.platform.mcp.util.McpConstants import com.demonwav.mcdev.util.CommonColors -import com.demonwav.mcdev.util.SemanticVersion +import com.intellij.openapi.module.Module +import java.awt.Color import javax.swing.Icon object McpModuleType : AbstractModuleType("", "") { @@ -33,10 +36,18 @@ object McpModuleType : AbstractModuleType("", "") { private const val ID = "MCP_MODULE_TYPE" init { - CommonColors.applyStandardColors(colorMap, McpConstants.TEXT_FORMATTING) CommonColors.applyStandardColors(colorMap, McpConstants.CHAT_FORMATTING) } + override fun classToColorMappings(module: Module): Map { + return colorMap.mapKeys { key -> + val parts = key.key.split('.') + val className = parts.dropLast(1).joinToString(".") + val fieldName = parts.last() + "${module.getMappedClass(className)}.${module.getMappedField(className, fieldName)}" + } + } + override val platformType = PlatformType.MCP override val icon: Icon? = null override val id = ID @@ -45,6 +56,4 @@ object McpModuleType : AbstractModuleType("", "") { override val hasIcon = false override fun generateModule(facet: MinecraftFacet) = McpModule(facet) - - val MC_1_12_2 = SemanticVersion.release(1, 12, 2) } diff --git a/src/main/kotlin/platform/mcp/actions/CopyAtAction.kt b/src/main/kotlin/platform/mcp/actions/CopyAtAction.kt index aa8bb7f9e..219ddbe02 100644 --- a/src/main/kotlin/platform/mcp/actions/CopyAtAction.kt +++ b/src/main/kotlin/platform/mcp/actions/CopyAtAction.kt @@ -20,7 +20,7 @@ package com.demonwav.mcdev.platform.mcp.actions -import com.demonwav.mcdev.platform.mcp.srg.McpSrgMap +import com.demonwav.mcdev.platform.mcp.mappings.Mappings import com.demonwav.mcdev.util.ActionData import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.editor.Editor @@ -32,12 +32,12 @@ import java.awt.Toolkit import java.awt.datatransfer.StringSelection class CopyAtAction : SrgActionBase() { - override fun withSrgTarget(parent: PsiElement, srgMap: McpSrgMap, e: AnActionEvent, data: ActionData) { + override fun withSrgTarget(parent: PsiElement, srgMap: Mappings, e: AnActionEvent, data: ActionData) { when (parent) { is PsiField -> { val containing = parent.containingClass ?: return showBalloon("No SRG name found", e) - val classSrg = srgMap.getSrgClass(containing) ?: return showBalloon("No SRG name found", e) - val srg = srgMap.getSrgField(parent) ?: return showBalloon("No SRG name found", e) + val classSrg = srgMap.getIntermediaryClass(containing) ?: return showBalloon("No SRG name found", e) + val srg = srgMap.getIntermediaryField(parent) ?: return showBalloon("No SRG name found", e) copyToClipboard( data.editor, data.element, @@ -46,8 +46,8 @@ class CopyAtAction : SrgActionBase() { } is PsiMethod -> { val containing = parent.containingClass ?: return showBalloon("No SRG name found", e) - val classSrg = srgMap.getSrgClass(containing) ?: return showBalloon("No SRG name found", e) - val srg = srgMap.getSrgMethod(parent) ?: return showBalloon("No SRG name found", e) + val classSrg = srgMap.getIntermediaryClass(containing) ?: return showBalloon("No SRG name found", e) + val srg = srgMap.getIntermediaryMethod(parent) ?: return showBalloon("No SRG name found", e) copyToClipboard( data.editor, data.element, @@ -55,7 +55,7 @@ class CopyAtAction : SrgActionBase() { ) } is PsiClass -> { - val classMcpToSrg = srgMap.getSrgClass(parent) ?: return showBalloon("No SRG name found", e) + val classMcpToSrg = srgMap.getIntermediaryClass(parent) ?: return showBalloon("No SRG name found", e) copyToClipboard(data.editor, data.element, classMcpToSrg) } else -> showBalloon("Not a valid element", e) diff --git a/src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt b/src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt index 3c398cb4e..c51bf138f 100644 --- a/src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt +++ b/src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt @@ -20,7 +20,7 @@ package com.demonwav.mcdev.platform.mcp.actions -import com.demonwav.mcdev.platform.mcp.srg.McpSrgMap +import com.demonwav.mcdev.platform.mcp.mappings.Mappings import com.demonwav.mcdev.util.ActionData import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.editor.Editor @@ -34,12 +34,12 @@ import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive class CopyCoremodTargetAction : SrgActionBase() { - override fun withSrgTarget(parent: PsiElement, srgMap: McpSrgMap, e: AnActionEvent, data: ActionData) { + override fun withSrgTarget(parent: PsiElement, srgMap: Mappings, e: AnActionEvent, data: ActionData) { when (parent) { is PsiField -> { val containing = parent.containingClass ?: return showBalloon("No SRG name found", e) - val classSrg = srgMap.getSrgClass(containing) ?: return showBalloon("No SRG name found", e) - val srg = srgMap.getSrgField(parent) ?: return showBalloon("No SRG name found", e) + val classSrg = srgMap.getIntermediaryClass(containing) ?: return showBalloon("No SRG name found", e) + val srg = srgMap.getIntermediaryField(parent) ?: return showBalloon("No SRG name found", e) copyToClipboard( data.editor, data.element, @@ -50,8 +50,8 @@ class CopyCoremodTargetAction : SrgActionBase() { } is PsiMethod -> { val containing = parent.containingClass ?: return showBalloon("No SRG name found", e) - val classSrg = srgMap.getSrgClass(containing) ?: return showBalloon("No SRG name found", e) - val srg = srgMap.getSrgMethod(parent) ?: return showBalloon("No SRG name found", e) + val classSrg = srgMap.getIntermediaryClass(containing) ?: return showBalloon("No SRG name found", e) + val srg = srgMap.getIntermediaryMethod(parent) ?: return showBalloon("No SRG name found", e) val srgDescriptor = srg.descriptor ?: return showBalloon("No SRG name found", e) copyToClipboard( data.editor, @@ -63,7 +63,7 @@ class CopyCoremodTargetAction : SrgActionBase() { ) } is PsiClass -> { - val classSrg = srgMap.getSrgClass(parent) ?: return showBalloon("No SRG name found", e) + val classSrg = srgMap.getIntermediaryClass(parent) ?: return showBalloon("No SRG name found", e) copyToClipboard( data.editor, data.element, diff --git a/src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt b/src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt index b0b17f42b..e9ad627e8 100644 --- a/src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt +++ b/src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt @@ -20,7 +20,7 @@ package com.demonwav.mcdev.platform.mcp.actions -import com.demonwav.mcdev.platform.mcp.srg.McpSrgMap +import com.demonwav.mcdev.platform.mcp.mappings.Mappings import com.demonwav.mcdev.util.ActionData import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.psi.PsiClass @@ -30,18 +30,18 @@ import com.intellij.psi.PsiMethod class FindSrgMappingAction : SrgActionBase() { - override fun withSrgTarget(parent: PsiElement, srgMap: McpSrgMap, e: AnActionEvent, data: ActionData) { + override fun withSrgTarget(parent: PsiElement, srgMap: Mappings, e: AnActionEvent, data: ActionData) { when (parent) { is PsiField -> { - val srg = srgMap.getSrgField(parent) ?: return showBalloon("No SRG name found", e) + val srg = srgMap.getIntermediaryField(parent) ?: return showBalloon("No SRG name found", e) showSuccessBalloon(data.editor, data.element, "SRG name: " + srg.name) } is PsiMethod -> { - val srg = srgMap.getSrgMethod(parent) ?: return showBalloon("No SRG name found", e) + val srg = srgMap.getIntermediaryMethod(parent) ?: return showBalloon("No SRG name found", e) showSuccessBalloon(data.editor, data.element, "SRG name: " + srg.name + srg.descriptor) } is PsiClass -> { - val classMcpToSrg = srgMap.getSrgClass(parent) ?: return showBalloon("No SRG name found", e) + val classMcpToSrg = srgMap.getIntermediaryClass(parent) ?: return showBalloon("No SRG name found", e) 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 489863b4b..d7645741d 100644 --- a/src/main/kotlin/platform/mcp/actions/GotoAtEntryAction.kt +++ b/src/main/kotlin/platform/mcp/actions/GotoAtEntryAction.kt @@ -22,7 +22,7 @@ package com.demonwav.mcdev.platform.mcp.actions import com.demonwav.mcdev.facet.MinecraftFacet import com.demonwav.mcdev.platform.mcp.McpModuleType -import com.demonwav.mcdev.platform.mcp.srg.SrgManager +import com.demonwav.mcdev.platform.mcp.mappings.MappingsManager import com.demonwav.mcdev.platform.mixin.handlers.ShadowHandler import com.demonwav.mcdev.util.ActionData import com.demonwav.mcdev.util.getDataFromActionEvent @@ -50,12 +50,12 @@ class GotoAtEntryAction : AnAction() { return } - val srgManager = data.instance.getModuleOfType(McpModuleType)?.srgManager + val mappingsManager = data.instance.getModuleOfType(McpModuleType)?.mappingsManager // Not all ATs are in MCP modules, fallback to this if possible // TODO try to find SRG references for all modules if current module isn't found? - ?: SrgManager.findAnyInstance(data.project) ?: return showBalloon(e) + ?: MappingsManager.findAnyInstance(data.project) ?: return showBalloon(e) - srgManager.srgMap.onSuccess { srgMap -> + mappingsManager.mappings.onSuccess { srgMap -> var parent = data.element.parent if (parent is PsiMember) { @@ -67,11 +67,11 @@ class GotoAtEntryAction : AnAction() { when (parent) { is PsiField -> { - val reference = srgMap.getSrgField(parent) ?: parent.simpleQualifiedMemberReference + val reference = srgMap.getIntermediaryField(parent) ?: parent.simpleQualifiedMemberReference searchForText(e, data, reference.name) } is PsiMethod -> { - val reference = srgMap.getSrgMethod(parent) ?: parent.qualifiedMemberReference + val reference = srgMap.getIntermediaryMethod(parent) ?: parent.qualifiedMemberReference searchForText(e, data, reference.name + reference.descriptor) } else -> diff --git a/src/main/kotlin/platform/mcp/actions/SrgActionBase.kt b/src/main/kotlin/platform/mcp/actions/SrgActionBase.kt index 0a962e7ac..aa1a28d78 100644 --- a/src/main/kotlin/platform/mcp/actions/SrgActionBase.kt +++ b/src/main/kotlin/platform/mcp/actions/SrgActionBase.kt @@ -21,7 +21,7 @@ package com.demonwav.mcdev.platform.mcp.actions import com.demonwav.mcdev.platform.mcp.McpModuleType -import com.demonwav.mcdev.platform.mcp.srg.McpSrgMap +import com.demonwav.mcdev.platform.mcp.mappings.Mappings import com.demonwav.mcdev.platform.mixin.handlers.ShadowHandler import com.demonwav.mcdev.util.ActionData import com.demonwav.mcdev.util.getDataFromActionEvent @@ -55,7 +55,7 @@ abstract class SrgActionBase : AnAction() { val mcpModule = data.instance.getModuleOfType(McpModuleType) ?: return showBalloon("No mappings found", e) - mcpModule.srgManager?.srgMap?.onSuccess { srgMap -> + mcpModule.mappingsManager?.mappings?.onSuccess { srgMap -> var parent = data.element.parent ?: return@onSuccess showBalloon("Not a valid element", e) if (parent is PsiMember) { @@ -75,7 +75,7 @@ abstract class SrgActionBase : AnAction() { } ?: showBalloon("No mappings found", e) } - abstract fun withSrgTarget(parent: PsiElement, srgMap: McpSrgMap, e: AnActionEvent, data: ActionData) + abstract fun withSrgTarget(parent: PsiElement, srgMap: Mappings, e: AnActionEvent, data: ActionData) companion object { fun showBalloon(message: String, e: AnActionEvent) { diff --git a/src/main/kotlin/platform/mcp/at/AtAnnotator.kt b/src/main/kotlin/platform/mcp/at/AtAnnotator.kt index f303f7363..300380d69 100644 --- a/src/main/kotlin/platform/mcp/at/AtAnnotator.kt +++ b/src/main/kotlin/platform/mcp/at/AtAnnotator.kt @@ -47,7 +47,7 @@ class AtAnnotator : Annotator { val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return val facet = MinecraftFacet.getInstance(module) ?: return val mcpModule = facet.getModuleOfType(McpModuleType) ?: return - val srgMap = mcpModule.srgManager?.srgMapNow ?: return + val srgMap = mcpModule.mappingsManager?.mappingsNow ?: return val reference = AtMemberReference.get(element, member) ?: return @@ -64,11 +64,11 @@ class AtAnnotator : Annotator { // We need to check the srg map, or it can't be resolved (and no underline) when (member) { is AtFieldName -> { - srgMap.getMcpField(reference)?.resolveMember(element.project) ?: return + srgMap.tryGetMappedField(reference)?.resolveMember(element.project) ?: return underline(member, holder) } is AtFunction -> { - srgMap.getMcpMethod(reference)?.resolveMember(element.project) ?: return + srgMap.tryGetMappedMethod(reference)?.resolveMember(element.project) ?: return underline(member.funcName, holder) } } diff --git a/src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt b/src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt index 32255457d..f53729b5b 100644 --- a/src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt +++ b/src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt @@ -55,12 +55,12 @@ class AtGotoDeclarationHandler : GotoDeclarationHandler { val mcpModule = instance.getModuleOfType(McpModuleType) ?: return null - val srgMap = mcpModule.srgManager?.srgMapNow ?: return null + val srgMap = mcpModule.mappingsManager?.mappingsNow ?: return null return when { sourceElement.node.treeParent.elementType === AtTypes.CLASS_NAME -> { val className = sourceElement.parent as AtClassName - val classSrgToMcp = srgMap.mapToMcpClass(className.classNameText) + val classSrgToMcp = srgMap.getMappedClass(className.classNameText) val psiClass = findQualifiedClass(sourceElement.project, classSrgToMcp) ?: return null arrayOf(psiClass) } @@ -69,7 +69,7 @@ class AtGotoDeclarationHandler : GotoDeclarationHandler { val function = funcName.parent as AtFunction val entry = function.parent as AtEntry - val reference = srgMap.mapToMcpMethod(AtMemberReference.get(entry, function) ?: return null) + val reference = srgMap.getMappedMethod(AtMemberReference.get(entry, function) ?: return null) val member = reference.resolveMember(sourceElement.project) ?: return null arrayOf(member) } @@ -77,12 +77,12 @@ class AtGotoDeclarationHandler : GotoDeclarationHandler { val fieldName = sourceElement.parent as AtFieldName val entry = fieldName.parent as AtEntry - val reference = srgMap.mapToMcpField(AtMemberReference.get(entry, fieldName) ?: return null) + val reference = srgMap.getMappedField(AtMemberReference.get(entry, fieldName) ?: return null) val member = reference.resolveMember(sourceElement.project) ?: return null arrayOf(member) } sourceElement.node.elementType === AtTypes.CLASS_VALUE -> { - val className = srgMap.mapToMcpClass(parseClassDescriptor(sourceElement.text)) + val className = srgMap.getMappedClass(parseClassDescriptor(sourceElement.text)) val psiClass = findQualifiedClass(sourceElement.project, className) ?: return null arrayOf(psiClass) } diff --git a/src/main/kotlin/platform/mcp/at/AtUsageInspection.kt b/src/main/kotlin/platform/mcp/at/AtUsageInspection.kt index 6a25c54bb..cdef1bffe 100644 --- a/src/main/kotlin/platform/mcp/at/AtUsageInspection.kt +++ b/src/main/kotlin/platform/mcp/at/AtUsageInspection.kt @@ -50,19 +50,19 @@ class AtUsageInspection : LocalInspectionTool() { val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return val instance = MinecraftFacet.getInstance(module) ?: return val mcpModule = instance.getModuleOfType(McpModuleType) ?: return - val srgMap = mcpModule.srgManager?.srgMapNow ?: return + val srgMap = mcpModule.mappingsManager?.mappingsNow ?: return val member = element.function ?: element.fieldName ?: return val reference = AtMemberReference.get(element, member) ?: return val psi = when (member) { is AtFunction -> - reference.resolveMember(element.project) ?: srgMap.getMcpMethod(reference)?.resolveMember( + reference.resolveMember(element.project) ?: srgMap.tryGetMappedMethod(reference)?.resolveMember( element.project, ) ?: return is AtFieldName -> reference.resolveMember(element.project) - ?: srgMap.getMcpField(reference)?.resolveMember(element.project) ?: return + ?: srgMap.tryGetMappedField(reference)?.resolveMember(element.project) ?: return else -> return } diff --git a/src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt b/src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt index d3d1b0605..ff323285b 100644 --- a/src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt +++ b/src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt @@ -221,7 +221,7 @@ class AtCompletionContributor : CompletionContributor() { val mcpModule = MinecraftFacet.getInstance(module)?.getModuleOfType(McpModuleType) ?: return - val srgMap = mcpModule.srgManager?.srgMapNow ?: return + val srgMap = mcpModule.mappingsManager?.mappingsNow ?: return val srgResult = result.withPrefixMatcher(SrgPrefixMatcher(text)) @@ -230,7 +230,7 @@ class AtCompletionContributor : CompletionContributor() { continue } - val memberReference = srgMap.getSrgField(field) ?: field.simpleQualifiedMemberReference + val memberReference = srgMap.getIntermediaryField(field) ?: field.simpleQualifiedMemberReference srgResult.addElement( PrioritizedLookupElement.withPriority( LookupElementBuilder @@ -263,7 +263,7 @@ class AtCompletionContributor : CompletionContributor() { continue } - val memberReference = srgMap.getSrgMethod(method) ?: method.qualifiedMemberReference + val memberReference = srgMap.getIntermediaryMethod(method) ?: method.qualifiedMemberReference srgResult.addElement( PrioritizedLookupElement.withPriority( LookupElementBuilder.create(method.nameAndParameterTypes) diff --git a/src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt b/src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt index 4b3cb7470..4160cfb66 100644 --- a/src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt +++ b/src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt @@ -20,10 +20,9 @@ package com.demonwav.mcdev.platform.mcp.inspections -import com.demonwav.mcdev.facet.MinecraftFacet -import com.demonwav.mcdev.platform.mcp.McpModuleType -import com.demonwav.mcdev.platform.mcp.srg.SrgMemberReference -import com.demonwav.mcdev.util.MemberReference +import com.demonwav.mcdev.platform.mcp.mappings.getMappedClass +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.ProblemDescriptor @@ -36,18 +35,15 @@ import com.intellij.psi.PsiClassType import com.intellij.psi.PsiExpression import com.intellij.psi.PsiField import com.intellij.psi.PsiReferenceExpression +import com.intellij.psi.util.createSmartPointer import com.siyeh.ig.BaseInspection import com.siyeh.ig.BaseInspectionVisitor import com.siyeh.ig.InspectionGadgetsFix import org.jetbrains.annotations.Nls -import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer class StackEmptyInspection : BaseInspection() { companion object { - const val STACK_FQ_NAME = "net.minecraft.item.ItemStack" - val STACK_JVM_NAME = STACK_FQ_NAME.replace('.', '/') - val EMPTY_SRG = SrgMemberReference.parse("$STACK_JVM_NAME/field_190927_a") - val IS_EMPTY_SRG = SrgMemberReference.parse("$STACK_JVM_NAME/func_190926_b") + const val STACK_FQ_NAME = "net.minecraft.world.item.ItemStack" } @Nls @@ -75,7 +71,7 @@ class StackEmptyInspection : BaseInspection() { val compareExpression = compareExpressionPointer.element ?: return val binaryExpression = binaryExpressionPointer.element ?: return - val mappedIsEmpty = compareExpression.findModule()?.getMappedMethod(IS_EMPTY_SRG)?.name ?: "isEmpty" + val mappedIsEmpty = compareExpression.findModule()?.getMappedMethod(STACK_FQ_NAME, "isEmpty", "()Z") var expressionText = "${compareExpression.text}.$mappedIsEmpty()" @@ -101,9 +97,10 @@ class StackEmptyInspection : BaseInspection() { val rightExpression = expression.rOperand // Check if both operands evaluate to an ItemStack - if (isExpressionStack(leftExpression) && isExpressionStack(rightExpression)) { - val leftEmpty = isExpressionEmptyConstant(leftExpression) - val rightEmpty = isExpressionEmptyConstant(rightExpression) + val module = expression.findModule() ?: return + if (isExpressionStack(module, leftExpression) && isExpressionStack(module, rightExpression)) { + val leftEmpty = isExpressionEmptyConstant(module, leftExpression) + val rightEmpty = isExpressionEmptyConstant(module, rightExpression) // Check that only one of the references are ItemStack.EMPTY if (leftEmpty xor rightEmpty) { @@ -117,26 +114,18 @@ class StackEmptyInspection : BaseInspection() { } } - private fun isExpressionStack(expression: PsiExpression?): Boolean { - return (expression?.type as? PsiClassType)?.resolve()?.fullQualifiedName == STACK_FQ_NAME + private fun isExpressionStack(module: Module, expression: PsiExpression?): Boolean { + val fqn = (expression?.type as? PsiClassType)?.resolve()?.fullQualifiedName + return fqn == module.getMappedClass(STACK_FQ_NAME) } - private fun isExpressionEmptyConstant(expression: PsiExpression?): Boolean { + private fun isExpressionEmptyConstant(module: Module, expression: PsiExpression?): Boolean { val reference = expression as? PsiReferenceExpression ?: return false val field = reference.resolve() as? PsiField ?: return false - val mappedEmpty = field.findModule()?.getMappedField(EMPTY_SRG)?.name ?: "EMPTY" - return field.name == mappedEmpty && field.containingClass?.fullQualifiedName == STACK_FQ_NAME + val mappedEmpty = module.getMappedField(STACK_FQ_NAME, "EMPTY") + return field.name == mappedEmpty && + field.containingClass?.fullQualifiedName == module.getMappedClass(STACK_FQ_NAME) } } } - - private fun Module.getMappedMethod(reference: MemberReference): MemberReference? { - val srgManager = MinecraftFacet.getInstance(this, McpModuleType)?.srgManager - return srgManager?.srgMapNow?.mapToMcpMethod(reference) - } - - private fun Module.getMappedField(reference: MemberReference): MemberReference? { - val srgManager = MinecraftFacet.getInstance(this, McpModuleType)?.srgManager - return srgManager?.srgMapNow?.mapToMcpField(reference) - } } diff --git a/src/main/kotlin/platform/mcp/mappings/HardcodedYarnToMojmap.kt b/src/main/kotlin/platform/mcp/mappings/HardcodedYarnToMojmap.kt new file mode 100644 index 000000000..7dfd4ea7c --- /dev/null +++ b/src/main/kotlin/platform/mcp/mappings/HardcodedYarnToMojmap.kt @@ -0,0 +1,41 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2023 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.mappings + +import com.google.common.collect.ImmutableBiMap + +/** + * A temporary solution until we get something more dynamic sorted + */ +object HardcodedYarnToMojmap { + fun createMappings() = Mappings( + ImmutableBiMap.ofEntries( + "net.minecraft.item.ItemStack" mapTo "net.minecraft.world.item.ItemStack", + "net.minecraft.util.Formatting" mapTo "net.minecraft.ChatFormatting", + ), + ImmutableBiMap.ofEntries(), + ImmutableBiMap.ofEntries(), + hashMapOf(), + false, + ) + + private infix fun T.mapTo(value: T) = java.util.AbstractMap.SimpleEntry(this, value) +} diff --git a/src/main/kotlin/platform/mcp/mappings/HasCustomNamedMappings.kt b/src/main/kotlin/platform/mcp/mappings/HasCustomNamedMappings.kt new file mode 100644 index 000000000..f950859f5 --- /dev/null +++ b/src/main/kotlin/platform/mcp/mappings/HasCustomNamedMappings.kt @@ -0,0 +1,25 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2023 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.mappings + +interface HasCustomNamedMappings { + val namedToMojangManager: MappingsManager? +} diff --git a/src/main/kotlin/platform/mcp/mappings/Mappings.kt b/src/main/kotlin/platform/mcp/mappings/Mappings.kt new file mode 100644 index 000000000..f7240c79c --- /dev/null +++ b/src/main/kotlin/platform/mcp/mappings/Mappings.kt @@ -0,0 +1,134 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2023 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.mappings + +import com.demonwav.mcdev.facet.MinecraftFacet +import com.demonwav.mcdev.util.MemberReference +import com.demonwav.mcdev.util.descriptor +import com.demonwav.mcdev.util.fullQualifiedName +import com.demonwav.mcdev.util.mapFirstNotNull +import com.demonwav.mcdev.util.qualifiedMemberReference +import com.demonwav.mcdev.util.simpleQualifiedMemberReference +import com.google.common.collect.ImmutableBiMap +import com.intellij.openapi.module.Module +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiField +import com.intellij.psi.PsiMethod + +class Mappings( + val classMap: ImmutableBiMap, + val fieldMap: ImmutableBiMap, + val methodMap: ImmutableBiMap, + private val intermediaryNames: HashMap, + val containsFieldDescriptors: Boolean, +) { + fun getIntermediaryClass(fullQualifiedName: String) = classMap[fullQualifiedName] + fun getIntermediaryClass(psiClass: PsiClass): String? { + return getIntermediaryClass(psiClass.fullQualifiedName ?: return null) + } + + fun getIntermediaryField(reference: MemberReference) = fieldMap[reference] + fun getIntermediaryField(field: PsiField) = getIntermediaryField( + if (containsFieldDescriptors) { + field.qualifiedMemberReference + } else { + field.simpleQualifiedMemberReference + } + ) + + fun getIntermediaryMethod(reference: MemberReference) = methodMap[reference] + fun getIntermediaryMethod(method: PsiMethod) = getIntermediaryMethod(method.qualifiedMemberReference) + + fun tryGetMappedClass(fullQualifiedName: String) = classMap.inverse()[fullQualifiedName] + fun getMappedClass(fullQualifiedName: String) = tryGetMappedClass(fullQualifiedName) ?: fullQualifiedName + + fun tryGetMappedField(reference: MemberReference) = fieldMap.inverse()[reference] + fun getMappedField(reference: MemberReference) = tryGetMappedField(reference) ?: reference + fun tryGetMappedField(field: PsiField) = tryGetMappedField(field.qualifiedMemberReference) + + fun tryGetMappedMethod(reference: MemberReference) = methodMap.inverse()[reference] + fun getMappedMethod(reference: MemberReference) = tryGetMappedMethod(reference) ?: reference + fun tryGetMappedMethod(method: PsiMethod) = tryGetMappedMethod(method.qualifiedMemberReference) + + fun mapIntermediaryToMapped(name: String) = intermediaryNames[name] +} + +private val Module.namedToMojang: Mappings? get() { + val mcFacet = MinecraftFacet.getInstance(this) ?: return null + val manager = mcFacet.modules.filterIsInstance().mapFirstNotNull { it.namedToMojangManager } + ?: return null + return manager.mappingsNow?.takeUnless { it.containsFieldDescriptors } +} + +fun Module.getMappedClass(mojangName: String): String { + return namedToMojang?.getMappedClass(mojangName) ?: mojangName +} + +fun Module.getMojangClass(mappedName: String): String { + return namedToMojang?.getIntermediaryClass(mappedName) ?: mappedName +} + +fun Module.getMojangClass(clazz: PsiClass): String? { + return getMojangClass(clazz.fullQualifiedName ?: return null) +} + +fun Module.getMappedField(mojangField: MemberReference): String { + return namedToMojang?.tryGetMappedField(mojangField.withoutDescriptor)?.name ?: mojangField.name +} + +fun Module.getMappedField(mojangClass: String, mojangField: String): String { + return getMappedField(MemberReference(mojangField, null, mojangClass)) +} + +fun Module.getMojangField(mappedField: MemberReference): String { + return namedToMojang?.getIntermediaryField(mappedField.withoutDescriptor)?.name ?: mappedField.name +} + +fun Module.getMojangField(mappedClass: String, mappedField: String): String { + return getMojangField(MemberReference(mappedField, null, mappedClass)) +} + +fun Module.getMojangField(field: PsiField): String? { + val clazz = field.containingClass?.fullQualifiedName ?: return null + return getMojangField(clazz, field.name) +} + +fun Module.getMappedMethod(mojangMethod: MemberReference): String { + return namedToMojang?.tryGetMappedMethod(mojangMethod)?.name ?: return mojangMethod.name +} + +fun Module.getMappedMethod(mojangClass: String, mojangMethod: String, mojangDescriptor: String): String { + return getMappedMethod(MemberReference(mojangMethod, mojangDescriptor, mojangClass)) +} + +fun Module.getMojangMethod(mappedMethod: MemberReference): String { + return namedToMojang?.getIntermediaryMethod(mappedMethod)?.name ?: return mappedMethod.name +} + +fun Module.getMojangMethod(mappedClass: String, mappedMethod: String, mappedDescriptor: String): String { + return getMojangMethod(MemberReference(mappedMethod, mappedDescriptor, mappedClass)) +} + +fun Module.getMojangMethod(method: PsiMethod): String? { + val clazz = method.containingClass?.fullQualifiedName ?: return null + val descriptor = method.descriptor ?: return null + return getMojangMethod(clazz, method.name, descriptor) +} diff --git a/src/main/kotlin/platform/mcp/srg/SrgManager.kt b/src/main/kotlin/platform/mcp/mappings/MappingsManager.kt similarity index 52% rename from src/main/kotlin/platform/mcp/srg/SrgManager.kt rename to src/main/kotlin/platform/mcp/mappings/MappingsManager.kt index cf58d9f38..5f51fb41f 100644 --- a/src/main/kotlin/platform/mcp/srg/SrgManager.kt +++ b/src/main/kotlin/platform/mcp/mappings/MappingsManager.kt @@ -18,10 +18,11 @@ * along with this program. If not, see . */ -package com.demonwav.mcdev.platform.mcp.srg +package com.demonwav.mcdev.platform.mcp.mappings import com.demonwav.mcdev.facet.MinecraftFacet import com.demonwav.mcdev.platform.mcp.McpModuleType +import com.demonwav.mcdev.platform.mcp.srg.SrgType import com.demonwav.mcdev.util.mapFirstNotNull import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.project.Project @@ -33,53 +34,67 @@ import java.util.concurrent.TimeoutException import kotlin.io.path.absolutePathString import org.jetbrains.concurrency.Promise import org.jetbrains.concurrency.rejectedPromise +import org.jetbrains.concurrency.resolvedPromise import org.jetbrains.concurrency.runAsync -class SrgManager(val file: String, val srgType: SrgType) { - - var srgMap: Promise = rejectedPromise("SRG map not loaded") +abstract class MappingsManager { + var mappings: Promise = rejectedPromise("Mappings not loaded") @Synchronized get - private set + protected set - val srgMapNow: McpSrgMap? + val mappingsNow: Mappings? @Synchronized get() = try { - srgMap.blockingGet(1, TimeUnit.NANOSECONDS) + mappings.blockingGet(1, TimeUnit.NANOSECONDS) } catch (e: ExecutionException) { null } catch (e: TimeoutException) { null } - @Synchronized - fun parse() { - if (srgMap.state == Promise.State.PENDING) { - return - } - - srgMap = if (file.isNotBlank()) { - val path = Paths.get(file) - if (Files.notExists(path)) { - rejectedPromise("No mapping data available at " + path.absolutePathString()) - } else { - runAsync { - // Load SRG map from files - srgType.srgParser.parseSrg(Paths.get(file)) - } - } - } else { - // Path to SRG files is unknown - rejectedPromise("No mapping data available: file path is blank") - } - } + abstract fun parse() companion object { - private val map = HashMap() + private val map = HashMap() - fun getInstance(file: String, srgType: SrgType) = map.computeIfAbsent(file) { SrgManager(it, srgType) } + @Deprecated("This needs replacing with something that doesn't cause memory leaks") + fun getInstance(file: String, srgType: SrgType) = map.computeIfAbsent(file) { SrgMappingsManager(it, srgType) } fun findAnyInstance(project: Project) = ModuleManager.getInstance(project).modules.mapFirstNotNull { - MinecraftFacet.getInstance(it, McpModuleType)?.srgManager + MinecraftFacet.getInstance(it, McpModuleType)?.mappingsManager } } + + class Immediate(mappings: Mappings) : MappingsManager() { + init { + this.mappings = resolvedPromise(mappings) + } + + override fun parse() { + } + } + + private class SrgMappingsManager(val file: String, val srgType: SrgType) : MappingsManager() { + @Synchronized + override fun parse() { + if (mappings.state == Promise.State.PENDING) { + return + } + + mappings = if (file.isNotBlank()) { + val path = Paths.get(file) + if (Files.notExists(path)) { + rejectedPromise("No mapping data available at " + path.absolutePathString()) + } else { + runAsync { + // Load SRG map from files + srgType.srgParser.parseSrg(Paths.get(file)) + } + } + } else { + // Path to SRG files is unknown + rejectedPromise("No mapping data available: file path is blank") + } + } + } } diff --git a/src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt b/src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt index d63060425..eeab68949 100644 --- a/src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt +++ b/src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt @@ -22,7 +22,7 @@ package com.demonwav.mcdev.platform.mcp.navigation import com.demonwav.mcdev.facet.MinecraftFacet import com.demonwav.mcdev.platform.mcp.McpModuleType -import com.demonwav.mcdev.platform.mcp.srg.McpSrgMap +import com.demonwav.mcdev.platform.mcp.mappings.Mappings import com.demonwav.mcdev.util.MemberReference import com.intellij.navigation.ChooseByNameContributor import com.intellij.navigation.NavigationItem @@ -34,7 +34,7 @@ import com.intellij.psi.search.GlobalSearchScope class SrgMemberChooseByNameContributor : ChooseByNameContributor { // Cached between uses - var srgMap: McpSrgMap? = null + var srgMap: Mappings? = null var module: Module? = null override fun getNames(project: Project, includeNonProjectItems: Boolean): Array { @@ -47,7 +47,7 @@ class SrgMemberChooseByNameContributor : ChooseByNameContributor { val modules = ModuleManager.getInstance(project).modules for (module in modules) { val mcpModule = MinecraftFacet.getInstance(module, McpModuleType) ?: continue - srgMap = mcpModule.srgManager?.srgMapNow ?: continue + srgMap = mcpModule.mappingsManager?.mappingsNow ?: continue this.module = module break // for speed's sake, only use the first one found } diff --git a/src/main/kotlin/platform/mcp/srg/McpSrgMap.kt b/src/main/kotlin/platform/mcp/srg/McpSrgMap.kt deleted file mode 100644 index 1641a8310..000000000 --- a/src/main/kotlin/platform/mcp/srg/McpSrgMap.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Minecraft Development for IntelliJ - * - * https://mcdev.io/ - * - * Copyright (C) 2023 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.srg - -import com.demonwav.mcdev.util.MemberReference -import com.demonwav.mcdev.util.fullQualifiedName -import com.demonwav.mcdev.util.qualifiedMemberReference -import com.demonwav.mcdev.util.simpleQualifiedMemberReference -import com.google.common.collect.ImmutableBiMap -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiField -import com.intellij.psi.PsiMethod - -class McpSrgMap( - val classMap: ImmutableBiMap, - val fieldMap: ImmutableBiMap, - val methodMap: ImmutableBiMap, - private val srgNames: HashMap, -) { - fun getSrgClass(fullQualifiedName: String) = classMap[fullQualifiedName] - fun getSrgClass(psiClass: PsiClass): String? { - return getSrgClass(psiClass.fullQualifiedName ?: return null) - } - - fun getSrgField(reference: MemberReference) = fieldMap[reference] - fun getSrgField(field: PsiField) = getSrgField(field.simpleQualifiedMemberReference) - - fun getSrgMethod(reference: MemberReference) = methodMap[reference] - fun getSrgMethod(method: PsiMethod) = getSrgMethod(method.qualifiedMemberReference) - - fun getMcpClass(fullQualifiedName: String) = classMap.inverse()[fullQualifiedName] - fun mapToMcpClass(fullQualifiedName: String) = getMcpClass(fullQualifiedName) ?: fullQualifiedName - - fun getMcpField(reference: MemberReference) = fieldMap.inverse()[reference] - fun mapToMcpField(reference: MemberReference) = getMcpField(reference) ?: reference - fun findMcpField(field: PsiField) = getMcpField(field.qualifiedMemberReference) - - fun getMcpMethod(reference: MemberReference) = methodMap.inverse()[reference] - fun mapToMcpMethod(reference: MemberReference) = getMcpMethod(reference) ?: reference - fun findMcpMethod(method: PsiMethod) = getMcpMethod(method.qualifiedMemberReference) - - fun mapMcpToSrgName(name: String) = srgNames[name] -} diff --git a/src/main/kotlin/platform/mcp/srg/McpUnscrambler.kt b/src/main/kotlin/platform/mcp/srg/McpUnscrambler.kt index 8492e7d53..1ccb6e95b 100644 --- a/src/main/kotlin/platform/mcp/srg/McpUnscrambler.kt +++ b/src/main/kotlin/platform/mcp/srg/McpUnscrambler.kt @@ -20,6 +20,7 @@ package com.demonwav.mcdev.platform.mcp.srg +import com.demonwav.mcdev.platform.mcp.mappings.MappingsManager import com.intellij.openapi.project.Project import com.intellij.unscramble.UnscrambleSupport import javax.swing.JComponent @@ -31,7 +32,7 @@ class McpUnscrambler : UnscrambleSupport { override fun getPresentableName() = "Remap SRG names" override fun unscramble(project: Project, text: String, logName: String, settings: JComponent?): String? { - val srgMap = SrgManager.findAnyInstance(project)?.srgMapNow ?: return null - return srgPattern.replace(text) { srgMap.mapMcpToSrgName(it.value) ?: it.value } + val srgMap = MappingsManager.findAnyInstance(project)?.mappingsNow ?: return null + return srgPattern.replace(text) { srgMap.mapIntermediaryToMapped(it.value) ?: it.value } } } diff --git a/src/main/kotlin/platform/mcp/srg/SrgParser.kt b/src/main/kotlin/platform/mcp/srg/SrgParser.kt index 01de09af7..d7ea8d1b8 100644 --- a/src/main/kotlin/platform/mcp/srg/SrgParser.kt +++ b/src/main/kotlin/platform/mcp/srg/SrgParser.kt @@ -20,8 +20,9 @@ package com.demonwav.mcdev.platform.mcp.srg +import com.demonwav.mcdev.platform.mcp.mappings.Mappings import java.nio.file.Path interface SrgParser { - fun parseSrg(path: Path): McpSrgMap + fun parseSrg(path: Path): Mappings } diff --git a/src/main/kotlin/platform/mcp/srg/StandardSrgParser.kt b/src/main/kotlin/platform/mcp/srg/StandardSrgParser.kt index 7d3da40de..766a9a4a8 100644 --- a/src/main/kotlin/platform/mcp/srg/StandardSrgParser.kt +++ b/src/main/kotlin/platform/mcp/srg/StandardSrgParser.kt @@ -20,13 +20,14 @@ package com.demonwav.mcdev.platform.mcp.srg +import com.demonwav.mcdev.platform.mcp.mappings.Mappings import com.demonwav.mcdev.util.MemberReference import com.google.common.collect.ImmutableBiMap import java.nio.file.Files import java.nio.file.Path object StandardSrgParser : SrgParser { - override fun parseSrg(path: Path): McpSrgMap { + override fun parseSrg(path: Path): Mappings { val classMapBuilder = ImmutableBiMap.builder() val fieldMapBuilder = ImmutableBiMap.builder() val methodMapBuilder = ImmutableBiMap.builder() @@ -55,6 +56,6 @@ object StandardSrgParser : SrgParser { } } - return McpSrgMap(classMapBuilder.build(), fieldMapBuilder.build(), methodMapBuilder.build(), srgNames) + return Mappings(classMapBuilder.build(), fieldMapBuilder.build(), methodMapBuilder.build(), srgNames, false) } } diff --git a/src/main/kotlin/platform/mcp/srg/TinySrgParser.kt b/src/main/kotlin/platform/mcp/srg/TinySrgParser.kt index 139799cc9..2d5bc64be 100644 --- a/src/main/kotlin/platform/mcp/srg/TinySrgParser.kt +++ b/src/main/kotlin/platform/mcp/srg/TinySrgParser.kt @@ -20,6 +20,7 @@ package com.demonwav.mcdev.platform.mcp.srg +import com.demonwav.mcdev.platform.mcp.mappings.Mappings import com.demonwav.mcdev.util.MemberReference import com.google.common.collect.ImmutableBiMap import com.intellij.openapi.util.registry.Registry @@ -32,7 +33,7 @@ import net.fabricmc.mappingio.MappingVisitor object TinySrgParser : SrgParser { private val commentRegex = Regex("#.+") - override fun parseSrg(path: Path): McpSrgMap { + override fun parseSrg(path: Path): Mappings { val classMapBuilder = ImmutableBiMap.builder() val fieldMapBuilder = ImmutableBiMap.builder() val methodMapBuilder = ImmutableBiMap.builder() @@ -44,11 +45,12 @@ object TinySrgParser : SrgParser { oldParser(path, classMapBuilder, fieldMapBuilder, methodMapBuilder, srgNames) } - return McpSrgMap( + return Mappings( classMapBuilder.build(), fieldMapBuilder.build(), methodMapBuilder.build(), srgNames, + false, ) } diff --git a/src/main/kotlin/platform/mcp/util/McpConstants.kt b/src/main/kotlin/platform/mcp/util/McpConstants.kt index 98ef295d5..f04747a23 100644 --- a/src/main/kotlin/platform/mcp/util/McpConstants.kt +++ b/src/main/kotlin/platform/mcp/util/McpConstants.kt @@ -22,14 +22,7 @@ package com.demonwav.mcdev.platform.mcp.util object McpConstants { - const val TEXT_FORMATTING = "net.minecraft.util.text.TextFormatting" const val CHAT_FORMATTING = "net.minecraft.ChatFormatting" - const val ENTITY = "net.minecraft.entity.Entity" - const val ENTITY_FX = "net.minecraft.client.particle.EntityFX" - const val WORLD = "net.minecraft.world.World" - const val ITEM_STACK = "net.minecraft.item.ItemStack" - const val BLOCK = "net.minecraft.block.Block" - const val ITEM = "net.minecraft.item.Item" const val MINECRAFT_SERVER = "net.minecraft.server.MinecraftServer" const val PNG_MCMETA = "*.png.mcmeta" } diff --git a/src/main/kotlin/platform/mixin/handlers/mixinextras/MixinExtrasInjectorAnnotationHandler.kt b/src/main/kotlin/platform/mixin/handlers/mixinextras/MixinExtrasInjectorAnnotationHandler.kt index 2c16a9ac4..4214a0b18 100644 --- a/src/main/kotlin/platform/mixin/handlers/mixinextras/MixinExtrasInjectorAnnotationHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/mixinextras/MixinExtrasInjectorAnnotationHandler.kt @@ -21,6 +21,7 @@ package com.demonwav.mcdev.platform.mixin.handlers.mixinextras import com.demonwav.mcdev.platform.mixin.handlers.InjectorAnnotationHandler +import com.demonwav.mcdev.platform.mixin.handlers.injectionPoint.NewInsnInjectionPoint import com.demonwav.mcdev.platform.mixin.inspection.injector.MethodSignature import com.demonwav.mcdev.platform.mixin.inspection.injector.ParameterGroup import com.demonwav.mcdev.platform.mixin.util.FieldTargetMember @@ -219,7 +220,7 @@ abstract class MixinExtrasInjectorAnnotationHandler : InjectorAnnotationHandler( .resolveAsm(annotation.project) as? MethodTargetMember )?.classAndMethod val parameters = mutableListOf() - if (insn.opcode != Opcodes.INVOKESTATIC) { + if (insn.opcode != Opcodes.INVOKESTATIC && insn.name != "") { val receiver = if (insn.opcode == Opcodes.INVOKESPECIAL && !oldSuperBehavior) { targetClass.name } else { @@ -270,6 +271,10 @@ abstract class MixinExtrasInjectorAnnotationHandler : InjectorAnnotationHandler( Opcodes.INSTANCEOF -> listOf(Parameter("object", Type.getType(Any::class.java).toPsiType(elementFactory))) + Opcodes.NEW -> NewInsnInjectionPoint.findInitCall(insn)?.let { + getPsiParameters(it, targetClass, annotation) + } + else -> null } } diff --git a/src/main/kotlin/platform/mixin/handlers/mixinextras/WrapOperationHandler.kt b/src/main/kotlin/platform/mixin/handlers/mixinextras/WrapOperationHandler.kt index 76f215eb9..8dfd8e194 100644 --- a/src/main/kotlin/platform/mixin/handlers/mixinextras/WrapOperationHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/mixinextras/WrapOperationHandler.kt @@ -35,7 +35,8 @@ import org.objectweb.asm.tree.MethodNode class WrapOperationHandler : MixinExtrasInjectorAnnotationHandler() { override val supportedInstructionTypes = listOf( - InstructionType.METHOD_CALL, InstructionType.FIELD_GET, InstructionType.FIELD_SET, InstructionType.INSTANCEOF + InstructionType.METHOD_CALL, InstructionType.FIELD_GET, InstructionType.FIELD_SET, InstructionType.INSTANCEOF, + InstructionType.INSTANTIATION ) override fun getAtKey(annotation: PsiAnnotation): String { diff --git a/src/main/kotlin/translations/identification/TranslationIdentifier.kt b/src/main/kotlin/translations/identification/TranslationIdentifier.kt index 883504fe5..52be6f702 100644 --- a/src/main/kotlin/translations/identification/TranslationIdentifier.kt +++ b/src/main/kotlin/translations/identification/TranslationIdentifier.kt @@ -28,6 +28,7 @@ import com.demonwav.mcdev.util.constantStringValue import com.demonwav.mcdev.util.constantValue import com.demonwav.mcdev.util.extractVarArgs import com.demonwav.mcdev.util.referencedMethod +import com.intellij.codeInsight.AnnotationUtil import com.intellij.codeInspection.dataFlow.CommonDataflow import com.intellij.openapi.project.Project import com.intellij.psi.CommonClassNames @@ -68,8 +69,8 @@ abstract class TranslationIdentifier { val method = call.referencedMethod ?: return null val parameter = method.parameterList.getParameter(index) ?: return null - val translatableAnnotation = parameter.getAnnotation(TranslationConstants.TRANSLATABLE_ANNOTATION) - ?: return null + val translatableAnnotation = + AnnotationUtil.findAnnotation(parameter, TranslationConstants.TRANSLATABLE_ANNOTATION) ?: return null val prefix = translatableAnnotation.findAttributeValue(TranslationConstants.PREFIX)?.constantStringValue ?: "" diff --git a/src/main/kotlin/update/ConfigurePluginUpdatesDialog.kt b/src/main/kotlin/update/ConfigurePluginUpdatesDialog.kt index 09526983f..bec37f179 100644 --- a/src/main/kotlin/update/ConfigurePluginUpdatesDialog.kt +++ b/src/main/kotlin/update/ConfigurePluginUpdatesDialog.kt @@ -91,8 +91,6 @@ class ConfigurePluginUpdatesDialog : DialogWrapper(true) { channelBox.component.addItem(channels.title) } - channelBox.component.selectedIndex = initialSelectedChannel - Channels.values().forEachIndexed { i, channel -> if (channel.hasChannel()) { initialSelectedChannel = i + 1 @@ -100,6 +98,8 @@ class ConfigurePluginUpdatesDialog : DialogWrapper(true) { } } + channelBox.component.selectedIndex = initialSelectedChannel + channelBox.component.addActionListener { resetUpdateStatus() } updateCheckInProgressIcon.component.isVisible = false init() diff --git a/src/main/kotlin/util/MemberReference.kt b/src/main/kotlin/util/MemberReference.kt index bbc5ab857..bc07c01eb 100644 --- a/src/main/kotlin/util/MemberReference.kt +++ b/src/main/kotlin/util/MemberReference.kt @@ -47,11 +47,18 @@ data class MemberReference( assert(owner?.contains('/') != true) } + val withoutDescriptor + get() = if (this.descriptor == null) { + this + } else { + copy(descriptor = null) + } + val withoutOwner get() = if (this.owner == null) { this } else { - MemberReference(this.name, this.descriptor, null, this.matchAllNames, this.matchAllDescs) + copy(owner = null) } override val methodDescriptor = descriptor?.takeIf { it.contains("(") }