From d823d6f4ab370ed4ceade43d1fde2346551b7ac7 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Mon, 1 Aug 2016 18:24:12 +0300 Subject: [PATCH] Debugger tests: mark objects using NodeDescriptorImpl.getMarkup. Primitive values cannot be marked. --- .../evaluate/KotlinCodeFragmentFactory.kt | 24 ++++++++------- .../debugger/tinyApp/outs/ldifferentTypes.out | 5 ++-- .../singleBreakpoint/labels/lIdentifier.kt | 12 ++++---- .../labels/ldifferentTypes.kt | 4 --- .../AbstractKotlinEvaluateExpressionTest.kt | 30 +++++++++---------- 5 files changed, 36 insertions(+), 39 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt index aed7ce55ace..6138385bde4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt @@ -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 = Key.create("_label_variable_value_key_") val DEBUG_LABEL_SUFFIX: String = "_DebugLabel" - @TestOnly val DEBUG_FRAME_FOR_TESTS: Key = Key.create("DEBUG_FRAME_FOR_TESTS") + @TestOnly val DEBUG_CONTEXT_FOR_TESTS: Key = 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 diff --git a/idea/testData/debugger/tinyApp/outs/ldifferentTypes.out b/idea/testData/debugger/tinyApp/outs/ldifferentTypes.out index ad7be4be30b..af0a46f8fa2 100644 --- a/idea/testData/debugger/tinyApp/outs/ldifferentTypes.out +++ b/idea/testData/debugger/tinyApp/outs/ldifferentTypes.out @@ -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 diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/labels/lIdentifier.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/labels/lIdentifier.kt index 330d0a6d337..a80d55a9a24 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/labels/lIdentifier.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/labels/lIdentifier.kt @@ -1,11 +1,11 @@ package lIdentifier fun main(args: Array) { - 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) { // DEBUG_LABEL: e = e-e // EXPRESSION: a -// RESULT: 1: I \ No newline at end of file +// RESULT: "1": Ljava/lang/String; \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/labels/ldifferentTypes.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/labels/ldifferentTypes.kt index 4131d1e666e..c512c89b2f6 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/labels/ldifferentTypes.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/labels/ldifferentTypes.kt @@ -10,10 +10,6 @@ fun main(args: Array) { // 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 diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt index 8512bf7d8fe..ac8e4d28c06 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt @@ -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() 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() 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 {