From b5f6df3144fa88e2eb47ab546349bf2bde89e89d Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Tue, 3 Jun 2014 12:44:31 +0400 Subject: [PATCH] Cache bytecodes for JetCodeFragment in Evaluate Expression --- .../jet/generators/tests/GenerateTests.kt | 3 +- idea/src/META-INF/plugin.xml | 3 + .../evaluate/KotlinEvaluateExpressionCache.kt | 119 ++++++++++ .../evaluate/KotlinEvaluationBuilder.kt | 124 ++++++---- ... allFilesPresentInMultipleBreakpoints.out} | 0 .../allFilesPresentInSingleBreakpoint.out | 0 .../debugger/tinyApp/outs/clearCache.out | 45 ++++ .../multipleBreakpoints/clearCache.kt | 206 ++++++++++++++++ .../{ => singleBreakpoint}/abstractFunCall.kt | 0 .../evaluate/{ => singleBreakpoint}/arrays.kt | 0 .../classFromAnotherPackage.kt | 0 .../{ => singleBreakpoint}/classObjectVal.kt | 0 .../{ => singleBreakpoint}/collections.kt | 0 .../collections.kt.fragment | 0 .../{ => singleBreakpoint}/dependentOnFile.kt | 0 .../{ => singleBreakpoint}/doubles.kt | 0 .../evaluate/{ => singleBreakpoint}/enums.kt | 0 .../evaluate/{ => singleBreakpoint}/errors.kt | 0 .../{ => singleBreakpoint}/errors.kt.fragment | 0 .../errors.kt.fragment2 | 0 .../extractLocalVariables.kt | 0 .../{ => singleBreakpoint}/extractThis.kt | 0 .../extractVariablesFromCall.kt | 0 .../{ => singleBreakpoint}/imports.kt | 0 .../{ => singleBreakpoint}/insertInBlock.kt | 0 .../multilineExpressionAtBreakpoint.kt | 0 .../{ => singleBreakpoint}/privateMember.kt | 0 .../{ => singleBreakpoint}/protectedMember.kt | 0 .../evaluate/{ => singleBreakpoint}/simple.kt | 0 .../{ => singleBreakpoint}/simple.kt.fragment | 0 .../evaluate/{ => singleBreakpoint}/stdlib.kt | 0 .../evaluate/{ => singleBreakpoint}/vars.kt | 0 .../AbstractKotlinEvaluateExpressionTest.kt | 73 ++++-- ...KotlinEvaluateExpressionTestGenerated.java | 223 ++++++++++-------- 34 files changed, 629 insertions(+), 167 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionCache.kt rename idea/testData/debugger/tinyApp/outs/{allFilesPresentInEvaluate.out => allFilesPresentInMultipleBreakpoints.out} (100%) create mode 100644 idea/testData/debugger/tinyApp/outs/allFilesPresentInSingleBreakpoint.out create mode 100644 idea/testData/debugger/tinyApp/outs/clearCache.out create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/clearCache.kt rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/abstractFunCall.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/arrays.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/classFromAnotherPackage.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/classObjectVal.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/collections.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/collections.kt.fragment (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/dependentOnFile.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/doubles.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/enums.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/errors.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/errors.kt.fragment (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/errors.kt.fragment2 (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/extractLocalVariables.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/extractThis.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/extractVariablesFromCall.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/imports.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/insertInBlock.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/multilineExpressionAtBreakpoint.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/privateMember.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/protectedMember.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/simple.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/simple.kt.fragment (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/stdlib.kt (100%) rename idea/testData/debugger/tinyApp/src/evaluate/{ => singleBreakpoint}/vars.kt (100%) diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt index 6ae85ebc612..20f8e5867ca 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -612,7 +612,8 @@ fun main(args: Array) { } testClass(javaClass()) { - model("debugger/tinyApp/src/evaluate") + model("debugger/tinyApp/src/evaluate/singleBreakpoint", testMethod = "doSingleBreakpointTest") + model("debugger/tinyApp/src/evaluate/multipleBreakpoints", testMethod = "doMultipleBreakpointsTest") } testClass(javaClass()) { diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 808fb2a6898..e89c4c8ba1d 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -155,6 +155,9 @@ + + diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionCache.kt b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionCache.kt new file mode 100644 index 00000000000..441e6776300 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionCache.kt @@ -0,0 +1,119 @@ +/* + * Copyright 2010-2014 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.jet.plugin.debugger.evaluate + +import com.intellij.openapi.project.Project +import com.intellij.psi.util.CachedValuesManager +import com.intellij.psi.util.CachedValueProvider +import com.intellij.psi.util.PsiModificationTracker +import org.jetbrains.jet.lang.psi.JetCodeFragment +import com.intellij.debugger.SourcePosition +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl +import java.util.ArrayList +import com.intellij.openapi.components.ServiceManager +import org.jetbrains.org.objectweb.asm.Type +import com.intellij.util.containers.MultiMap +import org.jetbrains.jet.lang.types.JetType +import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.openapi.application.ApplicationManager +import org.jetbrains.jet.lang.psi.JetFile +import com.intellij.psi.JavaPsiFacade +import org.jetbrains.jet.lang.resolve.DescriptorUtils +import org.jetbrains.jet.lang.descriptors.ClassDescriptor +import org.jetbrains.jet.plugin.caches.resolve.JavaResolveExtension +import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaClassImpl +import org.jetbrains.jet.lang.resolve.java.JvmClassName +import org.jetbrains.jet.codegen.AsmUtil + +class KotlinEvaluateExpressionCache(val project: Project) { + + private val cachedCompiledData = CachedValuesManager.getManager(project).createCachedValue( + { + CachedValueProvider.Result>( + MultiMap.create(), PsiModificationTracker.MODIFICATION_COUNT) + }, false) + + class object { + fun getInstance(project: Project) = ServiceManager.getService(project, javaClass())!! + + fun getOrCreateCompiledData( + codeFragment: JetCodeFragment, + sourcePosition: SourcePosition, + evaluationContext: EvaluationContextImpl, + create: (JetCodeFragment, SourcePosition) -> CompiledDataDescriptor + ): CompiledDataDescriptor { + val evaluateExpressionCache = getInstance(codeFragment.getProject()) + + return synchronized(evaluateExpressionCache.cachedCompiledData) { + (): CompiledDataDescriptor -> + val cache = evaluateExpressionCache.cachedCompiledData.getValue()!! + val text = "${codeFragment.importsToString()}\n${codeFragment.getText()}" + + val answer = cache[text].firstOrNull { + it.sourcePosition == sourcePosition || evaluateExpressionCache.canBeEvaluatedInThisContext(it, evaluationContext) + } + if (answer != null) return@synchronized answer + + val newCompiledData = create(codeFragment, sourcePosition) + cache.putValue(text, newCompiledData) + + return@synchronized newCompiledData + } + } + } + + private fun canBeEvaluatedInThisContext(compiledData: CompiledDataDescriptor, context: EvaluationContextImpl): Boolean { + return compiledData.parameters.all { (p): Boolean -> + val (name, jetType) = p + val value = context.getFrameProxy()?.getStackFrame()?.findLocalVariable(name, failIfNotFound = false) + if (value == null) return@all false + + val thisDescriptor = value.asmType.getClassDescriptor() + val superClassDescriptor = jetType.getConstructor().getDeclarationDescriptor() as? ClassDescriptor + return@all thisDescriptor != null && superClassDescriptor != null && DescriptorUtils.isSubclass(thisDescriptor, superClassDescriptor) + } + } + + private fun Type.getClassDescriptor(): ClassDescriptor? { + if (AsmUtil.isPrimitive(this)) return null + + val jvmName = JvmClassName.byInternalName(getInternalName()).getFqNameForClassNameWithoutDollars() + + val platformClasses = JavaToKotlinClassMap.getInstance().mapPlatformClass(jvmName) + if (platformClasses.notEmpty) return platformClasses.first() + + return ApplicationManager.getApplication()?.runReadAction { + val classes = JavaPsiFacade.getInstance(project).findClasses(jvmName.asString(), GlobalSearchScope.allScope(project)) + if (classes.isEmpty()) null else JavaResolveExtension[project].resolveClass(JavaClassImpl(classes.first())) + } + } + + data class CompiledDataDescriptor(val bytecodes: ByteArray, val sourcePosition: SourcePosition, val funName: String, val parameters: ParametersDescriptor) + + class ParametersDescriptor : Iterable> { + private val list = ArrayList>() + + fun add(name: String, jetType: JetType) { + list.add(name to jetType) + } + + fun getParameterNames() = list.map { it.first } + + override fun iterator() = list.iterator() + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt index a85b7b84c38..22942f81958 100644 --- a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt +++ b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt @@ -49,10 +49,7 @@ import org.jetbrains.jet.codegen.ClassFileFactory import org.jetbrains.jet.OutputFileCollection import org.jetbrains.jet.plugin.caches.resolve.getAnalysisResults import org.jetbrains.jet.lang.psi.JetCodeFragment -import org.jetbrains.jet.lang.psi.JetImportList import org.jetbrains.jet.lang.psi.codeFragmentUtil.skipVisibilityCheck -import org.jetbrains.jet.lang.psi.JetExpression -import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.Status import com.intellij.openapi.diagnostic.Logger import org.jetbrains.jet.codegen.CompilationErrorHandler import org.jetbrains.jet.lang.diagnostics.Severity @@ -60,6 +57,10 @@ import org.jetbrains.jet.lang.diagnostics.rendering.DefaultErrorMessages import com.sun.jdi.request.EventRequest import com.sun.jdi.ObjectReference import com.intellij.debugger.engine.SuspendContext +import org.jetbrains.jet.plugin.debugger.evaluate.KotlinEvaluateExpressionCache.* +import org.jetbrains.jet.lang.resolve.BindingContext +import com.sun.jdi.StackFrame +import com.sun.jdi.VirtualMachine object KotlinEvaluationBuilder: EvaluatorBuilder { override fun build(codeFragment: PsiElement, position: SourcePosition?): ExpressionEvaluator { @@ -86,9 +87,24 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment, val sourcePosition: SourcePosition ) : Evaluator { override fun evaluate(context: EvaluationContextImpl): Any? { + var isCompiledDataFromCache = true try { - val compiledData = extractAndCompile(codeFragment, sourcePosition) - return runEval4j(context, compiledData) + val compiledData = KotlinEvaluateExpressionCache.getOrCreateCompiledData(codeFragment, sourcePosition, context) { + fragment, position -> + isCompiledDataFromCache = false + extractAndCompile(fragment, position) + } + val args = context.getArgumentsByNames(compiledData.parameters.getParameterNames()) + val result = runEval4j(context, compiledData, args) + + val virtualMachine = context.getDebugProcess().getVirtualMachineProxy().getVirtualMachine() + + // If bytecode was taken from cache and exception was thrown - recompile bytecode and run eval4j again + if (result is ExceptionThrown && isCompiledDataFromCache) { + return runEval4j(context, extractAndCompile(codeFragment, sourcePosition), args).toJdiValue(virtualMachine) + } + + return result.toJdiValue(virtualMachine) } catch(e: EvaluateException) { throw e @@ -121,77 +137,79 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment, if (funName == null) { throw IllegalStateException("Extracted function should have a name: ${extractedFunction.getText()}") } - return CompiledDataDescriptor(outputFiles.first().asByteArray(), funName, extractedFunction.getParameterNamesForDebugger()) + return CompiledDataDescriptor(outputFiles.first().asByteArray(), sourcePosition, funName, extractedFunction.getParametersForDebugger()) } - private fun runEval4j(context: EvaluationContextImpl, compiledData: CompiledDataDescriptor): Any? { + private fun runEval4j( + context: EvaluationContextImpl, + compiledData: CompiledDataDescriptor, + args: List + ): InterpreterResult { val virtualMachine = context.getDebugProcess().getVirtualMachineProxy().getVirtualMachine() - var resultValue: Value? = null + var resultValue: InterpreterResult? = null ClassReader(compiledData.bytecodes).accept(object : ClassVisitor(ASM5) { override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array?): MethodVisitor? { if (name == compiledData.funName) { return object : MethodNode(Opcodes.ASM5, access, name, desc, signature, exceptions) { override fun visitEnd() { - val value = interpreterLoop( + resultValue = interpreterLoop( this, - makeInitialFrame(this, context.getArgumentsByNames(compiledData.parameterNames)), + makeInitialFrame(this, args), JDIEval(virtualMachine, context.getClassLoader()!!, - context.getSuspendContext().getThread()?.getThreadReference()!!, context.getSuspendContext().getInvokePolicy()) + context.getSuspendContext().getThread()?.getThreadReference()!!, + context.getSuspendContext().getInvokePolicy()) ) - - resultValue = when (value) { - is ValueReturned -> value.result - is ExceptionThrown -> exception(value.exception.toString()) - is AbnormalTermination -> exception(value.message) - else -> throw IllegalStateException("Unknown result value produced by eval4j") - } } } } + return super.visitMethod(access, name, desc, signature, exceptions) } }, 0) - if (resultValue == null) { - throw IllegalStateException("resultValue is null: cannot find method ${compiledData.funName}") - } + return resultValue ?: throw IllegalStateException("resultValue is null: cannot find method ${compiledData.funName}") + } - return resultValue!!.asJdiValue(virtualMachine, resultValue!!.asmType) + private fun InterpreterResult.toJdiValue(vm: VirtualMachine): com.sun.jdi.Value? { + val jdiValue = when (this) { + is ValueReturned -> result + is ExceptionThrown -> exception(exception.toString()) + is AbnormalTermination -> exception(message) + else -> throw IllegalStateException("Unknown result value produced by eval4j") + } + return jdiValue.asJdiValue(vm, jdiValue.asmType) } private fun SuspendContext.getInvokePolicy(): Int { return if (getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD) ObjectReference.INVOKE_SINGLE_THREADED else 0 } - private fun JetNamedFunction.getParameterNamesForDebugger(): List { - val result = arrayListOf() - if (getReceiverTypeRef() != null) { - result.add("this") - } - for (param in getValueParameters()) { - result.add(param.getName()!!) - } - return result + private fun JetNamedFunction.getParametersForDebugger(): ParametersDescriptor { + return ApplicationManager.getApplication()?.runReadAction(Computable { + val parameters = ParametersDescriptor() + val bindingContext = getAnalysisResults().getBindingContext() + val descriptor = bindingContext[BindingContext.FUNCTION, this] + if (descriptor != null) { + val receiver = descriptor.getReceiverParameter() + if (receiver != null) { + parameters.add("this", receiver.getType()) + } + + descriptor.getValueParameters().forEach { + param -> + parameters.add(param.getName().asString(), param.getType()) + } + } + parameters + })!! } private fun EvaluationContextImpl.getArgumentsByNames(parameterNames: List): List { val frames = getFrameProxy()?.getStackFrame() if (frames != null) { - fun getValue(name: String): Value { - return try { - when (name) { - "this" -> frames.thisObject().asValue() - else -> frames.getValue(frames.visibleVariableByName(name)).asValue() - } - } - catch(e: Exception) { - exception("Cannot get parameter value from local variables table: parameterName = ${name}. Note that captured parameters are unsupported yet.") - } - } - - return parameterNames.map { getValue(it) } + return parameterNames.map { frames.findLocalVariable(it)!! } } return Collections.emptyList() } @@ -283,6 +301,22 @@ fun checkForSyntacticErrors(file: JetFile) { } } -data class CompiledDataDescriptor(val bytecodes: ByteArray, val funName: String, val parameterNames: List) +fun StackFrame.findLocalVariable(name: String, failIfNotFound: Boolean = true): Value? { + return try { + when (name) { + "this" -> thisObject().asValue() + else -> getValue(visibleVariableByName(name)).asValue() + } + } + catch(e: Exception) { + if (failIfNotFound) { + throw EvaluateExceptionUtil.createEvaluateException( + "Cannot find local variable: name = ${name}. Note that captured variables are unsupported yet.") + } + else { + return null + } + } +} diff --git a/idea/testData/debugger/tinyApp/outs/allFilesPresentInEvaluate.out b/idea/testData/debugger/tinyApp/outs/allFilesPresentInMultipleBreakpoints.out similarity index 100% rename from idea/testData/debugger/tinyApp/outs/allFilesPresentInEvaluate.out rename to idea/testData/debugger/tinyApp/outs/allFilesPresentInMultipleBreakpoints.out diff --git a/idea/testData/debugger/tinyApp/outs/allFilesPresentInSingleBreakpoint.out b/idea/testData/debugger/tinyApp/outs/allFilesPresentInSingleBreakpoint.out new file mode 100644 index 00000000000..e69de29bb2d diff --git a/idea/testData/debugger/tinyApp/outs/clearCache.out b/idea/testData/debugger/tinyApp/outs/clearCache.out new file mode 100644 index 00000000000..4596499adcd --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/clearCache.out @@ -0,0 +1,45 @@ +LineBreakpoint created at clearCache.kt:12 +LineBreakpoint created at clearCache.kt:20 +LineBreakpoint created at clearCache.kt:31 +LineBreakpoint created at clearCache.kt:42 +LineBreakpoint created at clearCache.kt:52 +LineBreakpoint created at clearCache.kt:60 +LineBreakpoint created at clearCache.kt:78 +LineBreakpoint created at clearCache.kt:86 +LineBreakpoint created at clearCache.kt:95 +LineBreakpoint created at clearCache.kt:105 +LineBreakpoint created at clearCache.kt:113 +LineBreakpoint created at clearCache.kt:124 +LineBreakpoint created at clearCache.kt:133 +LineBreakpoint created at clearCache.kt:143 +LineBreakpoint created at clearCache.kt:151 +LineBreakpoint created at clearCache.kt:169 +LineBreakpoint created at clearCache.kt:174 +LineBreakpoint created at clearCache.kt:181 +LineBreakpoint created at clearCache.kt:189 +!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!;!RT_JAR! clearCache.ClearCachePackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +clearCache.kt:11 +clearCache.kt:19 +clearCache.kt:30 +clearCache.kt:30 +clearCache.kt:41 +clearCache.kt:41 +clearCache.kt:51 +clearCache.kt:59 +clearCache.kt:77 +clearCache.kt:85 +clearCache.kt:94 +clearCache.kt:104 +clearCache.kt:112 +clearCache.kt:123 +clearCache.kt:132 +clearCache.kt:142 +clearCache.kt:150 +clearCache.kt:168 +clearCache.kt:173 +clearCache.kt:180 +clearCache.kt:188 +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/src/evaluate/multipleBreakpoints/clearCache.kt b/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/clearCache.kt new file mode 100644 index 00000000000..290a9a81261 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/clearCache.kt @@ -0,0 +1,206 @@ +package clearCache + +import java.util.ArrayList +import java.util.HashSet + +fun primitiveTypes() { + if (true) { + val a: Any = 0 + // EXPRESSION: a + // RESULT: instance of java.lang.Integer(id=ID): Ljava/lang/Integer; + //Breakpoint! + val b = 1 + } + + if (true) { + val a = 1 + // EXPRESSION: a + // RESULT: 1: I + //Breakpoint! + val b = 1 + } + + for (i in 1..2) { + // EXPRESSION: i + // RESULT: 1: I + + // EXPRESSION: i + // RESULT: 2: I + + //Breakpoint! + val b = 1 + } + + for (i in 5.0..6.0) { + // EXPRESSION: i + // RESULT: 5.0: D + + // EXPRESSION: i + // RESULT: 6.0: D + + //Breakpoint! + val b = 1 + } +} + +fun subType() { + if (true) { + val o = Base() + // EXPRESSION: o.test() + // RESULT: 100: I + //Breakpoint! + val b = 1 + } + + if (true) { + val o = Derived() + // EXPRESSION: o.test() + // RESULT: 200: I + //Breakpoint! + val b = 1 + } +} + +open class Base { + open fun test() = 100 +} + +class Derived: Base() { + override fun test() = 200 +} + +fun subTypePlatform() { + if (true) { + val c: MutableList = ArrayList() + // EXPRESSION: c.size() + // RESULT: 0: I + //Breakpoint! + val b = 1 + } + + if (true) { + val c: List = ArrayList() + // EXPRESSION: c.size() + // RESULT: 0: I + //Breakpoint! + val b = 1 + } + + if (true) { + val c = ArrayList() + c.add("a") + // EXPRESSION: c.size() + // RESULT: 1: I + //Breakpoint! + val b = 1 + } + + if (true) { + val c = ArrayList() + c.add(1) + c.add(2) + // EXPRESSION: c.size() + // RESULT: 2: I + //Breakpoint! + val b = 1 + } + + if (true) { + val c = HashSet() + // EXPRESSION: c.size() + // RESULT: 0: I + //Breakpoint! + val b = 1 + } +} + +fun genericRerun() { + if (true) { + val c = ArrayList() + c.add(1) + // EXPRESSION: c.get(0) + // RESULT: 1: I + //Breakpoint! + val b = 1 + } + + if (true) { + val c = ArrayList() + c.add("a") + // EXPRESSION: c.get(0) + // RESULT: "a": Ljava/lang/String; + //Breakpoint! + val b = 1 + } +} + +fun innerClass() { + if (true) { + val o = TestInnerClasses.Base() + // EXPRESSION: o.test() + // RESULT: 100: I + //Breakpoint! + val b = 1 + } + + if (true) { + val o = TestInnerClasses.Derived() + // EXPRESSION: o.test() + // RESULT: 200: I + //Breakpoint! + val b = 1 + } +} + +class TestInnerClasses { + open class Base { + open fun test() = 100 + } + + class Derived: Base() { + override fun test() = 200 + } +} + +fun objects() { + // EXPRESSION: obj.test() + // RESULT: 1: I + //Breakpoint! + val a1 = 1 + + // EXPRESSION: obj.test() + // RESULT: 1: I + //Breakpoint! + val a2 = 1 + + if (true) { + val o: BaseObject = obj + // EXPRESSION: o.test() + // RESULT: 1: I + //Breakpoint! + val b = 1 + } + + if (true) { + val o = obj + // EXPRESSION: o.test() + // RESULT: 1: I + //Breakpoint! + val b = 1 + } +} + +val obj = object: BaseObject() { } + +open class BaseObject { + fun test() = 1 +} + +fun main(args: Array) { + primitiveTypes() + subType() + subTypePlatform() + genericRerun() + innerClass() + objects() +} diff --git a/idea/testData/debugger/tinyApp/src/evaluate/abstractFunCall.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/abstractFunCall.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/abstractFunCall.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/abstractFunCall.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/arrays.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/arrays.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/arrays.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/arrays.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/classFromAnotherPackage.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/classFromAnotherPackage.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/classFromAnotherPackage.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/classFromAnotherPackage.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/classObjectVal.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/classObjectVal.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/classObjectVal.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/classObjectVal.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/collections.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/collections.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/collections.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/collections.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/collections.kt.fragment b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/collections.kt.fragment similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/collections.kt.fragment rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/collections.kt.fragment diff --git a/idea/testData/debugger/tinyApp/src/evaluate/dependentOnFile.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/dependentOnFile.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/dependentOnFile.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/dependentOnFile.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/doubles.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/doubles.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/doubles.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/doubles.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/enums.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/enums.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/enums.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/enums.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/errors.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/errors.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/errors.kt.fragment b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt.fragment similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/errors.kt.fragment rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt.fragment diff --git a/idea/testData/debugger/tinyApp/src/evaluate/errors.kt.fragment2 b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt.fragment2 similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/errors.kt.fragment2 rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt.fragment2 diff --git a/idea/testData/debugger/tinyApp/src/evaluate/extractLocalVariables.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractLocalVariables.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/extractLocalVariables.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractLocalVariables.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/extractThis.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractThis.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/extractThis.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractThis.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/extractVariablesFromCall.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractVariablesFromCall.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/extractVariablesFromCall.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractVariablesFromCall.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/imports.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/imports.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/imports.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/imports.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/insertInBlock.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/insertInBlock.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/insertInBlock.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/insertInBlock.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/multilineExpressionAtBreakpoint.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/multilineExpressionAtBreakpoint.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/multilineExpressionAtBreakpoint.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/multilineExpressionAtBreakpoint.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/privateMember.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/privateMember.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/privateMember.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/privateMember.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/protectedMember.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/protectedMember.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/protectedMember.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/protectedMember.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/simple.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/simple.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/simple.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/simple.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/simple.kt.fragment b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/simple.kt.fragment similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/simple.kt.fragment rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/simple.kt.fragment diff --git a/idea/testData/debugger/tinyApp/src/evaluate/stdlib.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/stdlib.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/stdlib.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/stdlib.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/vars.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/vars.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/vars.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/vars.kt diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt index ab25a5b2e2c..18a53380877 100644 --- a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt +++ b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt @@ -37,12 +37,9 @@ import java.util.Collections import com.intellij.debugger.engine.evaluation.EvaluateException public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestCase() { - fun doTest(path: String) { + fun doSingleBreakpointTest(path: String) { val file = File(path) - val fileContent = FileUtil.loadFile(file, true) - val expressions = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileContent, "// EXPRESSION: ") - val expectedExpressionResults = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileContent, "// RESULT: ") - assert(expressions.size == expectedExpressionResults.size, "Sizes of test directives are different") + val expressions = loadTestDirectivesPairs(file, "// EXPRESSION: ", "// RESULT: ") val blocks = findFilesWithBlocks(file).map { FileUtil.loadFile(it, true) } val expectedBlockResults = blocks.map { InTextDirectivesUtils.findLinesWithPrefixesRemoved(it, "// RESULT: ").makeString("\n") } @@ -51,34 +48,68 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestC onBreakpoint { val exceptions = linkedMapOf() - for ((i, expression) in expressions.withIndices()) { - try { - evaluate(expression, CodeFragmentKind.EXPRESSION, expectedExpressionResults[i]) - } - catch (e: Throwable) { - exceptions.put(expression, e) + for ((expression, expected) in expressions) { + mayThrow(exceptions, expression) { + evaluate(expression, CodeFragmentKind.EXPRESSION, expected) } } for ((i, block) in blocks.withIndices()) { - try { + mayThrow(exceptions, block) { evaluate(block, CodeFragmentKind.CODE_BLOCK, expectedBlockResults[i]) } - catch (e: Throwable) { - exceptions.put(block, e) - } } - if (!exceptions.empty) { - for (exc in exceptions.values()) { - exc.printStackTrace() - } - throw AssertionError("Test failed:\n" + exceptions.map { "expression: ${it.key}, exception: ${it.value.getMessage()}" }.makeString("\n")) - } + checkExceptions(exceptions) } finish() } + fun doMultipleBreakpointsTest(path: String) { + val expressions = loadTestDirectivesPairs(File(path), "// EXPRESSION: ", "// RESULT: ") + + createDebugProcess(path) + + val exceptions = linkedMapOf() + for ((expression, expected) in expressions) { + mayThrow(exceptions, expression) { + onBreakpoint { + evaluate(expression, CodeFragmentKind.EXPRESSION, expected) + } + } + } + + checkExceptions(exceptions) + + finish() + } + + private fun checkExceptions(exceptions: MutableMap) { + if (!exceptions.empty) { + for (exc in exceptions.values()) { + exc.printStackTrace() + } + throw AssertionError("Test failed:\n" + exceptions.map { "expression: ${it.key}, exception: ${it.value.getMessage()}" }.makeString("\n")) + } + } + + private fun mayThrow(map: MutableMap, expression: String, f: () -> Unit) { + try { + f() + } + catch (e: Throwable) { + map.put(expression, e) + } + } + + private fun loadTestDirectivesPairs(file: File, directivePrefix: String, expectedPrefix: String): List> { + val fileContent = FileUtil.loadFile(file, true) + val directives = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileContent, directivePrefix) + val expected = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileContent, expectedPrefix) + assert(directives.size == expected.size, "Sizes of test directives are different") + return directives.zip(expected) + } + private fun findFilesWithBlocks(mainFile: File): List { val mainFileName = mainFile.getName() return mainFile.getParentFile()?.listFiles()?.filter { it.name.startsWith(mainFileName) && it.name != mainFileName } ?: Collections.emptyList() diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java index d2831a31d1c..a9fe9459d19 100644 --- a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -30,110 +30,133 @@ import org.jetbrains.jet.plugin.debugger.evaluate.AbstractKotlinEvaluateExpressi /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") -@TestMetadata("idea/testData/debugger/tinyApp/src/evaluate") +@InnerTestClasses({KotlinEvaluateExpressionTestGenerated.SingleBreakpoint.class, KotlinEvaluateExpressionTestGenerated.MultipleBreakpoints.class}) public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluateExpressionTest { - @TestMetadata("abstractFunCall.kt") - public void testAbstractFunCall() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/abstractFunCall.kt"); + @TestMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint") + public static class SingleBreakpoint extends AbstractKotlinEvaluateExpressionTest { + @TestMetadata("abstractFunCall.kt") + public void testAbstractFunCall() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/abstractFunCall.kt"); + } + + public void testAllFilesPresentInSingleBreakpoint() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("arrays.kt") + public void testArrays() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/arrays.kt"); + } + + @TestMetadata("classFromAnotherPackage.kt") + public void testClassFromAnotherPackage() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/classFromAnotherPackage.kt"); + } + + @TestMetadata("classObjectVal.kt") + public void testClassObjectVal() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/classObjectVal.kt"); + } + + @TestMetadata("collections.kt") + public void testCollections() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/collections.kt"); + } + + @TestMetadata("dependentOnFile.kt") + public void testDependentOnFile() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/dependentOnFile.kt"); + } + + @TestMetadata("doubles.kt") + public void testDoubles() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/doubles.kt"); + } + + @TestMetadata("enums.kt") + public void testEnums() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/enums.kt"); + } + + @TestMetadata("errors.kt") + public void testErrors() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt"); + } + + @TestMetadata("extractLocalVariables.kt") + public void testExtractLocalVariables() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractLocalVariables.kt"); + } + + @TestMetadata("extractThis.kt") + public void testExtractThis() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractThis.kt"); + } + + @TestMetadata("extractVariablesFromCall.kt") + public void testExtractVariablesFromCall() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractVariablesFromCall.kt"); + } + + @TestMetadata("imports.kt") + public void testImports() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/imports.kt"); + } + + @TestMetadata("insertInBlock.kt") + public void testInsertInBlock() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/insertInBlock.kt"); + } + + @TestMetadata("multilineExpressionAtBreakpoint.kt") + public void testMultilineExpressionAtBreakpoint() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/multilineExpressionAtBreakpoint.kt"); + } + + @TestMetadata("privateMember.kt") + public void testPrivateMember() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/privateMember.kt"); + } + + @TestMetadata("protectedMember.kt") + public void testProtectedMember() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/protectedMember.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/simple.kt"); + } + + @TestMetadata("stdlib.kt") + public void testStdlib() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/stdlib.kt"); + } + + @TestMetadata("vars.kt") + public void testVars() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/vars.kt"); + } + } - public void testAllFilesPresentInEvaluate() throws Exception { - JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/debugger/tinyApp/src/evaluate"), Pattern.compile("^(.+)\\.kt$"), true); + @TestMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints") + public static class MultipleBreakpoints extends AbstractKotlinEvaluateExpressionTest { + public void testAllFilesPresentInMultipleBreakpoints() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("clearCache.kt") + public void testClearCache() throws Exception { + doMultipleBreakpointsTest("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/clearCache.kt"); + } + } - @TestMetadata("arrays.kt") - public void testArrays() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/arrays.kt"); + public static Test suite() { + TestSuite suite = new TestSuite("KotlinEvaluateExpressionTestGenerated"); + suite.addTestSuite(SingleBreakpoint.class); + suite.addTestSuite(MultipleBreakpoints.class); + return suite; } - - @TestMetadata("classFromAnotherPackage.kt") - public void testClassFromAnotherPackage() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/classFromAnotherPackage.kt"); - } - - @TestMetadata("classObjectVal.kt") - public void testClassObjectVal() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/classObjectVal.kt"); - } - - @TestMetadata("collections.kt") - public void testCollections() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/collections.kt"); - } - - @TestMetadata("dependentOnFile.kt") - public void testDependentOnFile() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/dependentOnFile.kt"); - } - - @TestMetadata("doubles.kt") - public void testDoubles() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/doubles.kt"); - } - - @TestMetadata("enums.kt") - public void testEnums() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/enums.kt"); - } - - @TestMetadata("errors.kt") - public void testErrors() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/errors.kt"); - } - - @TestMetadata("extractLocalVariables.kt") - public void testExtractLocalVariables() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/extractLocalVariables.kt"); - } - - @TestMetadata("extractThis.kt") - public void testExtractThis() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/extractThis.kt"); - } - - @TestMetadata("extractVariablesFromCall.kt") - public void testExtractVariablesFromCall() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/extractVariablesFromCall.kt"); - } - - @TestMetadata("imports.kt") - public void testImports() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/imports.kt"); - } - - @TestMetadata("insertInBlock.kt") - public void testInsertInBlock() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/insertInBlock.kt"); - } - - @TestMetadata("multilineExpressionAtBreakpoint.kt") - public void testMultilineExpressionAtBreakpoint() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/multilineExpressionAtBreakpoint.kt"); - } - - @TestMetadata("privateMember.kt") - public void testPrivateMember() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/privateMember.kt"); - } - - @TestMetadata("protectedMember.kt") - public void testProtectedMember() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/protectedMember.kt"); - } - - @TestMetadata("simple.kt") - public void testSimple() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/simple.kt"); - } - - @TestMetadata("stdlib.kt") - public void testStdlib() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/stdlib.kt"); - } - - @TestMetadata("vars.kt") - public void testVars() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/vars.kt"); - } - }