From 2f931f36c87ef440f90be50d53d7f6ab1b172297 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Wed, 21 Jan 2015 15:40:51 +0300 Subject: [PATCH] Implement extra variables for debugger --- .../intellij/debugger/engine/annotations.xml | 9 +- idea/src/META-INF/plugin.xml | 1 + .../KotlinFrameExtraVariablesProvider.kt | 193 ++++++++++++++++++ .../outs/allFilesPresentInExtraVariables.out | 0 .../tinyApp/outs/delegatedPropertyInClass.out | 2 +- .../evBreakpointOnPropertyDeclaration.out | 36 ++++ .../tinyApp/outs/evDelegatedProperty.out | 31 +++ .../tinyApp/outs/evDuplicateItems.out | 26 +++ .../debugger/tinyApp/outs/evFinalProperty.out | 25 +++ .../debugger/tinyApp/outs/evLineRange.out | 40 ++++ .../debugger/tinyApp/outs/evProperty.out | 28 +++ .../tinyApp/outs/evPropertyRefExpr.out | 29 +++ .../tinyApp/outs/evSkipAnonymousObject.out | 41 ++++ .../debugger/tinyApp/outs/evSkipLambda.out | 36 ++++ .../tinyApp/outs/evSkipLocalClass.out | 37 ++++ .../tinyApp/outs/toStringRenderer.out | 2 +- .../evBreakpointOnPropertyDeclaration.kt | 18 ++ .../extraVariables/evDelegatedProperty.kt | 16 ++ .../extraVariables/evDuplicateItems.kt | 13 ++ .../extraVariables/evFinalProperty.kt | 13 ++ .../extraVariables/evLineRange.kt | 22 ++ .../extraVariables/evProperty.kt | 15 ++ .../extraVariables/evPropertyRefExpr.kt | 18 ++ .../extraVariables/evSkipAnonymousObject.kt | 26 +++ .../extraVariables/evSkipLambda.kt | 21 ++ .../extraVariables/evSkipLocalClass.kt | 22 ++ .../frame/delegatedPropertyInClass.kt | 2 +- .../renderer/toStringRenderer.kt | 2 +- .../AbstractKotlinEvaluateExpressionTest.kt | 28 ++- ...KotlinEvaluateExpressionTestGenerated.java | 71 ++++++- 30 files changed, 811 insertions(+), 12 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/debugger/KotlinFrameExtraVariablesProvider.kt create mode 100644 idea/testData/debugger/tinyApp/outs/allFilesPresentInExtraVariables.out create mode 100644 idea/testData/debugger/tinyApp/outs/evBreakpointOnPropertyDeclaration.out create mode 100644 idea/testData/debugger/tinyApp/outs/evDelegatedProperty.out create mode 100644 idea/testData/debugger/tinyApp/outs/evDuplicateItems.out create mode 100644 idea/testData/debugger/tinyApp/outs/evFinalProperty.out create mode 100644 idea/testData/debugger/tinyApp/outs/evLineRange.out create mode 100644 idea/testData/debugger/tinyApp/outs/evProperty.out create mode 100644 idea/testData/debugger/tinyApp/outs/evPropertyRefExpr.out create mode 100644 idea/testData/debugger/tinyApp/outs/evSkipAnonymousObject.out create mode 100644 idea/testData/debugger/tinyApp/outs/evSkipLambda.out create mode 100644 idea/testData/debugger/tinyApp/outs/evSkipLocalClass.out create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evBreakpointOnPropertyDeclaration.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evDelegatedProperty.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evDuplicateItems.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evFinalProperty.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evLineRange.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evProperty.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evPropertyRefExpr.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipAnonymousObject.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipLambda.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipLocalClass.kt diff --git a/annotations/com/intellij/debugger/engine/annotations.xml b/annotations/com/intellij/debugger/engine/annotations.xml index 709e447b547..fa2842eab8c 100644 --- a/annotations/com/intellij/debugger/engine/annotations.xml +++ b/annotations/com/intellij/debugger/engine/annotations.xml @@ -2,7 +2,14 @@ - + + + + + diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 5ab0ab9b1e0..351da25c534 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -380,6 +380,7 @@ + diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinFrameExtraVariablesProvider.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinFrameExtraVariablesProvider.kt new file mode 100644 index 00000000000..7247aae83cc --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinFrameExtraVariablesProvider.kt @@ -0,0 +1,193 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.debugger + +import com.intellij.debugger.engine.FrameExtraVariablesProvider +import com.intellij.debugger.SourcePosition +import com.intellij.debugger.engine.evaluation.EvaluationContext +import com.intellij.debugger.engine.evaluation.TextWithImports +import com.intellij.debugger.settings.DebuggerSettings +import com.intellij.debugger.engine.evaluation.TextWithImportsImpl +import com.intellij.debugger.engine.evaluation.CodeFragmentKind +import com.intellij.openapi.fileEditor.FileDocumentManager +import com.intellij.psi.PsiElement +import com.intellij.openapi.util.TextRange +import com.intellij.openapi.editor.Document +import com.intellij.psi.PsiFile +import com.intellij.util.text.CharArrayUtil +import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.idea.JetFileType +import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils +import java.util.LinkedHashSet +import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully + +public class KotlinFrameExtraVariablesProvider : FrameExtraVariablesProvider { + override fun isAvailable(sourcePosition: SourcePosition?, evalContext: EvaluationContext?): Boolean { + if (sourcePosition == null) return false + if (sourcePosition.getLine() < 0) return false + return sourcePosition.getFile().getFileType() == JetFileType.INSTANCE && DebuggerSettings.getInstance().AUTO_VARIABLES_MODE + } + + override fun collectVariables(sourcePosition: SourcePosition?, evalContext: EvaluationContext?, alreadyCollected: Set? + ): Set? { + if (sourcePosition != null) { + return runReadAction { findAdditionalExpressions(sourcePosition) } + } + return setOf() + } +} + +private fun findAdditionalExpressions(position: SourcePosition): Set { + val line = position.getLine() + val file = position.getFile() + + val vFile = file.getVirtualFile() + val doc = if (vFile != null) FileDocumentManager.getInstance().getDocument(vFile) else null + if (doc == null || doc.getLineCount() == 0 || line > (doc.getLineCount() - 1)) { + return setOf() + } + + val offset = doc.getLineStartOffset(line) + if (offset < 0) return setOf() + + val elem = file.findElementAt(offset) + val containingElement = getContainingElement(elem) ?: elem + + if (containingElement == null) return setOf() + + val limit = getLineRangeForElement(containingElement, doc) + + var startLine = Math.max(limit.getStartOffset(), line) + while (startLine - 1 > limit.getStartOffset() && shouldSkipLine(file, doc, startLine - 1)) { + startLine-- + } + + var endLine = Math.min(limit.getEndOffset(), line) + while (endLine + 1 < limit.getEndOffset() && shouldSkipLine(file, doc, endLine + 1)) { + endLine++ + } + + val lineRange = TextRange(doc.getLineStartOffset(startLine), doc.getLineEndOffset(endLine)) + if (lineRange.isEmpty()) return setOf() + + val expressions = LinkedHashSet() + + val variablesCollector = VariablesCollector(lineRange, expressions) + containingElement.accept(variablesCollector) + + return expressions +} + +private fun getContainingElement(element: PsiElement): JetElement? { + val contElement = PsiTreeUtil.getParentOfType(element, javaClass()) ?: PsiTreeUtil.getParentOfType(element, javaClass()) + if (contElement is JetProperty && contElement.isLocal()) { + val parent = contElement.getParent() + if (parent != null) { + return getContainingElement(parent) + } + } + + if (contElement is JetDeclarationWithBody) { + return contElement.getBodyExpression() + } + return contElement +} + +private fun getLineRangeForElement(containingElement: PsiElement, doc: Document): TextRange { + val elemRange = containingElement.getTextRange() + return TextRange(doc.getLineNumber(elemRange.getStartOffset()), doc.getLineNumber(elemRange.getEndOffset())) +} + +private fun shouldSkipLine(file: PsiFile, doc: Document, line: Int): Boolean { + val start = CharArrayUtil.shiftForward(doc.getCharsSequence(), doc.getLineStartOffset(line), " \n\t") + val end = doc.getLineEndOffset(line) + if (start >= end) { + return true + } + + val elemAtOffset = file.findElementAt(start) + val topmostElementAtOffset = CodeInsightUtils.getTopmostElementAtOffset(elemAtOffset, start) + return topmostElementAtOffset !is JetDeclaration +} + +private class VariablesCollector( + private val myLineRange: TextRange, + private val myExpressions: MutableSet +) : JetTreeVisitorVoid() { + + override fun visitJetElement(element: JetElement) { + if (element.isInRange()) { + super.visitJetElement(element) + } + } + + override fun visitQualifiedExpression(expression: JetQualifiedExpression) { + if (expression.isInRange()) { + val selector = expression.getSelectorExpression() + if (selector is JetReferenceExpression) { + if (isRefToProperty(selector)) { + myExpressions.add(expression.createText()) + return + } + } + } + super.visitQualifiedExpression(expression) + } + + private fun isRefToProperty(expression: JetReferenceExpression): Boolean { + val context = expression.analyzeFully() + val descriptor = context[BindingContext.REFERENCE_TARGET, expression] + if (descriptor is PropertyDescriptor) { + val getter = descriptor.getGetter() + return (getter == null || context[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getter] == null) && + descriptor.getCompileTimeInitializer() == null + } + return false + } + + override fun visitReferenceExpression(expression: JetReferenceExpression) { + if (expression.isInRange()) { + if (isRefToProperty(expression)) { + myExpressions.add(expression.createText()) + } + } + super.visitReferenceExpression(expression) + } + + private fun JetElement.isInRange(): Boolean = myLineRange.intersects(this.getTextRange()) + private fun JetElement.createText(): TextWithImports = TextWithImportsImpl(CodeFragmentKind.EXPRESSION, this.getText()) + + override fun visitClass(klass: JetClass) { + // Do not show expressions used in local classes + } + + override fun visitNamedFunction(function: JetNamedFunction) { + // Do not show expressions used in local functions + } + + override fun visitObjectLiteralExpression(expression: JetObjectLiteralExpression) { + // Do not show expressions used in anonymous objects + } + + override fun visitFunctionLiteralExpression(expression: JetFunctionLiteralExpression) { + // Do not show expressions used in lambdas + } +} \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/outs/allFilesPresentInExtraVariables.out b/idea/testData/debugger/tinyApp/outs/allFilesPresentInExtraVariables.out new file mode 100644 index 00000000000..e69de29bb2d diff --git a/idea/testData/debugger/tinyApp/outs/delegatedPropertyInClass.out b/idea/testData/debugger/tinyApp/outs/delegatedPropertyInClass.out index ea36113f228..354eb04ff78 100644 --- a/idea/testData/debugger/tinyApp/outs/delegatedPropertyInClass.out +++ b/idea/testData/debugger/tinyApp/outs/delegatedPropertyInClass.out @@ -9,7 +9,7 @@ import kotlin.properties.Delegates fun main(args: Array) { val a = A() //Breakpoint! - args.size + args.size() } class A { diff --git a/idea/testData/debugger/tinyApp/outs/evBreakpointOnPropertyDeclaration.out b/idea/testData/debugger/tinyApp/outs/evBreakpointOnPropertyDeclaration.out new file mode 100644 index 00000000000..960748410a2 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/evBreakpointOnPropertyDeclaration.out @@ -0,0 +1,36 @@ +LineBreakpoint created at evBreakpointOnPropertyDeclaration.kt:14 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! evBreakpointOnPropertyDeclaration.EvBreakpointOnPropertyDeclarationPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +evBreakpointOnPropertyDeclaration.kt:14 +package evBreakpointOnPropertyDeclaration + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a1 = A() + val a2 = A() + val a3 = A() + + val p1 = a1.prop + //Breakpoint! + val p2 = a2.prop + val p3 = a3.prop +} + +// PRINT_FRAME + frame = main():14, EvBreakpointOnPropertyDeclarationPackage$@packagePartHASH {evBreakpointOnPropertyDeclaration} + static = static = evBreakpointOnPropertyDeclaration.EvBreakpointOnPropertyDeclarationPackage$@packagePartHASH + local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = evBreakpointOnPropertyDeclaration.kt, 7) + local = a1: evBreakpointOnPropertyDeclaration.A = {evBreakpointOnPropertyDeclaration.A@uniqueID} (sp = evBreakpointOnPropertyDeclaration.kt, 8) + field = prop: int = 1 (sp = evBreakpointOnPropertyDeclaration.kt, 4) + local = a2: evBreakpointOnPropertyDeclaration.A = {evBreakpointOnPropertyDeclaration.A@uniqueID} (sp = evBreakpointOnPropertyDeclaration.kt, 9) + field = prop: int = 1 (sp = evBreakpointOnPropertyDeclaration.kt, 4) + local = a3: evBreakpointOnPropertyDeclaration.A = {evBreakpointOnPropertyDeclaration.A@uniqueID} (sp = evBreakpointOnPropertyDeclaration.kt, 10) + field = prop: int = 1 (sp = evBreakpointOnPropertyDeclaration.kt, 4) + local = p1: int = 1 (sp = evBreakpointOnPropertyDeclaration.kt, 12) + extra = a2.prop +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/evDelegatedProperty.out b/idea/testData/debugger/tinyApp/outs/evDelegatedProperty.out new file mode 100644 index 00000000000..cf1ca857593 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/evDelegatedProperty.out @@ -0,0 +1,31 @@ +LineBreakpoint created at evDelegatedProperty.kt:13 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! evDelegatedProperty.EvDelegatedPropertyPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +evDelegatedProperty.kt:13 +package evDelegatedProperty + +import kotlin.properties.Delegates + +class A { + var prop: Int by Delegates.notNull() +} + +fun main(args: Array) { + val a = A() + a.prop = 1 + //Breakpoint! + val b = a.prop +} + +// PRINT_FRAME + frame = main():13, EvDelegatedPropertyPackage$@packagePartHASH {evDelegatedProperty} + static = static = evDelegatedProperty.EvDelegatedPropertyPackage$@packagePartHASH + local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = evDelegatedProperty.kt, 9) + local = a: evDelegatedProperty.A = {evDelegatedProperty.A@uniqueID} (sp = evDelegatedProperty.kt, 10) + field = prop$delegate: kotlin.properties.ReadWriteProperty = {kotlin.properties.NotNullVar@uniqueID} (sp = evDelegatedProperty.kt, 6) + field = value: java.lang.Object = {java.lang.Integer@uniqueID}1 (sp = Delegation.!EXT!) + field = value: int = 1 (sp = Integer.!EXT!) + field = prop: int = 1 (sp = evDelegatedProperty.kt, 6) +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/evDuplicateItems.out b/idea/testData/debugger/tinyApp/outs/evDuplicateItems.out new file mode 100644 index 00000000000..e5308f6cf25 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/evDuplicateItems.out @@ -0,0 +1,26 @@ +LineBreakpoint created at evDuplicateItems.kt:10 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! evDuplicateItems.EvDuplicateItemsPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +evDuplicateItems.kt:10 +package evDuplicateItems + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a = A() + //Breakpoint! + val b = a.prop + a.prop +} + +// PRINT_FRAME + frame = main():10, EvDuplicateItemsPackage$@packagePartHASH {evDuplicateItems} + static = static = evDuplicateItems.EvDuplicateItemsPackage$@packagePartHASH + local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = evDuplicateItems.kt, 7) + local = a: evDuplicateItems.A = {evDuplicateItems.A@uniqueID} (sp = evDuplicateItems.kt, 8) + field = prop: int = 1 (sp = evDuplicateItems.kt, 4) + extra = a.prop +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/evFinalProperty.out b/idea/testData/debugger/tinyApp/outs/evFinalProperty.out new file mode 100644 index 00000000000..4fe17d8030c --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/evFinalProperty.out @@ -0,0 +1,25 @@ +LineBreakpoint created at evFinalProperty.kt:10 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! evFinalProperty.EvFinalPropertyPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +evFinalProperty.kt:10 +package evFinalProperty + +class A { + val prop = 1 +} + +fun main(args: Array) { + val a = A() + //Breakpoint! + val b = a.prop +} + +// PRINT_FRAME + frame = main():10, EvFinalPropertyPackage$@packagePartHASH {evFinalProperty} + static = static = evFinalProperty.EvFinalPropertyPackage$@packagePartHASH + local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = evFinalProperty.kt, 7) + local = a: evFinalProperty.A = {evFinalProperty.A@uniqueID} (sp = evFinalProperty.kt, 8) + field = prop: int = 1 (sp = evFinalProperty.kt, 4) +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/evLineRange.out b/idea/testData/debugger/tinyApp/outs/evLineRange.out new file mode 100644 index 00000000000..f05a63a2a9b --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/evLineRange.out @@ -0,0 +1,40 @@ +LineBreakpoint created at evLineRange.kt:15 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! evLineRange.EvLineRangePackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +evLineRange.kt:15 +package evLineRange + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a1 = A() + val a2 = A() + val a3 = A() + + foo(a1.prop) + val i1 = 1 + //Breakpoint! + foo(a2.prop) + val i2 = 1 + foo(a3.prop) +} + +fun foo(i: Int) {} + +// PRINT_FRAME + frame = main():15, EvLineRangePackage$@packagePartHASH {evLineRange} + static = static = evLineRange.EvLineRangePackage$@packagePartHASH + local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = evLineRange.kt, 7) + local = a1: evLineRange.A = {evLineRange.A@uniqueID} (sp = evLineRange.kt, 8) + field = prop: int = 1 (sp = evLineRange.kt, 4) + local = a2: evLineRange.A = {evLineRange.A@uniqueID} (sp = evLineRange.kt, 9) + field = prop: int = 1 (sp = evLineRange.kt, 4) + local = a3: evLineRange.A = {evLineRange.A@uniqueID} (sp = evLineRange.kt, 10) + field = prop: int = 1 (sp = evLineRange.kt, 4) + local = i1: int = 1 (sp = evLineRange.kt, 13) + extra = a2.prop +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/evProperty.out b/idea/testData/debugger/tinyApp/outs/evProperty.out new file mode 100644 index 00000000000..bd717d3ff9c --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/evProperty.out @@ -0,0 +1,28 @@ +LineBreakpoint created at evProperty.kt:10 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! evProperty.EvPropertyPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +evProperty.kt:10 +package evProperty + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a = A() + //Breakpoint! + if (a.prop == 1) { + + } +} + +// PRINT_FRAME + frame = main():10, EvPropertyPackage$@packagePartHASH {evProperty} + static = static = evProperty.EvPropertyPackage$@packagePartHASH + local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = evProperty.kt, 7) + local = a: evProperty.A = {evProperty.A@uniqueID} (sp = evProperty.kt, 8) + field = prop: int = 1 (sp = evProperty.kt, 4) + extra = a.prop +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/evPropertyRefExpr.out b/idea/testData/debugger/tinyApp/outs/evPropertyRefExpr.out new file mode 100644 index 00000000000..0c23fc551a9 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/evPropertyRefExpr.out @@ -0,0 +1,29 @@ +LineBreakpoint created at evPropertyRefExpr.kt:8 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! evPropertyRefExpr.EvPropertyRefExprPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +evPropertyRefExpr.kt:8 +package evPropertyRefExpr + +class A { + var prop = 1 + + fun test() { + //Breakpoint! + if (prop == 1) { + + } + } +} + +fun main(args: Array) { + A().test() +} + +// PRINT_FRAME + frame = test():8, A {evPropertyRefExpr} + this = this = {evPropertyRefExpr.A@uniqueID} + field = prop: int = 1 (sp = evPropertyRefExpr.kt, 4) + extra = prop +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/evSkipAnonymousObject.out b/idea/testData/debugger/tinyApp/outs/evSkipAnonymousObject.out new file mode 100644 index 00000000000..9427a38c98d --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/evSkipAnonymousObject.out @@ -0,0 +1,41 @@ +LineBreakpoint created at evSkipAnonymousObject.kt:12 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! evSkipAnonymousObject.EvSkipAnonymousObjectPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +evSkipAnonymousObject.kt:12 +package evSkipAnonymousObject + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a1 = A() + val a2 = A() + + //Breakpoint! + foo(a1.prop) + object: T { + override fun f() { + foo(a2.prop) + } + } +} + +trait T { + fun f() {} +} + +fun foo(i: Int) {} + +// PRINT_FRAME + frame = main():12, EvSkipAnonymousObjectPackage$@packagePartHASH {evSkipAnonymousObject} + static = static = evSkipAnonymousObject.EvSkipAnonymousObjectPackage$@packagePartHASH + local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = evSkipAnonymousObject.kt, 7) + local = a1: evSkipAnonymousObject.A = {evSkipAnonymousObject.A@uniqueID} (sp = evSkipAnonymousObject.kt, 8) + field = prop: int = 1 (sp = evSkipAnonymousObject.kt, 4) + local = a2: evSkipAnonymousObject.A = {evSkipAnonymousObject.A@uniqueID} (sp = evSkipAnonymousObject.kt, 9) + field = prop: int = 1 (sp = evSkipAnonymousObject.kt, 4) + extra = a1.prop +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/evSkipLambda.out b/idea/testData/debugger/tinyApp/outs/evSkipLambda.out new file mode 100644 index 00000000000..5aca0dae0b5 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/evSkipLambda.out @@ -0,0 +1,36 @@ +LineBreakpoint created at evSkipLambda.kt:12 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! evSkipLambda.EvSkipLambdaPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +evSkipLambda.kt:12 +package evSkipLambda + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a1 = A() + val a2 = A() + + //Breakpoint! + foo(a1.prop) + l { + foo(a2.prop) + } +} + +fun foo(i: Int) {} +fun l(f: () -> Unit) {} + +// PRINT_FRAME + frame = main():12, EvSkipLambdaPackage$@packagePartHASH {evSkipLambda} + static = static = evSkipLambda.EvSkipLambdaPackage$@packagePartHASH + local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = evSkipLambda.kt, 7) + local = a1: evSkipLambda.A = {evSkipLambda.A@uniqueID} (sp = evSkipLambda.kt, 8) + field = prop: int = 1 (sp = evSkipLambda.kt, 4) + local = a2: evSkipLambda.A = {evSkipLambda.A@uniqueID} (sp = evSkipLambda.kt, 9) + field = prop: int = 1 (sp = evSkipLambda.kt, 4) + extra = a1.prop +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/evSkipLocalClass.out b/idea/testData/debugger/tinyApp/outs/evSkipLocalClass.out new file mode 100644 index 00000000000..459b9ba43e5 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/evSkipLocalClass.out @@ -0,0 +1,37 @@ +LineBreakpoint created at evSkipLocalClass.kt:12 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! evSkipLocalClass.EvSkipLocalClassPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +evSkipLocalClass.kt:12 +package evSkipLocalClass + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a1 = A() + val a2 = A() + + //Breakpoint! + foo(a1.prop) + class B { + fun bar() { + foo(a2.prop) + } + } +} + +fun foo(i: Int) {} + +// PRINT_FRAME + frame = main():12, EvSkipLocalClassPackage$@packagePartHASH {evSkipLocalClass} + static = static = evSkipLocalClass.EvSkipLocalClassPackage$@packagePartHASH + local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = evSkipLocalClass.kt, 7) + local = a1: evSkipLocalClass.A = {evSkipLocalClass.A@uniqueID} (sp = evSkipLocalClass.kt, 8) + field = prop: int = 1 (sp = evSkipLocalClass.kt, 4) + local = a2: evSkipLocalClass.A = {evSkipLocalClass.A@uniqueID} (sp = evSkipLocalClass.kt, 9) + field = prop: int = 1 (sp = evSkipLocalClass.kt, 4) + extra = a1.prop +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/toStringRenderer.out b/idea/testData/debugger/tinyApp/outs/toStringRenderer.out index 75274c6c408..9332ef8ad5c 100644 --- a/idea/testData/debugger/tinyApp/outs/toStringRenderer.out +++ b/idea/testData/debugger/tinyApp/outs/toStringRenderer.out @@ -7,7 +7,7 @@ package toStringRenderer fun main(args: Array) { val a = A() //Breakpoint! - args.size + args.size() } class A { diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evBreakpointOnPropertyDeclaration.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evBreakpointOnPropertyDeclaration.kt new file mode 100644 index 00000000000..2eb040cc185 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evBreakpointOnPropertyDeclaration.kt @@ -0,0 +1,18 @@ +package evBreakpointOnPropertyDeclaration + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a1 = A() + val a2 = A() + val a3 = A() + + val p1 = a1.prop + //Breakpoint! + val p2 = a2.prop + val p3 = a3.prop +} + +// PRINT_FRAME \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evDelegatedProperty.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evDelegatedProperty.kt new file mode 100644 index 00000000000..bdc0c2d8462 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evDelegatedProperty.kt @@ -0,0 +1,16 @@ +package evDelegatedProperty + +import kotlin.properties.Delegates + +class A { + var prop: Int by Delegates.notNull() +} + +fun main(args: Array) { + val a = A() + a.prop = 1 + //Breakpoint! + val b = a.prop +} + +// PRINT_FRAME \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evDuplicateItems.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evDuplicateItems.kt new file mode 100644 index 00000000000..79c74a3e5b4 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evDuplicateItems.kt @@ -0,0 +1,13 @@ +package evDuplicateItems + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a = A() + //Breakpoint! + val b = a.prop + a.prop +} + +// PRINT_FRAME \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evFinalProperty.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evFinalProperty.kt new file mode 100644 index 00000000000..b96d492d24a --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evFinalProperty.kt @@ -0,0 +1,13 @@ +package evFinalProperty + +class A { + val prop = 1 +} + +fun main(args: Array) { + val a = A() + //Breakpoint! + val b = a.prop +} + +// PRINT_FRAME \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evLineRange.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evLineRange.kt new file mode 100644 index 00000000000..781b22db9df --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evLineRange.kt @@ -0,0 +1,22 @@ +package evLineRange + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a1 = A() + val a2 = A() + val a3 = A() + + foo(a1.prop) + val i1 = 1 + //Breakpoint! + foo(a2.prop) + val i2 = 1 + foo(a3.prop) +} + +fun foo(i: Int) {} + +// PRINT_FRAME \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evProperty.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evProperty.kt new file mode 100644 index 00000000000..9870f1f9d97 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evProperty.kt @@ -0,0 +1,15 @@ +package evProperty + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a = A() + //Breakpoint! + if (a.prop == 1) { + + } +} + +// PRINT_FRAME \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evPropertyRefExpr.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evPropertyRefExpr.kt new file mode 100644 index 00000000000..ef499a771a6 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evPropertyRefExpr.kt @@ -0,0 +1,18 @@ +package evPropertyRefExpr + +class A { + var prop = 1 + + fun test() { + //Breakpoint! + if (prop == 1) { + + } + } +} + +fun main(args: Array) { + A().test() +} + +// PRINT_FRAME \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipAnonymousObject.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipAnonymousObject.kt new file mode 100644 index 00000000000..c40960a231b --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipAnonymousObject.kt @@ -0,0 +1,26 @@ +package evSkipAnonymousObject + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a1 = A() + val a2 = A() + + //Breakpoint! + foo(a1.prop) + object: T { + override fun f() { + foo(a2.prop) + } + } +} + +trait T { + fun f() {} +} + +fun foo(i: Int) {} + +// PRINT_FRAME \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipLambda.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipLambda.kt new file mode 100644 index 00000000000..cf3af30f1d6 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipLambda.kt @@ -0,0 +1,21 @@ +package evSkipLambda + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a1 = A() + val a2 = A() + + //Breakpoint! + foo(a1.prop) + l { + foo(a2.prop) + } +} + +fun foo(i: Int) {} +fun l(f: () -> Unit) {} + +// PRINT_FRAME \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipLocalClass.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipLocalClass.kt new file mode 100644 index 00000000000..d723b42755b --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipLocalClass.kt @@ -0,0 +1,22 @@ +package evSkipLocalClass + +class A { + var prop = 1 +} + +fun main(args: Array) { + val a1 = A() + val a2 = A() + + //Breakpoint! + foo(a1.prop) + class B { + fun bar() { + foo(a2.prop) + } + } +} + +fun foo(i: Int) {} + +// PRINT_FRAME \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/delegatedPropertyInClass.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/delegatedPropertyInClass.kt index 6b8c8ab10bc..21332e8857f 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/delegatedPropertyInClass.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/delegatedPropertyInClass.kt @@ -5,7 +5,7 @@ import kotlin.properties.Delegates fun main(args: Array) { val a = A() //Breakpoint! - args.size + args.size() } class A { diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/renderer/toStringRenderer.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/renderer/toStringRenderer.kt index b236a8c6591..01235b3fed7 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/renderer/toStringRenderer.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/renderer/toStringRenderer.kt @@ -3,7 +3,7 @@ package toStringRenderer fun main(args: Array) { val a = A() //Breakpoint! - args.size + args.size() } class A { 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 fc707b871d3..37a15214ad2 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt @@ -59,9 +59,10 @@ import com.intellij.debugger.DebuggerManagerEx import com.intellij.psi.PsiDocumentManager import com.intellij.openapi.application.ModalityState import com.intellij.debugger.settings.NodeRendererSettings -import com.intellij.debugger.impl.DebuggerContextImpl import com.intellij.debugger.SourcePosition import com.intellij.debugger.engine.SourcePositionProvider +import com.intellij.debugger.engine.evaluation.TextWithImports +import com.intellij.debugger.ui.impl.watch.WatchItemDescriptor public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestBase() { private val logger = Logger.getLogger(javaClass())!! @@ -223,7 +224,11 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestB tree.rebuild(debuggerContext) expandAll(tree, Runnable { try { - Printer().printTree(tree) + val printer = Printer() + printer.printTree(tree) + for (extra in getExtraVars()) { + printer.printDescriptor(tree.getNodeFactory().getWatchItemDescriptor(null, extra, null), 2) + } } finally { resume(this@printFrame) @@ -232,6 +237,10 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestB } } + fun getExtraVars(): Set { + return KotlinFrameExtraVariablesProvider().collectVariables(debuggerContext.getSourcePosition(), evaluationContext, hashSetOf())!! + } + private inner class Printer() { fun printTree(tree: DebuggerTree) { val root = tree.getMutableModel()!!.getRoot() as DebuggerTreeNodeImpl @@ -240,14 +249,22 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestB private fun printNode(node: DebuggerTreeNodeImpl, indent: Int) { val descriptor: NodeDescriptorImpl = node.getDescriptor()!! - if (descriptor is DefaultNodeDescriptor) return + + if (printDescriptor(descriptor, indent)) return + + printChildren(node, indent + 2) + } + + fun printDescriptor(descriptor: NodeDescriptorImpl, indent: Int): Boolean { + if (descriptor is DefaultNodeDescriptor) return true val label = descriptor.getLabel()!!.replaceAll("Package\\$[\\w]*\\$[0-9a-f]+", "Package\\$@packagePartHASH") - if (label.endsWith(XDebuggerUIConstants.COLLECTING_DATA_MESSAGE)) return + if (label.endsWith(XDebuggerUIConstants.COLLECTING_DATA_MESSAGE)) return true val curIndent = " ".repeat(indent) when (descriptor) { is StackFrameDescriptor -> logDescriptor(descriptor, "$curIndent frame = $label\n") + is WatchItemDescriptor -> logDescriptor(descriptor, "$curIndent extra = ${descriptor.calcValueName()}\n") is LocalVariableDescriptor -> logDescriptor(descriptor, "$curIndent local = $label" + " (sp = ${render(SourcePositionProvider.getSourcePosition(descriptor, myProject, debuggerContext))})\n") is StaticDescriptor -> logDescriptor(descriptor, "$curIndent static = $label\n") @@ -256,8 +273,7 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestB + " (sp = ${render(SourcePositionProvider.getSourcePosition(descriptor, myProject, debuggerContext))})\n") else -> logDescriptor(descriptor, "$curIndent unknown = $label\n") } - - printChildren(node, indent + 2) + return false } private fun printChildren(node: DebuggerTreeNodeImpl, indent: Int) { diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java index d37cb54aed0..2baaca35ce6 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -33,7 +33,7 @@ import java.util.regex.Pattern; public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluateExpressionTest { @TestMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint") @TestDataPath("$PROJECT_ROOT") - @InnerTestClasses({SingleBreakpoint.Frame.class, SingleBreakpoint.Lambdas.class, SingleBreakpoint.Renderer.class}) + @InnerTestClasses({SingleBreakpoint.ExtraVariables.class, SingleBreakpoint.Frame.class, SingleBreakpoint.Lambdas.class, SingleBreakpoint.Renderer.class}) @RunWith(JUnit3RunnerWithInners.class) public static class SingleBreakpoint extends AbstractKotlinEvaluateExpressionTest { @TestMetadata("abstractFunCall.kt") @@ -226,6 +226,75 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat doSingleBreakpointTest(fileName); } + @TestMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ExtraVariables extends AbstractKotlinEvaluateExpressionTest { + public void testAllFilesPresentInExtraVariables() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("evBreakpointOnPropertyDeclaration.kt") + public void testEvBreakpointOnPropertyDeclaration() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evBreakpointOnPropertyDeclaration.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("evDelegatedProperty.kt") + public void testEvDelegatedProperty() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evDelegatedProperty.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("evDuplicateItems.kt") + public void testEvDuplicateItems() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evDuplicateItems.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("evFinalProperty.kt") + public void testEvFinalProperty() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evFinalProperty.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("evLineRange.kt") + public void testEvLineRange() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evLineRange.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("evProperty.kt") + public void testEvProperty() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evProperty.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("evPropertyRefExpr.kt") + public void testEvPropertyRefExpr() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evPropertyRefExpr.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("evSkipAnonymousObject.kt") + public void testEvSkipAnonymousObject() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipAnonymousObject.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("evSkipLambda.kt") + public void testEvSkipLambda() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipLambda.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("evSkipLocalClass.kt") + public void testEvSkipLocalClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables/evSkipLocalClass.kt"); + doSingleBreakpointTest(fileName); + } + } + @TestMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)