Run Clean up on eval4j module
This commit is contained in:
@@ -56,7 +56,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
||||
}
|
||||
|
||||
override fun newOperation(insn: AbstractInsnNode): Value? {
|
||||
return when (insn.getOpcode()) {
|
||||
return when (insn.opcode) {
|
||||
ACONST_NULL -> {
|
||||
return NULL_VALUE
|
||||
}
|
||||
@@ -90,7 +90,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
||||
is Double -> double(cst)
|
||||
is String -> eval.loadString(cst)
|
||||
is Type -> {
|
||||
val sort = cst.getSort()
|
||||
val sort = cst.sort
|
||||
when (sort) {
|
||||
Type.OBJECT, Type.ARRAY -> eval.loadClass(cst)
|
||||
Type.METHOD -> throw UnsupportedByteCodeException("Mothod handles are not supported")
|
||||
@@ -113,7 +113,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
||||
}
|
||||
|
||||
override fun unaryOperation(insn: AbstractInsnNode, value: Value): Value? {
|
||||
return when (insn.getOpcode()) {
|
||||
return when (insn.opcode) {
|
||||
INEG -> int(-value.int)
|
||||
IINC -> int(value.int + (insn as IincInsnNode).incr)
|
||||
L2I -> int(value.long.toInt())
|
||||
@@ -187,7 +187,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
||||
ObjectValue(value.obj(), targetType)
|
||||
}
|
||||
else {
|
||||
throwEvalException(ClassCastException("${value.asmType.getClassName()} cannot be cast to ${targetType.getClassName()}"))
|
||||
throwEvalException(ClassCastException("${value.asmType.className} cannot be cast to ${targetType.className}"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
||||
}
|
||||
|
||||
override fun binaryOperation(insn: AbstractInsnNode, value1: Value, value2: Value): Value? {
|
||||
return when (insn.getOpcode()) {
|
||||
return when (insn.opcode) {
|
||||
IALOAD, BALOAD, CALOAD, SALOAD,
|
||||
FALOAD, LALOAD, DALOAD,
|
||||
AALOAD -> eval.getArrayElement(value1, value2)
|
||||
@@ -280,7 +280,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
||||
l1 == l2 -> 0
|
||||
l1 < l2 -> -1
|
||||
// one of them is NaN
|
||||
else -> if (insn.getOpcode() == FCMPG) 1 else -1
|
||||
else -> if (insn.opcode == FCMPG) 1 else -1
|
||||
})
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
||||
l1 == l2 -> 0
|
||||
l1 < l2 -> -1
|
||||
// one of them is NaN
|
||||
else -> if (insn.getOpcode() == DCMPG) 1 else -1
|
||||
else -> if (insn.opcode == DCMPG) 1 else -1
|
||||
})
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
||||
}
|
||||
|
||||
override fun ternaryOperation(insn: AbstractInsnNode, value1: Value, value2: Value, value3: Value): Value? {
|
||||
return when (insn.getOpcode()) {
|
||||
return when (insn.opcode) {
|
||||
IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE -> {
|
||||
eval.setArrayElement(value1, value2, value3)
|
||||
null
|
||||
@@ -338,7 +338,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
||||
}
|
||||
|
||||
override fun naryOperation(insn: AbstractInsnNode, values: List<Value>): Value {
|
||||
return when (insn.getOpcode()) {
|
||||
return when (insn.opcode) {
|
||||
MULTIANEWARRAY -> {
|
||||
val node = insn as MultiANewArrayInsnNode
|
||||
eval.newMultiDimensionalArray(Type.getType(node.desc), values.map { v -> v.int })
|
||||
@@ -348,8 +348,8 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
||||
eval.invokeMethod(
|
||||
values[0],
|
||||
MethodDescription(insn as MethodInsnNode),
|
||||
values.subList(1, values.size()),
|
||||
insn.getOpcode() == INVOKESPECIAL
|
||||
values.subList(1, values.size),
|
||||
insn.opcode == INVOKESPECIAL
|
||||
)
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
||||
|
||||
|
||||
override fun returnOperation(insn: AbstractInsnNode, value: Value, expected: Value) {
|
||||
when (insn.getOpcode()) {
|
||||
when (insn.opcode) {
|
||||
IRETURN, LRETURN, FRETURN, DRETURN, ARETURN -> {
|
||||
// Handled by interpreter loop
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
import org.jetbrains.org.objectweb.asm.util.Printer
|
||||
import java.util.ArrayList
|
||||
import java.util.*
|
||||
|
||||
public interface InterpreterResult {
|
||||
override fun toString(): String
|
||||
@@ -61,7 +61,7 @@ public interface InterpretationEventHandler {
|
||||
}
|
||||
|
||||
abstract class ThrownFromEvalExceptionBase(cause: Throwable): RuntimeException(cause) {
|
||||
override fun toString(): String = "Thrown by evaluator: ${getCause()}"
|
||||
override fun toString(): String = "Thrown by evaluator: ${cause}"
|
||||
}
|
||||
|
||||
class BrokenCode(cause: Throwable): ThrownFromEvalExceptionBase(cause)
|
||||
@@ -77,7 +77,7 @@ public fun interpreterLoop(
|
||||
eval: Eval,
|
||||
handler: InterpretationEventHandler = InterpretationEventHandler.NONE
|
||||
): InterpreterResult {
|
||||
val firstInsn = m.instructions.getFirst()
|
||||
val firstInsn = m.instructions.first
|
||||
if (firstInsn == null) throw IllegalArgumentException("Empty method")
|
||||
|
||||
var currentInsn = firstInsn
|
||||
@@ -122,9 +122,9 @@ public fun interpreterLoop(
|
||||
try {
|
||||
val exceptionClass = exception.javaClass
|
||||
val _class = Class.forName(
|
||||
exceptionType.getInternalName().replace('/', '.'),
|
||||
exceptionType.internalName.replace('/', '.'),
|
||||
true,
|
||||
exceptionClass.getClassLoader()
|
||||
exceptionClass.classLoader
|
||||
)
|
||||
_class.isAssignableFrom(exceptionClass)
|
||||
}
|
||||
@@ -137,8 +137,8 @@ public fun interpreterLoop(
|
||||
|
||||
try {
|
||||
loop@ while (true) {
|
||||
val insnOpcode = currentInsn.getOpcode()
|
||||
val insnType = currentInsn.getType()
|
||||
val insnOpcode = currentInsn.opcode
|
||||
val insnType = currentInsn.type
|
||||
|
||||
when (insnType) {
|
||||
AbstractInsnNode.LABEL,
|
||||
@@ -168,7 +168,7 @@ public fun interpreterLoop(
|
||||
IRETURN, LRETURN, FRETURN, DRETURN, ARETURN -> {
|
||||
val value = frame.getStackTop()
|
||||
val expectedType = Type.getReturnType(m.desc)
|
||||
if (expectedType.getSort() == Type.OBJECT || expectedType.getSort() == Type.ARRAY) {
|
||||
if (expectedType.sort == Type.OBJECT || expectedType.sort == Type.ARRAY) {
|
||||
val coerced = if (value != NULL_VALUE && value.asmType != expectedType)
|
||||
ObjectValue(value.obj(), expectedType)
|
||||
else value
|
||||
@@ -177,7 +177,7 @@ public fun interpreterLoop(
|
||||
if (value.asmType != expectedType) {
|
||||
assert(insnOpcode == IRETURN) { "Only ints should be coerced: ${Printer.OPCODES[insnOpcode]}" }
|
||||
|
||||
val coerced = when (expectedType.getSort()) {
|
||||
val coerced = when (expectedType.sort) {
|
||||
Type.BOOLEAN -> boolean(value.boolean)
|
||||
Type.BYTE -> byte(value.int.toByte())
|
||||
Type.SHORT -> short(value.int.toShort())
|
||||
@@ -221,7 +221,7 @@ public fun interpreterLoop(
|
||||
frame.execute(currentInsn, interpreter)
|
||||
}
|
||||
catch (e: ThrownFromEvalExceptionBase) {
|
||||
val exception = e.getCause()!!
|
||||
val exception = e.cause!!
|
||||
val exceptionValue = ObjectValue(exception, Type.getType(exception.javaClass))
|
||||
val handled = handler.exceptionThrown(frame, currentInsn,
|
||||
exceptionValue)
|
||||
@@ -243,7 +243,7 @@ public fun interpreterLoop(
|
||||
val handled = handler.instructionProcessed(currentInsn)
|
||||
if (handled != null) return handled
|
||||
|
||||
goto(currentInsn.getNext())
|
||||
goto(currentInsn.next)
|
||||
}
|
||||
}
|
||||
catch(e: ResultException) {
|
||||
@@ -251,7 +251,7 @@ public fun interpreterLoop(
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T: Value> Frame<T>.getStackTop(i: Int = 0) = this.getStack(this.getStackSize() - 1 - i) ?: throwBrokenCodeException(IllegalArgumentException("Couldn't get value with index = $i from top of stack"))
|
||||
private fun <T: Value> Frame<T>.getStackTop(i: Int = 0) = this.getStack(this.stackSize - 1 - i) ?: throwBrokenCodeException(IllegalArgumentException("Couldn't get value with index = $i from top of stack"))
|
||||
|
||||
// Copied from org.jetbrains.org.objectweb.asm.tree.analysis.Analyzer.analyze()
|
||||
fun computeHandlers(m: MethodNode): Array<out List<TryCatchBlockNode>?> {
|
||||
|
||||
@@ -24,7 +24,7 @@ import java.lang.reflect.AccessibleObject
|
||||
import com.sun.jdi.Type as jdi_Type
|
||||
import com.sun.jdi.Value as jdi_Value
|
||||
|
||||
val CLASS = Type.getType(javaClass<Class<*>>())
|
||||
val CLASS = Type.getType(Class::class.java)
|
||||
val OBJECT = Type.getType(Any::class.java)
|
||||
val BOOTSTRAP_CLASS_DESCRIPTORS = setOf("Ljava/lang/String;", "Ljava/lang/ClassLoader;", "Ljava/lang/Class;")
|
||||
|
||||
@@ -36,14 +36,14 @@ public class JDIEval(
|
||||
) : Eval {
|
||||
|
||||
private val primitiveTypes = mapOf(
|
||||
Type.BOOLEAN_TYPE.getClassName() to vm.mirrorOf(true).type(),
|
||||
Type.BYTE_TYPE.getClassName() to vm.mirrorOf(1.toByte()).type(),
|
||||
Type.SHORT_TYPE.getClassName() to vm.mirrorOf(1.toShort()).type(),
|
||||
Type.INT_TYPE.getClassName() to vm.mirrorOf(1.toInt()).type(),
|
||||
Type.CHAR_TYPE.getClassName() to vm.mirrorOf('1').type(),
|
||||
Type.LONG_TYPE.getClassName() to vm.mirrorOf(1L).type(),
|
||||
Type.FLOAT_TYPE.getClassName() to vm.mirrorOf(1.0f).type(),
|
||||
Type.DOUBLE_TYPE.getClassName() to vm.mirrorOf(1.0).type()
|
||||
Type.BOOLEAN_TYPE.className to vm.mirrorOf(true).type(),
|
||||
Type.BYTE_TYPE.className to vm.mirrorOf(1.toByte()).type(),
|
||||
Type.SHORT_TYPE.className to vm.mirrorOf(1.toShort()).type(),
|
||||
Type.INT_TYPE.className to vm.mirrorOf(1.toInt()).type(),
|
||||
Type.CHAR_TYPE.className to vm.mirrorOf('1').type(),
|
||||
Type.LONG_TYPE.className to vm.mirrorOf(1L).type(),
|
||||
Type.FLOAT_TYPE.className to vm.mirrorOf(1.0f).type(),
|
||||
Type.DOUBLE_TYPE.className to vm.mirrorOf(1.0).type()
|
||||
)
|
||||
|
||||
override fun loadClass(classType: Type): Value {
|
||||
@@ -51,34 +51,34 @@ public class JDIEval(
|
||||
}
|
||||
|
||||
fun loadClass(classType: Type, classLoader: ClassLoaderReference?): Value {
|
||||
val loadedClasses = vm.classesByName(classType.getInternalName())
|
||||
val loadedClasses = vm.classesByName(classType.internalName)
|
||||
if (!loadedClasses.isEmpty()) {
|
||||
val loadedClass = loadedClasses[0]
|
||||
if (classType.getDescriptor() in BOOTSTRAP_CLASS_DESCRIPTORS || loadedClass.classLoader() == classLoader) {
|
||||
if (classType.descriptor in BOOTSTRAP_CLASS_DESCRIPTORS || loadedClass.classLoader() == classLoader) {
|
||||
return loadedClass.classObject().asValue()
|
||||
}
|
||||
}
|
||||
if (classLoader == null) {
|
||||
return invokeStaticMethod(
|
||||
MethodDescription(
|
||||
CLASS.getInternalName(),
|
||||
CLASS.internalName,
|
||||
"forName",
|
||||
"(Ljava/lang/String;)Ljava/lang/Class;",
|
||||
true
|
||||
),
|
||||
listOf(vm.mirrorOf(classType.getInternalName().replace('/', '.')).asValue())
|
||||
listOf(vm.mirrorOf(classType.internalName.replace('/', '.')).asValue())
|
||||
)
|
||||
}
|
||||
else {
|
||||
return invokeStaticMethod(
|
||||
MethodDescription(
|
||||
CLASS.getInternalName(),
|
||||
CLASS.internalName,
|
||||
"forName",
|
||||
"(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;",
|
||||
true
|
||||
),
|
||||
listOf(
|
||||
vm.mirrorOf(classType.getInternalName().replace('/', '.')).asValue(),
|
||||
vm.mirrorOf(classType.internalName.replace('/', '.')).asValue(),
|
||||
boolean(true),
|
||||
classLoader.asValue()
|
||||
)
|
||||
@@ -93,7 +93,7 @@ public class JDIEval(
|
||||
}
|
||||
|
||||
override fun isInstanceOf(value: Value, targetType: Type): Boolean {
|
||||
assert(targetType.getSort() == Type.OBJECT || targetType.getSort() == Type.ARRAY) {
|
||||
assert(targetType.sort == Type.OBJECT || targetType.sort == Type.ARRAY) {
|
||||
"Can't check isInstanceOf() for non-object type $targetType"
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ public class JDIEval(
|
||||
return invokeMethod(
|
||||
_class,
|
||||
MethodDescription(
|
||||
CLASS.getInternalName(),
|
||||
CLASS.internalName,
|
||||
"isInstance",
|
||||
"(Ljava/lang/Object;)Z",
|
||||
false
|
||||
@@ -119,12 +119,12 @@ public class JDIEval(
|
||||
|
||||
private val Type.arrayElementType: Type
|
||||
get(): Type {
|
||||
assert(getSort() == Type.ARRAY) { "Not an array type: $this" }
|
||||
return Type.getType(getDescriptor().substring(1))
|
||||
assert(sort == Type.ARRAY) { "Not an array type: $this" }
|
||||
return Type.getType(descriptor.substring(1))
|
||||
}
|
||||
|
||||
private fun fillArray(elementType: Type, size: Int, nestedSizes: List<Int>): Value {
|
||||
val arr = newArray(Type.getType("[" + elementType.getDescriptor()), size)
|
||||
val arr = newArray(Type.getType("[" + elementType.descriptor), size)
|
||||
if (!nestedSizes.isEmpty()) {
|
||||
val nestedElementType = elementType.arrayElementType
|
||||
val nestedSize = nestedSizes[0]
|
||||
@@ -151,7 +151,7 @@ public class JDIEval(
|
||||
return array.array().getValue(index.int).asValue()
|
||||
}
|
||||
catch (e: IndexOutOfBoundsException) {
|
||||
throwEvalException(ArrayIndexOutOfBoundsException(e.getMessage()))
|
||||
throwEvalException(ArrayIndexOutOfBoundsException(e.message))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ public class JDIEval(
|
||||
return array.array().setValue(index.int, newValue.asJdiValue(vm, array.asmType.arrayElementType))
|
||||
}
|
||||
catch (e: IndexOutOfBoundsException) {
|
||||
throwEvalException(ArrayIndexOutOfBoundsException(e.getMessage()))
|
||||
throwEvalException(ArrayIndexOutOfBoundsException(e.message))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ public class JDIEval(
|
||||
|
||||
private fun findStaticField(fieldDesc: FieldDescription): Field {
|
||||
val field = findField(fieldDesc)
|
||||
if (!field.isStatic()) {
|
||||
if (!field.isStatic) {
|
||||
throwBrokenCodeException(NoSuchFieldError("Field is not static: $fieldDesc"))
|
||||
}
|
||||
return field
|
||||
@@ -189,7 +189,7 @@ public class JDIEval(
|
||||
override fun setStaticField(fieldDesc: FieldDescription, newValue: Value) {
|
||||
val field = findStaticField(fieldDesc)
|
||||
|
||||
if (field.isFinal()) {
|
||||
if (field.isFinal) {
|
||||
throwBrokenCodeException(NoSuchFieldError("Can't modify a final field: $field"))
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ public class JDIEval(
|
||||
|
||||
override fun invokeStaticMethod(methodDesc: MethodDescription, arguments: List<Value>): Value {
|
||||
val method = findMethod(methodDesc)
|
||||
if (!method.isStatic()) {
|
||||
if (!method.isStatic) {
|
||||
throwBrokenCodeException(NoSuchMethodError("Method is not static: $methodDesc"))
|
||||
}
|
||||
val _class = method.declaringType()
|
||||
@@ -261,7 +261,7 @@ public class JDIEval(
|
||||
Type.BYTE_TYPE -> MethodDescription("java/lang/Byte", "byteValue", "()B", false)
|
||||
Type.FLOAT_TYPE -> MethodDescription("java/lang/Float", "floatValue", "()F", false)
|
||||
Type.DOUBLE_TYPE -> MethodDescription("java/lang/Double", "doubleValue", "()D", false)
|
||||
else -> throw UnsupportedOperationException("Couldn't unbox non primitive type ${type.getInternalName()}")
|
||||
else -> throw UnsupportedOperationException("Couldn't unbox non primitive type ${type.internalName}")
|
||||
}
|
||||
return invokeMethod(boxedValue, method, listOf(), true)
|
||||
}
|
||||
@@ -276,7 +276,7 @@ public class JDIEval(
|
||||
Type.CHAR_TYPE -> MethodDescription("java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false)
|
||||
Type.FLOAT_TYPE -> MethodDescription("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false)
|
||||
Type.DOUBLE_TYPE -> MethodDescription("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false)
|
||||
else -> throw UnsupportedOperationException("Couldn't box non primitive type ${value.asmType.getInternalName()}")
|
||||
else -> throw UnsupportedOperationException("Couldn't box non primitive type ${value.asmType.internalName}")
|
||||
}
|
||||
return invokeStaticMethod(method, listOf(value))
|
||||
}
|
||||
@@ -397,7 +397,7 @@ public class JDIEval(
|
||||
if (dimensions == 0)
|
||||
baseType
|
||||
else
|
||||
Type.getType("[".repeat(dimensions) + baseType.asType().getDescriptor()).asReferenceType(declaringType().classLoader())
|
||||
Type.getType("[".repeat(dimensions) + baseType.asType().descriptor).asReferenceType(declaringType().classLoader())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public fun makeInitialFrame(methodNode: MethodNode, arguments: List<Value>): Fra
|
||||
val isStatic = (methodNode.access and ACC_STATIC) != 0
|
||||
|
||||
val params = Type.getArgumentTypes(methodNode.desc)
|
||||
assert(arguments.size() == (if (isStatic) params.size() else params.size() + 1)) {
|
||||
assert(arguments.size == (if (isStatic) params.size else params.size + 1)) {
|
||||
"Wrong number of arguments for $methodNode: $arguments"
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public fun makeInitialFrame(methodNode: MethodNode, arguments: List<Value>): Fra
|
||||
var index = 0
|
||||
for ((i, arg) in arguments.withIndex()) {
|
||||
frame.setLocal(index++, arg)
|
||||
if (arg.getSize() == 2) {
|
||||
if (arg.size == 2) {
|
||||
frame.setLocal(index++, NOT_A_VALUE)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
package org.jetbrains.eval4j
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
|
||||
|
||||
open class MemberDescription protected constructor(
|
||||
val ownerInternalName: String,
|
||||
@@ -64,7 +64,7 @@ fun MethodDescription(insn: MethodInsnNode): MethodDescription =
|
||||
insn.owner,
|
||||
insn.name,
|
||||
insn.desc,
|
||||
insn.getOpcode() == INVOKESTATIC
|
||||
insn.opcode == INVOKESTATIC
|
||||
)
|
||||
|
||||
val MethodDescription.returnType: Type
|
||||
@@ -86,7 +86,7 @@ fun FieldDescription(insn: FieldInsnNode): FieldDescription =
|
||||
insn.owner,
|
||||
insn.name,
|
||||
insn.desc,
|
||||
insn.getOpcode() in setOf(GETSTATIC, PUTSTATIC)
|
||||
insn.opcode in setOf(GETSTATIC, PUTSTATIC)
|
||||
)
|
||||
|
||||
val FieldDescription.fieldType: Type
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
||||
public interface Value : org.jetbrains.org.objectweb.asm.tree.analysis.Value {
|
||||
public val asmType: Type
|
||||
public val valid: Boolean
|
||||
override fun getSize(): Int = asmType.getSize()
|
||||
override fun getSize(): Int = asmType.size
|
||||
|
||||
override fun toString(): String
|
||||
}
|
||||
@@ -42,7 +42,7 @@ object VOID_VALUE: Value {
|
||||
}
|
||||
|
||||
fun makeNotInitializedValue(t: Type): Value? {
|
||||
return when (t.getSort()) {
|
||||
return when (t.sort) {
|
||||
Type.VOID -> null
|
||||
else -> NotInitialized(t)
|
||||
}
|
||||
|
||||
@@ -16,24 +16,25 @@
|
||||
|
||||
package org.jetbrains.eval4j.jdi.test
|
||||
|
||||
import org.jetbrains.eval4j.*
|
||||
import com.sun.jdi.*
|
||||
import junit.framework.TestSuite
|
||||
import org.jetbrains.eval4j.test.buildTestSuite
|
||||
import junit.framework.TestCase
|
||||
import org.junit.Assert.*
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import org.jetbrains.eval4j.jdi.*
|
||||
import java.io.File
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.eval4j.test.getTestName
|
||||
import com.sun.jdi.ObjectReference
|
||||
import com.sun.jdi.event.BreakpointEvent
|
||||
import com.sun.jdi.event.ClassPrepareEvent
|
||||
import junit.framework.TestCase
|
||||
import junit.framework.TestSuite
|
||||
import org.jetbrains.eval4j.*
|
||||
import org.jetbrains.eval4j.jdi.JDIEval
|
||||
import org.jetbrains.eval4j.jdi.asValue
|
||||
import org.jetbrains.eval4j.jdi.jdiObj
|
||||
import org.jetbrains.eval4j.jdi.makeInitialFrame
|
||||
import org.jetbrains.eval4j.test.buildTestSuite
|
||||
import org.jetbrains.eval4j.test.getTestName
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import java.io.File
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
val DEBUGEE_CLASS = javaClass<Debugee>()
|
||||
val DEBUGEE_CLASS = Debugee::class.java
|
||||
|
||||
fun suite(): TestSuite {
|
||||
val connectors = Bootstrap.virtualMachineManager().launchingConnectors()
|
||||
@@ -42,7 +43,7 @@ fun suite(): TestSuite {
|
||||
|
||||
val connectorArgs = connector.defaultArguments()
|
||||
|
||||
val debugeeName = DEBUGEE_CLASS.getName()
|
||||
val debugeeName = DEBUGEE_CLASS.name
|
||||
println("Debugee name: $debugeeName")
|
||||
connectorArgs["main"]!!.setValue(debugeeName)
|
||||
connectorArgs["options"]!!.setValue("-classpath out/production/eval4j${File.pathSeparator}out/test/eval4j")
|
||||
@@ -111,7 +112,7 @@ fun suite(): TestSuite {
|
||||
val args = if ((methodNode.access and Opcodes.ACC_STATIC) == 0) {
|
||||
// Instance method
|
||||
val newInstance = eval.newInstance(Type.getType(ownerClass))
|
||||
val thisValue = eval.invokeMethod(newInstance, MethodDescription(ownerClass.getName(), "<init>", "()V", false), listOf(), true)
|
||||
val thisValue = eval.invokeMethod(newInstance, MethodDescription(ownerClass.name, "<init>", "()V", false), listOf(), true)
|
||||
listOf(thisValue)
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -16,20 +16,17 @@
|
||||
|
||||
package org.jetbrains.eval4j.test
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import java.lang.reflect.Modifier
|
||||
import org.jetbrains.eval4j.*
|
||||
import org.junit.Assert.*
|
||||
import junit.framework.TestSuite
|
||||
import junit.framework.TestCase
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Constructor
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
import java.lang.reflect.Array as JArray
|
||||
import junit.framework.TestSuite
|
||||
import org.jetbrains.eval4j.*
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_STATIC
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import java.lang.reflect.*
|
||||
import java.lang.reflect.Array as JArray
|
||||
|
||||
fun suite(): TestSuite = buildTestSuite {
|
||||
methodNode, ownerClass, expected ->
|
||||
@@ -59,13 +56,13 @@ fun suite(): TestSuite = buildTestSuite {
|
||||
return methodNode.visibleAnnotations?.any {
|
||||
val annotationDesc = it.desc
|
||||
annotationDesc != null &&
|
||||
Type.getType(annotationDesc) == Type.getType(javaClass<IgnoreInReflectionTests>())
|
||||
Type.getType(annotationDesc) == Type.getType(IgnoreInReflectionTests::class.java)
|
||||
} ?: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Class<*>.getInternalName(): String = Type.getType(this).getInternalName()
|
||||
fun Class<*>.getInternalName(): String = Type.getType(this).internalName
|
||||
|
||||
fun initFrame(
|
||||
owner: String,
|
||||
@@ -83,9 +80,9 @@ fun initFrame(
|
||||
}
|
||||
|
||||
val args = Type.getArgumentTypes(m.desc)
|
||||
for (i in 0..args.size() - 1) {
|
||||
for (i in 0..args.size - 1) {
|
||||
current.setLocal(local++, makeNotInitializedValue(args[i]))
|
||||
if (args[i].getSize() == 2) {
|
||||
if (args[i].size == 2) {
|
||||
current.setLocal(local++, NOT_A_VALUE)
|
||||
}
|
||||
}
|
||||
@@ -98,7 +95,7 @@ fun initFrame(
|
||||
}
|
||||
|
||||
fun objectToValue(obj: Any?, expectedType: Type): Value {
|
||||
return when (expectedType.getSort()) {
|
||||
return when (expectedType.sort) {
|
||||
Type.VOID -> VOID_VALUE
|
||||
Type.BOOLEAN -> boolean(obj as Boolean)
|
||||
Type.BYTE -> byte(obj as Byte)
|
||||
@@ -115,13 +112,13 @@ fun objectToValue(obj: Any?, expectedType: Type): Value {
|
||||
|
||||
object REFLECTION_EVAL : Eval {
|
||||
|
||||
val lookup = ReflectionLookup(javaClass<ReflectionLookup>().getClassLoader()!!)
|
||||
val lookup = ReflectionLookup(ReflectionLookup::class.java.classLoader!!)
|
||||
|
||||
override fun loadClass(classType: Type): Value {
|
||||
return ObjectValue(findClass(classType), Type.getType(javaClass<Class<*>>()))
|
||||
return ObjectValue(findClass(classType), Type.getType(Class::class.java))
|
||||
}
|
||||
|
||||
override fun loadString(str: String): Value = ObjectValue(str, Type.getType(javaClass<String>()))
|
||||
override fun loadString(str: String): Value = ObjectValue(str, Type.getType(String::class.java))
|
||||
|
||||
override fun newInstance(classType: Type): Value {
|
||||
return NewObjectValue(classType)
|
||||
@@ -134,11 +131,11 @@ object REFLECTION_EVAL : Eval {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun newArray(arrayType: Type, size: Int): Value {
|
||||
return ObjectValue(JArray.newInstance(findClass(arrayType).getComponentType() as Class<Any>, size), arrayType)
|
||||
return ObjectValue(JArray.newInstance(findClass(arrayType).componentType as Class<Any>, size), arrayType)
|
||||
}
|
||||
|
||||
override fun newMultiDimensionalArray(arrayType: Type, dimensionSizes: List<Int>): Value {
|
||||
return ObjectValue(ArrayHelper.newMultiArray(findClass(arrayType.getElementType()), *dimensionSizes.toTypedArray()), arrayType)
|
||||
return ObjectValue(ArrayHelper.newMultiArray(findClass(arrayType.elementType), *dimensionSizes.toTypedArray()), arrayType)
|
||||
}
|
||||
|
||||
override fun getArrayLength(array: Value): Value {
|
||||
@@ -147,11 +144,11 @@ object REFLECTION_EVAL : Eval {
|
||||
|
||||
override fun getArrayElement(array: Value, index: Value): Value {
|
||||
val asmType = array.asmType
|
||||
val elementType = if (asmType.getDimensions() == 1) asmType.getElementType() else Type.getType(asmType.getDescriptor().substring(1))
|
||||
val elementType = if (asmType.dimensions == 1) asmType.elementType else Type.getType(asmType.descriptor.substring(1))
|
||||
val arr = array.obj().checkNull()
|
||||
val ind = index.int
|
||||
return mayThrow {
|
||||
when (elementType.getSort()) {
|
||||
when (elementType.sort) {
|
||||
Type.BOOLEAN -> boolean(JArray.getBoolean(arr, ind))
|
||||
Type.BYTE -> byte(JArray.getByte(arr, ind))
|
||||
Type.SHORT -> short(JArray.getShort(arr, ind))
|
||||
@@ -173,13 +170,13 @@ object REFLECTION_EVAL : Eval {
|
||||
override fun setArrayElement(array: Value, index: Value, newValue: Value) {
|
||||
val arr = array.obj().checkNull()
|
||||
val ind = index.int
|
||||
if (array.asmType.getDimensions() > 1) {
|
||||
if (array.asmType.dimensions > 1) {
|
||||
JArray.set(arr, ind, newValue.obj())
|
||||
return
|
||||
}
|
||||
val elementType = array.asmType.getElementType()
|
||||
val elementType = array.asmType.elementType
|
||||
mayThrow {
|
||||
when (elementType.getSort()) {
|
||||
when (elementType.sort) {
|
||||
Type.BOOLEAN -> JArray.setBoolean(arr, ind, newValue.boolean)
|
||||
Type.BYTE -> JArray.setByte(arr, ind, newValue.int.toByte())
|
||||
Type.SHORT -> JArray.setShort(arr, ind, newValue.int.toShort())
|
||||
@@ -203,7 +200,7 @@ object REFLECTION_EVAL : Eval {
|
||||
return f()
|
||||
}
|
||||
catch (ite: InvocationTargetException) {
|
||||
throw ite.getCause() ?: ite
|
||||
throw ite.cause ?: ite
|
||||
}
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
@@ -228,7 +225,7 @@ object REFLECTION_EVAL : Eval {
|
||||
assertTrue(fieldDesc.isStatic)
|
||||
val field = findClass(fieldDesc).findField(fieldDesc)
|
||||
assertNotNull("Field not found: $fieldDesc", field)
|
||||
assertTrue("Field is not static: $field", (field!!.getModifiers() and Modifier.STATIC) != 0)
|
||||
assertTrue("Field is not static: $field", (field!!.modifiers and Modifier.STATIC) != 0)
|
||||
return field
|
||||
}
|
||||
|
||||
@@ -308,7 +305,7 @@ object REFLECTION_EVAL : Eval {
|
||||
class ReflectionLookup(val classLoader: ClassLoader) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun findClass(asmType: Type): Class<*>? {
|
||||
return when (asmType.getSort()) {
|
||||
return when (asmType.sort) {
|
||||
Type.BOOLEAN -> java.lang.Boolean.TYPE
|
||||
Type.BYTE -> java.lang.Byte.TYPE
|
||||
Type.SHORT -> java.lang.Short.TYPE
|
||||
@@ -317,8 +314,8 @@ class ReflectionLookup(val classLoader: ClassLoader) {
|
||||
Type.LONG -> java.lang.Long.TYPE
|
||||
Type.FLOAT -> java.lang.Float.TYPE
|
||||
Type.DOUBLE -> java.lang.Double.TYPE
|
||||
Type.OBJECT -> classLoader.loadClass(asmType.getInternalName().replace('/', '.'))
|
||||
Type.ARRAY -> Class.forName(asmType.getDescriptor().replace('/', '.'))
|
||||
Type.OBJECT -> classLoader.loadClass(asmType.internalName.replace('/', '.'))
|
||||
Type.ARRAY -> Class.forName(asmType.descriptor.replace('/', '.'))
|
||||
else -> throw UnsupportedOperationException("Unsupported type: $asmType")
|
||||
}
|
||||
}
|
||||
@@ -326,14 +323,14 @@ class ReflectionLookup(val classLoader: ClassLoader) {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun Class<Any>.findMethod(methodDesc: MethodDescription): Method? {
|
||||
for (declared in getDeclaredMethods()) {
|
||||
for (declared in declaredMethods) {
|
||||
if (methodDesc.matches(declared)) return declared
|
||||
}
|
||||
|
||||
val fromSuperClass = (getSuperclass() as Class<Any>).findMethod(methodDesc)
|
||||
val fromSuperClass = (superclass as Class<Any>).findMethod(methodDesc)
|
||||
if (fromSuperClass != null) return fromSuperClass
|
||||
|
||||
for (supertype in getInterfaces()) {
|
||||
for (supertype in interfaces) {
|
||||
val fromSuper = (supertype as Class<Any>).findMethod(methodDesc)
|
||||
if (fromSuper != null) return fromSuper
|
||||
}
|
||||
@@ -343,15 +340,15 @@ fun Class<Any>.findMethod(methodDesc: MethodDescription): Method? {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun Class<Any>.findConstructor(methodDesc: MethodDescription): Constructor<Any?>? {
|
||||
for (declared in getDeclaredConstructors()) {
|
||||
for (declared in declaredConstructors) {
|
||||
if (methodDesc.matches(declared)) return declared as Constructor<Any?>
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun MethodDescription.matches(ctor: Constructor<*>): Boolean {
|
||||
val methodParams = ctor.getParameterTypes()!!
|
||||
if (parameterTypes.size() != methodParams.size()) return false
|
||||
val methodParams = ctor.parameterTypes!!
|
||||
if (parameterTypes.size != methodParams.size) return false
|
||||
for ((i, p) in parameterTypes.withIndex()) {
|
||||
if (!p.matches(methodParams[i])) return false
|
||||
}
|
||||
@@ -360,30 +357,30 @@ fun MethodDescription.matches(ctor: Constructor<*>): Boolean {
|
||||
}
|
||||
|
||||
fun MethodDescription.matches(method: Method): Boolean {
|
||||
if (name != method.getName()) return false
|
||||
if (name != method.name) return false
|
||||
|
||||
val methodParams = method.getParameterTypes()!!
|
||||
if (parameterTypes.size() != methodParams.size()) return false
|
||||
val methodParams = method.parameterTypes!!
|
||||
if (parameterTypes.size != methodParams.size) return false
|
||||
for ((i, p) in parameterTypes.withIndex()) {
|
||||
if (!p.matches(methodParams[i])) return false
|
||||
}
|
||||
|
||||
return returnType.matches(method.getReturnType()!!)
|
||||
return returnType.matches(method.returnType!!)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun Class<Any>.findField(fieldDesc: FieldDescription): Field? {
|
||||
for (declared in getDeclaredFields()) {
|
||||
for (declared in declaredFields) {
|
||||
if (fieldDesc.matches(declared)) return declared
|
||||
}
|
||||
|
||||
val superclass = getSuperclass()
|
||||
val superclass = superclass
|
||||
if (superclass != null) {
|
||||
val fromSuperClass = (superclass as Class<Any>).findField(fieldDesc)
|
||||
if (fromSuperClass != null) return fromSuperClass
|
||||
}
|
||||
|
||||
for (supertype in getInterfaces()) {
|
||||
for (supertype in interfaces) {
|
||||
val fromSuper = (supertype as Class<Any>).findField(fieldDesc)
|
||||
if (fromSuper != null) return fromSuper
|
||||
}
|
||||
@@ -392,9 +389,9 @@ fun Class<Any>.findField(fieldDesc: FieldDescription): Field? {
|
||||
}
|
||||
|
||||
fun FieldDescription.matches(field: Field): Boolean {
|
||||
if (name != field.getName()) return false
|
||||
if (name != field.name) return false
|
||||
|
||||
return fieldType.matches(field.getType()!!)
|
||||
return fieldType.matches(field.type!!)
|
||||
}
|
||||
|
||||
fun Type.matches(_class: Class<*>): Boolean = this == Type.getType(_class)
|
||||
@@ -16,29 +16,28 @@
|
||||
|
||||
package org.jetbrains.eval4j.test
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import junit.framework.TestCase
|
||||
import junit.framework.TestSuite
|
||||
import org.jetbrains.eval4j.ExceptionThrown
|
||||
import org.jetbrains.eval4j.InterpreterResult
|
||||
import org.jetbrains.eval4j.ObjectValue
|
||||
import org.jetbrains.eval4j.ValueReturned
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader
|
||||
import org.jetbrains.org.objectweb.asm.ClassVisitor
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.ASM5
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import java.lang.reflect.Modifier
|
||||
import org.jetbrains.eval4j.*
|
||||
import org.junit.Assert.*
|
||||
import junit.framework.TestSuite
|
||||
import junit.framework.TestCase
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Constructor
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
import java.lang.reflect.Array as JArray
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
|
||||
fun buildTestSuite(
|
||||
create: (MethodNode, Class<*>, InterpreterResult?) -> TestCase
|
||||
): TestSuite {
|
||||
val suite = TestSuite()
|
||||
|
||||
val ownerClass = javaClass<TestData>()
|
||||
val inputStream = ownerClass.getClassLoader()!!.getResourceAsStream(ownerClass.getInternalName() + ".class")!!
|
||||
val ownerClass = TestData::class.java
|
||||
val inputStream = ownerClass.classLoader!!.getResourceAsStream(ownerClass.getInternalName() + ".class")!!
|
||||
|
||||
ClassReader(inputStream).accept(object : ClassVisitor(ASM5) {
|
||||
|
||||
@@ -61,27 +60,27 @@ private fun buildTestCase(ownerClass: Class<TestData>,
|
||||
methodNode: MethodNode,
|
||||
create: (MethodNode, Class<out Any?>, InterpreterResult?) -> TestCase): TestCase? {
|
||||
var expected: InterpreterResult? = null
|
||||
for (method in ownerClass.getDeclaredMethods()) {
|
||||
if (method.getName() == methodNode.name) {
|
||||
val isStatic = (method.getModifiers() and Modifier.STATIC) != 0
|
||||
if (method.getParameterTypes()!!.size() > 0) {
|
||||
for (method in ownerClass.declaredMethods) {
|
||||
if (method.name == methodNode.name) {
|
||||
val isStatic = (method.modifiers and Modifier.STATIC) != 0
|
||||
if (method.parameterTypes!!.size > 0) {
|
||||
println("Skipping method with parameters: $method")
|
||||
}
|
||||
else if (!isStatic && !method.getName()!!.startsWith("test")) {
|
||||
else if (!isStatic && !method.name!!.startsWith("test")) {
|
||||
println("Skipping instance method (should be started with 'test') : $method")
|
||||
}
|
||||
else {
|
||||
method.setAccessible(true)
|
||||
method.isAccessible = true
|
||||
try {
|
||||
val result = method.invoke(if (isStatic) null else ownerClass.newInstance())
|
||||
val returnType = Type.getType(method.getReturnType()!!)
|
||||
val returnType = Type.getType(method.returnType!!)
|
||||
expected = ValueReturned(objectToValue(result, returnType))
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
println("Skipping $method: $e")
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
val cause = e.getCause() ?: e
|
||||
val cause = e.cause ?: e
|
||||
expected = ExceptionThrown(objectToValue(cause, Type.getType(cause.javaClass)) as ObjectValue, ExceptionThrown.ExceptionKind.FROM_EVALUATOR)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user