Debugger: Add breakpoint applicability tests
This commit adds a number of tests that check breakpoint placing behavior, and an inline action that work the same way as tests.
This commit is contained in:
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.ui.breakpoints.JavaLineBreakpointType
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointType
|
||||
import com.intellij.xdebugger.breakpoints.XLineBreakpointType
|
||||
import org.jetbrains.debugger.SourceInfo
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.util.*
|
||||
|
||||
class BreakpointChecker {
|
||||
private companion object {
|
||||
private val BREAKPOINT_TYPES = mapOf(
|
||||
KotlinLineBreakpointType::class.java to BreakpointType.Line,
|
||||
KotlinFieldBreakpointType::class.java to BreakpointType.Field,
|
||||
KotlinFunctionBreakpointType::class.java to BreakpointType.Function,
|
||||
JavaLineBreakpointType.LambdaJavaBreakpointVariant::class.java to BreakpointType.Lambda,
|
||||
KotlinLineBreakpointType.LineKotlinBreakpointVariant::class.java to BreakpointType.Line,
|
||||
KotlinLineBreakpointType.KotlinBreakpointVariant::class.java to BreakpointType.All
|
||||
)
|
||||
}
|
||||
|
||||
enum class BreakpointType(val prefix: String) {
|
||||
Line("L"),
|
||||
Field("F"),
|
||||
Function("M"), // method
|
||||
Lambda("λ"),
|
||||
All("*") // line & lambda
|
||||
}
|
||||
|
||||
@Suppress("SimplifiableCall")
|
||||
private val breakpointTypes: List<XLineBreakpointType<*>> = run {
|
||||
val extensionPoint = Extensions.getArea(null)
|
||||
.getExtensionPoint<XBreakpointType<*, *>>(XBreakpointType.EXTENSION_POINT_NAME.name)
|
||||
|
||||
extensionPoint.extensions
|
||||
.filterIsInstance<XLineBreakpointType<*>>()
|
||||
.filter { it is KotlinBreakpointType }
|
||||
}
|
||||
|
||||
fun check(file: KtFile, line: Int): EnumSet<BreakpointType> {
|
||||
val actualBreakpointTypes = EnumSet.noneOf(BreakpointType::class.java)
|
||||
|
||||
for (breakpointType in breakpointTypes) {
|
||||
val sign = BREAKPOINT_TYPES[breakpointType.javaClass] ?: continue
|
||||
val isApplicable = breakpointType.canPutAt(file.virtualFile, line, file.project)
|
||||
|
||||
if (breakpointType is KotlinLineBreakpointType) {
|
||||
if (isApplicable) {
|
||||
val variants = breakpointType.computeVariants(file.project, SourceInfo(file.virtualFile, line))
|
||||
if (variants.isNotEmpty()) {
|
||||
actualBreakpointTypes += variants.mapNotNull { BREAKPOINT_TYPES[it.javaClass] }
|
||||
} else {
|
||||
actualBreakpointTypes += sign
|
||||
}
|
||||
}
|
||||
} else if (isApplicable) {
|
||||
actualBreakpointTypes += sign
|
||||
}
|
||||
}
|
||||
|
||||
return actualBreakpointTypes
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.TextAnnotationGutterProvider
|
||||
import com.intellij.openapi.editor.colors.ColorKey
|
||||
import com.intellij.openapi.editor.colors.EditorFontType
|
||||
import org.jetbrains.kotlin.idea.core.util.getLineCount
|
||||
import org.jetbrains.kotlin.idea.debugger.breakpoints.BreakpointChecker.BreakpointType
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.awt.Color
|
||||
import java.util.*
|
||||
|
||||
class InspectBreakpointApplicabilityAction : AnAction() {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val data = e.getData() ?: return
|
||||
|
||||
if (data.editor.gutter.isAnnotationsShown) {
|
||||
data.editor.gutter.closeAllAnnotations()
|
||||
}
|
||||
|
||||
val checker = BreakpointChecker()
|
||||
|
||||
val lineCount = data.file.getLineCount()
|
||||
val breakpoints = (0..lineCount).map { line -> checker.check(data.file, line) }
|
||||
val gutterProvider = BreakpointsGutterProvider(breakpoints)
|
||||
data.editor.gutter.registerTextAnnotation(gutterProvider)
|
||||
}
|
||||
|
||||
private class BreakpointsGutterProvider(private val breakpoints: List<EnumSet<BreakpointType>>) : TextAnnotationGutterProvider {
|
||||
override fun getLineText(line: Int, editor: Editor?): String? {
|
||||
val breakpoints = breakpoints.getOrNull(line) ?: return null
|
||||
return breakpoints.map { it.prefix }.distinct().joinToString()
|
||||
}
|
||||
|
||||
override fun getToolTip(line: Int, editor: Editor?): String? = null
|
||||
override fun getStyle(line: Int, editor: Editor?) = EditorFontType.PLAIN
|
||||
|
||||
override fun getPopupActions(line: Int, editor: Editor?) = emptyList<AnAction>()
|
||||
override fun getColor(line: Int, editor: Editor?): ColorKey? = null
|
||||
override fun getBgColor(line: Int, editor: Editor?): Color? = null
|
||||
override fun gutterClosed() {}
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
e.presentation.isVisible = ApplicationManager.getApplication().isInternal
|
||||
e.presentation.isEnabled = e.getData() != null
|
||||
}
|
||||
|
||||
class ActionData(val editor: Editor, val file: KtFile)
|
||||
|
||||
private fun AnActionEvent.getData(): ActionData? {
|
||||
val editor = getData(CommonDataKeys.EDITOR) ?: return null
|
||||
val file = getData(CommonDataKeys.PSI_FILE) as? KtFile ?: return null
|
||||
return ActionData(editor, file)
|
||||
}
|
||||
}
|
||||
+5
-3
@@ -45,9 +45,11 @@ import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import javax.swing.JComponent
|
||||
|
||||
class KotlinFieldBreakpointType : JavaBreakpointType<KotlinPropertyBreakpointProperties>, XLineBreakpointType<KotlinPropertyBreakpointProperties>(
|
||||
"kotlin-field", KotlinBundle.message("debugger.field.watchpoints.tab.title")
|
||||
) {
|
||||
class KotlinFieldBreakpointType :
|
||||
JavaBreakpointType<KotlinPropertyBreakpointProperties>,
|
||||
XLineBreakpointType<KotlinPropertyBreakpointProperties>("kotlin-field", KotlinBundle.message("debugger.field.watchpoints.tab.title")),
|
||||
KotlinBreakpointType
|
||||
{
|
||||
override fun createJavaBreakpoint(project: Project, breakpoint: XBreakpoint<KotlinPropertyBreakpointProperties>): Breakpoint<KotlinPropertyBreakpointProperties> {
|
||||
return KotlinFieldBreakpoint(project, breakpoint)
|
||||
}
|
||||
|
||||
+4
-1
@@ -28,7 +28,10 @@ import static org.jetbrains.kotlin.idea.debugger.breakpoints.BreakpointTypeUtils
|
||||
// This class is copied from com.intellij.debugger.ui.breakpoints.MethodBreakpoint.
|
||||
// Changed parts are marked with '// MODIFICATION: ' comments.
|
||||
// This should be deleted when IDEA opens the method breakpoint API (presumably in 193).
|
||||
public class KotlinFunctionBreakpointType extends JavaLineBreakpointTypeBase<JavaMethodBreakpointProperties> {
|
||||
public class KotlinFunctionBreakpointType
|
||||
extends JavaLineBreakpointTypeBase<JavaMethodBreakpointProperties>
|
||||
implements KotlinBreakpointType
|
||||
{
|
||||
// MODIFICATION: Start Kotlin implementation
|
||||
public KotlinFunctionBreakpointType() {
|
||||
super("kotlin-function", KotlinBundle.message("debugger.function.breakpoints.tab.title"));
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.idea.debugger.breakpoints.BreakpointTypeUtilsKt.isBreakpointApplicable;
|
||||
|
||||
public class KotlinLineBreakpointType extends JavaLineBreakpointType {
|
||||
public class KotlinLineBreakpointType extends JavaLineBreakpointType implements KotlinBreakpointType {
|
||||
public KotlinLineBreakpointType() {
|
||||
super("kotlin-line", KotlinBundle.message("debugger.line.breakpoints.tab.title"));
|
||||
}
|
||||
|
||||
+2
@@ -39,6 +39,8 @@ import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||
import java.util.*
|
||||
|
||||
interface KotlinBreakpointType
|
||||
|
||||
class ApplicabilityResult(val isApplicable: Boolean, val shouldStop: Boolean) {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
|
||||
Reference in New Issue
Block a user