name.remal.org.objectweb.asm.tree.AbstractInsnNode.kt Maven / Gradle / Ivy
package name.remal
import org.objectweb.asm.Opcodes.ACONST_NULL
import org.objectweb.asm.Opcodes.DCONST_0
import org.objectweb.asm.Opcodes.DCONST_1
import org.objectweb.asm.Opcodes.FCONST_0
import org.objectweb.asm.Opcodes.FCONST_1
import org.objectweb.asm.Opcodes.FCONST_2
import org.objectweb.asm.Opcodes.ICONST_0
import org.objectweb.asm.Opcodes.ICONST_1
import org.objectweb.asm.Opcodes.LCONST_0
import org.objectweb.asm.Type
import org.objectweb.asm.Type.getType
import org.objectweb.asm.tree.AbstractInsnNode
import org.objectweb.asm.tree.InsnNode
import org.objectweb.asm.tree.LdcInsnNode
import org.objectweb.asm.tree.TypeAnnotationNode
val AbstractInsnNode.allTypeAnnotations: List
get() = sequenceOf(visibleTypeAnnotations, invisibleTypeAnnotations)
.filterNotNull()
.flatten()
.toList()
fun AbstractInsnNode.getPrevious(predicate: (node: AbstractInsnNode) -> Boolean): AbstractInsnNode? {
var node = previous
while (node != null) {
if (predicate(node)) return node
node = node.previous
}
return null
}
fun AbstractInsnNode.getNext(predicate: (node: AbstractInsnNode) -> Boolean): AbstractInsnNode? {
var node = next
while (node != null) {
if (predicate(node)) return node
node = node.next
}
return null
}
fun Any?.toInsnNode() = when (this) {
null -> InsnNode(ACONST_NULL)
is Boolean -> if (this) InsnNode(ICONST_1) else InsnNode(ICONST_0)
is Char -> this.toInt().let {
if (0 <= it && it <= 5) {
InsnNode(ICONST_0 + it)
} else {
LdcInsnNode(it)
}
}
is Byte -> this.toInt().let {
if (-1 <= it && it <= 5) {
InsnNode(ICONST_0 + it)
} else {
LdcInsnNode(it)
}
}
is Short -> this.toInt().let {
if (-1 <= it && it <= 5) {
InsnNode(ICONST_0 + it)
} else {
LdcInsnNode(it)
}
}
is Int -> this.let {
if (-1 <= it && it <= 5) {
InsnNode(ICONST_0 + it)
} else {
LdcInsnNode(it)
}
}
is Float -> this.let {
if (0.0f == it) {
InsnNode(FCONST_0)
} else if (1.0f == it) {
InsnNode(FCONST_1)
} else if (2.0f == it) {
InsnNode(FCONST_2)
} else {
LdcInsnNode(it)
}
}
is Long -> this.let {
if (0L <= it && it <= 1L) {
InsnNode(LCONST_0 + it.toInt())
} else {
LdcInsnNode(it)
}
}
is Double -> this.let {
if (0.0 == it) {
InsnNode(DCONST_0)
} else if (1.0 == it) {
InsnNode(DCONST_1)
} else {
LdcInsnNode(it)
}
}
is String -> LdcInsnNode(this)
is Type -> LdcInsnNode(this)
is Class<*> -> LdcInsnNode(getType(this))
else -> throw IllegalArgumentException("$this is not a constant")
}