User: joseph burton Date: 26 Sep 23 22:32 Revision: 2cc2f48dc83075dd1ccef75bf48940a7587ba623 Summary: Placeholder mappings API (#2135) TeamCity URL: http://ci.mcdev.io:80/viewModification.html?tab=vcsModificationFiles&modId=8807&personal=false Index: src/main/kotlin/facet/MinecraftFacet.kt =================================================================== --- src/main/kotlin/facet/MinecraftFacet.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/facet/MinecraftFacet.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -114,6 +114,7 @@ } newlyEnabled.forEach(AbstractModule::init) + modules.forEach(AbstractModule::refresh) ProjectView.getInstance(module.project).refresh() } Index: src/main/kotlin/platform/AbstractModule.kt =================================================================== --- src/main/kotlin/platform/AbstractModule.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/AbstractModule.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -93,4 +93,5 @@ open fun init() {} open fun dispose() {} + open fun refresh() {} } Index: src/main/kotlin/platform/fabric/FabricModule.kt =================================================================== --- src/main/kotlin/platform/fabric/FabricModule.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/fabric/FabricModule.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -26,6 +26,10 @@ 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.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 @@ 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 Index: src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt =================================================================== --- src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -67,9 +67,9 @@ ?: 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 { Index: src/main/kotlin/platform/forge/reflection/reference/ReflectedMemberReferenceBasePoly.kt =================================================================== --- src/main/kotlin/platform/forge/reflection/reference/ReflectedMemberReferenceBasePoly.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/forge/reflection/reference/ReflectedMemberReferenceBasePoly.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -49,9 +49,9 @@ 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 } Index: src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt =================================================================== --- src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -74,8 +74,8 @@ ?: 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 @@ .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 Index: src/main/kotlin/platform/mcp/McpModule.kt =================================================================== --- src/main/kotlin/platform/mcp/McpModule.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/McpModule.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -23,7 +23,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ connection.disconnect() accessTransformers.clear() - srgManager = null + mappingsManager = null } } Index: src/main/kotlin/platform/mcp/actions/CopyAtAction.kt =================================================================== --- src/main/kotlin/platform/mcp/actions/CopyAtAction.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/actions/CopyAtAction.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -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.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 @@ } 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 @@ ) } 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) Index: src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt =================================================================== --- src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -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.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 @@ } 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 @@ ) } 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, Index: src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt =================================================================== --- src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -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 @@ 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) Index: src/main/kotlin/platform/mcp/actions/GotoAtEntryAction.kt =================================================================== --- src/main/kotlin/platform/mcp/actions/GotoAtEntryAction.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/actions/GotoAtEntryAction.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -22,7 +22,7 @@ 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 @@ -56,12 +56,12 @@ 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) { @@ -73,11 +73,11 @@ 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 -> Index: src/main/kotlin/platform/mcp/actions/SrgActionBase.kt =================================================================== --- src/main/kotlin/platform/mcp/actions/SrgActionBase.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/actions/SrgActionBase.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -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 @@ -53,7 +53,7 @@ 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) { @@ -73,7 +73,7 @@ } ?: 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) { Index: src/main/kotlin/platform/mcp/at/AtAnnotator.kt =================================================================== --- src/main/kotlin/platform/mcp/at/AtAnnotator.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/at/AtAnnotator.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -47,7 +47,7 @@ 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 @@ // 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) } } Index: src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt =================================================================== --- src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -55,12 +55,12 @@ 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 @@ 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 @@ 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) } Index: src/main/kotlin/platform/mcp/at/AtUsageInspection.kt =================================================================== --- src/main/kotlin/platform/mcp/at/AtUsageInspection.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/at/AtUsageInspection.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -50,19 +50,19 @@ 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 } Index: src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt =================================================================== --- src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -221,7 +221,7 @@ 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 @@ continue } - val memberReference = srgMap.getSrgField(field) ?: field.simpleQualifiedMemberReference + val memberReference = srgMap.getIntermediaryField(field) ?: field.simpleQualifiedMemberReference srgResult.addElement( PrioritizedLookupElement.withPriority( LookupElementBuilder @@ -263,7 +263,7 @@ continue } - val memberReference = srgMap.getSrgMethod(method) ?: method.qualifiedMemberReference + val memberReference = srgMap.getIntermediaryMethod(method) ?: method.qualifiedMemberReference srgResult.addElement( PrioritizedLookupElement.withPriority( LookupElementBuilder.create(method.nameAndParameterTypes) Index: src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt =================================================================== --- src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -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.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 @@ 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 @@ 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 @@ } } - 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) - } -} Index: src/main/kotlin/platform/mcp/mappings/HardcodedYarnToMojmap.kt =================================================================== --- src/main/kotlin/platform/mcp/mappings/HardcodedYarnToMojmap.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) +++ src/main/kotlin/platform/mcp/mappings/HardcodedYarnToMojmap.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -0,0 +1,40 @@ +/* + * 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" + ), + ImmutableBiMap.ofEntries(), + ImmutableBiMap.ofEntries(), + hashMapOf(), + false, + ) + + private infix fun T.mapTo(value: T) = java.util.AbstractMap.SimpleEntry(this, value) +} Index: src/main/kotlin/platform/mcp/mappings/HasCustomNamedMappings.kt =================================================================== --- src/main/kotlin/platform/mcp/mappings/HasCustomNamedMappings.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) +++ src/main/kotlin/platform/mcp/mappings/HasCustomNamedMappings.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -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? +} Index: src/main/kotlin/platform/mcp/mappings/Mappings.kt =================================================================== --- src/main/kotlin/platform/mcp/mappings/Mappings.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) +++ src/main/kotlin/platform/mcp/mappings/Mappings.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -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) +} Index: src/main/kotlin/platform/mcp/mappings/MappingsManager.kt =================================================================== --- src/main/kotlin/platform/mcp/mappings/MappingsManager.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) +++ src/main/kotlin/platform/mcp/mappings/MappingsManager.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -0,0 +1,100 @@ +/* + * 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.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 +import java.nio.file.Files +import java.nio.file.Paths +import java.util.concurrent.ExecutionException +import java.util.concurrent.TimeUnit +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 + +abstract class MappingsManager { + var mappings: Promise = rejectedPromise("Mappings not loaded") + @Synchronized get + protected set + + val mappingsNow: Mappings? + @Synchronized get() = try { + mappings.blockingGet(1, TimeUnit.NANOSECONDS) + } catch (e: ExecutionException) { + null + } catch (e: TimeoutException) { + null + } + + abstract fun parse() + + companion object { + private val map = HashMap() + + @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)?.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") + } + } + } +} Index: src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt =================================================================== --- src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -22,7 +22,7 @@ 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 @@ 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 @@ 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 } Index: src/main/kotlin/platform/mcp/srg/McpSrgMap.kt =================================================================== --- src/main/kotlin/platform/mcp/srg/McpSrgMap.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/srg/McpSrgMap.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) @@ -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] -} Index: src/main/kotlin/platform/mcp/srg/McpUnscrambler.kt =================================================================== --- src/main/kotlin/platform/mcp/srg/McpUnscrambler.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/srg/McpUnscrambler.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -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 @@ 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 } } } Index: src/main/kotlin/platform/mcp/srg/SrgManager.kt =================================================================== --- src/main/kotlin/platform/mcp/srg/SrgManager.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/srg/SrgManager.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) @@ -1,85 +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.facet.MinecraftFacet -import com.demonwav.mcdev.platform.mcp.McpModuleType -import com.demonwav.mcdev.util.mapFirstNotNull -import com.intellij.openapi.module.ModuleManager -import com.intellij.openapi.project.Project -import java.nio.file.Files -import java.nio.file.Paths -import java.util.concurrent.ExecutionException -import java.util.concurrent.TimeUnit -import java.util.concurrent.TimeoutException -import kotlin.io.path.absolutePathString -import org.jetbrains.concurrency.Promise -import org.jetbrains.concurrency.rejectedPromise -import org.jetbrains.concurrency.runAsync - -class SrgManager(val file: String, val srgType: SrgType) { - - var srgMap: Promise = rejectedPromise("SRG map not loaded") - @Synchronized get - private set - - val srgMapNow: McpSrgMap? - @Synchronized get() = try { - srgMap.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") - } - } - - companion object { - private val map = HashMap() - - fun getInstance(file: String, srgType: SrgType) = map.computeIfAbsent(file) { SrgManager(it, srgType) } - - fun findAnyInstance(project: Project) = - ModuleManager.getInstance(project).modules.mapFirstNotNull { - MinecraftFacet.getInstance(it, McpModuleType)?.srgManager - } - } -} Index: src/main/kotlin/platform/mcp/srg/SrgParser.kt =================================================================== --- src/main/kotlin/platform/mcp/srg/SrgParser.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/srg/SrgParser.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -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 } Index: src/main/kotlin/platform/mcp/srg/StandardSrgParser.kt =================================================================== --- src/main/kotlin/platform/mcp/srg/StandardSrgParser.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/srg/StandardSrgParser.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -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 @@ } } - return McpSrgMap(classMapBuilder.build(), fieldMapBuilder.build(), methodMapBuilder.build(), srgNames) + return Mappings(classMapBuilder.build(), fieldMapBuilder.build(), methodMapBuilder.build(), srgNames, false) } } Index: src/main/kotlin/platform/mcp/srg/TinySrgParser.kt =================================================================== --- src/main/kotlin/platform/mcp/srg/TinySrgParser.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/platform/mcp/srg/TinySrgParser.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -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 @@ 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 @@ oldParser(path, classMapBuilder, fieldMapBuilder, methodMapBuilder, srgNames) } - return McpSrgMap( + return Mappings( classMapBuilder.build(), fieldMapBuilder.build(), methodMapBuilder.build(), srgNames, + false, ) } Index: src/main/kotlin/util/MemberReference.kt =================================================================== --- src/main/kotlin/util/MemberReference.kt (revision 44be6035e108d2f28cd185494856420ac6dc0613) +++ src/main/kotlin/util/MemberReference.kt (revision 2cc2f48dc83075dd1ccef75bf48940a7587ba623) @@ -47,11 +47,18 @@ 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("(") }