From 42868b1364d071f664b9114d28cd8c3df335cc26 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Fri, 7 Apr 2017 18:16:17 +0300 Subject: [PATCH] Fix evaluate for internal functions (KT-15854) #KT-15854 Fixed --- .../src/org/jetbrains/eval4j/jdi/jdiEval.kt | 24 ++++++++++++++++--- .../tinyApp/outs/internalFunctionEvaluate.out | 8 +++++++ .../tinyApp/outs/internalProperty.out | 9 +++++++ .../internalFunctionEvaluate.kt | 14 +++++++++++ .../singleBreakpoint/internalProperty.kt | 17 +++++++++++++ ...KotlinEvaluateExpressionTestGenerated.java | 12 ++++++++++ 6 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 idea/testData/debugger/tinyApp/outs/internalFunctionEvaluate.out create mode 100644 idea/testData/debugger/tinyApp/outs/internalProperty.out create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/internalFunctionEvaluate.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/internalProperty.kt diff --git a/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt b/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt index 7c8c81c615a..141122343e5 100644 --- a/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt +++ b/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt @@ -204,14 +204,32 @@ class JDIEval( } private fun findMethod(methodDesc: MethodDescription, _class: ReferenceType = methodDesc.ownerType.asReferenceType()): Method { + val methodName = methodDesc.name val method = when (_class) { is ClassType -> - _class.concreteMethodByName(methodDesc.name, methodDesc.desc) + _class.concreteMethodByName(methodName, methodDesc.desc) else -> - _class.methodsByName(methodDesc.name, methodDesc.desc).firstOrNull() + _class.methodsByName(methodName, methodDesc.desc).firstOrNull() } - return method ?: throwBrokenCodeException(NoSuchMethodError("Method not found: $methodDesc")) + if (method != null) { + return method + } + + if (methodName.contains('$')) { + // Module name can be different for internal functions during evaluation and compilation + val internalNamePrefix = methodName.substringBefore('$') + '$' + val internalMethods = _class.visibleMethods().filter { + it.name().startsWith(internalNamePrefix) && it.signature() == methodDesc.desc + } + + if (!internalMethods.isEmpty()) { + return internalMethods.singleOrNull() ?: + throwBrokenCodeException(IllegalArgumentException("Several internal methods found for $methodDesc")) + } + } + + throwBrokenCodeException(NoSuchMethodError("Method not found: $methodDesc")) } override fun invokeStaticMethod(methodDesc: MethodDescription, arguments: List): Value { diff --git a/idea/testData/debugger/tinyApp/outs/internalFunctionEvaluate.out b/idea/testData/debugger/tinyApp/outs/internalFunctionEvaluate.out new file mode 100644 index 00000000000..b7fffbf4bf1 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/internalFunctionEvaluate.out @@ -0,0 +1,8 @@ +LineBreakpoint created at internalFunctionEvaluate.kt:10 +Run Java +Connected to the target VM +internalFunctionEvaluate.kt:10 +Compile bytecode for sc.f() +Disconnected from the target VM + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/internalProperty.out b/idea/testData/debugger/tinyApp/outs/internalProperty.out new file mode 100644 index 00000000000..2a3358ba327 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/internalProperty.out @@ -0,0 +1,9 @@ +LineBreakpoint created at internalProperty.kt:5 +Run Java +Connected to the target VM +internalProperty.kt:5 +Compile bytecode for MyClass().internalVal +Compile bytecode for MyClass().internalValWithGetter +Disconnected from the target VM + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/internalFunctionEvaluate.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/internalFunctionEvaluate.kt new file mode 100644 index 00000000000..db1067c9db6 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/internalFunctionEvaluate.kt @@ -0,0 +1,14 @@ +package internalFunctionEvaluate + +class SomeClass { + internal fun f(): Int = 42 +} + +fun main(args: Array) { + val sc = SomeClass() + //Breakpoint! + val x = 12 +} + +// EXPRESSION: sc.f() +// RESULT: 42: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/internalProperty.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/internalProperty.kt new file mode 100644 index 00000000000..7a6deb2a7f8 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/internalProperty.kt @@ -0,0 +1,17 @@ +package internalProperty + +fun main(args: Array) { + //Breakpoint! + args.size +} + +class MyClass { + internal val internalVal = 42 + internal val internalValWithGetter: Int get() = 24 +} + +// EXPRESSION: MyClass().internalVal +// RESULT: 42: I + +// EXPRESSION: MyClass().internalValWithGetter +// RESULT: 24: I \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java index 0c5055c4399..0247dfbf6f3 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -218,6 +218,18 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat doSingleBreakpointTest(fileName); } + @TestMetadata("internalFunctionEvaluate.kt") + public void testInternalFunctionEvaluate() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/internalFunctionEvaluate.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("internalProperty.kt") + public void testInternalProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/internalProperty.kt"); + doSingleBreakpointTest(fileName); + } + @TestMetadata("kt12206BasePropertyWithoutBackingField.kt") public void testKt12206BasePropertyWithoutBackingField() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt12206BasePropertyWithoutBackingField.kt");