diff --git a/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/interpreter.kt b/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/interpreter.kt index 6974f08cff0..b21457d1179 100644 --- a/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/interpreter.kt +++ b/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/interpreter.kt @@ -82,23 +82,21 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter( BIPUSH, SIPUSH -> int((insn as IntInsnNode).operand) LDC -> { - val cst = ((insn as LdcInsnNode)).cst - when (cst) { + when (val cst = ((insn as LdcInsnNode)).cst) { is Int -> int(cst) is Float -> float(cst) is Long -> long(cst) is Double -> double(cst) is String -> eval.loadString(cst) is Type -> { - val sort = cst.sort - when (sort) { + when (cst.sort) { Type.OBJECT, Type.ARRAY -> eval.loadClass(cst) Type.METHOD -> throw UnsupportedByteCodeException("Method handles are not supported") - else -> throw UnsupportedByteCodeException("Illegal LDC constant " + cst) + else -> throw UnsupportedByteCodeException("Illegal LDC constant $cst") } } is Handle -> throw UnsupportedByteCodeException("Method handles are not supported") - else -> throw UnsupportedByteCodeException("Illegal LDC constant " + cst) + else -> throw UnsupportedByteCodeException("Illegal LDC constant $cst") } } JSR -> LabelValue((insn as JumpInsnNode).label) @@ -157,13 +155,13 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter( NEWARRAY -> { val typeStr = when ((insn as IntInsnNode).operand) { T_BOOLEAN -> "[Z" - T_CHAR -> "[C" - T_BYTE -> "[B" - T_SHORT -> "[S" - T_INT -> "[I" - T_FLOAT -> "[F" - T_DOUBLE -> "[D" - T_LONG -> "[J" + T_CHAR -> "[C" + T_BYTE -> "[B" + T_SHORT -> "[S" + T_INT -> "[I" + T_FLOAT -> "[F" + T_DOUBLE -> "[D" + T_LONG -> "[J" else -> throw AnalyzerException(insn, "Invalid array type") } eval.newArray(Type.getType(typeStr), value.int) @@ -310,11 +308,13 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter( val l1 = value1.long val l2 = value2.long - int(when { - l1 > l2 -> 1 - l1 == l2 -> 0 - else -> -1 - }) + int( + when { + l1 > l2 -> 1 + l1 == l2 -> 0 + else -> -1 + } + ) } FCMPL, @@ -322,13 +322,15 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter( val l1 = value1.float val l2 = value2.float - int(when { - l1 > l2 -> 1 - l1 == l2 -> 0 - l1 < l2 -> -1 - // one of them is NaN - else -> if (insn.opcode == FCMPG) 1 else -1 - }) + int( + when { + l1 > l2 -> 1 + l1 == l2 -> 0 + l1 < l2 -> -1 + // one of them is NaN + else -> if (insn.opcode == FCMPG) 1 else -1 + } + ) } DCMPL, @@ -336,13 +338,15 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter( val l1 = value1.double val l2 = value2.double - int(when { - l1 > l2 -> 1 - l1 == l2 -> 0 - l1 < l2 -> -1 - // one of them is NaN - else -> if (insn.opcode == DCMPG) 1 else -1 - }) + int( + when { + l1 > l2 -> 1 + l1 == l2 -> 0 + l1 < l2 -> -1 + // one of them is NaN + else -> if (insn.opcode == DCMPG) 1 else -1 + } + ) } IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE -> { @@ -393,10 +397,10 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter( INVOKEVIRTUAL, INVOKESPECIAL, INVOKEINTERFACE -> { eval.invokeMethod( - values[0], - MethodDescription(insn as MethodInsnNode), - values.subList(1, values.size), - insn.opcode == INVOKESPECIAL + values[0], + MethodDescription(insn as MethodInsnNode), + values.subList(1, values.size), + insn.opcode == INVOKESPECIAL ) } diff --git a/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/interpreterLoop.kt b/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/interpreterLoop.kt index ac3cc9fd17e..9799b911343 100644 --- a/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/interpreterLoop.kt +++ b/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/interpreterLoop.kt @@ -28,7 +28,7 @@ interface InterpreterResult { override fun toString(): String } -class ExceptionThrown(val exception: ObjectValue, val kind: ExceptionKind): InterpreterResult { +class ExceptionThrown(val exception: ObjectValue, val kind: ExceptionKind) : InterpreterResult { override fun toString(): String = "Thrown $exception: $kind" enum class ExceptionKind { @@ -38,11 +38,11 @@ class ExceptionThrown(val exception: ObjectValue, val kind: ExceptionKind): Inte } } -data class ValueReturned(val result: Value): InterpreterResult { +data class ValueReturned(val result: Value) : InterpreterResult { override fun toString(): String = "Returned $result" } -class AbnormalTermination(val message: String): InterpreterResult { +class AbnormalTermination(val message: String) : InterpreterResult { override fun toString(): String = "Terminated abnormally: $message" } @@ -60,7 +60,7 @@ interface InterpretationEventHandler { fun exceptionCaught(currentState: Frame, currentInsn: AbstractInsnNode, exception: Value): InterpreterResult? } -abstract class ThrownFromEvalExceptionBase(cause: Throwable): RuntimeException(cause) { +abstract class ThrownFromEvalExceptionBase(cause: Throwable) : RuntimeException(cause) { override fun toString(): String = "Thrown by evaluator: ${cause}" } @@ -69,15 +69,15 @@ class BrokenCode(cause: Throwable) : ThrownFromEvalExceptionBase(cause) // Interpreting exceptions should not be sent to EA class Eval4JInterpretingException(override val cause: Throwable) : RuntimeException(cause) -class ThrownFromEvaluatedCodeException(val exception: ObjectValue): RuntimeException() { +class ThrownFromEvaluatedCodeException(val exception: ObjectValue) : RuntimeException() { override fun toString(): String = "Thrown from evaluated code: $exception" } fun interpreterLoop( - m: MethodNode, - initialState: Frame, - eval: Eval, - handler: InterpretationEventHandler = InterpretationEventHandler.NONE + m: MethodNode, + initialState: Frame, + eval: Eval, + handler: InterpretationEventHandler = InterpretationEventHandler.NONE ): InterpreterResult { val firstInsn = m.instructions.first if (firstInsn == null) throw IllegalArgumentException("Empty method") @@ -93,7 +93,7 @@ fun interpreterLoop( val frame = Frame(initialState) val handlers = computeHandlers(m) - class ResultException(val result: InterpreterResult): RuntimeException() + class ResultException(val result: InterpreterResult) : RuntimeException() fun exceptionCaught(exceptionValue: Value, instanceOf: (Type) -> Boolean): Boolean { val catchBlocks = handlers[m.instructions.indexOf(currentInsn)] ?: listOf() @@ -114,23 +114,21 @@ fun interpreterLoop( return false } - fun exceptionCaught(exceptionValue: Value): Boolean = exceptionCaught(exceptionValue) { - exceptionType -> eval.isInstanceOf(exceptionValue, exceptionType) + fun exceptionCaught(exceptionValue: Value): Boolean = exceptionCaught(exceptionValue) { exceptionType -> + eval.isInstanceOf(exceptionValue, exceptionType) } fun exceptionFromEvalCaught(exception: Throwable, exceptionValue: Value): Boolean { - return exceptionCaught(exceptionValue) { - exceptionType -> + return exceptionCaught(exceptionValue) { exceptionType -> try { val exceptionClass = exception::class.java val _class = Class.forName( - exceptionType.internalName.replace('/', '.'), - true, - exceptionClass.classLoader + exceptionType.internalName.replace('/', '.'), + true, + exceptionClass.classLoader ) _class.isAssignableFrom(exceptionClass) - } - catch (e: ClassNotFoundException) { + } catch (e: ClassNotFoundException) { // If the class is not available in this VM, it can not be a superclass of an exception trown in it false } @@ -164,16 +162,16 @@ fun interpreterLoop( } // TODO: switch - LOOKUPSWITCH -> UnsupportedByteCodeException("LOOKUPSWITCH is not supported yet") - TABLESWITCH -> UnsupportedByteCodeException("TABLESWITCH is not supported yet") + LOOKUPSWITCH -> throw UnsupportedByteCodeException("LOOKUPSWITCH is not supported yet") + TABLESWITCH -> throw UnsupportedByteCodeException("TABLESWITCH is not supported yet") IRETURN, LRETURN, FRETURN, DRETURN, ARETURN -> { val value = frame.getStackTop() val expectedType = Type.getReturnType(m.desc) if (expectedType.sort == Type.OBJECT || expectedType.sort == Type.ARRAY) { val coerced = if (value != NULL_VALUE && value.asmType != expectedType) - ObjectValue(value.obj(), expectedType) - else value + ObjectValue(value.obj(), expectedType) + else value return ValueReturned(coerced) } if (value.asmType != expectedType) { @@ -216,24 +214,25 @@ fun interpreterLoop( } // Workaround for a bug in Kotlin: NoPatterMatched exception is thrown otherwise! - else -> {} + else -> { + } } try { frame.execute(currentInsn, interpreter) - } - catch (e: ThrownFromEvalExceptionBase) { + } catch (e: ThrownFromEvalExceptionBase) { val exception = e.cause!! val exceptionValue = ObjectValue(exception, Type.getType(exception::class.java)) - val handled = handler.exceptionThrown(frame, currentInsn, - exceptionValue) + val handled = handler.exceptionThrown( + frame, currentInsn, + exceptionValue + ) if (handled != null) return handled if (exceptionFromEvalCaught(exception, exceptionValue)) continue@loop val exceptionType = if (e is BrokenCode) ExceptionKind.BROKEN_CODE else ExceptionKind.FROM_EVALUATOR return ExceptionThrown(exceptionValue, exceptionType) - } - catch (e: ThrownFromEvaluatedCodeException) { + } catch (e: ThrownFromEvaluatedCodeException) { val handled = handler.exceptionThrown(frame, currentInsn, e.exception) if (handled != null) return handled if (exceptionCaught(e.exception)) continue@loop @@ -247,23 +246,24 @@ fun interpreterLoop( goto(currentInsn.next) } - } - catch(e: ResultException) { + } catch (e: ResultException) { return e.result } } -private fun Frame.getStackTop(i: Int = 0) = this.getStack(this.stackSize - 1 - i) ?: throwBrokenCodeException(IllegalArgumentException("Couldn't get value with index = $i from top of stack")) +private fun Frame.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?> { val insns = m.instructions - val handlers = Array?>(insns.size()) {null} + val handlers = Array?>(insns.size()) { null } for (tcb in m.tryCatchBlocks) { val begin = insns.indexOf(tcb.start) val end = insns.indexOf(tcb.end) - for (i in begin..end - 1) { - val insnHandlers = handlers[i] ?: ArrayList() + for (i in begin until end) { + val insnHandlers = handlers[i] ?: ArrayList() handlers[i] = insnHandlers insnHandlers.add(tcb) diff --git a/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt b/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt index afdf256f518..3721f5fe19b 100644 --- a/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt +++ b/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt @@ -32,21 +32,21 @@ private val OBJECT = Type.getType(Any::class.java) private val BOOTSTRAP_CLASS_DESCRIPTORS = setOf("Ljava/lang/String;", "Ljava/lang/ClassLoader;", "Ljava/lang/Class;") class JDIEval( - private val vm: VirtualMachine, - private val defaultClassLoader: ClassLoaderReference?, - private val thread: ThreadReference, - private val invokePolicy: Int + private val vm: VirtualMachine, + private val defaultClassLoader: ClassLoaderReference?, + private val thread: ThreadReference, + private val invokePolicy: Int ) : Eval { private val primitiveTypes = mapOf( - 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).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() + 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).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() ) private val isJava8OrLater = StringUtil.compareVersionNumbers(vm.version(), "1.8") >= 0 @@ -55,9 +55,9 @@ class JDIEval( return loadClass(classType, defaultClassLoader) } - fun loadClass(classType: Type, classLoader: ClassLoaderReference?): Value { + private fun loadClass(classType: Type, classLoader: ClassLoaderReference?): Value { val loadedClasses = vm.classesByName(classType.internalName) - if (!loadedClasses.isEmpty()) { + if (loadedClasses.isNotEmpty()) { for (loadedClass in loadedClasses) { if (loadedClass.isPrepared && (classType.descriptor in BOOTSTRAP_CLASS_DESCRIPTORS || loadedClass.classLoader() == classLoader)) { return loadedClass.classObject().asValue() @@ -66,33 +66,32 @@ class JDIEval( } if (classLoader == null) { return invokeStaticMethod( - MethodDescription( - CLASS.internalName, - "forName", - "(Ljava/lang/String;)Ljava/lang/Class;", - true - ), - listOf(vm.mirrorOf(classType.internalName.replace('/', '.')).asValue()) + MethodDescription( + CLASS.internalName, + "forName", + "(Ljava/lang/String;)Ljava/lang/Class;", + true + ), + listOf(vm.mirrorOf(classType.internalName.replace('/', '.')).asValue()) ) - } - else { + } else { return invokeStaticMethod( - MethodDescription( - CLASS.internalName, - "forName", - "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", - true - ), - listOf( - vm.mirrorOf(classType.internalName.replace('/', '.')).asValue(), - boolean(true), - classLoader.asValue() - ) + MethodDescription( + CLASS.internalName, + "forName", + "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", + true + ), + listOf( + vm.mirrorOf(classType.internalName.replace('/', '.')).asValue(), + boolean(true), + classLoader.asValue() + ) ) } } - fun loadClassByName(name: String, classLoader: ClassLoaderReference): jdi_Type { + private fun loadClassByName(name: String, classLoader: ClassLoaderReference): jdi_Type { val dimensions = name.count { it == '[' } val baseTypeName = if (dimensions > 0) name.substring(0, name.indexOf('[')) else name @@ -115,20 +114,24 @@ class JDIEval( "Can't check isInstanceOf() for non-object type $targetType" } - val _class = loadClass(targetType) + val clazz = loadClass(targetType) return invokeMethod( - _class, - MethodDescription( - CLASS.internalName, - "isInstance", - "(Ljava/lang/Object;)Z", - false - ), - listOf(value)).boolean + clazz, + MethodDescription( + CLASS.internalName, + "isInstance", + "(Ljava/lang/Object;)Z", + false + ), + listOf(value) + ).boolean } - fun Type.asReferenceType(classLoader: ClassLoaderReference? = this@JDIEval.defaultClassLoader): ReferenceType = loadClass(this, classLoader).jdiClass!!.reflectedType() - fun Type.asArrayType(classLoader: ClassLoaderReference? = this@JDIEval.defaultClassLoader): ArrayType = asReferenceType(classLoader) as ArrayType + private fun Type.asReferenceType(classLoader: ClassLoaderReference? = this@JDIEval.defaultClassLoader): ReferenceType = + loadClass(this, classLoader).jdiClass!!.reflectedType() + + private fun Type.asArrayType(classLoader: ClassLoaderReference? = this@JDIEval.defaultClassLoader): ArrayType = + asReferenceType(classLoader) as ArrayType override fun newArray(arrayType: Type, size: Int): Value { val jdiArrayType = arrayType.asArrayType() @@ -143,11 +146,11 @@ class JDIEval( private fun fillArray(elementType: Type, size: Int, nestedSizes: List): Value { val arr = newArray(Type.getType("[" + elementType.descriptor), size) - if (!nestedSizes.isEmpty()) { + if (nestedSizes.isNotEmpty()) { val nestedElementType = elementType.arrayElementType val nestedSize = nestedSizes[0] val tail = nestedSizes.drop(1) - for (i in 0..size - 1) { + for (i in 0 until size) { setArrayElement(arr, int(i), fillArray(nestedElementType, nestedSize, tail)) } } @@ -167,8 +170,7 @@ class JDIEval( override fun getArrayElement(array: Value, index: Value): Value { try { return array.array().getValue(index.int).asValue() - } - catch (e: IndexOutOfBoundsException) { + } catch (e: IndexOutOfBoundsException) { throwInterpretingException(ArrayIndexOutOfBoundsException(e.message)) } } @@ -176,8 +178,7 @@ class JDIEval( override fun setArrayElement(array: Value, index: Value, newValue: Value) { try { return array.array().setValue(index.int, newValue.asJdiValue(vm, array.asmType.arrayElementType)) - } - catch (e: IndexOutOfBoundsException) { + } catch (e: IndexOutOfBoundsException) { throwInterpretingException(ArrayIndexOutOfBoundsException(e.message)) } } @@ -210,13 +211,11 @@ class JDIEval( throwBrokenCodeException(NoSuchFieldError("Can't modify a final field: $field")) } - val _class = field.declaringType() - if (_class !is ClassType) { - throwBrokenCodeException(NoSuchFieldError("Can't a field in a non-class: $field")) - } + val clazz = field.declaringType() as? ClassType + ?: throwBrokenCodeException(NoSuchFieldError("Can't a field in a non-class: $field")) val jdiValue = newValue.asJdiValue(vm, field.type().asType()) - mayThrow { _class.setValue(field, jdiValue) }.ifFail(field) + mayThrow { clazz.setValue(field, jdiValue) }.ifFail(field) } private fun findMethod(methodDesc: MethodDescription, clazz: ReferenceType = methodDesc.ownerType.asReferenceType()): Method { @@ -260,9 +259,9 @@ class JDIEval( name.startsWith(internalNameWithoutSuffix) && canBeMangledInternalName(name) && it.signature() == methodDesc.desc } - if (!internalMethods.isEmpty()) { - return internalMethods.singleOrNull() ?: - throwBrokenCodeException(IllegalArgumentException("Several internal methods found for $methodDesc")) + if (internalMethods.isNotEmpty()) { + return internalMethods.singleOrNull() + ?: throwBrokenCodeException(IllegalArgumentException("Several internal methods found for $methodDesc")) } } @@ -313,9 +312,11 @@ class JDIEval( try { receiver.getValue(field) } catch (e: IllegalArgumentException) { - throw IllegalArgumentException("Possibly incompatible types: " + - "field declaring type = ${field.declaringType()}, " + - "instance type = ${receiver.referenceType()}") + throw IllegalArgumentException( + "Possibly incompatible types: " + + "field declaring type = ${field.declaringType()}, " + + "instance type = ${receiver.referenceType()}" + ) } }.ifFail(field, receiver).asValue() } @@ -328,7 +329,7 @@ class JDIEval( mayThrow { receiver.setValue(field, jdiValue) } } - fun unboxType(boxedValue: Value, type: Type): Value { + private fun unboxType(boxedValue: Value, type: Type): Value { val method = when (type) { Type.INT_TYPE -> MethodDescription("java/lang/Integer", "intValue", "()I", false) Type.BOOLEAN_TYPE -> MethodDescription("java/lang/Boolean", "booleanValue", "()Z", false) @@ -343,29 +344,14 @@ class JDIEval( return invokeMethod(boxedValue, method, listOf(), true) } - fun boxType(value: Value): Value { - val method = when (value.asmType) { - Type.INT_TYPE -> MethodDescription("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false) - Type.BYTE_TYPE -> MethodDescription("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false) - Type.SHORT_TYPE -> MethodDescription("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false) - Type.LONG_TYPE -> MethodDescription("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false) - Type.BOOLEAN_TYPE -> MethodDescription("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", 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.DOUBLE_TYPE -> MethodDescription("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false) - else -> throw UnsupportedOperationException("Couldn't box non-primitive type ${value.asmType.internalName}") - } - return invokeStaticMethod(method, listOf(value)) - } - override fun invokeMethod(instance: Value, methodDesc: MethodDescription, arguments: List, invokespecial: Boolean): Value { if (invokespecial && methodDesc.name == "") { // Constructor call val ctor = findMethod(methodDesc) - val _class = (instance as NewObjectValue).asmType.asReferenceType() as ClassType + val clazz = (instance as NewObjectValue).asmType.asReferenceType() as ClassType val args = mapArguments(arguments, ctor.safeArgumentTypes()) args.disableCollection() - val result = mayThrow { _class.newInstance(thread, ctor, args, invokePolicy) }.ifFail(ctor) + val result = mayThrow { clazz.newInstance(thread, ctor, args, invokePolicy) }.ifFail(ctor) args.enableCollection() instance.value = result return result.asValue() @@ -388,8 +374,7 @@ class JDIEval( return if (invokespecial) { val method = findMethod(methodDesc) doInvokeMethod(obj, method, invokePolicy or ObjectReference.INVOKE_NONVIRTUAL) - } - else { + } else { val method = findMethod(methodDesc, obj.referenceType() ?: methodDesc.ownerType.asReferenceType()) doInvokeMethod(obj, method, invokePolicy) } @@ -415,36 +400,36 @@ class JDIEval( private fun invokeMethodWithReflection(ownerType: Type, instance: Value, args: List, methodDesc: MethodDescription): Value { val methodToInvoke = invokeMethod( - loadClass(ownerType), - MethodDescription( - CLASS.internalName, - "getDeclaredMethod", - "(Ljava/lang/String;[L${CLASS.internalName};)Ljava/lang/reflect/Method;", - true - ), - listOf(vm.mirrorOf(methodDesc.name).asValue(), *methodDesc.parameterTypes.map { loadClass(it) }.toTypedArray()) + loadClass(ownerType), + MethodDescription( + CLASS.internalName, + "getDeclaredMethod", + "(Ljava/lang/String;[L${CLASS.internalName};)Ljava/lang/reflect/Method;", + true + ), + listOf(vm.mirrorOf(methodDesc.name).asValue(), *methodDesc.parameterTypes.map { loadClass(it) }.toTypedArray()) ) invokeMethod( - methodToInvoke, - MethodDescription( - Type.getType(AccessibleObject::class.java).internalName, - "setAccessible", - "(Z)V", - true - ), - listOf(vm.mirrorOf(true).asValue()) + methodToInvoke, + MethodDescription( + Type.getType(AccessibleObject::class.java).internalName, + "setAccessible", + "(Z)V", + true + ), + listOf(vm.mirrorOf(true).asValue()) ) val invocationResult = invokeMethod( - methodToInvoke, - MethodDescription( - methodToInvoke.asmType.internalName, - "invoke", - "(L${OBJECT.internalName};[L${OBJECT.internalName};)L${OBJECT.internalName};", - true - ), - listOf(instance, mirrorOfArgs(args)) + methodToInvoke, + MethodDescription( + methodToInvoke.asmType.internalName, + "invoke", + "(L${OBJECT.internalName};[L${OBJECT.internalName};)L${OBJECT.internalName};", + true + ), + listOf(instance, mirrorOfArgs(args)) ) if (methodDesc.returnType.sort != Type.OBJECT && methodDesc.returnType.sort != Type.ARRAY && methodDesc.returnType.sort != Type.VOID) { @@ -501,7 +486,7 @@ class JDIEval( "float" -> primitiveTypes.getValue(Type.FLOAT_TYPE.className) "double" -> primitiveTypes.getValue(Type.DOUBLE_TYPE.className) else -> virtualMachine().classesByName(name).firstOrNull() - ?: throw IllegalStateException("Unknown class $name") + ?: throw IllegalStateException("Unknown class $name") } } } @@ -510,18 +495,16 @@ class JDIEval( @Suppress("unused") private sealed class JdiOperationResult { - class Fail(val cause: Exception): JdiOperationResult() - class OK(val value: T): JdiOperationResult() + class Fail(val cause: Exception) : JdiOperationResult() + class OK(val value: T) : JdiOperationResult() } private fun mayThrow(f: () -> T): JdiOperationResult { - try { - return JdiOperationResult.OK(f()) - } - catch (e: IllegalArgumentException) { - return JdiOperationResult.Fail(e) - } - catch (e: InvocationException) { + return try { + JdiOperationResult.OK(f()) + } catch (e: IllegalArgumentException) { + JdiOperationResult.Fail(e) + } catch (e: InvocationException) { throw ThrownFromEvaluatedCodeException(e.exception().asValue()) } } @@ -535,13 +518,12 @@ private fun JdiOperationResult.ifFail(member: TypeComponent, thisObj: Obj } private fun JdiOperationResult.ifFail(lazyMessage: () -> String): T { - return when(this) { + return when (this) { is JdiOperationResult.OK -> this.value is JdiOperationResult.Fail -> { if (cause is IllegalArgumentException) { throwBrokenCodeException(IllegalArgumentException(lazyMessage(), this.cause)) - } - else { + } else { throwBrokenCodeException(IllegalStateException(lazyMessage(), this.cause)) } } diff --git a/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/jdi/jdiValues.kt b/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/jdi/jdiValues.kt index 78d89672a3c..f0b08a99ca0 100644 --- a/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/jdi/jdiValues.kt +++ b/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/jdi/jdiValues.kt @@ -62,7 +62,7 @@ fun makeInitialFrame(methodNode: MethodNode, arguments: List): Frame class FieldDescription( - ownerInternalName: String, - name: String, - desc: String, - isStatic: Boolean -) : MemberDescription(ownerInternalName, name, desc, isStatic) - -fun FieldDescription(insn: FieldInsnNode): FieldDescription = - FieldDescription( - insn.owner, - insn.name, - insn.desc, - insn.opcode in setOf(GETSTATIC, PUTSTATIC) - ) + ownerInternalName: String, + name: String, + desc: String, + isStatic: Boolean +) : MemberDescription(ownerInternalName, name, desc, isStatic) { + constructor(insn: FieldInsnNode) : this(insn.owner, insn.name, insn.desc, insn.opcode in setOf(GETSTATIC, PUTSTATIC)) +} val FieldDescription.fieldType: Type get() = Type.getType(desc) diff --git a/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/values.kt b/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/values.kt index ddcd04a9725..5734469d7f6 100644 --- a/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/values.kt +++ b/idea/jvm-debugger/eval4j/src/org/jetbrains/eval4j/values.kt @@ -27,7 +27,8 @@ interface Value : org.jetbrains.org.objectweb.asm.tree.analysis.Value { override fun toString(): String } -object NOT_A_VALUE: Value { +@Suppress("ClassName") +object NOT_A_VALUE : Value { override val asmType = Type.getObjectType("") override val valid = false override fun getSize(): Int = 1 @@ -35,7 +36,8 @@ object NOT_A_VALUE: Value { override fun toString() = "NOT_A_VALUE" } -object VOID_VALUE: Value { +@Suppress("ClassName") +object VOID_VALUE : Value { override val asmType: Type = Type.VOID_TYPE override val valid: Boolean = false override fun toString() = "VOID_VALUE" @@ -48,13 +50,13 @@ fun makeNotInitializedValue(t: Type): Value? { } } -class NotInitialized(override val asmType: Type): Value { +class NotInitialized(override val asmType: Type) : Value { override val valid = false override fun toString() = "NotInitialized: $asmType" } abstract class AbstractValueBase( - override val asmType: Type + override val asmType: Type ) : Value { override val valid = true abstract val value: V @@ -72,24 +74,22 @@ abstract class AbstractValueBase( } } -abstract class AbstractValue( - override val value: V, - asmType: Type -) : AbstractValueBase(asmType) +abstract class AbstractValue(override val value: V, asmType: Type) : AbstractValueBase(asmType) -class IntValue(value: Int, asmType: Type): AbstractValue(value, asmType) -class LongValue(value: Long): AbstractValue(value, Type.LONG_TYPE) -class FloatValue(value: Float): AbstractValue(value, Type.FLOAT_TYPE) -class DoubleValue(value: Double): AbstractValue(value, Type.DOUBLE_TYPE) -open class ObjectValue(value: Any?, asmType: Type): AbstractValue(value, asmType) -class NewObjectValue(asmType: Type): ObjectValue(null, asmType) { +class IntValue(value: Int, asmType: Type) : AbstractValue(value, asmType) +class LongValue(value: Long) : AbstractValue(value, Type.LONG_TYPE) +class FloatValue(value: Float) : AbstractValue(value, Type.FLOAT_TYPE) +class DoubleValue(value: Double) : AbstractValue(value, Type.DOUBLE_TYPE) +open class ObjectValue(value: Any?, asmType: Type) : AbstractValue(value, asmType) + +class NewObjectValue(asmType: Type) : ObjectValue(null, asmType) { override var value: Any? = null get(): Any? { return field ?: throw IllegalStateException("Trying to access an unitialized object: $this") } } -class LabelValue(value: LabelNode): AbstractValue(value, Type.VOID_TYPE) +class LabelValue(value: LabelNode) : AbstractValue(value, Type.VOID_TYPE) fun boolean(v: Boolean) = IntValue(if (v) 1 else 0, Type.BOOLEAN_TYPE) fun byte(v: Byte) = IntValue(v.toInt(), Type.BYTE_TYPE) @@ -99,7 +99,6 @@ fun int(v: Int) = IntValue(v, Type.INT_TYPE) fun long(v: Long) = LongValue(v) fun float(v: Float) = FloatValue(v) fun double(v: Double) = DoubleValue(v) -//fun obj(v: T, t: Type = if (v != null) Type.getType(v.javaClass) else Type.getType(Any::class.java)) = ObjectValue(v, t) val NULL_VALUE = ObjectValue(null, Type.getObjectType("null")) @@ -108,12 +107,13 @@ val Value.int: Int get() = (this as IntValue).value val Value.long: Long get() = (this as LongValue).value val Value.float: Float get() = (this as FloatValue).value val Value.double: Double get() = (this as DoubleValue).value + fun Value.obj(expectedType: Type = asmType): Any? { - return when { - expectedType == Type.BOOLEAN_TYPE -> this.boolean - expectedType == Type.SHORT_TYPE -> (this as IntValue).int.toShort() - expectedType == Type.BYTE_TYPE -> (this as IntValue).int.toByte() - expectedType == Type.CHAR_TYPE -> (this as IntValue).int.toChar() + return when (expectedType) { + Type.BOOLEAN_TYPE -> this.boolean + Type.SHORT_TYPE -> (this as IntValue).int.toShort() + Type.BYTE_TYPE -> (this as IntValue).int.toByte() + Type.CHAR_TYPE -> (this as IntValue).int.toChar() else -> (this as AbstractValue<*>).value } }