Skip all same line locations when stepping over inline call (KT-20351)
#KT-20351
This commit is contained in:
+12
-12
@@ -336,7 +336,7 @@ fun getStepOverAction(
|
|||||||
return ktFile?.name ?: this.sourceName(KOTLIN_STRATA_NAME)
|
return ktFile?.name ?: this.sourceName(KOTLIN_STRATA_NAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isLocationSuitable(nextLocation: Location): Boolean {
|
fun isThisMethodLocation(nextLocation: Location): Boolean {
|
||||||
if (nextLocation.method() != location.method()) {
|
if (nextLocation.method() != location.method()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -358,7 +358,7 @@ fun getStepOverAction(
|
|||||||
val previousSuitableLocation = methodLocations.reversed()
|
val previousSuitableLocation = methodLocations.reversed()
|
||||||
.dropWhile { it != location }
|
.dropWhile { it != location }
|
||||||
.drop(1)
|
.drop(1)
|
||||||
.filter(::isLocationSuitable)
|
.filter(::isThisMethodLocation)
|
||||||
.dropWhile { it.ktLineNumber() == location.ktLineNumber() }
|
.dropWhile { it.ktLineNumber() == location.ktLineNumber() }
|
||||||
.firstOrNull()
|
.firstOrNull()
|
||||||
|
|
||||||
@@ -368,7 +368,7 @@ fun getStepOverAction(
|
|||||||
val patchedLocation = if (isBackEdgeLocation()) {
|
val patchedLocation = if (isBackEdgeLocation()) {
|
||||||
// Pretend we had already done a backing step
|
// Pretend we had already done a backing step
|
||||||
methodLocations
|
methodLocations
|
||||||
.filter(::isLocationSuitable)
|
.filter(::isThisMethodLocation)
|
||||||
.firstOrNull { it.ktLineNumber() == location.ktLineNumber() } ?: location
|
.firstOrNull { it.ktLineNumber() == location.ktLineNumber() } ?: location
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -388,22 +388,22 @@ fun getStepOverAction(
|
|||||||
|
|
||||||
val inlineRangeVariables = getInlineRangeLocalVariables(frameProxy)
|
val inlineRangeVariables = getInlineRangeLocalVariables(frameProxy)
|
||||||
|
|
||||||
// Try to find the range of inlined lines:
|
// Try to find the range for step over:
|
||||||
// - Lines from other files and from functions that are not in range of current one are definitely inlined
|
// - Lines from other files and from functions that are not in range of current one are definitely inlined and should be stepped over.
|
||||||
// - Lines in function arguments of inlined functions are inlined too as we found them starting from the position of inlined call.
|
// - Lines in function arguments of inlined functions are inlined too as we found them starting from the position of inlined call.
|
||||||
|
// - Current line locations should also be stepped over.
|
||||||
//
|
//
|
||||||
// It also thinks that too many lines are inlined when there's a call of function argument or other
|
// We might erroneously extend this range too much when there's a call of function argument or other
|
||||||
// inline function in last statement of inline function. The list of inlineRangeVariables is used to overcome it.
|
// inline function in last statement of inline function. The list of inlineRangeVariables will be used later to overcome it.
|
||||||
val probablyInlinedLocations = methodLocations
|
val stepOverLocations = methodLocations
|
||||||
.dropWhile { it != patchedLocation }
|
.dropWhile { it != patchedLocation }
|
||||||
.drop(1)
|
.drop(1)
|
||||||
.dropWhile { it.ktLineNumber() == patchedLineNumber }
|
.dropWhile { it.ktLineNumber() == patchedLineNumber }
|
||||||
.takeWhile { loc ->
|
.takeWhile { loc ->
|
||||||
!isLocationSuitable(loc) || lambdaArgumentRanges.any { loc.ktLineNumber() in it }
|
!isThisMethodLocation(loc) || lambdaArgumentRanges.any { loc.ktLineNumber() in it } || loc.ktLineNumber() == patchedLineNumber
|
||||||
}
|
}
|
||||||
.dropWhile { it.ktLineNumber() == patchedLineNumber }
|
|
||||||
|
|
||||||
if (!probablyInlinedLocations.isEmpty()) {
|
if (!stepOverLocations.isEmpty()) {
|
||||||
// Some Kotlin inlined methods with 'for' (and maybe others) generates bytecode that after dexing have a strange artifact.
|
// Some Kotlin inlined methods with 'for' (and maybe others) generates bytecode that after dexing have a strange artifact.
|
||||||
// GOTO instructions are moved to the end of method and as they don't have proper line, line is obtained from the previous
|
// GOTO instructions are moved to the end of method and as they don't have proper line, line is obtained from the previous
|
||||||
// instruction. It might be method return or previous GOTO from the inlining. Simple stepping over such function is really
|
// instruction. It might be method return or previous GOTO from the inlining. Simple stepping over such function is really
|
||||||
@@ -423,7 +423,7 @@ fun getStepOverAction(
|
|||||||
|
|
||||||
return Action.STEP_OVER_INLINED(StepOverFilterData(
|
return Action.STEP_OVER_INLINED(StepOverFilterData(
|
||||||
patchedLineNumber,
|
patchedLineNumber,
|
||||||
probablyInlinedLocations.map { it.ktLineNumber() }.toSet(),
|
stepOverLocations.map { it.ktLineNumber() }.toSet(),
|
||||||
inlineRangeVariables,
|
inlineRangeVariables,
|
||||||
isDexDebug,
|
isDexDebug,
|
||||||
returnCodeIndex
|
returnCodeIndex
|
||||||
|
|||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
package soInlineCallsInOneLine
|
||||||
|
|
||||||
|
fun test(i: Int): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo() {}
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
//Breakpoint!
|
||||||
|
val listOf = listOf(1)
|
||||||
|
val testSome = listOf.filterNot(::test)
|
||||||
|
foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// STEP_OVER: 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
LineBreakpoint created at soInlineCallsInOneLine.kt:11
|
||||||
|
Run Java
|
||||||
|
Connected to the target VM
|
||||||
|
soInlineCallsInOneLine.kt:11
|
||||||
|
soInlineCallsInOneLine.kt:12
|
||||||
|
soInlineCallsInOneLine.kt:13
|
||||||
|
soInlineCallsInOneLine.kt:14
|
||||||
|
Disconnected from the target VM
|
||||||
|
|
||||||
|
Process finished with exit code 0
|
||||||
@@ -578,6 +578,12 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest {
|
|||||||
doStepOverTest(fileName);
|
doStepOverTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("soInlineCallsInOneLine.kt")
|
||||||
|
public void testSoInlineCallsInOneLine() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/soInlineCallsInOneLine.kt");
|
||||||
|
doStepOverTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("soInlineFunCallInLastStatementOfInlineWithArgumentFromCalleeAndOwn.kt")
|
@TestMetadata("soInlineFunCallInLastStatementOfInlineWithArgumentFromCalleeAndOwn.kt")
|
||||||
public void testSoInlineFunCallInLastStatementOfInlineWithArgumentFromCalleeAndOwn() throws Exception {
|
public void testSoInlineFunCallInLastStatementOfInlineWithArgumentFromCalleeAndOwn() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/soInlineFunCallInLastStatementOfInlineWithArgumentFromCalleeAndOwn.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/soInlineFunCallInLastStatementOfInlineWithArgumentFromCalleeAndOwn.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user