Debugger: A dirty fix for setting breakpoints inside finally {} in case if exception is thrown from try {} (#KT-22654)

This commit is contained in:
Yan Zhulanow
2018-03-02 20:58:49 +03:00
parent eec9c6bffa
commit 966480a155
7 changed files with 92 additions and 7 deletions
@@ -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
View File
@@ -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
View File
@@ -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
@@ -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");