Debugger: change usage of getSourcePosition method to SourcePositionManager

(cherry picked from commit f1c4e36)
This commit is contained in:
Natalia Ukhorskaya
2014-12-11 15:31:46 +03:00
committed by Zalim Bashorov
parent c6777db64f
commit c6d134d63c
6 changed files with 115 additions and 172 deletions
+1 -1
View File
@@ -372,7 +372,7 @@
<debuggerEditorTextProvider language="jet" implementationClass="org.jetbrains.jet.plugin.debugger.KotlinEditorTextProvider"/>
<debuggerClassFilterProvider implementation="org.jetbrains.jet.plugin.debugger.filter.KotlinDebuggerInternalClassesFilterProvider"/>
<debugger.nodeRenderer implementation="org.jetbrains.jet.plugin.debugger.render.KotlinClassWithDelegatedPropertyRenderer"/>
<debugger.nodeRenderer implementation="org.jetbrains.jet.plugin.debugger.render.KotlinObjectRenderer"/>
<debugger.sourcePositionProvider implementation="org.jetbrains.jet.plugin.debugger.KotlinSourcePositionProvider"/>
<xdebugger.settings implementation="org.jetbrains.jet.plugin.debugger.KotlinDebuggerSettings"/>
<codeInsight.implementMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler"/>
@@ -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<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
}
}
@@ -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)) {
@@ -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<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,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!)
@@ -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<KotlinEvaluateExpressionCache>())!!
@@ -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")
}