Debugger: change usage of getSourcePosition method to SourcePositionManager
(cherry picked from commit f1c4e36)
This commit is contained in:
committed by
Zalim Bashorov
parent
c6777db64f
commit
c6d134d63c
@@ -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
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -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!)
|
||||
|
||||
+3
-3
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user