diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 79bf6fe288a..a444dc035f9 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -372,7 +372,7 @@
-
+
diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/KotlinSourcePositionProvider.kt b/idea/src/org/jetbrains/jet/plugin/debugger/KotlinSourcePositionProvider.kt
new file mode 100644
index 00000000000..7ad64d72b66
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/debugger/KotlinSourcePositionProvider.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2010-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jet.plugin.debugger
+
+import com.intellij.debugger.engine.SourcePositionProvider
+import com.intellij.debugger.ui.tree.NodeDescriptor
+import com.intellij.openapi.project.Project
+import com.intellij.debugger.impl.DebuggerContextImpl
+import com.intellij.debugger.SourcePosition
+import org.jetbrains.jet.codegen.AsmUtil
+import org.jetbrains.jet.lang.psi.JetClassOrObject
+import com.intellij.debugger.impl.DebuggerContextUtil
+import com.sun.jdi.ReferenceType
+import com.intellij.psi.PsiElement
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.jet.lang.resolve.java.JvmClassName
+import com.intellij.psi.JavaPsiFacade
+import org.jetbrains.jet.lang.psi.psiUtil.getStrictParentOfType
+import com.sun.jdi.AbsentInformationException
+import com.sun.jdi.ClassNotPreparedException
+import com.intellij.debugger.ui.tree.FieldDescriptor
+
+public class KotlinSourcePositionProvider: SourcePositionProvider() {
+ override fun computeSourcePosition(descriptor: NodeDescriptor, project: Project, context: DebuggerContextImpl, nearest: Boolean): SourcePosition? {
+ if (context.getFrameProxy() == null) return null
+
+ if (descriptor is FieldDescriptor) {
+ return computeSourcePosition(descriptor, project, context, nearest)
+ }
+
+ return null
+ }
+
+ fun computeSourcePosition(descriptor: FieldDescriptor, project: Project, context: DebuggerContextImpl, nearest: Boolean): SourcePosition? {
+ val fieldName = descriptor.getField().name()
+ if (fieldName == AsmUtil.CAPTURED_THIS_FIELD || fieldName == AsmUtil.CAPTURED_RECEIVER_FIELD) {
+ return null
+ }
+
+ val type = descriptor.getField().declaringType()
+ val myClass = findClassByType(project, 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(project: Project, type: ReferenceType, context: DebuggerContextImpl): PsiElement? {
+ val session = context.getDebuggerSession()
+ val scope = if (session != null) session.getSearchScope() else GlobalSearchScope.allScope(project)
+ val className = JvmClassName.byInternalName(type.name()).getFqNameForClassNameWithoutDollars().asString()
+
+ val myClass = JavaPsiFacade.getInstance(project).findClass(className, scope)
+ if (myClass != null) return myClass
+
+ val position = getLastSourcePosition(type, context)
+ if (position != null) {
+ val element = position.getElementAt()
+ if (element != null) {
+ return element.getStrictParentOfType()
+ }
+ }
+ 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
+ }
+}
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/render/KotlinClassWithDelegatedPropertyRenderer.kt b/idea/src/org/jetbrains/jet/plugin/debugger/render/KotlinClassWithDelegatedPropertyRenderer.kt
index 981142f8c57..03324a8bb56 100644
--- a/idea/src/org/jetbrains/jet/plugin/debugger/render/KotlinClassWithDelegatedPropertyRenderer.kt
+++ b/idea/src/org/jetbrains/jet/plugin/debugger/render/KotlinClassWithDelegatedPropertyRenderer.kt
@@ -16,6 +16,7 @@
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
@@ -36,9 +37,8 @@ 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 : KotlinObjectRenderer() {
+public class KotlinClassWithDelegatedPropertyRenderer : ClassRenderer() {
override fun isApplicable(jdiType: Type?): Boolean {
if (!super.isApplicable(jdiType)) return false
@@ -68,7 +68,7 @@ public class KotlinClassWithDelegatedPropertyRenderer : KotlinObjectRenderer() {
continue
}
- val fieldDescriptor = createFieldDescriptor(builder.getParentDescriptor() as ValueDescriptorImpl, nodeDescriptorFactory, value, field, context)
+ val fieldDescriptor = nodeDescriptorFactory.getFieldDescriptor(builder.getParentDescriptor(), value, field)
children.add(nodeManager.createNode(fieldDescriptor, context))
if (field.name().endsWith(JvmAbi.DELEGATED_PROPERTY_NAME_SUFFIX)) {
diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/render/KotlinObjectRenderer.kt b/idea/src/org/jetbrains/jet/plugin/debugger/render/KotlinObjectRenderer.kt
deleted file mode 100644
index 0ef1c91790f..00000000000
--- a/idea/src/org/jetbrains/jet/plugin/debugger/render/KotlinObjectRenderer.kt
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright 2010-2014 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.jetbrains.jet.plugin.debugger.render
-
-import com.intellij.debugger.ui.tree.render.ClassRenderer
-import com.sun.jdi.Type
-import com.intellij.debugger.engine.evaluation.EvaluationContext
-import com.sun.jdi.ObjectReference
-import com.sun.jdi.Field
-import com.sun.jdi.ClassType
-import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl
-import com.intellij.debugger.ui.tree.NodeDescriptorFactory
-import com.intellij.debugger.ui.tree.FieldDescriptor
-import com.intellij.debugger.ui.impl.watch.FieldDescriptorImpl
-import com.intellij.openapi.project.Project
-import com.intellij.debugger.impl.DebuggerContextImpl
-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.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
-import org.jetbrains.jet.lang.psi.psiUtil.getStrictParentOfType
-
-public open class KotlinObjectRenderer : ClassRenderer() {
-
- override fun isApplicable(jdiType: Type?): Boolean {
- if (!super.isApplicable(jdiType)) return false
-
- var isCustomRendererApplicable = false
- NodeRendererSettings.getInstance().getCustomRenderers().iterateRenderers {
- isCustomRendererApplicable = it.isApplicable(jdiType)
- !isCustomRendererApplicable
- }
-
- if (isCustomRendererApplicable) return false
-
- return jdiType.isKotlinClass()
- }
-
- override fun createFieldDescriptor(
- parentDescriptor: ValueDescriptorImpl?,
- nodeDescriptorFactory: NodeDescriptorFactory?,
- objRef: ObjectReference?,
- field: Field?,
- evaluationContext: EvaluationContext?
- ): FieldDescriptor {
- if (field?.declaringType().isKotlinClass()) {
- return KotlinObjectFieldDescriptor(evaluationContext?.getProject(), objRef, field)
- }
- return super.createFieldDescriptor(parentDescriptor, nodeDescriptorFactory, objRef, field, evaluationContext)
- }
-
- override fun calcLabel(
- descriptor: ValueDescriptor?,
- evaluationContext: EvaluationContext?,
- labelListener: DescriptorLabelListener?
- ): String? {
- val toStringRenderer = NodeRendererSettings.getInstance().getToStringRenderer()
- if (toStringRenderer.isApplicable(descriptor?.getValue()?.type())) {
- return toStringRenderer.calcLabel(descriptor, evaluationContext, labelListener)
- }
- return super.calcLabel(descriptor, evaluationContext, labelListener)
- }
-}
-
-public class KotlinObjectFieldDescriptor(
- project: Project?,
- objRef: ObjectReference?,
- field: Field?
-) : 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 element.getStrictParentOfType()
- }
- }
- 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() }
-}
-
diff --git a/idea/testData/debugger/tinyApp/outs/delegatedPropertyInClass.out b/idea/testData/debugger/tinyApp/outs/delegatedPropertyInClass.out
index cd9b3d49fab..b0e66be3177 100644
--- a/idea/testData/debugger/tinyApp/outs/delegatedPropertyInClass.out
+++ b/idea/testData/debugger/tinyApp/outs/delegatedPropertyInClass.out
@@ -30,10 +30,10 @@ 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} (sp = null)
- field = prop: int = 1
- field = propEx$delegate: delegatedPropertyInClass.MyDelegateThrowsException = {delegatedPropertyInClass.MyDelegateThrowsException@uniqueID} (sp = null)
- field = propEx: java.lang.IllegalStateException = {java.lang.IllegalStateException@uniqueID}java.lang.IllegalStateException
+ field = prop$delegate: delegatedPropertyInClass.MyDelegate = {delegatedPropertyInClass.MyDelegate@uniqueID} (sp = delegatedPropertyInClass.kt, 12)
+ field = prop: int = 1 (sp = delegatedPropertyInClass.kt, 12)
+ field = propEx$delegate: delegatedPropertyInClass.MyDelegateThrowsException = {delegatedPropertyInClass.MyDelegateThrowsException@uniqueID} (sp = delegatedPropertyInClass.kt, 13)
+ field = propEx: java.lang.IllegalStateException = {java.lang.IllegalStateException@uniqueID}java.lang.IllegalStateException (sp = delegatedPropertyInClass.kt, 13)
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!)
diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt
index 862a8a32cb1..8c3e9039d6a 100644
--- a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt
+++ b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt
@@ -62,6 +62,7 @@ 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
+import com.intellij.debugger.engine.SourcePositionProvider
public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestBase() {
private val logger = Logger.getLogger(javaClass())!!
@@ -252,9 +253,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")
+ is FieldDescriptor -> logDescriptor(descriptor, "$curIndent field = $label"
+ + " (sp = ${render(SourcePositionProvider.getSourcePosition(descriptor, myProject, debuggerContext))})\n")
else -> logDescriptor(descriptor, "$curIndent unknown = $label\n")
}