Change the way 'step over' over inline calls works (KT-13751)
Previously it worked by invoking 'Run To Cursor' for the last position of inline function. As there's only one 'run to cursor' breakpoint available in Idea framework, it couldn't work when inline function call was was used in conditions of control flow statements. A new approach works through multiple step over operation and controlling stop position. In other words we try to "step over" inlined lines. Same thing is actually done in "Smart Step Into" action. (cherry picked from commit 2e8775d) #KT-13751 Fixed
This commit is contained in:
committed by
Nikolay Krasko
parent
9594316b0a
commit
7992df7b93
@@ -0,0 +1,16 @@
|
||||
package inlineInIfFalse
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val bar = ""
|
||||
//Breakpoint!
|
||||
if (inlineCall { true }) {
|
||||
foo()
|
||||
}
|
||||
foo()
|
||||
}
|
||||
|
||||
fun foo() {}
|
||||
|
||||
inline fun inlineCall(predicate: (String?) -> Boolean): Boolean {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package inlineInIfTrue
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val bar = ""
|
||||
//Breakpoint!
|
||||
if (inlineCall { true }) {
|
||||
foo()
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {}
|
||||
|
||||
inline fun inlineCall(predicate: (String?) -> Boolean): Boolean {
|
||||
return true
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package soInlineAnonymousFunctionArgument
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
//Breakpoint!
|
||||
val b = 1 // 1
|
||||
|
||||
foo( // 2
|
||||
fun (){ test(1) }
|
||||
)
|
||||
|
||||
foo(fun (){ test(1) }) // 3
|
||||
} // 4
|
||||
|
||||
inline fun foo(f: () -> Unit) {
|
||||
f()
|
||||
}
|
||||
|
||||
fun test(i: Int) = 1
|
||||
|
||||
// STEP_OVER: 6
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
package soInlineCallInLastStatementInInline
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
bar()
|
||||
}
|
||||
|
||||
inline fun bar() {
|
||||
//Breakpoint!
|
||||
val a = 1
|
||||
foo { 42 }
|
||||
}
|
||||
|
||||
inline fun foo(f: () -> Unit) {
|
||||
f()
|
||||
}
|
||||
|
||||
// STEP_OVER: 2
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
package soInlineCallInLastStatementInInlineInInline
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
bar()
|
||||
val i = 45
|
||||
}
|
||||
|
||||
inline fun bar() {
|
||||
val a = 1
|
||||
foo { 42 }
|
||||
}
|
||||
|
||||
inline fun foo(f: () -> Unit) {
|
||||
//Breakpoint!
|
||||
f()
|
||||
}
|
||||
|
||||
// STEP_OVER: 4
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package soInlineFunCallInLastStatementOfInlineWithArgumentFromCalleeAndOwn
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
bar {
|
||||
println("")
|
||||
}
|
||||
}
|
||||
|
||||
inline fun bar(f2: () -> Unit) {
|
||||
//Breakpoint! (lambdaOrdinal = -1)
|
||||
foo({ 42 },
|
||||
f2)
|
||||
}
|
||||
|
||||
inline fun foo(f1: () -> Unit, f2: () -> Unit) {
|
||||
f1()
|
||||
f2()
|
||||
}
|
||||
|
||||
// STEP_OVER 5
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package soInlineFunWithLastStatementMultilineArgumentCall
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
var k = 444
|
||||
bar {
|
||||
val b = 1
|
||||
}
|
||||
|
||||
k++
|
||||
}
|
||||
|
||||
inline fun bar(f: (Int) -> Unit) {
|
||||
//Breakpoint!
|
||||
f(1)
|
||||
}
|
||||
|
||||
// STEP_OVER: 1
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package soInlineFunWithLastStatementOneLineArgumentCall
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
var k = 444
|
||||
bar { val b = 1 }
|
||||
k++
|
||||
}
|
||||
|
||||
inline fun bar(f: (Int) -> Unit) {
|
||||
//Breakpoint!
|
||||
f(1)
|
||||
}
|
||||
|
||||
// STEP_OVER: 4
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package soInlineIfConditionLambdaFalse
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
bar {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
inline fun bar(f: (Int) -> Boolean) {
|
||||
//Breakpoint!
|
||||
if (f(42)) {
|
||||
foo()
|
||||
}
|
||||
else {
|
||||
foo()
|
||||
}
|
||||
|
||||
foo()
|
||||
}
|
||||
|
||||
fun foo() {}
|
||||
|
||||
// STEP_OVER: 4
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package soInlineIfConditionLambdaTrue
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
bar {
|
||||
true
|
||||
}
|
||||
} // 4
|
||||
|
||||
inline fun bar(f: (Int) -> Boolean) {
|
||||
//Breakpoint!
|
||||
if (f(42)) { // 1
|
||||
foo() // 2
|
||||
}
|
||||
else {
|
||||
foo()
|
||||
}
|
||||
|
||||
foo() // 3
|
||||
}
|
||||
|
||||
fun foo() {}
|
||||
|
||||
// STEP_OVER: 4
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package soInlineWhileCondition
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
//Breakpoint!
|
||||
var i = 1 // 1
|
||||
// inline in while condition (true)
|
||||
while (id { i < 2 }) { // 2 4
|
||||
i++ // 3
|
||||
}
|
||||
|
||||
// inline in while condition (false)
|
||||
while (id { false }) { // 5
|
||||
bar()
|
||||
}
|
||||
} // 6
|
||||
|
||||
inline fun id(f: () -> Boolean): Boolean {
|
||||
return f()
|
||||
}
|
||||
|
||||
fun bar() {}
|
||||
|
||||
// STEP_OVER: 6
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package soReifiedInlineIfConditionFalse
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
// Reified function call in if condition
|
||||
//Breakpoint!
|
||||
if (reified(11) != 11) { // 1
|
||||
val a = 22
|
||||
}
|
||||
} // 2
|
||||
|
||||
inline fun <reified T> reified(f: T): T {
|
||||
val a = 33
|
||||
return f
|
||||
}
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package soSimpleInlineIfCondition
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
//Breakpoint!
|
||||
if (foo {
|
||||
test(2)
|
||||
}) {
|
||||
bar()
|
||||
}
|
||||
|
||||
bar()
|
||||
}
|
||||
|
||||
inline fun foo(f: () -> Boolean): Boolean = f()
|
||||
|
||||
fun test(i: Int): Boolean = true
|
||||
|
||||
fun bar() {}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package stepOverDeclarationInInlineFun
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
foo { 1 }
|
||||
}
|
||||
|
||||
inline fun foo(f: () -> Int): Int {
|
||||
//Breakpoint!
|
||||
val a = 15
|
||||
return f()
|
||||
}
|
||||
+13
-23
@@ -2,45 +2,40 @@ package stepOverIfWithInline
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
//Breakpoint!
|
||||
val prop = 1
|
||||
val prop = 1 // 1
|
||||
// False with braces
|
||||
val a = if (1 > 2) {
|
||||
val a = if (1 > 2) { // 2 4(?)
|
||||
foo { test(1) }
|
||||
}
|
||||
else {
|
||||
foo { test(1) }
|
||||
foo { test(1) } // 3
|
||||
}
|
||||
|
||||
// False without braces
|
||||
val b = if (1 > 2)
|
||||
val b = if (1 > 2) // 5 7(?)
|
||||
foo { test(1) }
|
||||
else
|
||||
foo { test(1) }
|
||||
foo { test(1) } // 6
|
||||
|
||||
// One line
|
||||
val c = if (1 > 2) foo { test(1) } else foo { test(1) }
|
||||
val c = if (1 > 2) foo { test(1) } else foo { test(1) } // 8
|
||||
|
||||
// Else on next line, false
|
||||
val d = if (1 > 2) foo { test(1) }
|
||||
else foo { test(1) }
|
||||
val d = if (1 > 2) foo { test(1) } // 9 11
|
||||
else foo { test(1) } // 10
|
||||
|
||||
// Else on next line, true
|
||||
val e = if (1 < 2) foo { test(1) }
|
||||
val e = if (1 < 2) foo { test(1) } // 12
|
||||
else foo { test(1) }
|
||||
|
||||
// Inline function call in condition
|
||||
val f = if (foo { test(1) } > 2) {
|
||||
val f = if (foo { test(1) } > 2) { // 13 15(?)
|
||||
foo { test(1) }
|
||||
}
|
||||
else {
|
||||
foo { test(1) }
|
||||
foo { test(1) } // 14
|
||||
}
|
||||
|
||||
// Reified function call in if condition
|
||||
if (reified(1) != 1) {
|
||||
val a = 1
|
||||
}
|
||||
}
|
||||
} // 16
|
||||
|
||||
inline fun foo(f: () -> Int): Int {
|
||||
val a = 1
|
||||
@@ -49,9 +44,4 @@ inline fun foo(f: () -> Int): Int {
|
||||
|
||||
fun test(i: Int) = 1
|
||||
|
||||
inline fun <reified T> reified(f: T): Int {
|
||||
val a = 1
|
||||
return 1
|
||||
}
|
||||
|
||||
// STEP_OVER: 25
|
||||
// STEP_OVER: 17
|
||||
+2
-4
@@ -1,8 +1,8 @@
|
||||
package stepOverInlinedLambda
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val a = A()
|
||||
//Breakpoint!
|
||||
val a = A()
|
||||
foo { test(1) }
|
||||
foo {
|
||||
test(2)
|
||||
@@ -27,8 +27,6 @@ fun main(args: Array<String>) {
|
||||
})
|
||||
|
||||
val b = foo { test(1) }
|
||||
|
||||
foo(fun (){ test(1) })
|
||||
}
|
||||
|
||||
inline fun foo(f: () -> Unit) {
|
||||
@@ -49,4 +47,4 @@ class A {
|
||||
|
||||
fun test(i: Int) = 1
|
||||
|
||||
// STEP_OVER: 11
|
||||
// STEP_OVER: 12
|
||||
+4
-4
@@ -3,16 +3,16 @@ package stepOverInlinedLambdaStdlib
|
||||
fun main(args: Array<String>) {
|
||||
//Breakpoint!
|
||||
val a = listOf(1, 2, 3)
|
||||
a.filter { it > 1 }
|
||||
a.filter { it > 1 } /*!*/
|
||||
|
||||
a.filter { it > 1 }.map { it * 2 }
|
||||
a.filter { it > 1 }.map { it * 2 } /*!*/
|
||||
|
||||
a.filter {
|
||||
a.filter { /*!*/
|
||||
it > 1
|
||||
}.map {
|
||||
it * 2
|
||||
}
|
||||
}
|
||||
} /*!*/
|
||||
|
||||
// TRACING_FILTERS_ENABLED: false
|
||||
// STEP_OVER: 4
|
||||
+4
-1
@@ -9,8 +9,11 @@ fun main(args: Array<String>) {
|
||||
inline fun bar(f: (Int) -> Unit) {
|
||||
//Breakpoint!
|
||||
val a = 1
|
||||
foo()
|
||||
val f = f(1)
|
||||
val c = 1
|
||||
}
|
||||
|
||||
// STEP_OVER: 3
|
||||
fun foo() {}
|
||||
|
||||
// STEP_OVER: 4
|
||||
+16
-16
@@ -4,43 +4,43 @@ fun main(args: Array<String>) {
|
||||
try {
|
||||
bar()
|
||||
}
|
||||
catch(e: Exception) {
|
||||
val a = 1
|
||||
catch(e: Exception) { // 13
|
||||
val a = 1 // 14
|
||||
}
|
||||
}
|
||||
} // 15
|
||||
|
||||
fun bar() {
|
||||
//Breakpoint!
|
||||
val prop = 1
|
||||
val prop = 1 // 1
|
||||
// Try
|
||||
try {
|
||||
foo { test(1) }
|
||||
try { // 2
|
||||
foo { test(1) } // 3
|
||||
}
|
||||
catch(e: Exception) {
|
||||
foo { test(1) }
|
||||
}
|
||||
|
||||
// Many catch clauses
|
||||
try {
|
||||
throw IllegalStateException()
|
||||
try { // 4
|
||||
throw IllegalStateException() // 5
|
||||
}
|
||||
catch(e: IllegalStateException) {
|
||||
foo { test(1) }
|
||||
catch(e: IllegalStateException) { // 6
|
||||
foo { test(1) } // 7
|
||||
}
|
||||
catch(e: Exception) {
|
||||
foo { test(1) }
|
||||
}
|
||||
|
||||
// exception in lambda
|
||||
try {
|
||||
foo { throw IllegalStateException() }
|
||||
try { // 8
|
||||
foo { throw IllegalStateException() } // 9
|
||||
}
|
||||
catch(e: Exception) {
|
||||
foo { test(1) }
|
||||
catch(e: Exception) { // 10
|
||||
foo { test(1) } // 11
|
||||
}
|
||||
|
||||
// Exception without catch
|
||||
foo { throw IllegalStateException() }
|
||||
foo { throw IllegalStateException() } // 12
|
||||
val prop2 = 1
|
||||
}
|
||||
|
||||
@@ -51,4 +51,4 @@ inline fun foo(f: () -> Int): Int {
|
||||
|
||||
fun test(i: Int) = 1
|
||||
|
||||
// STEP_OVER: 20
|
||||
// STEP_OVER: 15
|
||||
+6
-6
@@ -1,23 +1,23 @@
|
||||
package stepOverWhenInReturn
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
whenInReturn()
|
||||
}
|
||||
whenInReturn() // 4?
|
||||
} // 5
|
||||
|
||||
fun whenInReturn(): Int {
|
||||
val a = 1
|
||||
//Breakpoint!
|
||||
return when(a) {
|
||||
1 -> foo { 1 }
|
||||
return when(a) { // 1 3?
|
||||
1 -> foo { 1 } // 2
|
||||
else -> 3
|
||||
}
|
||||
}
|
||||
|
||||
inline fun foo(f: () -> Int): Int {
|
||||
val a = 1
|
||||
val a = 15
|
||||
return f()
|
||||
}
|
||||
|
||||
fun test(i: Int) = 1
|
||||
fun test(i: Int) = 42
|
||||
|
||||
// STEP_OVER: 6
|
||||
+26
-26
@@ -2,45 +2,45 @@ package stepOverWhenWithInline
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
//Breakpoint!
|
||||
val prop = 1
|
||||
val prop = 1 // 1
|
||||
// Break after second
|
||||
val a = when {
|
||||
1 > 2 -> foo { test(1) }
|
||||
2 > 1 -> foo { test(1) }
|
||||
val a = when { // 4
|
||||
1 > 2 -> foo { test(1) } // 2
|
||||
2 > 1 -> foo { test(1) } // 3
|
||||
else -> foo { test(1) }
|
||||
}
|
||||
|
||||
val b = when {
|
||||
1 > 2 -> {
|
||||
val b = when { // 8
|
||||
1 > 2 -> { // 5
|
||||
foo { test(1) }
|
||||
}
|
||||
2 > 1 -> {
|
||||
foo { test(1) }
|
||||
2 > 1 -> { // 6
|
||||
foo { test(1) } // 7
|
||||
}
|
||||
else -> {
|
||||
foo { test(1) }
|
||||
}
|
||||
}
|
||||
|
||||
val c = when {
|
||||
foo { test(1) } > 2 -> 1
|
||||
2 > foo { test(1) } -> 2
|
||||
val c = when { // 11
|
||||
foo { test(1) } > 2 -> 1 // 9
|
||||
2 > foo { test(1) } -> 2 // 10
|
||||
else -> foo { test(1) }
|
||||
}
|
||||
|
||||
// When with expression
|
||||
val a1 = when(prop) {
|
||||
val a1 = when(1) { // 12 14
|
||||
2 -> foo { test(1) }
|
||||
1 -> foo { test(1) }
|
||||
1 -> foo { test(1) } // 13
|
||||
else -> foo { test(1) }
|
||||
}
|
||||
|
||||
val b1 = when(prop) {
|
||||
val b1 = when(1) { // 15 17
|
||||
2 -> {
|
||||
foo { test(1) }
|
||||
}
|
||||
1 -> {
|
||||
foo { test(1) }
|
||||
foo { test(1) } // 16
|
||||
}
|
||||
else -> {
|
||||
foo { test(1) }
|
||||
@@ -48,21 +48,21 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
|
||||
// Break after first
|
||||
val c1 = when(prop) {
|
||||
foo { test(1) } -> 1
|
||||
val c1 = when(1) { // 18 20
|
||||
foo { test(1) } -> 1 // 19
|
||||
foo { test(2) } -> 2
|
||||
else -> foo { test(1) }
|
||||
}
|
||||
|
||||
val a2 = when {
|
||||
2 > 1 -> foo { test(1) }
|
||||
val a2 = when { // 22
|
||||
2 > 1 -> foo { test(1) } // 21
|
||||
1 > 2 -> foo { test(1) }
|
||||
else -> foo { test(1) }
|
||||
}
|
||||
|
||||
val b2 = when {
|
||||
2 > 1 -> {
|
||||
foo { test(1) }
|
||||
val b2 = when { // 25
|
||||
2 > 1 -> { // 23
|
||||
foo { test(1) } // 24
|
||||
}
|
||||
1 > 2 -> {
|
||||
foo { test(1) }
|
||||
@@ -72,12 +72,12 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
}
|
||||
|
||||
val c2 = when {
|
||||
2 > foo { test(1) } -> 2
|
||||
val c2 = when { // 27
|
||||
2 > foo { test(1) } -> 2 // 26
|
||||
foo { test(1) } > 2 -> 1
|
||||
else -> foo { test(1) }
|
||||
}
|
||||
}
|
||||
} // 28
|
||||
|
||||
inline fun foo(f: () -> Int): Int {
|
||||
val a = 1
|
||||
@@ -86,4 +86,4 @@ inline fun foo(f: () -> Int): Int {
|
||||
|
||||
fun test(i: Int) = i
|
||||
|
||||
// STEP_OVER: 41
|
||||
// STEP_OVER: 30
|
||||
+15
-26
@@ -2,40 +2,29 @@ package stepOverWhileWithInline
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
//Breakpoint!
|
||||
var prop = 0
|
||||
var prop = 0 // 1
|
||||
// inline on last line of while
|
||||
while(prop < 1) {
|
||||
prop++
|
||||
foo { test(1) }
|
||||
while(prop < 1) { // 2 5
|
||||
prop++ // 3
|
||||
foo { test(1) } // 4
|
||||
}
|
||||
|
||||
// inline call inside while
|
||||
while(prop < 2) {
|
||||
foo { test(1) }
|
||||
prop++
|
||||
while(prop < 2) { // 6 9
|
||||
foo { test(1) } // 7
|
||||
prop++ // 8
|
||||
}
|
||||
|
||||
do {
|
||||
prop++
|
||||
foo { test(1) }
|
||||
} while(prop < 3)
|
||||
prop++ // 10
|
||||
foo { test(1) } // 11
|
||||
} while(prop < 3) // 12
|
||||
|
||||
do {
|
||||
foo { test(1) }
|
||||
prop++
|
||||
} while(prop < 4)
|
||||
|
||||
var i = 1
|
||||
// inline in while condition (true)
|
||||
while(foo { test(i++) } == 1) {
|
||||
prop++
|
||||
}
|
||||
|
||||
// inline in while condition (false)
|
||||
while(foo { test(2) } == 1) {
|
||||
prop++
|
||||
}
|
||||
}
|
||||
foo { test(1) } // 13
|
||||
prop++ // 14
|
||||
} while(prop < 4) // 15
|
||||
} // 16
|
||||
|
||||
inline fun foo(f: () -> Int): Int {
|
||||
val a = 1
|
||||
@@ -44,4 +33,4 @@ inline fun foo(f: () -> Int): Int {
|
||||
|
||||
fun test(i: Int) = i
|
||||
|
||||
// STEP_OVER: 41
|
||||
// STEP_OVER: 16
|
||||
Reference in New Issue
Block a user