mirror of
https://github.com/architectury/architectury-plugin.git
synced 2026-04-03 05:57:41 -05:00
Allow Expect Platform on interface static methods
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user