Skip to content

Commit 1d86aa7

Browse files
committed
Treat parameter locals as named on Fabric mixin >= 0.17.0
1 parent 3f627fa commit 1d86aa7

File tree

4 files changed

+61
-9
lines changed

4 files changed

+61
-9
lines changed

src/main/kotlin/platform/mixin/expression/MEExpressionCompletionUtil.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import com.demonwav.mcdev.platform.mixin.util.MethodTargetMember
5757
import com.demonwav.mcdev.platform.mixin.util.MixinConstants
5858
import com.demonwav.mcdev.platform.mixin.util.SignatureToPsi
5959
import com.demonwav.mcdev.platform.mixin.util.canonicalName
60+
import com.demonwav.mcdev.platform.mixin.util.fabricMixinCompatibility
6061
import com.demonwav.mcdev.platform.mixin.util.hasAccess
6162
import com.demonwav.mcdev.platform.mixin.util.hasNamedLocalVariables
6263
import com.demonwav.mcdev.platform.mixin.util.isPrimitive
@@ -92,6 +93,7 @@ import com.intellij.openapi.command.CommandProcessor
9293
import com.intellij.openapi.command.WriteCommandAction
9394
import com.intellij.openapi.editor.Editor
9495
import com.intellij.openapi.editor.FoldRegion
96+
import com.intellij.openapi.module.Module
9597
import com.intellij.openapi.project.Project
9698
import com.intellij.openapi.util.text.StringUtil
9799
import com.intellij.patterns.PlatformPatterns
@@ -302,6 +304,7 @@ object MEExpressionCompletionUtil {
302304
.flatMap { methodTarget ->
303305
getCompletionVariantsFromBytecode(
304306
project,
307+
module,
305308
mixinClass,
306309
cursorOffset,
307310
statement.copy() as MEStatement,
@@ -315,6 +318,7 @@ object MEExpressionCompletionUtil {
315318

316319
private fun getCompletionVariantsFromBytecode(
317320
project: Project,
321+
module: Module,
318322
mixinClass: PsiClass,
319323
cursorOffsetIn: Int,
320324
statement: MEStatement,
@@ -523,6 +527,7 @@ object MEExpressionCompletionUtil {
523527
val eliminableResults = cursorInstructions.flatMap { insn ->
524528
getCompletionsForInstruction(
525529
project,
530+
module,
526531
targetClass,
527532
targetMethod,
528533
insn.insn,
@@ -692,6 +697,7 @@ object MEExpressionCompletionUtil {
692697

693698
private fun getCompletionsForInstruction(
694699
project: Project,
700+
module: Module,
695701
targetClass: ClassNode,
696702
targetMethod: MethodNode,
697703
insn: VirtualInsn,
@@ -719,6 +725,7 @@ object MEExpressionCompletionUtil {
719725
}
720726
is VarInsnNode -> return createLocalVariableLookups(
721727
project,
728+
module,
722729
targetClass,
723730
targetMethod,
724731
originalInsn,
@@ -728,6 +735,7 @@ object MEExpressionCompletionUtil {
728735
)
729736
is IincInsnNode -> return createLocalVariableLookups(
730737
project,
738+
module,
731739
targetClass,
732740
targetMethod,
733741
originalInsn,
@@ -952,6 +960,7 @@ object MEExpressionCompletionUtil {
952960

953961
private fun createLocalVariableLookups(
954962
project: Project,
963+
module: Module,
955964
targetClass: ClassNode,
956965
targetMethod: MethodNode,
957966
originalInsn: AbstractInsnNode,
@@ -994,6 +1003,8 @@ object MEExpressionCompletionUtil {
9941003
val elementFactory = JavaPsiFacade.getElementFactory(project)
9951004
val hasNamedLocalVariables = mixinClass.hasNamedLocalVariables(targetClass.name.replace('/', '.'))
9961005

1006+
val hasNamedArguments = module.fabricMixinCompatibility?.let { it >= 17000 } == true
1007+
9971008
return locals.map { localVariable ->
9981009
val localPsiType = if (localVariable.signature != null) {
9991010
val sigToPsi = SignatureToPsi(elementFactory, mixinClass)
@@ -1006,7 +1017,7 @@ object MEExpressionCompletionUtil {
10061017
val ordinal = localsOfMyType.indexOf(localVariable)
10071018
val mixinLocalName = localVariable.name.takeIf {
10081019
// Don't complete to names for arguments to workaround FabricMC/Mixin#189
1009-
!isArgsOnly && hasNamedLocalVariables
1020+
(!isArgsOnly || hasNamedArguments) && hasNamedLocalVariables
10101021
}
10111022
val isImplicit = localsOfMyType.size == 1
10121023
val localName = localVariable.name.toValidIdentifier()

src/main/kotlin/platform/mixin/util/LocalInfo.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,27 @@ class LocalInfo(
5353
): Array<LocalVariables.LocalVariable?>? {
5454
return if (argsOnly) {
5555
val args = mutableListOf<LocalVariables.LocalVariable?>()
56+
var index = 0
5657
if (!methodNode.hasAccess(Opcodes.ACC_STATIC)) {
5758
val thisDesc = Type.getObjectType(targetClass.name).descriptor
5859
args.add(LocalVariables.LocalVariable("this", thisDesc, null, null, null, 0))
60+
index++
5961
}
6062
for (argType in Type.getArgumentTypes(methodNode.desc)) {
63+
val hasNamedArguments = module.fabricMixinCompatibility?.let { it >= 17000 } == true
64+
val localName = methodNode.localVariables?.getOrNull(index)?.name
65+
val name = if (localName != null && hasNamedArguments) {
66+
localName
67+
} else {
68+
"arg${args.size}"
69+
}
6170
args.add(
62-
LocalVariables.LocalVariable("arg${args.size}", argType.descriptor, null, null, null, args.size, isNamed = false),
71+
LocalVariables.LocalVariable(name, argType.descriptor, null, null, null, args.size, isNamed = hasNamedArguments),
6372
)
6473
if (argType.size == 2) {
6574
args.add(null)
6675
}
76+
index++
6777
}
6878
args.toTypedArray()
6979
} else {

src/main/kotlin/platform/mixin/util/LocalVariables.kt

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -412,10 +412,10 @@ object LocalVariables {
412412
private val resurrectLocalsChange = SemanticVersion.release(0, 8, 3)
413413
private fun detectCurrentSettings(module: Module): Settings? {
414414
val mixinVersion = module.mixinVersion ?: return null
415-
return if (mixinVersion < resurrectLocalsChange) {
416-
Settings.NO_RESURRECT
417-
} else {
418-
Settings.DEFAULT
415+
return when {
416+
mixinVersion < resurrectLocalsChange -> Settings.NO_RESURRECT
417+
module.fabricMixinCompatibility?.let { it >= 17000 } != true -> Settings.NO_NAMED_PARAMETERS
418+
else -> Settings.DEFAULT
419419
}
420420
}
421421

@@ -441,16 +441,23 @@ object LocalVariables {
441441
val frames = method.instructions.iterator().asSequence().filterIsInstance<FrameNode>().toList()
442442
val frame = arrayOfNulls<LocalVariable>(method.maxLocals)
443443
var local = 0
444-
var index = 0
444+
var staticOffset = 0
445445

446446
// Initialise implicit "this" reference in non-static methods
447447
if (!method.hasAccess(Opcodes.ACC_STATIC)) {
448448
frame[local++] = LocalVariable("this", Type.getObjectType(classNode.name).toString(), null, null, null, 0)
449+
staticOffset = 1
449450
}
450451

451452
// Initialise method arguments
452-
for (argType in Type.getArgumentTypes(method.desc)) {
453-
frame[local] = LocalVariable("arg" + index++, argType.toString(), null, null, null, local, isNamed = false)
453+
for ((index, argType) in Type.getArgumentTypes(method.desc).withIndex()) {
454+
val localName = method.localVariables?.getOrNull(index + staticOffset)?.name
455+
val name = if (localName == null || !settings.namedParameters) {
456+
"arg$index"
457+
} else {
458+
localName
459+
}
460+
frame[local] = LocalVariable(name, argType.toString(), null, null, null, local, isNamed = localName != null && settings.namedParameters)
454461
local += argType.size
455462
}
456463

@@ -836,6 +843,7 @@ object LocalVariables {
836843
val resurrectExposedOnLoad: Boolean,
837844
val resurrectExposedOnStore: Boolean,
838845
val resurrectForBogusTop: Boolean,
846+
val namedParameters: Boolean,
839847
) {
840848
companion object {
841849
val NO_RESURRECT = Settings(
@@ -846,6 +854,18 @@ object LocalVariables {
846854
resurrectExposedOnLoad = false,
847855
resurrectExposedOnStore = false,
848856
resurrectForBogusTop = false,
857+
namedParameters = false,
858+
)
859+
860+
val NO_NAMED_PARAMETERS = Settings(
861+
choppedInsnThreshold = -1,
862+
choppedFrameThreshold = 1,
863+
trimmedInsnThreshold = -1,
864+
trimmedFrameThreshold = -1,
865+
resurrectExposedOnLoad = true,
866+
resurrectExposedOnStore = true,
867+
resurrectForBogusTop = true,
868+
namedParameters = false,
849869
)
850870

851871
val DEFAULT = Settings(
@@ -856,6 +876,7 @@ object LocalVariables {
856876
resurrectExposedOnLoad = true,
857877
resurrectExposedOnStore = true,
858878
resurrectForBogusTop = true,
879+
namedParameters = true,
859880
)
860881
}
861882
}

src/main/kotlin/platform/mixin/util/Mixin.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import com.demonwav.mcdev.platform.mixin.util.MixinConstants.MixinExtras.OPERATI
3131
import com.demonwav.mcdev.util.SemanticVersion
3232
import com.demonwav.mcdev.util.cached
3333
import com.demonwav.mcdev.util.computeStringArray
34+
import com.demonwav.mcdev.util.constantValue
3435
import com.demonwav.mcdev.util.findModule
3536
import com.demonwav.mcdev.util.resolveClassArray
3637
import com.intellij.openapi.module.Module
@@ -290,6 +291,15 @@ private fun isClassAssignable(leftClass: PsiClass, rightClass: PsiClass): Boolea
290291
val PsiElement.isFabricMixin: Boolean get() =
291292
JavaPsiFacade.getInstance(project).findClass(MixinConstants.Classes.FABRIC_UTIL, resolveScope) != null
292293

294+
val Module.fabricMixinCompatibility: Int?
295+
get() {
296+
val facade = JavaPsiFacade.getInstance(project)
297+
val fabricUtil = facade.findClass(MixinConstants.Classes.FABRIC_UTIL, moduleWithLibrariesScope)
298+
?: return null
299+
val compatibilityLatestField = fabricUtil.findFieldByName("COMPATIBILITY_LATEST", false) ?: return null
300+
return compatibilityLatestField.initializer?.constantValue as? Int
301+
}
302+
293303
val Module.mixinVersion: SemanticVersion?
294304
get() {
295305
val facade = JavaPsiFacade.getInstance(project)

0 commit comments

Comments
 (0)