Debugger: Do not validate line breakpoints for irrelevant classes (KT-30714)

This commit is contained in:
Yan Zhulanow
2019-03-29 22:27:18 +03:00
parent 2c5e8dab23
commit 15db1c8a8f
3 changed files with 84 additions and 3 deletions
@@ -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
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"
}
@@ -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<out XBreakpointProperties<*>>?
) : LineBreakpoint<JavaLineBreakpointProperties>(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
}
}
@@ -45,6 +45,14 @@ public class KotlinLineBreakpointType extends JavaLineBreakpointType {
super("kotlin-line", "Kotlin Line Breakpoints");
}
@NotNull
@Override
public Breakpoint<JavaLineBreakpointProperties> createJavaBreakpoint(
Project project, XBreakpoint<JavaLineBreakpointProperties> breakpoint
) {
return new KotlinLineBreakpoint(project, breakpoint);
}
@Override
public boolean matchesPosition(@NotNull LineBreakpoint<?> breakpoint, @NotNull SourcePosition position) {
JavaBreakpointProperties properties = getProperties(breakpoint);