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? {
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>?> {
+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.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)
}
}
+4 -4
View File
@@ -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
+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 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 {
+44 -47
View File
@@ -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)
}
}