Debugger: refactor smart step into to use descriptors instead of psi elements (KT-13485)

#KT-13485 Fixed
This commit is contained in:
Natalia Ukhorskaya
2016-10-27 17:13:24 +03:00
committed by Nikolay Krasko
parent f7203da2d6
commit 0fb5a18a26
10 changed files with 163 additions and 68 deletions
@@ -50,9 +50,9 @@ import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import java.util.* import java.util.*
@@ -116,9 +116,9 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
if (lambdaOrFunIfInside != null) { if (lambdaOrFunIfInside != null) {
return SourcePosition.createFromElement(lambdaOrFunIfInside.bodyExpression!!) return SourcePosition.createFromElement(lambdaOrFunIfInside.bodyExpression!!)
} }
val property = getParameterIfInConstructor(location, psiFile, lineNumber) val elementInDeclaration = getElementForDeclarationLine(location, psiFile, lineNumber)
if (property != null) { if (elementInDeclaration != null) {
return SourcePosition.createFromElement(property) return SourcePosition.createFromElement(elementInDeclaration)
} }
if (lineNumber > psiFile.getLineCount() && myDebugProcess.isDexDebug()) { if (lineNumber > psiFile.getLineCount() && myDebugProcess.isDexDebug()) {
@@ -134,18 +134,25 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
return SourcePosition.createFromLine(psiFile, lineNumber) return SourcePosition.createFromLine(psiFile, lineNumber)
} }
private fun getParameterIfInConstructor(location: Location, file: KtFile, lineNumber: Int): KtParameter? { // Returns a property or a constructor if debugger stops at class declaration
private fun getElementForDeclarationLine(location: Location, file: KtFile, lineNumber: Int): KtElement? {
val lineStartOffset = file.getLineStartOffset(lineNumber) ?: return null val lineStartOffset = file.getLineStartOffset(lineNumber) ?: return null
val elementAt = file.findElementAt(lineStartOffset) val elementAt = file.findElementAt(lineStartOffset)
val contextElement = KotlinCodeFragmentFactory.getContextElement(elementAt) val contextElement = KotlinCodeFragmentFactory.getContextElement(elementAt)
if (contextElement !is KtClass) return null
val methodName = location.method().name() val methodName = location.method().name()
if (contextElement is KtClass && JvmAbi.isGetterName(methodName)) { return when {
val parameterForGetter = contextElement.getPrimaryConstructor()?.valueParameters?.firstOrNull() { JvmAbi.isGetterName(methodName) -> {
it.hasValOrVar() && it.name != null && JvmAbi.getterName(it.name!!) == methodName val parameterForGetter = contextElement.getPrimaryConstructor()?.valueParameters?.firstOrNull() {
} ?: return null it.hasValOrVar() && it.name != null && JvmAbi.getterName(it.name!!) == methodName
return parameterForGetter } ?: return null
parameterForGetter
}
methodName == "<init>" -> contextElement.getPrimaryConstructor()
else -> null
} }
return null
} }
private fun getLambdaOrFunIfInside(location: Location, file: KtFile, lineNumber: Int): KtFunction? { private fun getLambdaOrFunIfInside(location: Location, file: KtFile, lineNumber: Int): KtFunction? {
@@ -16,31 +16,31 @@
package org.jetbrains.kotlin.idea.debugger.stepping package org.jetbrains.kotlin.idea.debugger.stepping
import com.intellij.debugger.SourcePosition
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.debugger.impl.DebuggerUtilsEx
import com.intellij.util.Range import com.intellij.util.Range
import com.sun.jdi.Location import com.sun.jdi.Location
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
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.load.java.JvmAbi
import org.jetbrains.kotlin.psi.KtAnonymousInitializer import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtConstructor import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPropertyAccessor import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypesAndPredicate
import org.jetbrains.kotlin.resolve.findTopMostOverriddenDescriptors
class KotlinBasicStepMethodFilter( class KotlinBasicStepMethodFilter(
val resolvedElement: KtElement, val descriptor: CallableDescriptor,
val myCallingExpressionLines: Range<Int> val myCallingExpressionLines: Range<Int>
) : NamedMethodFilter { ) : NamedMethodFilter {
private val myTargetMethodName: String private val myTargetMethodName: String
init { init {
myTargetMethodName = when (resolvedElement) { myTargetMethodName = when (descriptor) {
is KtAnonymousInitializer -> "<init>" is ClassDescriptor, is ConstructorDescriptor -> "<init>"
is KtConstructor<*> -> "<init>" is PropertyAccessorDescriptor -> JvmAbi.getterName(descriptor.correspondingProperty.name.asString())
is KtPropertyAccessor -> JvmAbi.getterName((resolvedElement.property).name!!) else -> descriptor.name.asString()
else -> resolvedElement.name!!
} }
} }
@@ -52,13 +52,35 @@ class KotlinBasicStepMethodFilter(
val method = location.method() val method = location.method()
if (myTargetMethodName != method.name()) return false if (myTargetMethodName != method.name()) return false
val sourcePosition = runReadAction { SourcePosition.createFromElement(resolvedElement) } ?: return false
val positionManager = process.positionManager ?: return false val positionManager = process.positionManager ?: return false
val classes = positionManager.getAllClasses(sourcePosition) val descriptor = runReadAction {
val elementAt = positionManager.getSourcePosition(location)?.elementAt
return classes.any { val declaration = elementAt?.getParentOfTypesAndPredicate(false, KtDeclaration::class.java) {
it == location.declaringType() || DebuggerUtilsEx.isAssignableFrom(it.name(), location.declaringType()) it !is KtProperty || !it.isLocal
}
if (declaration is KtClass && method.name() == "<init>") {
(declaration.resolveToDescriptor() as? ClassDescriptor)?.unsubstitutedPrimaryConstructor
} else {
declaration?.resolveToDescriptor()
}
} ?: return false
fun compareDescriptors(d1: DeclarationDescriptor, d2: DeclarationDescriptor): Boolean {
return d1 == d2 || d1.original == d2.original
} }
if (compareDescriptors(descriptor, this.descriptor)) return true
if (descriptor is CallableDescriptor) {
return descriptor.findTopMostOverriddenDescriptors().any { compareDescriptors(it, this.descriptor) } ||
this.descriptor.findTopMostOverriddenDescriptors().any { compareDescriptors(it, descriptor)}
}
return false
} }
} }
@@ -3,23 +3,23 @@ package org.jetbrains.kotlin.idea.debugger.stepping
import com.intellij.debugger.actions.SmartStepTarget 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.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor 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.psi.KtElement
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import javax.swing.Icon import javax.swing.Icon
class KotlinMethodSmartStepTarget( class KotlinMethodSmartStepTarget(
val resolvedElement: KtElement, val descriptor: CallableDescriptor,
label: String, label: String,
highlightElement: PsiElement, highlightElement: PsiElement,
lines: Range<Int> lines: Range<Int>
): SmartStepTarget(label, highlightElement, false, lines) { ): SmartStepTarget(label, highlightElement, false, lines) {
override fun getIcon(): Icon? { override fun getIcon(): Icon? {
return when { return when {
resolvedElement is KtNamedFunction && resolvedElement.receiverTypeReference != null -> KotlinIcons.EXTENSION_FUNCTION descriptor.isExtension -> KotlinIcons.EXTENSION_FUNCTION
else -> KotlinIcons.FUNCTION else -> KotlinIcons.FUNCTION
} }
} }
@@ -43,8 +43,8 @@ class KotlinMethodSmartStepTarget(
if (other == null || other !is KotlinMethodSmartStepTarget) return false if (other == null || other !is KotlinMethodSmartStepTarget) return false
return resolvedElement == other.resolvedElement return descriptor == other.descriptor
} }
override fun hashCode() = resolvedElement.hashCode() override fun hashCode() = descriptor.hashCode()
} }
@@ -27,12 +27,14 @@ import com.intellij.util.Range
import com.intellij.util.containers.OrderedSet import com.intellij.util.containers.OrderedSet
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor 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.analyzeFully import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.load.java.isFromJava
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
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
@@ -146,20 +148,15 @@ class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
val delegatedResolvedCall = bindingContext[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor] val delegatedResolvedCall = bindingContext[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor]
if (delegatedResolvedCall == null) { if (delegatedResolvedCall == null) {
val getter = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, getterDescriptor) val getter = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, getterDescriptor)
if (getter is KtPropertyAccessor && (getter.bodyExpression != null || getter.equalsToken != null)) { if (getter is KtPropertyAccessor && getter.hasBody()) {
val label = KotlinMethodSmartStepTarget.calcLabel(getterDescriptor) val label = KotlinMethodSmartStepTarget.calcLabel(getterDescriptor)
result.add(KotlinMethodSmartStepTarget(getter, label, expression, lines)) result.add(KotlinMethodSmartStepTarget(getterDescriptor, label, expression, lines))
} }
} }
else { else {
val delegatedPropertyGetterDescriptor = delegatedResolvedCall.resultingDescriptor val delegatedPropertyGetterDescriptor = delegatedResolvedCall.resultingDescriptor
if (delegatedPropertyGetterDescriptor is CallableMemberDescriptor) { val label = "${propertyDescriptor.name}." + KotlinMethodSmartStepTarget.calcLabel(delegatedPropertyGetterDescriptor)
val function = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, delegatedPropertyGetterDescriptor) result.add(KotlinMethodSmartStepTarget(delegatedPropertyGetterDescriptor, label, expression, lines))
if (function is KtNamedFunction || function is KtSecondaryConstructor) {
val label = "${propertyDescriptor.name}." + KotlinMethodSmartStepTarget.calcLabel(delegatedPropertyGetterDescriptor)
result.add(KotlinMethodSmartStepTarget(function as KtFunction, label, expression, lines))
}
}
} }
} }
} }
@@ -172,19 +169,22 @@ class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
val descriptor = resolvedCall.resultingDescriptor val descriptor = resolvedCall.resultingDescriptor
if (descriptor is FunctionDescriptor && !isIntrinsic(descriptor)) { if (descriptor is FunctionDescriptor && !isIntrinsic(descriptor)) {
val resolvedElement = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, descriptor) if (descriptor.isFromJava) {
if (resolvedElement is KtNamedFunction || resolvedElement is KtConstructor<*>) { (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 label = KotlinMethodSmartStepTarget.calcLabel(descriptor) val label = KotlinMethodSmartStepTarget.calcLabel(descriptor)
result.add(KotlinMethodSmartStepTarget(resolvedElement as KtFunction, label, expression, lines)) result.add(KotlinMethodSmartStepTarget(descriptor, label, expression, lines))
}
else if (resolvedElement is PsiMethod) {
result.add(MethodSmartStepTarget(resolvedElement, null, expression, false, lines))
}
else if (resolvedElement is KtClass) {
resolvedElement.getAnonymousInitializers().firstOrNull()?.let {
val label = KotlinMethodSmartStepTarget.calcLabel(descriptor)
result.add(KotlinMethodSmartStepTarget(it, label, expression, lines))
}
} }
} }
} }
@@ -195,7 +195,7 @@ class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
override fun createMethodFilter(stepTarget: SmartStepTarget?): MethodFilter? { override fun createMethodFilter(stepTarget: SmartStepTarget?): MethodFilter? {
return when (stepTarget) { return when (stepTarget) {
is KotlinMethodSmartStepTarget -> KotlinBasicStepMethodFilter(stepTarget.resolvedElement, stepTarget.callingExpressionLines!!) is KotlinMethodSmartStepTarget -> KotlinBasicStepMethodFilter(stepTarget.descriptor, stepTarget.callingExpressionLines!!)
is KotlinLambdaSmartStepTarget -> KotlinLambdaMethodFilter(stepTarget.getLambda(), stepTarget.callingExpressionLines!!, stepTarget.isInline) is KotlinLambdaSmartStepTarget -> KotlinLambdaMethodFilter(stepTarget.getLambda(), stepTarget.callingExpressionLines!!, stepTarget.isInline)
else -> super.createMethodFilter(stepTarget) else -> super.createMethodFilter(stepTarget)
} }
@@ -9,30 +9,36 @@ LineBreakpoint created at smartStepIntoConstructor.kt:35
LineBreakpoint created at smartStepIntoConstructor.kt:39 LineBreakpoint created at smartStepIntoConstructor.kt:39
LineBreakpoint created at smartStepIntoConstructor.kt:43 LineBreakpoint created at smartStepIntoConstructor.kt:43
LineBreakpoint created at smartStepIntoConstructor.kt:47 LineBreakpoint created at smartStepIntoConstructor.kt:47
LineBreakpoint created at smartStepIntoConstructor.kt:51
LineBreakpoint created at smartStepIntoConstructor.kt:55
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! smartStepIntoConstructor.SmartStepIntoConstructorKt !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! smartStepIntoConstructor.SmartStepIntoConstructorKt
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
smartStepIntoConstructor.kt:7 smartStepIntoConstructor.kt:7
smartStepIntoConstructor.kt:51 smartStepIntoConstructor.kt:59
smartStepIntoConstructor.kt:11 smartStepIntoConstructor.kt:11
smartStepIntoConstructor.kt:52 smartStepIntoConstructor.kt:60
smartStepIntoConstructor.kt:15 smartStepIntoConstructor.kt:15
smartStepIntoConstructor.kt:54 smartStepIntoConstructor.kt:62
smartStepIntoConstructor.kt:19 smartStepIntoConstructor.kt:19
smartStepIntoConstructor.kt:57 smartStepIntoConstructor.kt:65
smartStepIntoConstructor.kt:23 smartStepIntoConstructor.kt:23
smartStepIntoConstructor.kt:61
smartStepIntoConstructor.kt:27
smartStepIntoConstructor.kt:66
smartStepIntoConstructor.kt:31
smartStepIntoConstructor.kt:69 smartStepIntoConstructor.kt:69
smartStepIntoConstructor.kt:35 smartStepIntoConstructor.kt:27
smartStepIntoConstructor.kt:74 smartStepIntoConstructor.kt:74
smartStepIntoConstructor.kt:31
smartStepIntoConstructor.kt:77
smartStepIntoConstructor.kt:35
smartStepIntoConstructor.kt:82
smartStepIntoConstructor.kt:39 smartStepIntoConstructor.kt:39
smartStepIntoConstructor.kt:81
smartStepIntoConstructor.kt:43
smartStepIntoConstructor.kt:89 smartStepIntoConstructor.kt:89
smartStepIntoConstructor.kt:47 smartStepIntoConstructor.kt:43
smartStepIntoConstructor.kt:97 smartStepIntoConstructor.kt:97
smartStepIntoConstructor.kt:47
smartStepIntoConstructor.kt:105
smartStepIntoConstructor.kt:51
smartStepIntoConstructor.kt:112
smartStepIntoConstructor.kt:55
smartStepIntoConstructor.kt:113
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0 Process finished with exit code 0
@@ -0,0 +1,13 @@
LineBreakpoint created at smartStepIntoInterfaceFun.kt:23
LineBreakpoint created at smartStepIntoInterfaceFun.kt:27
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! smartStepIntoInterfaceFun.SmartStepIntoInterfaceFunKt
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
smartStepIntoInterfaceFun.kt:23
smartStepIntoInterfaceFun.kt:11
smartStepIntoInterfaceFun.kt:27
smartStepIntoInterfaceFun.kt:14
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -45,6 +45,14 @@ fun main(args: Array<String>) {
// RESUME: 1 // RESUME: 1
//Breakpoint! //Breakpoint!
N(1) N(1)
// SMART_STEP_INTO_BY_INDEX: 1
// RESUME: 1
//Breakpoint!
O(1)
// SMART_STEP_INTO_BY_INDEX: 1
// RESUME: 1
//Breakpoint!
O(1, "1")
} }
@@ -100,4 +108,8 @@ class N {
constructor() { constructor() {
} }
}
class O<T>(i: T) {
constructor(i: Int, j: T): this(j) {
}
} }
@@ -0,0 +1,28 @@
// KT-13485
package smartStepIntoInterfaceFun
interface ObjectFace<T> {
fun act()
fun act2(t: T)
}
class ObjectClass : ObjectFace<Int> {
override fun act() {
println()
}
override fun act2(t: Int) {
println()
}
}
fun main(args: Array<String>) {
val simple: ObjectFace<Int> = ObjectClass()
// SMART_STEP_INTO_BY_INDEX: 1
// RESUME: 1
//Breakpoint!
simple.act()
// SMART_STEP_INTO_BY_INDEX: 1
// RESUME: 1
//Breakpoint!
simple.act2(1)
}
@@ -55,6 +55,7 @@ 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
import java.io.File import java.io.File
import java.lang.AssertionError
import javax.swing.SwingUtilities import javax.swing.SwingUtilities
abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() { abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() {
@@ -213,7 +214,7 @@ abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() {
stepTarget -> stepTarget ->
when (stepTarget) { when (stepTarget) {
is KotlinLambdaSmartStepTarget -> KotlinLambdaMethodFilter(stepTarget.getLambda(), stepTarget.getCallingExpressionLines()!!, stepTarget.isInline) is KotlinLambdaSmartStepTarget -> KotlinLambdaMethodFilter(stepTarget.getLambda(), stepTarget.getCallingExpressionLines()!!, stepTarget.isInline)
is KotlinMethodSmartStepTarget -> KotlinBasicStepMethodFilter(stepTarget.resolvedElement, stepTarget.getCallingExpressionLines()!!) is KotlinMethodSmartStepTarget -> KotlinBasicStepMethodFilter(stepTarget.descriptor, stepTarget.getCallingExpressionLines()!!)
is MethodSmartStepTarget -> BasicStepMethodFilter(stepTarget.method, stepTarget.getCallingExpressionLines()) is MethodSmartStepTarget -> BasicStepMethodFilter(stepTarget.method, stepTarget.getCallingExpressionLines())
else -> null else -> null
} }
@@ -890,6 +890,12 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest {
doCustomTest(fileName); doCustomTest(fileName);
} }
@TestMetadata("smartStepIntoInterfaceFun.kt")
public void testSmartStepIntoInterfaceFun() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/smartStepIntoInterfaceFun.kt");
doCustomTest(fileName);
}
@TestMetadata("smartStepIntoInterfaceImpl.kt") @TestMetadata("smartStepIntoInterfaceImpl.kt")
public void testSmartStepIntoInterfaceImpl() throws Exception { public void testSmartStepIntoInterfaceImpl() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/smartStepIntoInterfaceImpl.kt"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/smartStepIntoInterfaceImpl.kt");