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 (tryCatchBlockEnd != null) {
|
||||||
|
if (finallyBlockStackElement != null) {
|
||||||
|
markLineNumber(finallyBlockStackElement.expression, true);
|
||||||
|
}
|
||||||
|
|
||||||
v.goTo(tryCatchBlockEnd);
|
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.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
|
||||||
import org.jetbrains.kotlin.psi.KtFunction
|
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
import com.intellij.debugger.engine.DebuggerUtils as JDebuggerUtils
|
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.
|
// have been merged into one), but it's impossible to correctly map locations to actual source expressions now.
|
||||||
val locationIndex = sameLineLocations.indexOf(location)
|
val locationIndex = sameLineLocations.indexOf(location)
|
||||||
if (locationIndex > 0) {
|
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);
|
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")
|
@TestMetadata("funLiteral.kt")
|
||||||
public void testFunLiteral() throws Exception {
|
public void testFunLiteral() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/funLiteral.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/funLiteral.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user