Allow Expect Platform on interface static methods

This commit is contained in:
shedaniel
2020-11-12 23:41:03 +08:00
parent 49f129ae8c
commit 12d54b078f

View File

@@ -10,62 +10,59 @@ import java.lang.invoke.MethodType
const val expectPlatform = "Lme/shedaniel/architectury/ExpectPlatform;"
fun transformExpectPlatform(): (ClassNode, (String, ByteArray) -> Unit) -> ClassNode = { clazz, classAdder ->
if (clazz.access and Opcodes.ACC_INTERFACE == 0) {
clazz.methods.filter { method -> method?.visibleAnnotations?.any { it.desc == expectPlatform } == true }
.forEach { method ->
if (method.access and Opcodes.ACC_STATIC == 0) {
System.err.println("@ExpectPlatform can only apply to static methods!")
} else {
println("Found ${clazz.name}#${method.name}")
method.instructions.clear()
val endOfDesc = method.desc.lastIndexOf(')')
val returnValue = method.desc.substring(endOfDesc + 1)
val args = method.desc.substring(1, endOfDesc)
var cursor = 0
var inClass = false
var index = 0
while (cursor < args.length) {
val char = args[cursor]
if (inClass) {
if (char == ';') {
method.instructions.addLoad(char, index++)
inClass = false
}
} else when (char) {
'[' -> Unit
'L' -> inClass = true
else -> method.instructions.addLoad(char, index++)
clazz.methods.filter { method -> method?.visibleAnnotations?.any { it.desc == expectPlatform } == true }
.forEach { method ->
if (method.access and Opcodes.ACC_STATIC == 0) {
System.err.println("@ExpectPlatform can only apply to static methods!")
} else {
method.instructions.clear()
val endOfDesc = method.desc.lastIndexOf(')')
val returnValue = method.desc.substring(endOfDesc + 1)
val args = method.desc.substring(1, endOfDesc)
var cursor = 0
var inClass = false
var index = 0
while (cursor < args.length) {
val char = args[cursor]
if (inClass) {
if (char == ';') {
method.instructions.addLoad(char, index++)
inClass = false
}
cursor++
} else when (char) {
'[' -> Unit
'L' -> inClass = true
else -> method.instructions.addLoad(char, index++)
}
val methodType = MethodType.methodType(
CallSite::class.java,
MethodHandles.Lookup::class.java,
String::class.java,
MethodType::class.java
)
val handle = Handle(
Opcodes.H_INVOKESTATIC,
"me/shedaniel/architectury/PlatformMethods",
"platform",
methodType.toMethodDescriptorString(),
false
)
method.instructions.add(
InvokeDynamicInsnNode(
method.name,
method.desc,
handle
)
)
method.instructions.addReturn(returnValue.first { it != '[' })
cursor++
}
val methodType = MethodType.methodType(
CallSite::class.java,
MethodHandles.Lookup::class.java,
String::class.java,
MethodType::class.java
)
val handle = Handle(
Opcodes.H_INVOKESTATIC,
"me/shedaniel/architectury/PlatformMethods",
"platform",
methodType.toMethodDescriptorString(),
false
)
method.instructions.add(
InvokeDynamicInsnNode(
method.name,
method.desc,
handle
)
)
method.instructions.addReturn(returnValue.first { it != '[' })
}
}
}
clazz
}