@@ -3,10 +3,7 @@ package io.github.rothes.esu.bukkit.util.version.remapper.transformer
33import net.neoforged.srgutils.IMappingFile
44import org.objectweb.asm.Opcodes
55import 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
118class 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