Debugger: implement getSourcePosition for fields
This commit is contained in:
+4
-8
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.jet.plugin.debugger.render
|
||||
|
||||
import com.intellij.debugger.ui.tree.render.ClassRenderer
|
||||
import com.sun.jdi.Type as JdiType
|
||||
import com.sun.jdi.Value
|
||||
import com.intellij.debugger.ui.tree.render.ChildrenBuilder
|
||||
@@ -24,7 +23,6 @@ import com.intellij.debugger.engine.evaluation.EvaluationContext
|
||||
import com.intellij.debugger.ui.tree.DebuggerTreeNode
|
||||
import org.jetbrains.org.objectweb.asm.Type as AsmType
|
||||
import com.intellij.debugger.engine.DebuggerManagerThreadImpl
|
||||
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl
|
||||
import com.sun.jdi.ObjectReference
|
||||
import com.intellij.xdebugger.settings.XDebuggerSettingsManager
|
||||
import com.intellij.debugger.ui.impl.watch.NodeManagerImpl
|
||||
@@ -32,20 +30,18 @@ import com.intellij.debugger.ui.impl.watch.MessageDescriptor
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi
|
||||
import com.sun.jdi.Field
|
||||
import com.intellij.debugger.engine.DebuggerUtils
|
||||
import com.intellij.debugger.ui.impl.watch.FieldDescriptorImpl
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException
|
||||
import com.sun.jdi.ReferenceType
|
||||
import com.sun.jdi.Type
|
||||
import com.sun.jdi.InvocationException
|
||||
import com.sun.jdi.Method
|
||||
import org.jetbrains.jet.codegen.PropertyCodegen
|
||||
import org.jetbrains.jet.lang.resolve.name.Name
|
||||
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl
|
||||
|
||||
public class KotlinClassWithDelegatedPropertyRenderer : ClassRenderer() {
|
||||
public class KotlinClassWithDelegatedPropertyRenderer : KotlinObjectRenderer() {
|
||||
|
||||
override fun isApplicable(jdiType: Type?): Boolean {
|
||||
if (!super<ClassRenderer>.isApplicable(jdiType)) return false
|
||||
if (!super.isApplicable(jdiType)) return false
|
||||
|
||||
if (jdiType !is ReferenceType) return false
|
||||
|
||||
@@ -72,7 +68,7 @@ public class KotlinClassWithDelegatedPropertyRenderer : ClassRenderer() {
|
||||
continue
|
||||
}
|
||||
|
||||
val fieldDescriptor = nodeDescriptorFactory.getFieldDescriptor(builder.getParentDescriptor(), value, field)
|
||||
val fieldDescriptor = createFieldDescriptor(builder.getParentDescriptor() as ValueDescriptorImpl, nodeDescriptorFactory, value, field, context)
|
||||
children.add(nodeManager.createNode(fieldDescriptor, context))
|
||||
|
||||
if (field.name().endsWith(JvmAbi.DELEGATED_PROPERTY_NAME_SUFFIX)) {
|
||||
|
||||
@@ -32,8 +32,22 @@ import org.jetbrains.jet.lang.resolve.java.JvmAbi
|
||||
import com.intellij.debugger.ui.tree.ValueDescriptor
|
||||
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener
|
||||
import com.intellij.debugger.settings.NodeRendererSettings
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.debugger.SourcePosition
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.debugger.impl.DebuggerContextUtil
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.sun.jdi.AbsentInformationException
|
||||
import com.sun.jdi.ClassNotPreparedException
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.jet.lang.psi.JetClass
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName
|
||||
import com.sun.jdi.ReferenceType
|
||||
import org.jetbrains.jet.codegen.AsmUtil
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject
|
||||
|
||||
public class KotlinObjectRenderer : ClassRenderer() {
|
||||
public open class KotlinObjectRenderer : ClassRenderer() {
|
||||
|
||||
override fun isApplicable(jdiType: Type?): Boolean {
|
||||
if (!super.isApplicable(jdiType)) return false
|
||||
@@ -65,18 +79,75 @@ public class KotlinObjectRenderer : ClassRenderer() {
|
||||
}
|
||||
return super.calcLabel(descriptor, evaluationContext, labelListener)
|
||||
}
|
||||
|
||||
private fun Type?.isKotlinClass(): Boolean {
|
||||
return this is ClassType && this.allInterfaces().any { it.name() == JvmAbi.K_OBJECT.asString() }
|
||||
}
|
||||
}
|
||||
|
||||
public class KotlinObjectFieldDescriptor(
|
||||
project: Project?,
|
||||
objRef: ObjectReference?,
|
||||
field: Field?
|
||||
): FieldDescriptorImpl(project, objRef, field) {
|
||||
override fun getSourcePosition(project: Project?, context: DebuggerContextImpl?) = null
|
||||
override fun getSourcePosition(project: Project?, context: DebuggerContextImpl?, nearest: Boolean) = null
|
||||
) : FieldDescriptorImpl(project, objRef, field) {
|
||||
override fun getSourcePosition(project: Project?, context: DebuggerContextImpl?, nearest: Boolean): SourcePosition? {
|
||||
if (context == null || context.getFrameProxy() == null) return null
|
||||
|
||||
val fieldName = getField().name()
|
||||
if (fieldName == AsmUtil.CAPTURED_THIS_FIELD || fieldName == AsmUtil.CAPTURED_RECEIVER_FIELD) {
|
||||
return null
|
||||
}
|
||||
|
||||
val type = getField().declaringType()
|
||||
val myClass = findClassByType(type, context)?.getNavigationElement()
|
||||
if (myClass !is JetClassOrObject) {
|
||||
return null
|
||||
}
|
||||
|
||||
val field = myClass.getDeclarations().firstOrNull { fieldName == it.getName() }
|
||||
if (field == null) return null
|
||||
|
||||
if (nearest) {
|
||||
return DebuggerContextUtil.findNearest(context, field, myClass.getContainingFile())
|
||||
}
|
||||
return SourcePosition.createFromOffset(field.getContainingFile(), field.getTextOffset())
|
||||
}
|
||||
|
||||
private fun findClassByType(type: ReferenceType, context: DebuggerContextImpl): PsiElement? {
|
||||
val session = context.getDebuggerSession()
|
||||
val scope = if (session != null) session.getSearchScope() else GlobalSearchScope.allScope(myProject)
|
||||
val className = JvmClassName.byInternalName(type.name()).getFqNameForClassNameWithoutDollars().asString()
|
||||
|
||||
val myClass = JavaPsiFacade.getInstance(myProject).findClass(className, scope)
|
||||
if (myClass != null) return myClass
|
||||
|
||||
val position = getLastSourcePosition(type, context)
|
||||
if (position != null) {
|
||||
val element = position.getElementAt()
|
||||
if (element != null) {
|
||||
return PsiTreeUtil.getParentOfType(element, javaClass<JetClassOrObject>())
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
private fun getLastSourcePosition(type: ReferenceType, context: DebuggerContextImpl): SourcePosition? {
|
||||
val debugProcess = context.getDebugProcess()
|
||||
if (debugProcess != null) {
|
||||
try {
|
||||
val locations = type.allLineLocations()
|
||||
if (!locations.isEmpty()) {
|
||||
val lastLocation = locations.get(locations.size() - 1)
|
||||
return debugProcess.getPositionManager().getSourcePosition(lastLocation)
|
||||
}
|
||||
}
|
||||
catch (ignored: AbsentInformationException) {
|
||||
}
|
||||
catch (ignored: ClassNotPreparedException) {
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun Type?.isKotlinClass(): Boolean {
|
||||
return this is ClassType && this.allInterfaces().any { it.name() == JvmAbi.K_OBJECT.asString() }
|
||||
}
|
||||
|
||||
|
||||
@@ -30,13 +30,13 @@ class MyDelegateThrowsException {
|
||||
static = static = delegatedPropertyInClass.DelegatedPropertyInClassPackage$@packagePartHASH
|
||||
local = args: java.lang.String[] = {java.lang.String[0]@uniqueID}
|
||||
local = a: delegatedPropertyInClass.A = {delegatedPropertyInClass.A@uniqueID}
|
||||
field = prop$delegate: delegatedPropertyInClass.MyDelegate = {delegatedPropertyInClass.MyDelegate@uniqueID}
|
||||
field = prop$delegate: delegatedPropertyInClass.MyDelegate = {delegatedPropertyInClass.MyDelegate@uniqueID} (sp = null)
|
||||
field = prop: int = 1
|
||||
field = propEx$delegate: delegatedPropertyInClass.MyDelegateThrowsException = {delegatedPropertyInClass.MyDelegateThrowsException@uniqueID}
|
||||
field = propEx$delegate: delegatedPropertyInClass.MyDelegateThrowsException = {delegatedPropertyInClass.MyDelegateThrowsException@uniqueID} (sp = null)
|
||||
field = propEx: java.lang.IllegalStateException = {java.lang.IllegalStateException@uniqueID}java.lang.IllegalStateException
|
||||
field = detailMessage: java.lang.String = null
|
||||
field = cause: java.lang.Throwable = {java.lang.IllegalStateException@uniqueID}java.lang.IllegalStateException
|
||||
field = stackTrace: java.lang.StackTraceElement[] = null
|
||||
field = detailMessage: java.lang.String = null (sp = Throwable.!EXT!)
|
||||
field = cause: java.lang.Throwable = {java.lang.IllegalStateException@uniqueID}java.lang.IllegalStateException (sp = Throwable.!EXT!)
|
||||
field = stackTrace: java.lang.StackTraceElement[] = null (sp = Throwable.!EXT!)
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -27,9 +27,9 @@ fun foo(f: () -> Unit) {
|
||||
// PRINT_FRAME
|
||||
frame = invoke():11, FrameAnonymousObjectPackage$@packagePartHASH$main$o$1$run$1 {frameAnonymousObject}
|
||||
this = this = {frameAnonymousObject.FrameAnonymousObjectPackage$@packagePartHASH$main$o$1$run$1@uniqueID}kotlin.Function0<kotlin.Unit>
|
||||
field = this$0: frameAnonymousObject.FrameAnonymousObjectPackage$@packagePartHASH$main$o$1 = {frameAnonymousObject.FrameAnonymousObjectPackage$@packagePartHASH$main$o$1@uniqueID}
|
||||
field = obProp: int = 1
|
||||
field = $val1: int = 1
|
||||
field = this$0: frameAnonymousObject.FrameAnonymousObjectPackage$@packagePartHASH$main$o$1 = {frameAnonymousObject.FrameAnonymousObjectPackage$@packagePartHASH$main$o$1@uniqueID} (sp = null)
|
||||
field = obProp: int = 1 (sp = frameAnonymousObject.kt, 5)
|
||||
field = $val1: int = 1 (sp = null)
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -70,16 +70,16 @@ fun lambda(f: () -> Unit) {
|
||||
// RESULT: 1: I
|
||||
frame = invoke():22, Outer$foo$LocalClass$test$1 {frameExtFunExtFun}
|
||||
this = this = {frameExtFunExtFun.Outer$foo$LocalClass$test$1@uniqueID}kotlin.Function0<kotlin.Unit>
|
||||
field = this$0: frameExtFunExtFun.Outer$foo$LocalClass = {frameExtFunExtFun.Outer$foo$LocalClass@uniqueID}
|
||||
field = lcProp: int = 1
|
||||
field = this$0: frameExtFunExtFun.Outer = {frameExtFunExtFun.Outer@uniqueID}
|
||||
field = outerProp: int = 1
|
||||
field = receiver$0: frameExtFunExtFun.A = {frameExtFunExtFun.A@uniqueID}
|
||||
field = aProp: int = 1
|
||||
field = $valFoo: int = 1
|
||||
field = receiver$0: frameExtFunExtFun.B = {frameExtFunExtFun.B@uniqueID}
|
||||
field = bProp: int = 1
|
||||
field = $valTest: int = 1
|
||||
field = this$0: frameExtFunExtFun.Outer$foo$LocalClass = {frameExtFunExtFun.Outer$foo$LocalClass@uniqueID} (sp = null)
|
||||
field = lcProp: int = 1 (sp = frameExtFunExtFun.kt, 16)
|
||||
field = this$0: frameExtFunExtFun.Outer = {frameExtFunExtFun.Outer@uniqueID} (sp = null)
|
||||
field = outerProp: int = 1 (sp = frameExtFunExtFun.kt, 11)
|
||||
field = receiver$0: frameExtFunExtFun.A = {frameExtFunExtFun.A@uniqueID} (sp = null)
|
||||
field = aProp: int = 1 (sp = frameExtFunExtFun.kt, 7)
|
||||
field = $valFoo: int = 1 (sp = null)
|
||||
field = receiver$0: frameExtFunExtFun.B = {frameExtFunExtFun.B@uniqueID} (sp = null)
|
||||
field = bProp: int = 1 (sp = frameExtFunExtFun.kt, 38)
|
||||
field = $valTest: int = 1 (sp = null)
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -25,7 +25,7 @@ fun A.foo() {
|
||||
frame = foo():13, FrameExtensionFunPackage$@packagePartHASH {frameExtensionFun}
|
||||
static = static = frameExtensionFun.FrameExtensionFunPackage$@packagePartHASH
|
||||
local = $receiver: frameExtensionFun.A = {frameExtensionFun.A@uniqueID}
|
||||
field = prop: int = 1
|
||||
field = prop: int = 1 (sp = frameExtensionFun.kt, 7)
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -32,9 +32,9 @@ class A {
|
||||
// RESULT: 1: I
|
||||
frame = test():15, A$Inner {frameInnerClass}
|
||||
this = this = {frameInnerClass.A$Inner@uniqueID}
|
||||
field = prop2: int = 1
|
||||
field = this$0: frameInnerClass.A = {frameInnerClass.A@uniqueID}
|
||||
field = prop1: int = 1
|
||||
field = prop2: int = 1 (sp = frameInnerClass.kt, 10)
|
||||
field = this$0: frameInnerClass.A = {frameInnerClass.A@uniqueID} (sp = null)
|
||||
field = prop1: int = 1 (sp = frameInnerClass.kt, 7)
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -34,9 +34,9 @@ fun foo(f: () -> Unit) {
|
||||
// RESULT: 2: I
|
||||
frame = invoke():9, FrameInnerLambdaPackage$@packagePartHASH$main$1$1 {frameInnerLambda}
|
||||
this = this = {frameInnerLambda.FrameInnerLambdaPackage$@packagePartHASH$main$1$1@uniqueID}kotlin.Function0<kotlin.Unit>
|
||||
field = this$0: frameInnerLambda.FrameInnerLambdaPackage$@packagePartHASH$main$1 = {frameInnerLambda.FrameInnerLambdaPackage$@packagePartHASH$main$1@uniqueID}kotlin.Function0<kotlin.Unit>
|
||||
field = $val1: int = 1
|
||||
field = $val2: int = 1
|
||||
field = this$0: frameInnerLambda.FrameInnerLambdaPackage$@packagePartHASH$main$1 = {frameInnerLambda.FrameInnerLambdaPackage$@packagePartHASH$main$1@uniqueID}kotlin.Function0<kotlin.Unit> (sp = null)
|
||||
field = $val1: int = 1 (sp = null)
|
||||
field = $val2: int = 1 (sp = null)
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -23,7 +23,7 @@ fun foo(f: () -> Unit) {
|
||||
// RESULT: 1: I
|
||||
frame = invoke():7, FrameLambdaPackage$@packagePartHASH$main$1 {frameLambda}
|
||||
this = this = {frameLambda.FrameLambdaPackage$@packagePartHASH$main$1@uniqueID}kotlin.Function0<kotlin.Unit>
|
||||
field = $val1: int = 1
|
||||
field = $val1: int = 1 (sp = null)
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -23,8 +23,8 @@ fun foo(f: () -> Unit) {
|
||||
// RESULT: 1: I
|
||||
frame = invoke():7, FrameSharedVarPackage$@packagePartHASH$main$1 {frameSharedVar}
|
||||
this = this = {frameSharedVar.FrameSharedVarPackage$@packagePartHASH$main$1@uniqueID}kotlin.Function0<kotlin.Unit>
|
||||
field = $var1: kotlin.jvm.internal.Ref$IntRef = {kotlin.jvm.internal.Ref$IntRef@uniqueID}1
|
||||
field = element: int = 1
|
||||
field = $var1: kotlin.jvm.internal.Ref$IntRef = {kotlin.jvm.internal.Ref$IntRef@uniqueID}1 (sp = null)
|
||||
field = element: int = 1 (sp = Ref.!EXT!)
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -25,7 +25,7 @@ inline fun foo(f: () -> Unit) {
|
||||
static = static = frameSharedVarLocalVar.FrameSharedVarLocalVarPackage$@packagePartHASH
|
||||
local = args: java.lang.String[] = {java.lang.String[0]@uniqueID}
|
||||
local = var1: kotlin.jvm.internal.Ref$IntRef = {kotlin.jvm.internal.Ref$IntRef@uniqueID}1
|
||||
field = element: int = 1
|
||||
field = element: int = 1 (sp = Ref.!EXT!)
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -32,17 +32,17 @@ fun main(args: Array<String>) {
|
||||
// RESULT: 2: I
|
||||
frame = main():9, FrameSimplePackage$@packagePartHASH {frameSimple}
|
||||
static = static = frameSimple.FrameSimplePackage$@packagePartHASH
|
||||
field = topVal1: int = 1
|
||||
field = topVal1: int = 1 (sp = null)
|
||||
local = args: java.lang.String[] = {java.lang.String[0]@uniqueID}
|
||||
local = val1: int = 1
|
||||
local = val2: java.lang.String = {@uniqueID}str
|
||||
field = value: char[] = {char[3]@uniqueID}
|
||||
field = value: char[] = {char[3]@uniqueID} (sp = String.!EXT!)
|
||||
unknown = [0] = 's' 115
|
||||
unknown = [1] = 't' 116
|
||||
unknown = [2] = 'r' 114
|
||||
field = offset: int = 0
|
||||
field = count: int = 3
|
||||
field = hash: int = 0
|
||||
field = offset: int = 0 (sp = String.!EXT!)
|
||||
field = count: int = 3 (sp = String.!EXT!)
|
||||
field = hash: int = 0 (sp = String.!EXT!)
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -44,9 +44,9 @@ fun foo(f: () -> Unit) {
|
||||
// RESULT: 3: I
|
||||
frame = invoke():15, A$test$1 {frameThis0}
|
||||
this = this = {frameThis0.A$test$1@uniqueID}kotlin.Function0<kotlin.Unit>
|
||||
field = this$0: frameThis0.A = {frameThis0.A@uniqueID}
|
||||
field = prop1: int = 1
|
||||
field = $val1: int = 1
|
||||
field = this$0: frameThis0.A = {frameThis0.A@uniqueID} (sp = null)
|
||||
field = prop1: int = 1 (sp = frameThis0.kt, 7)
|
||||
field = $val1: int = 1 (sp = null)
|
||||
local = val2: int = 1
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
|
||||
@@ -55,11 +55,11 @@ fun foo(f: () -> Unit) {
|
||||
// RESULT: 2: I
|
||||
frame = invoke():14, A$testExt$1 {frameThis0Ext}
|
||||
this = this = {frameThis0Ext.A$testExt$1@uniqueID}kotlin.Function0<kotlin.Unit>
|
||||
field = this$0: frameThis0Ext.A = {frameThis0Ext.A@uniqueID}
|
||||
field = prop1: int = 1
|
||||
field = receiver$0: frameThis0Ext.AExt = {frameThis0Ext.AExt@uniqueID}
|
||||
field = prop2: int = 1
|
||||
field = $val1: int = 1
|
||||
field = this$0: frameThis0Ext.A = {frameThis0Ext.A@uniqueID} (sp = null)
|
||||
field = prop1: int = 1 (sp = frameThis0Ext.kt, 7)
|
||||
field = receiver$0: frameThis0Ext.AExt = {frameThis0Ext.AExt@uniqueID} (sp = null)
|
||||
field = prop2: int = 1 (sp = frameThis0Ext.kt, 23)
|
||||
field = $val1: int = 1 (sp = null)
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -46,11 +46,11 @@ fun foo(f: () -> Unit) {
|
||||
// RESULT: 3: I
|
||||
frame = invoke():16, A$test$1$1 {frameThis0This0}
|
||||
this = this = {frameThis0This0.A$test$1$1@uniqueID}kotlin.Function0<kotlin.Unit>
|
||||
field = this$0: frameThis0This0.A$test$1 = {frameThis0This0.A$test$1@uniqueID}kotlin.Function0<kotlin.Unit>
|
||||
field = this$0: frameThis0This0.A = {frameThis0This0.A@uniqueID}
|
||||
field = prop1: int = 1
|
||||
field = $val1: int = 1
|
||||
field = $val2: int = 1
|
||||
field = this$0: frameThis0This0.A$test$1 = {frameThis0This0.A$test$1@uniqueID}kotlin.Function0<kotlin.Unit> (sp = null)
|
||||
field = this$0: frameThis0This0.A = {frameThis0This0.A@uniqueID} (sp = null)
|
||||
field = prop1: int = 1 (sp = frameThis0This0.kt, 7)
|
||||
field = $val1: int = 1 (sp = null)
|
||||
field = $val2: int = 1 (sp = null)
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.openapi.roots.libraries.LibraryUtil
|
||||
import org.jetbrains.jet.plugin.JetJdkAndLibraryProjectDescriptor
|
||||
import com.intellij.openapi.roots.JdkOrderEntry
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.debugger.SourcePosition
|
||||
|
||||
abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() {
|
||||
|
||||
@@ -54,25 +55,29 @@ abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() {
|
||||
}
|
||||
|
||||
val sourcePosition = PositionUtil.getSourcePosition(this)
|
||||
if (sourcePosition == null) {
|
||||
return@runReadAction println("SourcePosition is null", ProcessOutputTypes.SYSTEM)
|
||||
}
|
||||
|
||||
val virtualFile = sourcePosition.getFile().getVirtualFile()
|
||||
if (virtualFile == null) {
|
||||
return@runReadAction println("VirtualFile for position is null", ProcessOutputTypes.SYSTEM)
|
||||
}
|
||||
|
||||
val libraryEntry = LibraryUtil.findLibraryEntry(virtualFile, getProject())
|
||||
if (libraryEntry != null && (libraryEntry is JdkOrderEntry ||
|
||||
libraryEntry.getPresentableName() == JetJdkAndLibraryProjectDescriptor.LIBRARY_NAME)) {
|
||||
return@runReadAction println(FileUtil.getNameWithoutExtension(virtualFile.getName()) + ".!EXT!", ProcessOutputTypes.SYSTEM)
|
||||
}
|
||||
|
||||
println(virtualFile.getName() + ":" + sourcePosition.getLine(), ProcessOutputTypes.SYSTEM)
|
||||
println(renderSourcePosition(sourcePosition), ProcessOutputTypes.SYSTEM)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun renderSourcePosition(sourcePosition: SourcePosition?): String {
|
||||
if (sourcePosition == null) {
|
||||
return "null"
|
||||
}
|
||||
|
||||
val virtualFile = sourcePosition.getFile().getVirtualFile()
|
||||
if (virtualFile == null) {
|
||||
return "VirtualFile for position is null"
|
||||
}
|
||||
|
||||
val libraryEntry = LibraryUtil.findLibraryEntry(virtualFile, getProject())
|
||||
if (libraryEntry != null && (libraryEntry is JdkOrderEntry ||
|
||||
libraryEntry.getPresentableName() == JetJdkAndLibraryProjectDescriptor.LIBRARY_NAME)) {
|
||||
return FileUtil.getNameWithoutExtension(virtualFile.getName()) + ".!EXT!"
|
||||
}
|
||||
|
||||
return virtualFile.getName() + ":" + sourcePosition.getLine()
|
||||
}
|
||||
|
||||
protected fun finish() {
|
||||
onBreakpoint {
|
||||
resume(this)
|
||||
|
||||
+16
-4
@@ -58,8 +58,10 @@ import com.intellij.psi.PsiManager
|
||||
import com.intellij.debugger.DebuggerManagerEx
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.debugger.ui.tree.render.ClassRenderer
|
||||
import com.intellij.debugger.settings.NodeRendererSettings
|
||||
import com.intellij.debugger.ui.impl.watch.FieldDescriptorImpl
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl
|
||||
import com.intellij.debugger.SourcePosition
|
||||
|
||||
public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestBase() {
|
||||
private val logger = Logger.getLogger(javaClass<KotlinEvaluateExpressionCache>())!!
|
||||
@@ -221,13 +223,17 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestB
|
||||
invokeRatherLater(this) {
|
||||
tree.rebuild(debuggerContext)
|
||||
expandAll(tree, Runnable {
|
||||
PRINTER.printTree(tree)
|
||||
resume(this@printFrame)
|
||||
try {
|
||||
Printer(debuggerContext).printTree(tree)
|
||||
}
|
||||
finally {
|
||||
resume(this@printFrame)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private val PRINTER = object {
|
||||
private inner class Printer(val debuggerContext: DebuggerContextImpl) {
|
||||
fun printTree(tree: DebuggerTree) {
|
||||
val root = tree.getMutableModel()!!.getRoot() as DebuggerTreeNodeImpl
|
||||
printNode(root, 0)
|
||||
@@ -246,6 +252,8 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestB
|
||||
is LocalVariableDescriptor -> logDescriptor(descriptor, "$curIndent local = $label\n")
|
||||
is StaticDescriptor -> logDescriptor(descriptor, "$curIndent static = $label\n")
|
||||
is ThisDescriptorImpl -> logDescriptor(descriptor, "$curIndent this = $label\n")
|
||||
is FieldDescriptorImpl -> logDescriptor(descriptor, "$curIndent field = $label"
|
||||
+ " (sp = ${render(descriptor.getSourcePosition(myProject, debuggerContext))})\n")
|
||||
is FieldDescriptor -> logDescriptor(descriptor, "$curIndent field = $label\n")
|
||||
else -> logDescriptor(descriptor, "$curIndent unknown = $label\n")
|
||||
}
|
||||
@@ -259,6 +267,10 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestB
|
||||
printNode(e.nextElement() as DebuggerTreeNodeImpl, indent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun render(sp: SourcePosition?): String {
|
||||
return renderSourcePosition(sp).replace(":", ", ")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkExceptions(exceptions: MutableMap<String, Throwable>) {
|
||||
|
||||
Reference in New Issue
Block a user