Do not skip invoke call on parameters during smart step into (KT-18577)
#KT-18577 Fixed
This commit is contained in:
+29
-3
@@ -20,8 +20,10 @@ import com.intellij.debugger.engine.DebugProcessImpl
|
|||||||
import com.intellij.debugger.engine.NamedMethodFilter
|
import com.intellij.debugger.engine.NamedMethodFilter
|
||||||
import com.intellij.util.Range
|
import com.intellij.util.Range
|
||||||
import com.sun.jdi.Location
|
import com.sun.jdi.Location
|
||||||
|
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.*
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
import org.jetbrains.kotlin.idea.core.getDirectlyOverriddenDeclarations
|
import org.jetbrains.kotlin.idea.core.getDirectlyOverriddenDeclarations
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
@@ -33,8 +35,8 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypesAndPredicate
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
|
||||||
class KotlinBasicStepMethodFilter(
|
class KotlinBasicStepMethodFilter(
|
||||||
val targetDescriptor: CallableMemberDescriptor,
|
private val targetDescriptor: CallableMemberDescriptor,
|
||||||
val myCallingExpressionLines: Range<Int>
|
private val myCallingExpressionLines: Range<Int>
|
||||||
) : NamedMethodFilter {
|
) : NamedMethodFilter {
|
||||||
private val myTargetMethodName = when (targetDescriptor) {
|
private val myTargetMethodName = when (targetDescriptor) {
|
||||||
is ClassDescriptor, is ConstructorDescriptor -> "<init>"
|
is ClassDescriptor, is ConstructorDescriptor -> "<init>"
|
||||||
@@ -50,7 +52,7 @@ class KotlinBasicStepMethodFilter(
|
|||||||
val method = location.method()
|
val method = location.method()
|
||||||
if (myTargetMethodName != method.name()) return false
|
if (myTargetMethodName != method.name()) return false
|
||||||
|
|
||||||
val positionManager = process.positionManager ?: return false
|
val positionManager = process.positionManager
|
||||||
|
|
||||||
val currentDescriptor = runReadAction {
|
val currentDescriptor = runReadAction {
|
||||||
val elementAt = positionManager.getSourcePosition(location)?.elementAt
|
val elementAt = positionManager.getSourcePosition(location)?.elementAt
|
||||||
@@ -72,6 +74,10 @@ class KotlinBasicStepMethodFilter(
|
|||||||
|
|
||||||
if (compareDescriptors(currentDescriptor, targetDescriptor)) return true
|
if (compareDescriptors(currentDescriptor, targetDescriptor)) return true
|
||||||
|
|
||||||
|
if (targetDescriptor is FunctionInvokeDescriptor && currentDescriptor is FunctionDescriptor) {
|
||||||
|
return isCompatibleSignatures(targetDescriptor, currentDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
// We should stop if current descriptor overrides the target one or some base descriptor of target
|
// We should stop if current descriptor overrides the target one or some base descriptor of target
|
||||||
// (if target descriptor is delegation or fake override)
|
// (if target descriptor is delegation or fake override)
|
||||||
|
|
||||||
@@ -94,4 +100,24 @@ class KotlinBasicStepMethodFilter(
|
|||||||
|
|
||||||
private fun compareDescriptors(d1: DeclarationDescriptor, d2: DeclarationDescriptor): Boolean {
|
private fun compareDescriptors(d1: DeclarationDescriptor, d2: DeclarationDescriptor): Boolean {
|
||||||
return d1 == d2 || d1.original == d2.original
|
return d1 == d2 || d1.original == d2.original
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isCompatibleSignatures(target: FunctionDescriptor, current: FunctionDescriptor): Boolean {
|
||||||
|
// A very primitive approximation
|
||||||
|
if (target.valueParameters.size != current.valueParameters.size) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.returnType != current.returnType) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((i, targetParam) in target.valueParameters.withIndex()) {
|
||||||
|
val currentParam = current.valueParameters[i]
|
||||||
|
if (targetParam.type != currentParam.type) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
package smartStepIntoToLambdaParameter
|
||||||
|
|
||||||
|
fun nonDefaultParameter(paramFun: (Int) -> Int) {
|
||||||
|
// SMART_STEP_INTO_BY_INDEX: 0
|
||||||
|
// RESUME: 1
|
||||||
|
//Breakpoint!
|
||||||
|
paramFun(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun defaultParameter(f: (String) -> Int = { it.toInt() }) {
|
||||||
|
// SMART_STEP_INTO_BY_INDEX: 0
|
||||||
|
// RESUME: 1
|
||||||
|
//Breakpoint!
|
||||||
|
f("12")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun badSignatureIsSkipped(f: (String) -> Int = { it.toInt() }, paramFun: (Int) -> Int) {
|
||||||
|
// SMART_STEP_INTO_BY_INDEX: 0
|
||||||
|
// RESUME: 1
|
||||||
|
//Breakpoint!
|
||||||
|
paramFun(f("12"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun nonDefaultWithAnonymousFun(paramFun: (Int) -> Int) {
|
||||||
|
// SMART_STEP_INTO_BY_INDEX: 0
|
||||||
|
// RESUME: 1
|
||||||
|
//Breakpoint!
|
||||||
|
paramFun(12)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withExtensionParameters(paramFun: Int.() -> Int) {
|
||||||
|
// SMART_STEP_INTO_BY_INDEX: 0
|
||||||
|
// RESUME: 1
|
||||||
|
//Breakpoint!
|
||||||
|
12.paramFun()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
val localFun : (Int) -> Int = { it + 1 }
|
||||||
|
|
||||||
|
nonDefaultParameter(localFun)
|
||||||
|
|
||||||
|
defaultParameter()
|
||||||
|
|
||||||
|
badSignatureIsSkipped { it + 1 }
|
||||||
|
|
||||||
|
nonDefaultWithAnonymousFun(fun (i: Int): Int { return i })
|
||||||
|
|
||||||
|
withExtensionParameters { this }
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
LineBreakpoint created at smartStepIntoToLambdaParameter.kt:7
|
||||||
|
LineBreakpoint created at smartStepIntoToLambdaParameter.kt:14
|
||||||
|
LineBreakpoint created at smartStepIntoToLambdaParameter.kt:21
|
||||||
|
LineBreakpoint created at smartStepIntoToLambdaParameter.kt:28
|
||||||
|
LineBreakpoint created at smartStepIntoToLambdaParameter.kt:35
|
||||||
|
Run Java
|
||||||
|
Connected to the target VM
|
||||||
|
smartStepIntoToLambdaParameter.kt:7
|
||||||
|
smartStepIntoToLambdaParameter.kt:39
|
||||||
|
smartStepIntoToLambdaParameter.kt:14
|
||||||
|
smartStepIntoToLambdaParameter.kt:10
|
||||||
|
smartStepIntoToLambdaParameter.kt:21
|
||||||
|
smartStepIntoToLambdaParameter.kt:45
|
||||||
|
smartStepIntoToLambdaParameter.kt:28
|
||||||
|
smartStepIntoToLambdaParameter.kt:47
|
||||||
|
smartStepIntoToLambdaParameter.kt:35
|
||||||
|
smartStepIntoToLambdaParameter.kt:49
|
||||||
|
Disconnected from the target VM
|
||||||
|
|
||||||
|
Process finished with exit code 0
|
||||||
@@ -1259,6 +1259,12 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest {
|
|||||||
doCustomTest(fileName);
|
doCustomTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("smartStepIntoToLambdaParameter.kt")
|
||||||
|
public void testSmartStepIntoToLambdaParameter() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/smartStepIntoToLambdaParameter.kt");
|
||||||
|
doCustomTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("smartStepIntoWithDelegates.kt")
|
@TestMetadata("smartStepIntoWithDelegates.kt")
|
||||||
public void testSmartStepIntoWithDelegates() throws Exception {
|
public void testSmartStepIntoWithDelegates() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/smartStepIntoWithDelegates.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/smartStepIntoWithDelegates.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user