Skip to content

Commit ebd872a

Browse files
committed
Support remapping getDeclaredMethod
1 parent 52a634a commit ebd872a

File tree

1 file changed

+71
-13
lines changed

1 file changed

+71
-13
lines changed

bukkit/src/main/kotlin/io/github/rothes/esu/bukkit/util/version/remapper/transformer/ReflectionTransformer.kt

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ package io.github.rothes.esu.bukkit.util.version.remapper.transformer
33
import net.neoforged.srgutils.IMappingFile
44
import org.objectweb.asm.Opcodes
55
import org.objectweb.asm.Type
6-
import org.objectweb.asm.tree.ClassNode
7-
import org.objectweb.asm.tree.LdcInsnNode
8-
import org.objectweb.asm.tree.MethodInsnNode
9-
import org.objectweb.asm.tree.MethodNode
6+
import org.objectweb.asm.tree.*
107

118
class ReflectionTransformer(
129
mapping: IMappingFile,
@@ -15,23 +12,24 @@ class ReflectionTransformer(
1512
override fun transform(classNode: ClassNode): Boolean {
1613
var modified = false
1714
for (method in classNode.methods) {
18-
modified = modified || handleMethod(method)
15+
val instructions = method.instructions.toArray()
16+
modified = modified or transformDeclaredField(instructions) or transformDeclaredMethod(instructions)
1917
}
2018
return modified
2119
}
2220

23-
private fun handleMethod(method: MethodNode): Boolean {
21+
private fun transformDeclaredField(instructions: Array<AbstractInsnNode>): Boolean {
2422
var modified = false
25-
val instructions = method.instructions.toArray()
2623
for (i in 0 until instructions.size - 3) {
27-
if ((instructions[i].opcode and (Opcodes.INVOKEVIRTUAL or Opcodes.LDC) != 0)
28-
&& instructions[i + 1].opcode == Opcodes.LDC &&
29-
instructions[i + 2].opcode == Opcodes.INVOKEVIRTUAL) {
24+
if ((instructions[i].isOp(Opcodes.INVOKEVIRTUAL) || instructions[i].isOp(Opcodes.LDC))
25+
&& instructions[i + 1].isOp(Opcodes.LDC)
26+
&& instructions[i + 2].isOp(Opcodes.INVOKEVIRTUAL)) {
3027

3128
val call = instructions[i + 2] as MethodInsnNode
32-
if (call.owner != "java/lang/Class" || call.name != "getDeclaredField"
33-
|| call.desc != "(Ljava/lang/String;)Ljava/lang/reflect/Field;")
34-
continue
29+
if (call.owner != "java/lang/Class"
30+
|| call.name != "getDeclaredField"
31+
|| call.desc != "(Ljava/lang/String;)Ljava/lang/reflect/Field;"
32+
) continue
3533

3634
val fieldNode = instructions[i + 1] as LdcInsnNode
3735
if (fieldNode.cst !is String) continue
@@ -55,4 +53,64 @@ class ReflectionTransformer(
5553
return modified
5654
}
5755

56+
private fun transformDeclaredMethod(instructions: Array<AbstractInsnNode>): Boolean {
57+
var modified = false
58+
var i = instructions.size
59+
while (--i >= 3) {
60+
if (instructions[i].isOp(Opcodes.INVOKEVIRTUAL)) {
61+
val call = instructions[i] as MethodInsnNode
62+
if (call.owner != "java/lang/Class"
63+
|| call.name != "getDeclaredMethod"
64+
|| call.desc != "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"
65+
) continue
66+
67+
val params = mutableListOf<String>()
68+
var ldc = i - 1
69+
var found = false
70+
while (ldc > 0) {
71+
if (instructions[ldc].isOp(Opcodes.LDC) && instructions[ldc - 1].isOp(Opcodes.LDC)) {
72+
found = true
73+
break
74+
} else if (instructions[ldc].isOp(Opcodes.GETSTATIC)) {
75+
val node = instructions[ldc] as FieldInsnNode
76+
if (node.name == "TYPE") {
77+
when(node.owner) {
78+
"java/lang/Boolean" -> params.add("Z")
79+
"java/lang/Byte" -> params.add("B")
80+
"java/lang/Character" -> params.add("C")
81+
"java/lang/Short" -> params.add("S")
82+
"java/lang/Integer" -> params.add("I")
83+
"java/lang/Long" -> params.add("J")
84+
"java/lang/Float" -> params.add("F")
85+
"java/lang/Double" -> params.add("D")
86+
}
87+
}
88+
// TODO class param?
89+
}
90+
ldc--
91+
}
92+
if (!found) continue // Cannot find class and method name
93+
val clazzNode = instructions[ldc - 1] as LdcInsnNode
94+
val methodNode = instructions[ldc] as LdcInsnNode
95+
96+
val clazz = (clazzNode.cst as Type).internalName
97+
val method = methodNode.cst as String
98+
99+
params.reverse()
100+
val paramsString = params.joinToString("")
101+
val iClass = mapping.getClass(clazz) ?: continue
102+
val mapped = iClass.methods.find {
103+
it.original == method && it.descriptor.substringBefore(')').substring(1) == paramsString
104+
} ?: continue
105+
methodNode.cst = mapped.mapped
106+
modified = true
107+
}
108+
}
109+
return modified
110+
}
111+
112+
private fun AbstractInsnNode.isOp(opcode: Int): Boolean {
113+
return this.opcode == opcode
114+
}
115+
58116
}

0 commit comments

Comments
 (0)