Run Clean up on eval4j module

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