User: joe Date: 23 Dec 25 23:06 Revision: 1d86aa7f7337ec725bb3d6178b7dde3f1024a393 Summary: Treat parameter locals as named on Fabric mixin >= 0.17.0 TeamCity URL: http://ci.mcdev.io:80/viewModification.html?tab=vcsModificationFiles&modId=10373&personal=false Index: src/main/kotlin/platform/mixin/expression/MEExpressionCompletionUtil.kt =================================================================== --- src/main/kotlin/platform/mixin/expression/MEExpressionCompletionUtil.kt (revision 3f627fad91eff95a3927b9a790d9575b7a9221c6) +++ src/main/kotlin/platform/mixin/expression/MEExpressionCompletionUtil.kt (revision 1d86aa7f7337ec725bb3d6178b7dde3f1024a393) @@ -57,6 +57,7 @@ import com.demonwav.mcdev.platform.mixin.util.MixinConstants import com.demonwav.mcdev.platform.mixin.util.SignatureToPsi import com.demonwav.mcdev.platform.mixin.util.canonicalName +import com.demonwav.mcdev.platform.mixin.util.fabricMixinCompatibility import com.demonwav.mcdev.platform.mixin.util.hasAccess import com.demonwav.mcdev.platform.mixin.util.hasNamedLocalVariables import com.demonwav.mcdev.platform.mixin.util.isPrimitive @@ -92,6 +93,7 @@ import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.FoldRegion +import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project import com.intellij.openapi.util.text.StringUtil import com.intellij.patterns.PlatformPatterns @@ -302,6 +304,7 @@ .flatMap { methodTarget -> getCompletionVariantsFromBytecode( project, + module, mixinClass, cursorOffset, statement.copy() as MEStatement, @@ -315,6 +318,7 @@ private fun getCompletionVariantsFromBytecode( project: Project, + module: Module, mixinClass: PsiClass, cursorOffsetIn: Int, statement: MEStatement, @@ -523,6 +527,7 @@ val eliminableResults = cursorInstructions.flatMap { insn -> getCompletionsForInstruction( project, + module, targetClass, targetMethod, insn.insn, @@ -692,6 +697,7 @@ private fun getCompletionsForInstruction( project: Project, + module: Module, targetClass: ClassNode, targetMethod: MethodNode, insn: VirtualInsn, @@ -719,6 +725,7 @@ } is VarInsnNode -> return createLocalVariableLookups( project, + module, targetClass, targetMethod, originalInsn, @@ -728,6 +735,7 @@ ) is IincInsnNode -> return createLocalVariableLookups( project, + module, targetClass, targetMethod, originalInsn, @@ -952,6 +960,7 @@ private fun createLocalVariableLookups( project: Project, + module: Module, targetClass: ClassNode, targetMethod: MethodNode, originalInsn: AbstractInsnNode, @@ -994,6 +1003,8 @@ val elementFactory = JavaPsiFacade.getElementFactory(project) val hasNamedLocalVariables = mixinClass.hasNamedLocalVariables(targetClass.name.replace('/', '.')) + val hasNamedArguments = module.fabricMixinCompatibility?.let { it >= 17000 } == true + return locals.map { localVariable -> val localPsiType = if (localVariable.signature != null) { val sigToPsi = SignatureToPsi(elementFactory, mixinClass) @@ -1006,7 +1017,7 @@ val ordinal = localsOfMyType.indexOf(localVariable) val mixinLocalName = localVariable.name.takeIf { // Don't complete to names for arguments to workaround FabricMC/Mixin#189 - !isArgsOnly && hasNamedLocalVariables + (!isArgsOnly || hasNamedArguments) && hasNamedLocalVariables } val isImplicit = localsOfMyType.size == 1 val localName = localVariable.name.toValidIdentifier() Index: src/main/kotlin/platform/mixin/util/LocalInfo.kt =================================================================== --- src/main/kotlin/platform/mixin/util/LocalInfo.kt (revision 3f627fad91eff95a3927b9a790d9575b7a9221c6) +++ src/main/kotlin/platform/mixin/util/LocalInfo.kt (revision 1d86aa7f7337ec725bb3d6178b7dde3f1024a393) @@ -53,17 +53,27 @@ ): Array? { return if (argsOnly) { val args = mutableListOf() + var index = 0 if (!methodNode.hasAccess(Opcodes.ACC_STATIC)) { val thisDesc = Type.getObjectType(targetClass.name).descriptor args.add(LocalVariables.LocalVariable("this", thisDesc, null, null, null, 0)) + index++ } for (argType in Type.getArgumentTypes(methodNode.desc)) { + val hasNamedArguments = module.fabricMixinCompatibility?.let { it >= 17000 } == true + val localName = methodNode.localVariables?.getOrNull(index)?.name + val name = if (localName != null && hasNamedArguments) { + localName + } else { + "arg${args.size}" + } args.add( - LocalVariables.LocalVariable("arg${args.size}", argType.descriptor, null, null, null, args.size, isNamed = false), + LocalVariables.LocalVariable(name, argType.descriptor, null, null, null, args.size, isNamed = hasNamedArguments), ) if (argType.size == 2) { args.add(null) } + index++ } args.toTypedArray() } else { Index: src/main/kotlin/platform/mixin/util/LocalVariables.kt =================================================================== --- src/main/kotlin/platform/mixin/util/LocalVariables.kt (revision 3f627fad91eff95a3927b9a790d9575b7a9221c6) +++ src/main/kotlin/platform/mixin/util/LocalVariables.kt (revision 1d86aa7f7337ec725bb3d6178b7dde3f1024a393) @@ -412,10 +412,10 @@ private val resurrectLocalsChange = SemanticVersion.release(0, 8, 3) private fun detectCurrentSettings(module: Module): Settings? { val mixinVersion = module.mixinVersion ?: return null - return if (mixinVersion < resurrectLocalsChange) { - Settings.NO_RESURRECT - } else { - Settings.DEFAULT + return when { + mixinVersion < resurrectLocalsChange -> Settings.NO_RESURRECT + module.fabricMixinCompatibility?.let { it >= 17000 } != true -> Settings.NO_NAMED_PARAMETERS + else -> Settings.DEFAULT } } @@ -441,16 +441,23 @@ val frames = method.instructions.iterator().asSequence().filterIsInstance().toList() val frame = arrayOfNulls(method.maxLocals) var local = 0 - var index = 0 + var staticOffset = 0 // Initialise implicit "this" reference in non-static methods if (!method.hasAccess(Opcodes.ACC_STATIC)) { frame[local++] = LocalVariable("this", Type.getObjectType(classNode.name).toString(), null, null, null, 0) + staticOffset = 1 } // Initialise method arguments - for (argType in Type.getArgumentTypes(method.desc)) { - frame[local] = LocalVariable("arg" + index++, argType.toString(), null, null, null, local, isNamed = false) + for ((index, argType) in Type.getArgumentTypes(method.desc).withIndex()) { + val localName = method.localVariables?.getOrNull(index + staticOffset)?.name + val name = if (localName == null || !settings.namedParameters) { + "arg$index" + } else { + localName + } + frame[local] = LocalVariable(name, argType.toString(), null, null, null, local, isNamed = localName != null && settings.namedParameters) local += argType.size } @@ -836,6 +843,7 @@ val resurrectExposedOnLoad: Boolean, val resurrectExposedOnStore: Boolean, val resurrectForBogusTop: Boolean, + val namedParameters: Boolean, ) { companion object { val NO_RESURRECT = Settings( @@ -846,8 +854,20 @@ resurrectExposedOnLoad = false, resurrectExposedOnStore = false, resurrectForBogusTop = false, + namedParameters = false, ) + val NO_NAMED_PARAMETERS = Settings( + choppedInsnThreshold = -1, + choppedFrameThreshold = 1, + trimmedInsnThreshold = -1, + trimmedFrameThreshold = -1, + resurrectExposedOnLoad = true, + resurrectExposedOnStore = true, + resurrectForBogusTop = true, + namedParameters = false, + ) + val DEFAULT = Settings( choppedInsnThreshold = -1, choppedFrameThreshold = 1, @@ -856,6 +876,7 @@ resurrectExposedOnLoad = true, resurrectExposedOnStore = true, resurrectForBogusTop = true, + namedParameters = true, ) } } Index: src/main/kotlin/platform/mixin/util/Mixin.kt =================================================================== --- src/main/kotlin/platform/mixin/util/Mixin.kt (revision 3f627fad91eff95a3927b9a790d9575b7a9221c6) +++ src/main/kotlin/platform/mixin/util/Mixin.kt (revision 1d86aa7f7337ec725bb3d6178b7dde3f1024a393) @@ -31,6 +31,7 @@ import com.demonwav.mcdev.util.SemanticVersion import com.demonwav.mcdev.util.cached import com.demonwav.mcdev.util.computeStringArray +import com.demonwav.mcdev.util.constantValue import com.demonwav.mcdev.util.findModule import com.demonwav.mcdev.util.resolveClassArray import com.intellij.openapi.module.Module @@ -290,6 +291,15 @@ val PsiElement.isFabricMixin: Boolean get() = JavaPsiFacade.getInstance(project).findClass(MixinConstants.Classes.FABRIC_UTIL, resolveScope) != null +val Module.fabricMixinCompatibility: Int? + get() { + val facade = JavaPsiFacade.getInstance(project) + val fabricUtil = facade.findClass(MixinConstants.Classes.FABRIC_UTIL, moduleWithLibrariesScope) + ?: return null + val compatibilityLatestField = fabricUtil.findFieldByName("COMPATIBILITY_LATEST", false) ?: return null + return compatibilityLatestField.initializer?.constantValue as? Int + } + val Module.mixinVersion: SemanticVersion? get() { val facade = JavaPsiFacade.getInstance(project)