Skip to content

Commit 502ac80

Browse files
committed
Do not skip invoke call on parameters during smart step into (KT-18577)
#KT-18577 Fixed
1 parent e5ce91d commit 502ac80

File tree

4 files changed

+105
-3
lines changed

4 files changed

+105
-3
lines changed

idea/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinBasicStepMethodFilter.kt

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ import com.intellij.debugger.engine.DebugProcessImpl
2020
import com.intellij.debugger.engine.NamedMethodFilter
2121
import com.intellij.util.Range
2222
import com.sun.jdi.Location
23+
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
2324
import org.jetbrains.kotlin.descriptors.*
2425
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.*
26+
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
2527
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
2628
import org.jetbrains.kotlin.idea.core.getDirectlyOverriddenDeclarations
2729
import org.jetbrains.kotlin.idea.util.application.runReadAction
@@ -33,8 +35,8 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypesAndPredicate
3335
import org.jetbrains.kotlin.resolve.DescriptorUtils
3436

3537
class KotlinBasicStepMethodFilter(
36-
val targetDescriptor: CallableMemberDescriptor,
37-
val myCallingExpressionLines: Range<Int>
38+
private val targetDescriptor: CallableMemberDescriptor,
39+
private val myCallingExpressionLines: Range<Int>
3840
) : NamedMethodFilter {
3941
private val myTargetMethodName = when (targetDescriptor) {
4042
is ClassDescriptor, is ConstructorDescriptor -> "<init>"
@@ -50,7 +52,7 @@ class KotlinBasicStepMethodFilter(
5052
val method = location.method()
5153
if (myTargetMethodName != method.name()) return false
5254

53-
val positionManager = process.positionManager ?: return false
55+
val positionManager = process.positionManager
5456

5557
val currentDescriptor = runReadAction {
5658
val elementAt = positionManager.getSourcePosition(location)?.elementAt
@@ -72,6 +74,10 @@ class KotlinBasicStepMethodFilter(
7274

7375
if (compareDescriptors(currentDescriptor, targetDescriptor)) return true
7476

77+
if (targetDescriptor is FunctionInvokeDescriptor && currentDescriptor is FunctionDescriptor) {
78+
return isCompatibleSignatures(targetDescriptor, currentDescriptor)
79+
}
80+
7581
// We should stop if current descriptor overrides the target one or some base descriptor of target
7682
// (if target descriptor is delegation or fake override)
7783

@@ -94,4 +100,24 @@ class KotlinBasicStepMethodFilter(
94100

95101
private fun compareDescriptors(d1: DeclarationDescriptor, d2: DeclarationDescriptor): Boolean {
96102
return d1 == d2 || d1.original == d2.original
103+
}
104+
105+
private fun isCompatibleSignatures(target: FunctionDescriptor, current: FunctionDescriptor): Boolean {
106+
// A very primitive approximation
107+
if (target.valueParameters.size != current.valueParameters.size) {
108+
return false
109+
}
110+
111+
if (target.returnType != current.returnType) {
112+
return false
113+
}
114+
115+
for ((i, targetParam) in target.valueParameters.withIndex()) {
116+
val currentParam = current.valueParameters[i]
117+
if (targetParam.type != currentParam.type) {
118+
return false
119+
}
120+
}
121+
122+
return true
97123
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package smartStepIntoToLambdaParameter
2+
3+
fun nonDefaultParameter(paramFun: (Int) -> Int) {
4+
// SMART_STEP_INTO_BY_INDEX: 0
5+
// RESUME: 1
6+
//Breakpoint!
7+
paramFun(1)
8+
}
9+
10+
fun defaultParameter(f: (String) -> Int = { it.toInt() }) {
11+
// SMART_STEP_INTO_BY_INDEX: 0
12+
// RESUME: 1
13+
//Breakpoint!
14+
f("12")
15+
}
16+
17+
fun badSignatureIsSkipped(f: (String) -> Int = { it.toInt() }, paramFun: (Int) -> Int) {
18+
// SMART_STEP_INTO_BY_INDEX: 0
19+
// RESUME: 1
20+
//Breakpoint!
21+
paramFun(f("12"))
22+
}
23+
24+
fun nonDefaultWithAnonymousFun(paramFun: (Int) -> Int) {
25+
// SMART_STEP_INTO_BY_INDEX: 0
26+
// RESUME: 1
27+
//Breakpoint!
28+
paramFun(12)
29+
}
30+
31+
fun withExtensionParameters(paramFun: Int.() -> Int) {
32+
// SMART_STEP_INTO_BY_INDEX: 0
33+
// RESUME: 1
34+
//Breakpoint!
35+
12.paramFun()
36+
}
37+
38+
fun main(args: Array<String>) {
39+
val localFun : (Int) -> Int = { it + 1 }
40+
41+
nonDefaultParameter(localFun)
42+
43+
defaultParameter()
44+
45+
badSignatureIsSkipped { it + 1 }
46+
47+
nonDefaultWithAnonymousFun(fun (i: Int): Int { return i })
48+
49+
withExtensionParameters { this }
50+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
LineBreakpoint created at smartStepIntoToLambdaParameter.kt:7
2+
LineBreakpoint created at smartStepIntoToLambdaParameter.kt:14
3+
LineBreakpoint created at smartStepIntoToLambdaParameter.kt:21
4+
LineBreakpoint created at smartStepIntoToLambdaParameter.kt:28
5+
LineBreakpoint created at smartStepIntoToLambdaParameter.kt:35
6+
Run Java
7+
Connected to the target VM
8+
smartStepIntoToLambdaParameter.kt:7
9+
smartStepIntoToLambdaParameter.kt:39
10+
smartStepIntoToLambdaParameter.kt:14
11+
smartStepIntoToLambdaParameter.kt:10
12+
smartStepIntoToLambdaParameter.kt:21
13+
smartStepIntoToLambdaParameter.kt:45
14+
smartStepIntoToLambdaParameter.kt:28
15+
smartStepIntoToLambdaParameter.kt:47
16+
smartStepIntoToLambdaParameter.kt:35
17+
smartStepIntoToLambdaParameter.kt:49
18+
Disconnected from the target VM
19+
20+
Process finished with exit code 0

idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,12 @@ public void testSmartStepIntoSubClass() throws Exception {
12591259
doCustomTest(fileName);
12601260
}
12611261

1262+
@TestMetadata("smartStepIntoToLambdaParameter.kt")
1263+
public void testSmartStepIntoToLambdaParameter() throws Exception {
1264+
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/smartStepIntoToLambdaParameter.kt");
1265+
doCustomTest(fileName);
1266+
}
1267+
12621268
@TestMetadata("smartStepIntoWithDelegates.kt")
12631269
public void testSmartStepIntoWithDelegates() throws Exception {
12641270
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/smartStepIntoWithDelegates.kt");

0 commit comments

Comments
 (0)