Evaluate Expression: fix for anonymous objects - expressions where anonymous type can be replaced with super type can be evaluated

This commit is contained in:
Natalia Ukhorskaya
2014-12-02 15:28:19 +03:00
parent b056fd7e2e
commit 3ab7c6c8e9
4 changed files with 55 additions and 0 deletions
@@ -76,6 +76,7 @@ import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.plugin.util.attachment.attachmentByPsiFile
import com.intellij.openapi.diagnostic.Attachment
import org.jetbrains.jet.plugin.util.attachment.mergeAttachments
import com.sun.jdi.ClassType
private val RECEIVER_NAME = "\$receiver"
private val THIS_NAME = "this"
@@ -346,6 +347,22 @@ private fun SuspendContext.getInvokePolicy(): Int {
return if (getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD) ObjectReference.INVOKE_SINGLE_THREADED else 0
}
private fun com.sun.jdi.Type?.isSubclass(superClassName: String): Boolean {
if (this !is ClassType) return false
if (allInterfaces().any { it.name() == superClassName }) {
return true
}
var superClass = this.superclass()
while (superClass != null) {
if (superClass.name() == superClassName) {
return true
}
superClass = superClass.superclass()
}
return false
}
fun EvaluationContextImpl.findLocalVariable(name: String, asmType: Type?, checkType: Boolean, failIfNotFound: Boolean): Value? {
val project = getDebugProcess().getProject()
val frame = getFrameProxy()?.getStackFrame()
@@ -355,6 +372,10 @@ fun EvaluationContextImpl.findLocalVariable(name: String, asmType: Type?, checkT
if (!shouldCheckType || asmType == null || value.asmType == asmType) return true
if (project == null) return false
if ((value.obj() as? com.sun.jdi.ObjectReference)?.referenceType().isSubclass(asmType.getClassName())) {
return true
}
val thisDesc = value.asmType.getClassDescriptor(project)
val expDesc = asmType.getClassDescriptor(project)
return thisDesc != null && expDesc != null && runReadAction { DescriptorUtils.isSubclass(thisDesc, expDesc) }
@@ -0,0 +1,9 @@
LineBreakpoint created at anonymousObjects.kt:11
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! anonymousObjects.AnonymousObjectsPackage
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
anonymousObjects.kt:11
Compile bytecode for test(2)
Compile bytecode for i
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -0,0 +1,19 @@
package anonymousObjects
fun main(args: Array<String>) {
val a = object: AbstractClass(1) {}
a.test(1)
}
abstract class AbstractClass(val i: Int) {
fun test(i: Int): Int {
//Breakpoint!
return i
}
}
// EXPRESSION: test(2)
// RESULT: 2: I
// EXPRESSION: i
// RESULT: 1: I
@@ -46,6 +46,12 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("anonymousObjects.kt")
public void testAnonymousObjects() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/anonymousObjects.kt");
doSingleBreakpointTest(fileName);
}
@TestMetadata("arrays.kt")
public void testArrays() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/arrays.kt");