From 15db1c8a8fb12e991274d0bbe8197e255a68e20c Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Fri, 29 Mar 2019 22:27:18 +0300 Subject: [PATCH] Debugger: Do not validate line breakpoints for irrelevant classes (KT-30714) --- .../debugger/NoStrataPositionManagerHelper.kt | 13 +++- .../breakpoints/KotlinLineBreakpoint.kt | 66 +++++++++++++++++++ .../breakpoints/KotlinLineBreakpointType.java | 8 +++ 3 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinLineBreakpoint.kt diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/NoStrataPositionManagerHelper.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/NoStrataPositionManagerHelper.kt index be090575866..0a57f322718 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/NoStrataPositionManagerHelper.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/NoStrataPositionManagerHelper.kt @@ -29,6 +29,7 @@ import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.containers.ConcurrentFactoryMap import com.sun.jdi.Location import com.sun.jdi.ReferenceType +import com.sun.jdi.VirtualMachine import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches import org.jetbrains.kotlin.idea.refactoring.getLineCount @@ -329,6 +330,12 @@ private fun inlinedLinesNumbers( @Volatile var emulateDexDebugInTests: Boolean = false -fun DebugProcess.isDexDebug() = - (emulateDexDebugInTests && ApplicationManager.getApplication().isUnitTestMode) || - (this.virtualMachineProxy as? VirtualMachineProxyImpl)?.virtualMachine?.name() == "Dalvik" // TODO: check other machine names \ No newline at end of file +fun DebugProcess.isDexDebug(): Boolean { + val virtualMachine = (this.virtualMachineProxy as? VirtualMachineProxyImpl)?.virtualMachine + return virtualMachine.isDexDebug() +} + +fun VirtualMachine?.isDexDebug(): Boolean { + // TODO: check other machine names + return (emulateDexDebugInTests && ApplicationManager.getApplication().isUnitTestMode) || this?.name() == "Dalvik" +} \ No newline at end of file diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinLineBreakpoint.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinLineBreakpoint.kt new file mode 100644 index 00000000000..58d5bd8e8eb --- /dev/null +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinLineBreakpoint.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.debugger.breakpoints + +import com.intellij.debugger.engine.DebugProcess +import com.intellij.debugger.impl.DebuggerUtilsEx +import com.intellij.debugger.ui.breakpoints.LineBreakpoint +import com.intellij.openapi.project.Project +import com.intellij.xdebugger.XSourcePosition +import com.intellij.xdebugger.breakpoints.XBreakpoint +import com.intellij.xdebugger.breakpoints.XBreakpointProperties +import com.sun.jdi.AbsentInformationException +import com.sun.jdi.ReferenceType +import org.jetbrains.java.debugger.breakpoints.properties.JavaLineBreakpointProperties +import org.jetbrains.kotlin.codegen.inline.KOTLIN_STRATA_NAME +import org.jetbrains.kotlin.idea.debugger.isDexDebug + +class KotlinLineBreakpoint( + project: Project?, + xBreakpoint: XBreakpoint>? +) : LineBreakpoint(project, xBreakpoint) { + override fun processClassPrepare(debugProcess: DebugProcess?, classType: ReferenceType?) { + val sourcePosition = xBreakpoint?.sourcePosition + + if (classType != null && sourcePosition != null) { + if (!hasTargetLine(classType, sourcePosition)) { + return + } + } + + super.processClassPrepare(debugProcess, classType) + } + + /** + * Returns false if `classType` definitely does not contain a location for a given `sourcePosition`. + */ + private fun hasTargetLine(classType: ReferenceType, sourcePosition: XSourcePosition): Boolean { + val allLineLocations = DebuggerUtilsEx.allLineLocations(classType) ?: return true + + if (classType.virtualMachine().isDexDebug()) { + return true + } + + val fileName = sourcePosition.file.name + val lineNumber = sourcePosition.line + 1 + + for (location in allLineLocations) { + try { + val kotlinFileName = location.sourceName(KOTLIN_STRATA_NAME) + val kotlinLineNumber = location.lineNumber(KOTLIN_STRATA_NAME) + if (kotlinFileName == fileName && kotlinLineNumber == lineNumber) { + return true + } + } catch (e: AbsentInformationException) { + if (location.sourceName() == fileName && location.lineNumber() == lineNumber) { + return true + } + } + } + + return false + } +} \ No newline at end of file diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinLineBreakpointType.java b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinLineBreakpointType.java index e0f9d97649e..a65519bf527 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinLineBreakpointType.java +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinLineBreakpointType.java @@ -45,6 +45,14 @@ public class KotlinLineBreakpointType extends JavaLineBreakpointType { super("kotlin-line", "Kotlin Line Breakpoints"); } + @NotNull + @Override + public Breakpoint createJavaBreakpoint( + Project project, XBreakpoint breakpoint + ) { + return new KotlinLineBreakpoint(project, breakpoint); + } + @Override public boolean matchesPosition(@NotNull LineBreakpoint breakpoint, @NotNull SourcePosition position) { JavaBreakpointProperties properties = getProperties(breakpoint);