Debugger: A dirty fix for setting breakpoints inside finally {} in case if exception is thrown from try {} (#KT-22654)
This commit is contained in:
@@ -1488,6 +1488,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
if (tryCatchBlockEnd != null) {
|
||||
if (finallyBlockStackElement != null) {
|
||||
markLineNumber(finallyBlockStackElement.expression, true);
|
||||
}
|
||||
|
||||
v.goTo(tryCatchBlockEnd);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -16,4 +16,4 @@ fun foo() {
|
||||
}
|
||||
}
|
||||
|
||||
// 2 3 7 4 5 7 8 +10 11 15 12 13 15 10 17
|
||||
// 2 3 7 8 4 5 7 8 7 8 +10 11 15 16 12 13 15 16 15 10 17
|
||||
+1
-1
@@ -12,4 +12,4 @@ fun foo() {
|
||||
}
|
||||
}
|
||||
|
||||
// 2 3 5 6 +8 9 11 8 13
|
||||
// 2 3 5 6 5 6 +8 9 11 12 11 8 13
|
||||
@@ -58,10 +58,8 @@ import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import com.intellij.debugger.engine.DebuggerUtils as JDebuggerUtils
|
||||
@@ -166,7 +164,16 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
|
||||
// have been merged into one), but it's impossible to correctly map locations to actual source expressions now.
|
||||
val locationIndex = sameLineLocations.indexOf(location)
|
||||
if (locationIndex > 0) {
|
||||
return KotlinReentrantSourcePosition(SourcePosition.createFromLine(psiFile, sourceLineNumber))
|
||||
/*
|
||||
`finally {}` block code is placed in the class file twice.
|
||||
Unless the debugger metadata is available, we can't figure out if we are inside `finally {}`, so we have to check it using PSI.
|
||||
This is conceptually wrong and won't work in some cases, but it's still better than nothing.
|
||||
*/
|
||||
val elementAt = psiFile.getLineStartOffset(lineNumber)?.let { psiFile.findElementAt(it) }
|
||||
val isInsideDuplicatedFinally = elementAt != null && elementAt.getStrictParentOfType<KtFinallySection>() != null
|
||||
if (!isInsideDuplicatedFinally) {
|
||||
return KotlinReentrantSourcePosition(SourcePosition.createFromLine(psiFile, sourceLineNumber))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package finallyBlock
|
||||
|
||||
fun throwException() { throw RuntimeException() }
|
||||
fun foo() {}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
fun wrap(f: () -> Unit) = try { f() } catch (e: Throwable) {}
|
||||
|
||||
wrap(::test1)
|
||||
wrap(::test2)
|
||||
wrap(::test3)
|
||||
}
|
||||
|
||||
fun test1() {
|
||||
try {
|
||||
//Breakpoint!
|
||||
throwException()
|
||||
} finally {
|
||||
//Breakpoint!
|
||||
foo()
|
||||
}
|
||||
}
|
||||
|
||||
fun test2() {
|
||||
try {
|
||||
//Breakpoint!
|
||||
foo()
|
||||
} finally {
|
||||
//Breakpoint!
|
||||
foo()
|
||||
}
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
try {
|
||||
//Breakpoint!
|
||||
throwException()
|
||||
} finally {
|
||||
//Breakpoint!
|
||||
try {
|
||||
throwException()
|
||||
} finally {
|
||||
//Breakpoint!
|
||||
foo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RESUME: 7
|
||||
@@ -0,0 +1,19 @@
|
||||
LineBreakpoint created at finallyBlock.kt:17
|
||||
LineBreakpoint created at finallyBlock.kt:20
|
||||
LineBreakpoint created at finallyBlock.kt:27
|
||||
LineBreakpoint created at finallyBlock.kt:30
|
||||
LineBreakpoint created at finallyBlock.kt:37
|
||||
LineBreakpoint created at finallyBlock.kt:40
|
||||
LineBreakpoint created at finallyBlock.kt:44
|
||||
Run Java
|
||||
Connected to the target VM
|
||||
finallyBlock.kt:17
|
||||
finallyBlock.kt:20
|
||||
finallyBlock.kt:27
|
||||
finallyBlock.kt:30
|
||||
finallyBlock.kt:37
|
||||
finallyBlock.kt:40
|
||||
finallyBlock.kt:44
|
||||
Disconnected from the target VM
|
||||
|
||||
Process finished with exit code 0
|
||||
+6
@@ -1176,6 +1176,12 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest {
|
||||
doCustomTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("finallyBlock.kt")
|
||||
public void testFinallyBlock() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/finallyBlock.kt");
|
||||
doCustomTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funLiteral.kt")
|
||||
public void testFunLiteral() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/funLiteral.kt");
|
||||
|
||||
Reference in New Issue
Block a user