diff --git a/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt b/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt index 5304f15714f..7ac62ffe074 100644 --- a/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt +++ b/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt @@ -183,7 +183,7 @@ class JDIEval( override fun getStaticField(fieldDesc: FieldDescription): Value { val field = findStaticField(fieldDesc) - return mayThrow { field.declaringType().getValue(field) }.asValue() + return mayThrow { field.declaringType().getValue(field) }.ifFail(field).asValue() } override fun setStaticField(fieldDesc: FieldDescription, newValue: Value) { @@ -199,7 +199,7 @@ class JDIEval( } val jdiValue = newValue.asJdiValue(vm, field.type().asType()) - mayThrow { _class.setValue(field, jdiValue) } + mayThrow { _class.setValue(field, jdiValue) }.ifFail(field) } private fun findMethod(methodDesc: MethodDescription, _class: ReferenceType = methodDesc.ownerType.asReferenceType()): Method { @@ -231,7 +231,7 @@ class JDIEval( } args.disableCollection() - val result = mayThrow { _class.invokeMethod(thread, method, args, invokePolicy) } + val result = mayThrow { _class.invokeMethod(thread, method, args, invokePolicy) }.ifFail(method) args.enableCollection() return result.asValue() } @@ -240,7 +240,7 @@ class JDIEval( val field = findField(fieldDesc) val obj = instance.jdiObj.checkNull() - return mayThrow { obj.getValue(field) }.asValue() + return mayThrow { obj.getValue(field) }.ifFail(field, obj).asValue() } override fun setField(instance: Value, fieldDesc: FieldDescription, newValue: Value) { @@ -288,7 +288,7 @@ class JDIEval( val _class = (instance as NewObjectValue).asmType.asReferenceType() as ClassType val args = mapArguments(arguments, ctor.safeArgumentTypes()) args.disableCollection() - val result = mayThrow { _class.newInstance(thread, ctor, args, invokePolicy) } + val result = mayThrow { _class.newInstance(thread, ctor, args, invokePolicy) }.ifFail(ctor) args.enableCollection() instance.value = result return result.asValue() @@ -302,7 +302,7 @@ class JDIEval( } args.disableCollection() - val result = mayThrow { obj.invokeMethod(thread, method, args, policy) } + val result = mayThrow { obj.invokeMethod(thread, method, args, policy) }.ifFail(method, obj) args.enableCollection() return result.asValue() } @@ -403,11 +403,41 @@ class JDIEval( } } -fun mayThrow(f: () -> T): T { +private sealed class JdiOperationResult { + class Fail(val cause: Exception): JdiOperationResult() + class OK(val value: T): JdiOperationResult() +} + +private fun mayThrow(f: () -> T): JdiOperationResult { try { - return f() + return JdiOperationResult.OK(f()) + } + catch (e: IllegalArgumentException) { + return JdiOperationResult.Fail(e) } catch (e: InvocationException) { throw ThrownFromEvaluatedCodeException(e.exception().asValue()) } +} + +private fun memberInfo(member: TypeComponent, thisObj: ObjectReference?): String { + return "\nmember = $member\nobjectRef = $thisObj" +} + +private fun JdiOperationResult.ifFail(member: TypeComponent, thisObj: ObjectReference? = null): T { + return ifFail { memberInfo(member, thisObj) } +} + +private fun JdiOperationResult.ifFail(lazyMessage: () -> String): T { + return when(this) { + is JdiOperationResult.OK -> this.value + is JdiOperationResult.Fail -> { + if (cause is IllegalArgumentException) { + throwBrokenCodeException(IllegalArgumentException(lazyMessage(), this.cause)) + } + else { + throwBrokenCodeException(IllegalStateException(lazyMessage(), this.cause)) + } + } + } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt index ddcdbd0b669..631dc89bfc1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt @@ -301,6 +301,9 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour if (this.kind == ExceptionThrown.ExceptionKind.FROM_EVALUATED_CODE) { exception(InvocationException(this.exception.value as ObjectReference)) } + else if (this.kind == ExceptionThrown.ExceptionKind.BROKEN_CODE) { + throw exception.value as Throwable + } else { exception(exception.toString()) }