Fix leak in debugger (KT-24903)
#KT-24903 Fixed
This commit is contained in:
+25
-42
@@ -18,17 +18,14 @@ package org.jetbrains.kotlin.idea.debugger.stepping
|
|||||||
|
|
||||||
import com.intellij.debugger.engine.DebugProcessImpl
|
import com.intellij.debugger.engine.DebugProcessImpl
|
||||||
import com.intellij.debugger.engine.NamedMethodFilter
|
import com.intellij.debugger.engine.NamedMethodFilter
|
||||||
|
import com.intellij.psi.SmartPsiElementPointer
|
||||||
import com.intellij.util.Range
|
import com.intellij.util.Range
|
||||||
import com.intellij.util.SofterReference
|
|
||||||
import com.sun.jdi.Location
|
import com.sun.jdi.Location
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.codegen.SamCodegenUtil
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.*
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||||
import org.jetbrains.kotlin.idea.core.getDirectlyOverriddenDeclarations
|
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtProperty
|
import org.jetbrains.kotlin.psi.KtProperty
|
||||||
@@ -36,32 +33,26 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypesAndPredicate
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
|
||||||
class KotlinBasicStepMethodFilter(
|
class KotlinBasicStepMethodFilter(
|
||||||
targetDescriptor: CallableMemberDescriptor,
|
private val declarationPtr: SmartPsiElementPointer<KtDeclaration>?,
|
||||||
|
private val isInvoke: Boolean,
|
||||||
|
private val targetMethodName: String,
|
||||||
private val myCallingExpressionLines: Range<Int>
|
private val myCallingExpressionLines: Range<Int>
|
||||||
) : NamedMethodFilter {
|
) : NamedMethodFilter {
|
||||||
private val myTargetMethodName: String = when (targetDescriptor) {
|
init {
|
||||||
is ClassDescriptor, is ConstructorDescriptor -> "<init>"
|
assert(declarationPtr != null || isInvoke)
|
||||||
is PropertyAccessorDescriptor -> JvmAbi.getterName(targetDescriptor.correspondingProperty.name.asString())
|
|
||||||
else -> targetDescriptor.name.asString()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _targetDescriptor = SofterReference(
|
|
||||||
(targetDescriptor as? FunctionDescriptor)?.let { SamCodegenUtil.getOriginalIfSamAdapter(it) } ?: targetDescriptor
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun getCallingExpressionLines() = myCallingExpressionLines
|
override fun getCallingExpressionLines() = myCallingExpressionLines
|
||||||
|
|
||||||
override fun getMethodName() = myTargetMethodName
|
override fun getMethodName() = targetMethodName
|
||||||
|
|
||||||
override fun locationMatches(process: DebugProcessImpl, location: Location): Boolean {
|
override fun locationMatches(process: DebugProcessImpl, location: Location): Boolean {
|
||||||
val targetDescriptor = _targetDescriptor.get() ?: return true
|
|
||||||
|
|
||||||
val method = location.method()
|
val method = location.method()
|
||||||
if (myTargetMethodName != method.name()) return false
|
if (targetMethodName != method.name()) return false
|
||||||
|
|
||||||
val positionManager = process.positionManager
|
val positionManager = process.positionManager
|
||||||
|
|
||||||
val currentDescriptor = runReadAction {
|
val (currentDescriptor, currentDeclaration) = runReadAction {
|
||||||
val elementAt = positionManager.getSourcePosition(location)?.elementAt
|
val elementAt = positionManager.getSourcePosition(location)?.elementAt
|
||||||
|
|
||||||
val declaration = elementAt?.getParentOfTypesAndPredicate(false, KtDeclaration::class.java) {
|
val declaration = elementAt?.getParentOfTypesAndPredicate(false, KtDeclaration::class.java) {
|
||||||
@@ -69,44 +60,36 @@ class KotlinBasicStepMethodFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (declaration is KtClass && method.name() == "<init>") {
|
if (declaration is KtClass && method.name() == "<init>") {
|
||||||
declaration.resolveToDescriptorIfAny()?.unsubstitutedPrimaryConstructor
|
declaration.resolveToDescriptorIfAny()?.unsubstitutedPrimaryConstructor to declaration
|
||||||
} else {
|
} else {
|
||||||
declaration?.resolveToDescriptorIfAny()
|
declaration?.resolveToDescriptorIfAny() to declaration
|
||||||
}
|
}
|
||||||
} ?: return false // TODO: Check that we can always find a descriptor (libraries with sources, libraries without sources)
|
}
|
||||||
|
|
||||||
|
if (currentDescriptor == null || currentDeclaration == null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("FoldInitializerAndIfToElvis")
|
@Suppress("FoldInitializerAndIfToElvis")
|
||||||
if (currentDescriptor !is CallableMemberDescriptor) return false
|
if (currentDescriptor !is CallableMemberDescriptor) return false
|
||||||
if (currentDescriptor.kind != DECLARATION) return false
|
if (currentDescriptor.kind != DECLARATION) return false
|
||||||
|
|
||||||
if (targetDescriptor is FunctionInvokeDescriptor) {
|
if (isInvoke) {
|
||||||
// There can be only one 'invoke' target at the moment so consider position as expected.
|
// There can be only one 'invoke' target at the moment so consider position as expected.
|
||||||
// Descriptors can be not-equal, say when parameter has type `(T) -> T` and lambda is `Int.() -> Int`.
|
// Descriptors can be not-equal, say when parameter has type `(T) -> T` and lambda is `Int.() -> Int`.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compareDescriptors(currentDescriptor, targetDescriptor)) return true
|
val declaration = declarationPtr?.element
|
||||||
|
?: return true // Element is lost. But we know that name is matches, so stop.
|
||||||
|
|
||||||
// We should stop if current descriptor overrides the target one or some base descriptor of target
|
if (currentDeclaration.isEquivalentTo(declaration)) {
|
||||||
// (if target descriptor is delegation or fake override)
|
|
||||||
|
|
||||||
val baseDescriptors = when (targetDescriptor.kind) {
|
|
||||||
DELEGATION, FAKE_OVERRIDE ->
|
|
||||||
targetDescriptor.getDirectlyOverriddenDeclarations()
|
|
||||||
DECLARATION, SYNTHESIZED ->
|
|
||||||
listOf(targetDescriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (baseDescriptors.any { baseOfTarget -> compareDescriptors(baseOfTarget, currentDescriptor) }) {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return DescriptorUtils.getAllOverriddenDescriptors(currentDescriptor).any { baseOfCurrent ->
|
return DescriptorUtils.getAllOverriddenDescriptors(currentDescriptor).any { baseOfCurrent ->
|
||||||
baseDescriptors.any { baseOfTarget -> compareDescriptors(baseOfCurrent, baseOfTarget) }
|
val currentBaseDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(currentDeclaration.project, baseOfCurrent)
|
||||||
|
declaration.isEquivalentTo(currentBaseDeclaration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun compareDescriptors(d1: DeclarationDescriptor, d2: DeclarationDescriptor): Boolean {
|
|
||||||
return d1 == d2 || d1.original == d2.original
|
|
||||||
}
|
|
||||||
+24
-8
@@ -4,23 +4,39 @@ import com.intellij.debugger.actions.SmartStepTarget
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.util.Range
|
import com.intellij.util.Range
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
|
||||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy
|
import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||||
import javax.swing.Icon
|
import javax.swing.Icon
|
||||||
|
|
||||||
class KotlinMethodSmartStepTarget(
|
class KotlinMethodSmartStepTarget(
|
||||||
val descriptor: CallableMemberDescriptor,
|
descriptor: CallableMemberDescriptor,
|
||||||
|
val declaration: KtDeclaration?,
|
||||||
label: String,
|
label: String,
|
||||||
highlightElement: PsiElement,
|
highlightElement: PsiElement,
|
||||||
lines: Range<Int>
|
lines: Range<Int>
|
||||||
) : SmartStepTarget(label, highlightElement, false, lines) {
|
) : SmartStepTarget(label, highlightElement, false, lines) {
|
||||||
|
val isInvoke = descriptor is FunctionInvokeDescriptor
|
||||||
|
|
||||||
|
init {
|
||||||
|
assert(declaration != null || isInvoke)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val isExtension = descriptor.isExtension
|
||||||
|
|
||||||
|
val targetMethodName: String = when (descriptor) {
|
||||||
|
is ClassDescriptor, is ConstructorDescriptor -> "<init>"
|
||||||
|
is PropertyAccessorDescriptor -> JvmAbi.getterName(descriptor.correspondingProperty.name.asString())
|
||||||
|
else -> descriptor.name.asString()
|
||||||
|
}
|
||||||
|
|
||||||
override fun getIcon(): Icon? {
|
override fun getIcon(): Icon? {
|
||||||
return when {
|
return when {
|
||||||
descriptor.isExtension -> KotlinIcons.EXTENSION_FUNCTION
|
isExtension -> KotlinIcons.EXTENSION_FUNCTION
|
||||||
else -> KotlinIcons.FUNCTION
|
else -> KotlinIcons.FUNCTION
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,19 +60,19 @@ class KotlinMethodSmartStepTarget(
|
|||||||
|
|
||||||
if (other == null || other !is KotlinMethodSmartStepTarget) return false
|
if (other == null || other !is KotlinMethodSmartStepTarget) return false
|
||||||
|
|
||||||
if (descriptor is FunctionInvokeDescriptor && other.descriptor is FunctionInvokeDescriptor) {
|
if (isInvoke && other.isInvoke) {
|
||||||
// Don't allow to choose several invoke targets in smart step into as we can't distinguish them reliably during debug
|
// Don't allow to choose several invoke targets in smart step into as we can't distinguish them reliably during debug
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return descriptor == other.descriptor
|
return declaration === other.declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
if (descriptor is FunctionInvokeDescriptor) {
|
if (isInvoke) {
|
||||||
// Predefined value to make all FunctionInvokeDescriptor targets equal
|
// Predefined value to make all FunctionInvokeDescriptor targets equal
|
||||||
return 42
|
return 42
|
||||||
}
|
}
|
||||||
return descriptor.hashCode()
|
return declaration!!.hashCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+68
-51
@@ -26,13 +26,11 @@ import com.intellij.psi.PsiMethod
|
|||||||
import com.intellij.util.Range
|
import com.intellij.util.Range
|
||||||
import com.intellij.util.containers.OrderedSet
|
import com.intellij.util.containers.OrderedSet
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||||
|
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||||
import org.jetbrains.kotlin.config.JvmTarget
|
import org.jetbrains.kotlin.config.JvmTarget
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||||
@@ -40,6 +38,7 @@ import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
|||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.load.java.isFromJava
|
import org.jetbrains.kotlin.load.java.isFromJava
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getParentCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getParentCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
@@ -150,62 +149,69 @@ class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
||||||
val resolvedCall = expression.getResolvedCall(bindingContext)
|
recordGetter(expression)
|
||||||
if (resolvedCall != null) {
|
super.visitSimpleNameExpression(expression)
|
||||||
val propertyDescriptor = resolvedCall.resultingDescriptor
|
}
|
||||||
if (propertyDescriptor is PropertyDescriptor) {
|
|
||||||
val getterDescriptor = propertyDescriptor.getter
|
private fun recordGetter(expression: KtSimpleNameExpression) {
|
||||||
if (getterDescriptor != null && !getterDescriptor.isDefault) {
|
val resolvedCall = expression.getResolvedCall(bindingContext) ?: return
|
||||||
val delegatedResolvedCall = bindingContext[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor]
|
val propertyDescriptor = resolvedCall.resultingDescriptor as? PropertyDescriptor ?: return
|
||||||
if (delegatedResolvedCall == null) {
|
|
||||||
val getter = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, getterDescriptor)
|
val getterDescriptor = propertyDescriptor.getter
|
||||||
if (getter is KtPropertyAccessor && getter.hasBody()) {
|
if (getterDescriptor == null || getterDescriptor.isDefault) return
|
||||||
val label = KotlinMethodSmartStepTarget.calcLabel(getterDescriptor)
|
|
||||||
result.add(KotlinMethodSmartStepTarget(getterDescriptor, label, expression, lines))
|
val ktDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, getterDescriptor) as? KtDeclaration ?: return
|
||||||
}
|
|
||||||
} else {
|
val delegatedResolvedCall = bindingContext[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor]
|
||||||
val delegatedPropertyGetterDescriptor = delegatedResolvedCall.resultingDescriptor
|
if (delegatedResolvedCall != null) {
|
||||||
val label =
|
val delegatedPropertyGetterDescriptor = delegatedResolvedCall.resultingDescriptor
|
||||||
"${propertyDescriptor.name}." + KotlinMethodSmartStepTarget.calcLabel(delegatedPropertyGetterDescriptor)
|
val label = "${propertyDescriptor.name}." + KotlinMethodSmartStepTarget.calcLabel(delegatedPropertyGetterDescriptor)
|
||||||
result.add(KotlinMethodSmartStepTarget(delegatedPropertyGetterDescriptor, label, expression, lines))
|
result.add(KotlinMethodSmartStepTarget(delegatedPropertyGetterDescriptor, ktDeclaration, label, expression, lines))
|
||||||
}
|
} else {
|
||||||
}
|
if (ktDeclaration is KtPropertyAccessor && ktDeclaration.hasBody()) {
|
||||||
|
val label = KotlinMethodSmartStepTarget.calcLabel(getterDescriptor)
|
||||||
|
result.add(KotlinMethodSmartStepTarget(getterDescriptor, ktDeclaration, label, expression, lines))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.visitSimpleNameExpression(expression)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun recordFunction(expression: KtExpression) {
|
private fun recordFunction(expression: KtExpression) {
|
||||||
val resolvedCall = expression.getResolvedCall(bindingContext) ?: return
|
val resolvedCall = expression.getResolvedCall(bindingContext) ?: return
|
||||||
|
|
||||||
val descriptor = resolvedCall.resultingDescriptor
|
val descriptor = resolvedCall.resultingDescriptor
|
||||||
if (descriptor is FunctionDescriptor && !isIntrinsic(descriptor)) {
|
if (descriptor !is FunctionDescriptor || isIntrinsic(descriptor)) return
|
||||||
if (descriptor.isFromJava) {
|
|
||||||
(DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, descriptor) as? PsiMethod)?.let {
|
|
||||||
result.add(MethodSmartStepTarget(it, null, expression, false, lines))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (descriptor is ConstructorDescriptor && descriptor.isPrimary) {
|
|
||||||
val psiElement = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, descriptor)
|
|
||||||
if (psiElement is KtClass && psiElement.getAnonymousInitializers().isEmpty()) {
|
|
||||||
// There is no constructor or init block, so do not show it in smart step into
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val callLabel = KotlinMethodSmartStepTarget.calcLabel(descriptor)
|
val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, descriptor)
|
||||||
val label = when (descriptor) {
|
if (descriptor.isFromJava) {
|
||||||
is FunctionInvokeDescriptor -> {
|
(declaration as? PsiMethod)?.let {
|
||||||
when (expression) {
|
result.add(MethodSmartStepTarget(it, null, declaration, false, lines))
|
||||||
is KtSimpleNameExpression -> "${runReadAction { expression.text }}.$callLabel"
|
|
||||||
else -> callLabel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> callLabel
|
|
||||||
}
|
|
||||||
|
|
||||||
result.add(KotlinMethodSmartStepTarget(descriptor, label, expression, lines))
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (declaration == null && !isInvokeInBuiltinFunction(descriptor)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (declaration !is KtDeclaration?) return
|
||||||
|
|
||||||
|
if (descriptor is ConstructorDescriptor && descriptor.isPrimary) {
|
||||||
|
if (declaration is KtClass && declaration.getAnonymousInitializers().isEmpty()) {
|
||||||
|
// There is no constructor or init block, so do not show it in smart step into
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val callLabel = KotlinMethodSmartStepTarget.calcLabel(descriptor)
|
||||||
|
val label = when (descriptor) {
|
||||||
|
is FunctionInvokeDescriptor -> {
|
||||||
|
when (expression) {
|
||||||
|
is KtSimpleNameExpression -> "${runReadAction { expression.text }}.$callLabel"
|
||||||
|
else -> callLabel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> callLabel
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(KotlinMethodSmartStepTarget(descriptor, declaration, label, expression, lines))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, null)
|
}, null)
|
||||||
@@ -216,7 +222,12 @@ class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
|
|||||||
override fun createMethodFilter(stepTarget: SmartStepTarget?): MethodFilter? {
|
override fun createMethodFilter(stepTarget: SmartStepTarget?): MethodFilter? {
|
||||||
return when (stepTarget) {
|
return when (stepTarget) {
|
||||||
is KotlinMethodSmartStepTarget ->
|
is KotlinMethodSmartStepTarget ->
|
||||||
KotlinBasicStepMethodFilter(stepTarget.descriptor, stepTarget.callingExpressionLines!!)
|
KotlinBasicStepMethodFilter(
|
||||||
|
stepTarget.declaration?.createSmartPointer(),
|
||||||
|
stepTarget.isInvoke,
|
||||||
|
stepTarget.targetMethodName,
|
||||||
|
stepTarget.callingExpressionLines!!
|
||||||
|
)
|
||||||
is KotlinLambdaSmartStepTarget ->
|
is KotlinLambdaSmartStepTarget ->
|
||||||
KotlinLambdaMethodFilter(
|
KotlinLambdaMethodFilter(
|
||||||
stepTarget.getLambda(), stepTarget.callingExpressionLines!!, stepTarget.isInline, stepTarget.isSuspend
|
stepTarget.getLambda(), stepTarget.callingExpressionLines!!, stepTarget.isInline, stepTarget.isSuspend
|
||||||
@@ -231,4 +242,10 @@ class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
|
|||||||
private fun isIntrinsic(descriptor: CallableMemberDescriptor): Boolean {
|
private fun isIntrinsic(descriptor: CallableMemberDescriptor): Boolean {
|
||||||
return methods.getIntrinsic(descriptor) != null
|
return methods.getIntrinsic(descriptor) != null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isInvokeInBuiltinFunction(descriptor: DeclarationDescriptor): Boolean {
|
||||||
|
if (descriptor !is FunctionInvokeDescriptor) return false
|
||||||
|
val classDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return false
|
||||||
|
return classDescriptor.defaultType.isBuiltinFunctionalType
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinLineBreakpointType
|
|||||||
import org.jetbrains.kotlin.idea.debugger.stepping.*
|
import org.jetbrains.kotlin.idea.debugger.stepping.*
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils.findStringWithPrefixes
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils.findStringWithPrefixes
|
||||||
@@ -246,7 +247,11 @@ abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() {
|
|||||||
KotlinLambdaMethodFilter(
|
KotlinLambdaMethodFilter(
|
||||||
stepTarget.getLambda(), stepTarget.getCallingExpressionLines()!!, stepTarget.isInline, stepTarget.isSuspend)
|
stepTarget.getLambda(), stepTarget.getCallingExpressionLines()!!, stepTarget.isInline, stepTarget.isSuspend)
|
||||||
is KotlinMethodSmartStepTarget ->
|
is KotlinMethodSmartStepTarget ->
|
||||||
KotlinBasicStepMethodFilter(stepTarget.descriptor, stepTarget.getCallingExpressionLines()!!)
|
KotlinBasicStepMethodFilter(
|
||||||
|
stepTarget.declaration?.createSmartPointer(),
|
||||||
|
stepTarget.isInvoke,
|
||||||
|
stepTarget.targetMethodName,
|
||||||
|
stepTarget.getCallingExpressionLines()!!)
|
||||||
is MethodSmartStepTarget -> BasicStepMethodFilter(stepTarget.method, stepTarget.getCallingExpressionLines())
|
is MethodSmartStepTarget -> BasicStepMethodFilter(stepTarget.method, stepTarget.getCallingExpressionLines())
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user