Debugger tests: mark objects using NodeDescriptorImpl.getMarkup. Primitive values cannot be marked.

This commit is contained in:
Natalia Ukhorskaya
2016-08-01 18:24:12 +03:00
parent 252b8ec6db
commit d823d6f4ab
5 changed files with 36 additions and 39 deletions
@@ -20,8 +20,10 @@ import com.intellij.debugger.DebuggerManagerEx
import com.intellij.debugger.engine.evaluation.CodeFragmentFactory
import com.intellij.debugger.engine.evaluation.CodeFragmentKind
import com.intellij.debugger.engine.evaluation.TextWithImports
import com.intellij.debugger.jdi.StackFrameProxyImpl
import com.intellij.debugger.impl.DebuggerContextImpl
import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
@@ -141,7 +143,7 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
}
private fun getWrappedContextElement(project: Project, context: PsiElement?)
= wrapContextIfNeeded(project, getContextElement(context))
= wrapContextIfNeeded(project, context, getContextElement(context))
override fun createPresentationCodeFragment(item: TextWithImports, context: PsiElement?, project: Project): JavaCodeFragment {
val kotlinCodeFragment = createCodeFragment(item, context, project)
@@ -202,7 +204,7 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
companion object {
val LABEL_VARIABLE_VALUE_KEY: Key<Value> = Key.create<Value>("_label_variable_value_key_")
val DEBUG_LABEL_SUFFIX: String = "_DebugLabel"
@TestOnly val DEBUG_FRAME_FOR_TESTS: Key<StackFrameProxyImpl> = Key.create("DEBUG_FRAME_FOR_TESTS")
@TestOnly val DEBUG_CONTEXT_FOR_TESTS: Key<DebuggerContextImpl> = Key.create("DEBUG_CONTEXT_FOR_TESTS")
fun getContextElement(elementAt: PsiElement?): KtElement? {
if (elementAt == null) return null
@@ -283,17 +285,19 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
}
}
private fun wrapContextIfNeeded(project: Project, originalContext: KtElement?): KtElement? {
val session = XDebuggerManager.getInstance(project).currentSession as? XDebugSessionImpl
?: return originalContext
private fun wrapContextIfNeeded(project: Project, originalContext: PsiElement?, newContext: KtElement?): KtElement? {
val markupMap: Map<*, ValueMarkup>? =
if (ApplicationManager.getApplication().isUnitTestMode)
NodeDescriptorImpl.getMarkupMap(originalContext?.getCopyableUserData(DEBUG_CONTEXT_FOR_TESTS)?.debugProcess)
else
(XDebuggerManager.getInstance(project).currentSession as? XDebugSessionImpl)?.valueMarkers?.allMarkers
val markupMap = session.valueMarkers?.allMarkers
if (markupMap == null || markupMap.isEmpty()) return originalContext
if (markupMap == null || markupMap.isEmpty()) return newContext
val (text, labels) = createCodeFragmentForLabeledObjects(project, markupMap)
if (text.isEmpty()) return originalContext
if (text.isEmpty()) return newContext
return createWrappingContext(text, labels, originalContext, project)
return createWrappingContext(text, labels, newContext, project)
}
// internal for test
+2 -3
View File
@@ -1,10 +1,9 @@
LineBreakpoint created at ldifferentTypes.kt:92
LineBreakpoint created at ldifferentTypes.kt:88
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! ldifferentTypes.LdifferentTypesKt
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
ldifferentTypes.kt:92
ldifferentTypes.kt:88
Compile bytecode for str_DebugLabel
Compile bytecode for strArray_DebugLabel
Compile bytecode for primitive_DebugLabel
Compile bytecode for primitiveArray_DebugLabel
Compile bytecode for localObj_DebugLabel
Compile bytecode for localObjArray_DebugLabel
@@ -1,11 +1,11 @@
package lIdentifier
fun main(args: Array<String>) {
val a = 1
val b = 1
val c = 1
val d = 1
val e = 1
val a = "1"
val b = "1"
val c = "1"
val d = "1"
val e = "1"
//Breakpoint!
val f = 1
}
@@ -17,4 +17,4 @@ fun main(args: Array<String>) {
// DEBUG_LABEL: e = e-e
// EXPRESSION: a
// RESULT: 1: I
// RESULT: "1": Ljava/lang/String;
@@ -10,10 +10,6 @@ fun main(args: Array<String>) {
// DEBUG_LABEL: strArray = strArray
val strArray = arrayOf("str")
// EXPRESSION: primitive_DebugLabel
// RESULT: 1: I
// DEBUG_LABEL: primitive = primitive
val primitive = 1
// EXPRESSION: primitiveArray_DebugLabel
// RESULT: instance of java.lang.Integer[1] (id=ID): [Ljava/lang/Integer;
// DEBUG_LABEL: primitiveArray = primitiveArray
@@ -33,7 +33,6 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiExpression
import com.intellij.xdebugger.impl.XDebugSessionImpl
import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl
@@ -135,6 +134,8 @@ abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestBase() {
doOnBreakpoint {
val exceptions = linkedMapOf<String, Throwable>()
try {
createMarkers(fileText)
for ((expression, expected) in expressions) {
mayThrow(exceptions, expression) {
evaluate(expression, CodeFragmentKind.EXPRESSION, expected)
@@ -428,30 +429,24 @@ abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestBase() {
return mainFile.parentFile?.listFiles()?.filter { it.name.startsWith(mainFileName) && it.name != mainFileName } ?: Collections.emptyList()
}
private fun createContextElement(context: SuspendContextImpl): PsiElement {
val contextElement = ContextUtil.getContextElement(debuggerContext)!!
Assert.assertTrue("KotlinCodeFragmentFactory should be accepted for context element otherwise default evaluator will be called. ContextElement = ${contextElement.text}",
KotlinCodeFragmentFactory().isContextAccepted(contextElement))
private fun createMarkers(fileText: String) {
val labelsAsText = findLinesWithPrefixesRemoved(fileText, "// DEBUG_LABEL: ")
if (labelsAsText.isEmpty()) return
val labelsAsText = findLinesWithPrefixesRemoved(contextElement.containingFile.text, "// DEBUG_LABEL: ")
if (labelsAsText.isEmpty()) return contextElement
val markupMap = NodeDescriptorImpl.getMarkupMap(debugProcess)
val markupMap = hashMapOf<com.sun.jdi.Value, ValueMarkup>()
for (labelAsText in labelsAsText) {
val labelParts = labelAsText.split("=")
assert(labelParts.size == 2) { "Wrong format for DEBUG_LABEL directive: // DEBUG_LABEL: {localVariableName} = {labelText}"}
val localVariableName = labelParts[0].trim()
val labelName = labelParts[1].trim()
val localVariable = context.frameProxy!!.visibleVariableByName(localVariableName)
val localVariable = debuggerContext.frameProxy!!.visibleVariableByName(localVariableName)
assert(localVariable != null) { "Couldn't find localVariable for label: name = $localVariableName" }
val localVariableValue = context.frameProxy!!.getValue(localVariable)
val localVariableValue = debuggerContext.frameProxy!!.getValue(localVariable) as? ObjectReference
assert(localVariableValue != null) { "Local variable $localVariableName should be an ObjectReference" }
localVariableValue!!
markupMap.put(localVariableValue, ValueMarkup(labelName, null, labelName))
markupMap?.put(localVariableValue, ValueMarkup(labelName, null, labelName))
}
val (text, labels) = KotlinCodeFragmentFactory.createCodeFragmentForLabeledObjects(contextElement.project, markupMap)
return KotlinCodeFragmentFactory().createWrappingContext(text, labels, KotlinCodeFragmentFactory.getContextElement(contextElement), project)!!
}
private fun SuspendContextImpl.evaluate(text: String, codeFragmentKind: CodeFragmentKind, expectedResult: String?) {
@@ -461,9 +456,12 @@ abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestBase() {
private fun SuspendContextImpl.evaluate(item: TextWithImportsImpl, expectedResult: String?) {
runReadAction {
val sourcePosition = ContextUtil.getSourcePosition(this)
val contextElement = createContextElement(this)
contextElement.putCopyableUserData(KotlinCodeFragmentFactory.DEBUG_FRAME_FOR_TESTS, this@AbstractKotlinEvaluateExpressionTest.evaluationContext.frameProxy)
val contextElement = ContextUtil.getContextElement(debuggerContext)!!
Assert.assertTrue("KotlinCodeFragmentFactory should be accepted for context element otherwise default evaluator will be called. ContextElement = ${contextElement.text}",
KotlinCodeFragmentFactory().isContextAccepted(contextElement))
contextElement.putCopyableUserData(KotlinCodeFragmentFactory.DEBUG_CONTEXT_FOR_TESTS, this@AbstractKotlinEvaluateExpressionTest.debuggerContext)
try {