All Downloads are FREE. Search and download functionalities are using the official Maven repository.

name.remal.org.objectweb.asm.tree.MethodNode.kt Maven / Gradle / Ivy

package name.remal

import org.objectweb.asm.Opcodes.ACC_ABSTRACT
import org.objectweb.asm.Opcodes.ACC_BRIDGE
import org.objectweb.asm.Opcodes.ACC_FINAL
import org.objectweb.asm.Opcodes.ACC_MANDATED
import org.objectweb.asm.Opcodes.ACC_NATIVE
import org.objectweb.asm.Opcodes.ACC_PRIVATE
import org.objectweb.asm.Opcodes.ACC_PROTECTED
import org.objectweb.asm.Opcodes.ACC_PUBLIC
import org.objectweb.asm.Opcodes.ACC_STATIC
import org.objectweb.asm.Opcodes.ACC_STRICT
import org.objectweb.asm.Opcodes.ACC_SYNCHRONIZED
import org.objectweb.asm.Opcodes.ACC_SYNTHETIC
import org.objectweb.asm.Opcodes.ACC_VARARGS
import org.objectweb.asm.Type
import org.objectweb.asm.tree.AbstractInsnNode
import org.objectweb.asm.tree.AnnotationNode
import org.objectweb.asm.tree.JumpInsnNode
import org.objectweb.asm.tree.LabelNode
import org.objectweb.asm.tree.LineNumberNode
import org.objectweb.asm.tree.LookupSwitchInsnNode
import org.objectweb.asm.tree.MethodNode
import org.objectweb.asm.tree.TableSwitchInsnNode
import org.objectweb.asm.tree.TypeAnnotationNode

var MethodNode.isPublic: Boolean
    get() = (access and ACC_PUBLIC) != 0
    set(value) {
        if (value) {
            access = access or ACC_PUBLIC
            access = access and ACC_PROTECTED.inv()
            access = access and ACC_PRIVATE.inv()
        } else {
            access = access and ACC_PUBLIC.inv()
        }
    }

var MethodNode.isProtected: Boolean
    get() = (access and ACC_PROTECTED) != 0
    set(value) {
        if (value) {
            access = access and ACC_PUBLIC.inv()
            access = access or ACC_PROTECTED
            access = access and ACC_PRIVATE.inv()
        } else {
            access = access and ACC_PROTECTED.inv()
        }
    }

var MethodNode.isPrivate: Boolean
    get() = (access and ACC_PRIVATE) != 0
    set(value) {
        if (value) {
            access = access and ACC_PUBLIC.inv()
            access = access and ACC_PROTECTED.inv()
            access = access or ACC_PRIVATE
        } else {
            access = access and ACC_PRIVATE.inv()
        }
    }

var MethodNode.isPackagePrivate: Boolean
    get() = !isPublic && !isProtected && !isPrivate
    set(value) {
        if (value) {
            isPublic = false
            isProtected = false
            isPrivate = false
        }
    }

var MethodNode.isStatic: Boolean
    get() = (access and ACC_STATIC) != 0
    set(value) {
        access = if (value) access or ACC_STATIC else access and ACC_STATIC.inv()
    }

var MethodNode.isFinal: Boolean
    get() = (access and ACC_FINAL) != 0
    set(value) {
        access = if (value) access or ACC_FINAL else access and ACC_FINAL.inv()
    }

var MethodNode.isSynchronized: Boolean
    get() = (access and ACC_SYNCHRONIZED) != 0
    set(value) {
        access = if (value) access or ACC_SYNCHRONIZED else access and ACC_SYNCHRONIZED.inv()
    }

var MethodNode.isBridge: Boolean
    get() = (access and ACC_BRIDGE) != 0
    set(value) {
        access = if (value) access or ACC_BRIDGE else access and ACC_BRIDGE.inv()
    }

var MethodNode.isVarargs: Boolean
    get() = (access and ACC_VARARGS) != 0
    set(value) {
        access = if (value) access or ACC_VARARGS else access and ACC_VARARGS.inv()
    }

var MethodNode.isNative: Boolean
    get() = (access and ACC_NATIVE) != 0
    set(value) {
        access = if (value) access or ACC_NATIVE else access and ACC_NATIVE.inv()
    }

var MethodNode.isAbstract: Boolean
    get() = (access and ACC_ABSTRACT) != 0
    set(value) {
        access = if (value) access or ACC_ABSTRACT else access and ACC_ABSTRACT.inv()
    }

var MethodNode.isStrict: Boolean
    get() = (access and ACC_STRICT) != 0
    set(value) {
        access = if (value) access or ACC_STRICT else access and ACC_STRICT.inv()
    }

var MethodNode.isSynthetic: Boolean
    get() = (access and ACC_SYNTHETIC) != 0
    set(value) {
        access = if (value) access or ACC_SYNTHETIC else access and ACC_SYNTHETIC.inv()
    }

var MethodNode.isMandated: Boolean
    get() = (access and ACC_MANDATED) != 0
    set(value) {
        access = if (value) access or ACC_MANDATED else access and ACC_MANDATED.inv()
    }


val MethodNode.isStaticInitializer: Boolean get() = name == ""
val MethodNode.isConstructor: Boolean get() = name == ""


val MethodNode.hasParameters: Boolean get() = Type.getArgumentTypes(desc).isNotEmpty()

val MethodNode.allAnnotations: List
    get() = sequenceOf(visibleAnnotations, invisibleAnnotations)
        .filterNotNull()
        .flatten()
        .toList()

val MethodNode.allTypeAnnotations: List
    get() = sequenceOf(visibleTypeAnnotations, invisibleTypeAnnotations)
        .filterNotNull()
        .flatten()
        .toList()

val MethodNode.unusedLabelNodes: Set
    get() {
        val instructions = this.instructions ?: return emptySet()
        return buildSet {
            instructions.forEach { if (it is LabelNode) add(it) }

            run {
                var index = -1
                while ((++index) < instructions.size()) {
                    val insn = instructions[index]
                    if (insn is LabelNode) {
                        remove(insn)
                        break
                    } else if (insn is LineNumberNode) {
                        continue
                    } else {
                        break
                    }
                }
            }

            if (isNotEmpty()) {
                tryCatchBlocks?.forEach { remove(it.start); remove(it.end); remove(it.handler) }
                localVariables?.forEach { remove(it.start); remove(it.end) }
                visibleLocalVariableAnnotations?.forEach { it.start?.let(this::removeAll); it.end?.let(this::removeAll) }
                invisibleLocalVariableAnnotations?.forEach { it.start?.let(this::removeAll); it.end?.let(this::removeAll) }
                instructions.forEach {
                    if (it is JumpInsnNode) remove(it.label)
                    if (it is LookupSwitchInsnNode) {
                        remove(it.dflt)
                        it.labels?.let(this::removeAll)
                    }
                    if (it is TableSwitchInsnNode) {
                        remove(it.dflt)
                        it.labels?.let(this::removeAll)
                    }
                }
            }
        }
    }


fun MethodNode.getAllParameterAnnotations(paramIndex: Int): List {
    return sequenceOf(visibleParameterAnnotations, invisibleParameterAnnotations)
        .flatMap { it?.getOrNull(paramIndex)?.asSequence() ?: emptySequence() }
        .filterNotNull()
        .toList()
}


data class InstructionNodeContext(
    val node: T,
    val previousNode: AbstractInsnNode?,
    val nextNode: AbstractInsnNode?
)

data class InstructionNodeFilter(
    val nodeType: Class,
    val predicate: ((context: InstructionNodeContext) -> Boolean)? = null
)

fun  Class.toInstructionNodeFilter() = InstructionNodeFilter(this)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy