From 944b9b5b6c54101d5ddcdb42ca0e368cb3d1738a Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Fri, 14 Oct 2016 18:43:36 +0300 Subject: [PATCH] Evaluate overloaded toString() in watches for Kotlin classes with delegate properties (KT-14068) (cherry picked from commit 7774d2c) #KT-14068 Fixed --- ...otlinClassWithDelegatedPropertyRenderer.kt | 29 +++++++++++++-- .../delegatedPropertyInClassWithToString.out | 36 +++++++++++++++++++ .../delegatedPropertyInClassWithToString.kt | 21 +++++++++++ ...KotlinEvaluateExpressionTestGenerated.java | 6 ++++ 4 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 idea/testData/debugger/tinyApp/outs/delegatedPropertyInClassWithToString.out create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/delegatedPropertyInClassWithToString.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/render/KotlinClassWithDelegatedPropertyRenderer.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/render/KotlinClassWithDelegatedPropertyRenderer.kt index 26d7a6ccb7e..31c76ed0781 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/render/KotlinClassWithDelegatedPropertyRenderer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/render/KotlinClassWithDelegatedPropertyRenderer.kt @@ -16,13 +16,17 @@ package org.jetbrains.kotlin.idea.debugger.render +import com.intellij.debugger.DebuggerManagerEx import com.intellij.debugger.engine.DebuggerManagerThreadImpl import com.intellij.debugger.engine.evaluation.EvaluationContext +import com.intellij.debugger.settings.NodeRendererSettings import com.intellij.debugger.ui.impl.watch.MessageDescriptor import com.intellij.debugger.ui.impl.watch.NodeManagerImpl import com.intellij.debugger.ui.tree.DebuggerTreeNode +import com.intellij.debugger.ui.tree.ValueDescriptor import com.intellij.debugger.ui.tree.render.ChildrenBuilder import com.intellij.debugger.ui.tree.render.ClassRenderer +import com.intellij.debugger.ui.tree.render.DescriptorLabelListener import com.intellij.xdebugger.settings.XDebuggerSettingsManager import com.sun.jdi.ObjectReference import com.sun.jdi.ReferenceType @@ -34,8 +38,7 @@ import java.util.* import com.sun.jdi.Type as JdiType import org.jetbrains.org.objectweb.asm.Type as AsmType -class KotlinClassWithDelegatedPropertyRenderer : ClassRenderer() { - +class KotlinClassWithDelegatedPropertyRenderer(val rendererSettings: NodeRendererSettings) : ClassRenderer() { override fun isApplicable(jdiType: Type?): Boolean { if (!super.isApplicable(jdiType)) return false @@ -44,6 +47,28 @@ class KotlinClassWithDelegatedPropertyRenderer : ClassRenderer() { return jdiType.allFields().any { it.name().endsWith(JvmAbi.DELEGATED_PROPERTY_NAME_SUFFIX) } } + override fun calcLabel(descriptor: ValueDescriptor, + evaluationContext: EvaluationContext, + listener: DescriptorLabelListener): String { + val res = calcToStringLabel(descriptor, evaluationContext, listener) + if (res != null) { + return res + } + + return super.calcLabel(descriptor, evaluationContext, listener) + } + + private fun calcToStringLabel(descriptor: ValueDescriptor, evaluationContext: EvaluationContext, + listener: DescriptorLabelListener): String? { + val toStringRenderer = rendererSettings.toStringRenderer + if (toStringRenderer.isEnabled && DebuggerManagerEx.getInstanceEx(evaluationContext.project).context.isEvaluationPossible) { + if (toStringRenderer.isApplicable(descriptor.type)) { + return toStringRenderer.calcLabel(descriptor, evaluationContext, listener) + } + } + return null + } + override fun buildChildren(value: Value?, builder: ChildrenBuilder, context: EvaluationContext) { DebuggerManagerThreadImpl.assertIsManagerThread() diff --git a/idea/testData/debugger/tinyApp/outs/delegatedPropertyInClassWithToString.out b/idea/testData/debugger/tinyApp/outs/delegatedPropertyInClassWithToString.out new file mode 100644 index 00000000000..17450df2cbf --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/delegatedPropertyInClassWithToString.out @@ -0,0 +1,36 @@ +LineBreakpoint created at delegatedPropertyInClassWithToString.kt:8 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! delegatedPropertyInClassWithToString.DelegatedPropertyInClassWithToStringKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +delegatedPropertyInClassWithToString.kt:8 +package delegatedPropertyInClassWithToString + +import kotlin.reflect.KProperty + +fun main(args: Array) { + val a = A() + //Breakpoint! + args.size +} + +class A { + val prop by MyDelegate() + + override fun toString(): String = "KotlinTest" +} + +class MyDelegate { + operator fun getValue(t: Any?, p: KProperty<*>): Int = 1 +} + +// PRINT_FRAME + +Compile bytecode for args.size + frame = main:8, DelegatedPropertyInClassWithToStringKt {delegatedPropertyInClassWithToString} + local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = delegatedPropertyInClassWithToString.kt, 5) + local = a: delegatedPropertyInClassWithToString.A = {delegatedPropertyInClassWithToString.A@uniqueID}KotlinTest (sp = delegatedPropertyInClassWithToString.kt, 6) + field = prop$delegate: delegatedPropertyInClassWithToString.MyDelegate = {delegatedPropertyInClassWithToString.MyDelegate@uniqueID} (sp = delegatedPropertyInClassWithToString.kt, 12) + - Class has no fields + field = prop: int = 1 (sp = delegatedPropertyInClassWithToString.kt, 12) +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/delegatedPropertyInClassWithToString.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/delegatedPropertyInClassWithToString.kt new file mode 100644 index 00000000000..5752f67f84a --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/delegatedPropertyInClassWithToString.kt @@ -0,0 +1,21 @@ +package delegatedPropertyInClassWithToString + +import kotlin.reflect.KProperty + +fun main(args: Array) { + val a = A() + //Breakpoint! + args.size +} + +class A { + val prop by MyDelegate() + + override fun toString(): String = "KotlinTest" +} + +class MyDelegate { + operator fun getValue(t: Any?, p: KProperty<*>): Int = 1 +} + +// PRINT_FRAME 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 29bb33bad0b..fd577f7ed1e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -564,6 +564,12 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat doSingleBreakpointTest(fileName); } + @TestMetadata("delegatedPropertyInClassWithToString.kt") + public void testDelegatedPropertyInClassWithToString() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/delegatedPropertyInClassWithToString.kt"); + doSingleBreakpointTest(fileName); + } + @TestMetadata("delegatedPropertyInClassWoRenderer.kt") public void testDelegatedPropertyInClassWoRenderer() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/delegatedPropertyInClassWoRenderer.kt");