diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionCache.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionCache.kt index a4fc0351e12..a1a6d67830b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionCache.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionCache.kt @@ -84,7 +84,13 @@ class KotlinEvaluateExpressionCache(val project: Project) { } } - data class CompiledDataDescriptor(val bytecodes: ByteArray, val sourcePosition: SourcePosition, val funName: String, val parameters: ParametersDescriptor) + data class CompiledDataDescriptor( + val bytecodes: ByteArray, + val additionalClasses: List>, + val sourcePosition: SourcePosition, + val funName: String, + val parameters: ParametersDescriptor + ) class ParametersDescriptor : Iterable> { private val list = ArrayList>() diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt index 40584c5a074..6ddd99c2ddf 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt @@ -78,6 +78,7 @@ import com.intellij.openapi.diagnostic.Attachment import org.jetbrains.kotlin.idea.util.attachment.mergeAttachments import com.sun.jdi.ClassType import com.sun.jdi.InvocationException +import org.jetbrains.kotlin.idea.debugger.evaluate.compilingEvaluator.loadClasses private val RECEIVER_NAME = "\$receiver" private val THIS_NAME = "this" @@ -169,19 +170,37 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment, val classFileFactory = createClassFileFactory(codeFragment, extractedFunction) // KT-4509 - val outputFiles = (classFileFactory : OutputFileCollection).asList().filter { it.relativePath != "$packageInternalName.class" } - if (outputFiles.size() != 1) exception("Expression compiles to more than one class file. Note that lambdas, classes and objects are unsupported yet. List of files: ${outputFiles.joinToString(",")}") + val outputFiles = (classFileFactory : OutputFileCollection).asList() + .filter { it.relativePath != "$packageInternalName.class" } + .sortBy { it.relativePath.length() } val funName = extractedFunction.getName() if (funName == null) { throw IllegalStateException("Extracted function should have a name: ${extractedFunction.getText()}") } - return CompiledDataDescriptor(outputFiles.first().asByteArray(), sourcePosition, funName, extractedFunction.getParametersForDebugger()) + + val additionalFiles = if (outputFiles.size() < 2) emptyList() + else outputFiles.subList(1, outputFiles.size()).map { getClassName(it.relativePath) to it.asByteArray() } + + return CompiledDataDescriptor( + outputFiles.first().asByteArray(), + additionalFiles, + sourcePosition, + funName, + extractedFunction.getParametersForDebugger()) + } + + private fun getClassName(fileName: String): String { + return fileName.substringBeforeLast(".class").replaceAll("/", ".") } private fun runEval4j(context: EvaluationContextImpl, compiledData: CompiledDataDescriptor): InterpreterResult { val virtualMachine = context.getDebugProcess().getVirtualMachineProxy().getVirtualMachine() + if (compiledData.additionalClasses.isNotEmpty()) { + loadClasses(context, compiledData.additionalClasses) + } + 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? { diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilingEvaluator.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilingEvaluator.kt new file mode 100644 index 00000000000..62a4c54cf68 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilingEvaluator.kt @@ -0,0 +1,87 @@ +/* + * 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.evaluate.compilingEvaluator + +import kotlin.properties.Delegates +import com.intellij.debugger.engine.evaluation.EvaluateException +import com.intellij.debugger.engine.DebugProcess +import com.sun.jdi.ClassLoaderReference +import com.intellij.openapi.projectRoots.JdkVersionUtil +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl +import com.intellij.debugger.engine.evaluation.EvaluationContext +import com.intellij.openapi.util.SystemInfo +import org.jetbrains.kotlin.idea.debugger.evaluate.CompilingEvaluatorUtils + +public fun loadClasses(evaluationContext: EvaluationContextImpl, classes: Collection>) { + val process = evaluationContext.getDebugProcess() + + val classLoader: ClassLoaderReference + try { + classLoader = CompilingEvaluatorUtils.getClassLoader(evaluationContext, process) + } + catch (e: Exception) { + throw EvaluateException("Error creating evaluation class loader: " + e, e) + } + + val version = (process.getVirtualMachineProxy()).version() + val sdkVersion = JdkVersionUtil.getVersion(version) + + if (!SystemInfo.isJavaVersionAtLeast(sdkVersion.getDescription())) { + throw EvaluateException("Unable to compile for target level " + sdkVersion.getDescription() + ". Need to run IDEA on java version at least " + sdkVersion.getDescription() + ", currently running on " + SystemInfo.JAVA_RUNTIME_VERSION) + } + + try { + defineClasses(classes, evaluationContext, process, classLoader) + } + catch (e: Exception) { + throw EvaluateException("Error during classes definition " + e, e) + } + + evaluationContext.setClassLoader(classLoader) +} + +private fun defineClasses( + classes: Collection>, + context: EvaluationContext, + process: DebugProcess, + classLoader: ClassLoaderReference +) { + CompilingEvaluatorUtils.defineClass(FunctionImplBytes.name, FunctionImplBytes.bytes, context, process, classLoader) + + for ((className, bytes) in classes) { + CompilingEvaluatorUtils.defineClass(className, bytes, context, process, classLoader) + } +} + +private object FunctionImplBytes { + val bytes: ByteArray by Delegates.lazy { + (): ByteArray -> + val inputStream = this.javaClass.getClassLoader().getResourceAsStream("kotlin/jvm/internal/FunctionImpl.class") + if (inputStream != null) { + try { + return@lazy inputStream.readBytes() + } + finally { + inputStream.close() + } + } + + throw EvaluateException("Couldn't find kotlin.jvm.internal.FunctionImpl class in current classloader") + } + + val name = "kotlin.jvm.internal.FunctionImpl" +} \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/outs/allFilesPresentInCompilingEvaluator.out b/idea/testData/debugger/tinyApp/outs/allFilesPresentInCompilingEvaluator.out new file mode 100644 index 00000000000..e69de29bb2d diff --git a/idea/testData/debugger/tinyApp/outs/ceLambda.out b/idea/testData/debugger/tinyApp/outs/ceLambda.out new file mode 100644 index 00000000000..9c3192db155 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/ceLambda.out @@ -0,0 +1,9 @@ +LineBreakpoint created at ceLambda.kt:6 +!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! ceLambda.CeLambdaPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +ceLambda.kt:6 +Compile bytecode for foo { 1 } +Compile bytecode for foo { a } +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/ceLocalClass.out b/idea/testData/debugger/tinyApp/outs/ceLocalClass.out new file mode 100644 index 00000000000..43aa0ed16b8 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/ceLocalClass.out @@ -0,0 +1,16 @@ +LineBreakpoint created at ceLocalClass.kt:6 +!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! ceLocalClass.CeLocalClassPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +ceLocalClass.kt:6 +Compile bytecode for class MyClass { + fun test() = 2 +} + +val a = MyClass() +a.test() + +// RESULT: 2: I + +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/ceLocalClassMembers.out b/idea/testData/debugger/tinyApp/outs/ceLocalClassMembers.out new file mode 100644 index 00000000000..2fe9ec10cb2 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/ceLocalClassMembers.out @@ -0,0 +1,16 @@ +LineBreakpoint created at ceLocalClassMembers.kt:19 +!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! ceLocalClassMembers.CeLocalClassMembersPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +ceLocalClassMembers.kt:19 +Compile bytecode for class MyClass { + fun test() = publicFun() + publicVal + protectedFun() + protectedVal + privateFun() + privateFun() +} + +val a = MyClass() +a.test() + +// RESULT: 6: I + +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/ceLocalClassWithSuperClass.out b/idea/testData/debugger/tinyApp/outs/ceLocalClassWithSuperClass.out new file mode 100644 index 00000000000..efa30769f7c --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/ceLocalClassWithSuperClass.out @@ -0,0 +1,16 @@ +LineBreakpoint created at ceLocalClassWithSuperClass.kt:19 +!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! ceLocalClassWithSuperClass.CeLocalClassWithSuperClassPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +ceLocalClassWithSuperClass.kt:19 +Compile bytecode for class MyClass: MySuperClass() { + fun test() = publicFun() +} + +val a = MyClass() +a.test() + +// RESULT: 1: I + +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/ceMembers.out b/idea/testData/debugger/tinyApp/outs/ceMembers.out new file mode 100644 index 00000000000..939762e235b --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/ceMembers.out @@ -0,0 +1,13 @@ +LineBreakpoint created at ceMembers.kt:19 +!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! ceMembers.CeMembersPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +ceMembers.kt:19 +Compile bytecode for foo { publicFun() } +Compile bytecode for foo { publicVal } +Compile bytecode for foo { protectedFun() } +Compile bytecode for foo { protectedVal } +Compile bytecode for foo { privateFun() } +Compile bytecode for foo { privateVal } +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/ceObject.out b/idea/testData/debugger/tinyApp/outs/ceObject.out new file mode 100644 index 00000000000..41c5d94ab80 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/ceObject.out @@ -0,0 +1,7 @@ +LineBreakpoint created at ceObject.kt:5 +!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! ceObject.CeObjectPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +ceObject.kt:5 +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/ceSeveralLambdas.out b/idea/testData/debugger/tinyApp/outs/ceSeveralLambdas.out new file mode 100644 index 00000000000..23d05b12cd0 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/ceSeveralLambdas.out @@ -0,0 +1,8 @@ +LineBreakpoint created at ceSeveralLambdas.kt:5 +!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! ceSeveralLambdas.CeSeveralLambdasPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +ceSeveralLambdas.kt:5 +Compile bytecode for foo { 1 } + foo { 1 } +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/ceSuperAccess.out b/idea/testData/debugger/tinyApp/outs/ceSuperAccess.out new file mode 100644 index 00000000000..451eadc7de7 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/ceSuperAccess.out @@ -0,0 +1,13 @@ +LineBreakpoint created at ceSuperAccess.kt:20 +!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! ceSuperAccess.CeSuperAccessPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +ceSuperAccess.kt:20 +Compile bytecode for foo { publicFun() } +Compile bytecode for foo { publicVal } +Compile bytecode for foo { protectedFun() } +Compile bytecode for foo { protectedVal } +Compile bytecode for foo { privateFun() } +Compile bytecode for foo { privateVal } +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/singleBreakpoint/compilingEvaluator/ceLambda.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLambda.kt new file mode 100644 index 00000000000..e44e5a53be6 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLambda.kt @@ -0,0 +1,16 @@ +package ceLambda + +fun main(args: Array) { + val a = 1 + //Breakpoint! + args.size() +} + +fun foo(p: () -> Int) = p() + +// EXPRESSION: foo { 1 } +// RESULT: 1: I + +// EXPRESSION: foo { a } +// RESULT: 1: I + diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClass.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClass.kt new file mode 100644 index 00000000000..ffa89222056 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClass.kt @@ -0,0 +1,8 @@ +package ceLocalClass + +fun main(args: Array) { + val a = 1 + //Breakpoint! + args.size() +} + diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClass.kt.fragment b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClass.kt.fragment new file mode 100644 index 00000000000..1c7df9bf5bb --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClass.kt.fragment @@ -0,0 +1,8 @@ +class MyClass { + fun test() = 2 +} + +val a = MyClass() +a.test() + +// RESULT: 2: I diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassMembers.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassMembers.kt new file mode 100644 index 00000000000..efb2b559464 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassMembers.kt @@ -0,0 +1,25 @@ +package ceLocalClassMembers + +fun main(args: Array) { + A().test() +} + +class A { + public fun publicFun(): Int = 1 + public val publicVal: Int = 1 + + protected fun protectedFun(): Int = 1 + protected val protectedVal: Int = 1 + + private fun privateFun() = 1 + private val privateVal = 1 + + fun test() { + //Breakpoint! + val a = 1 + } +} + + + + diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassMembers.kt.fragment b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassMembers.kt.fragment new file mode 100644 index 00000000000..1b7163b2b9e --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassMembers.kt.fragment @@ -0,0 +1,8 @@ +class MyClass { + fun test() = publicFun() + publicVal + protectedFun() + protectedVal + privateFun() + privateFun() +} + +val a = MyClass() +a.test() + +// RESULT: 6: I diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassWithSuperClass.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassWithSuperClass.kt new file mode 100644 index 00000000000..1c36be647b6 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassWithSuperClass.kt @@ -0,0 +1,23 @@ +package ceLocalClassWithSuperClass + +fun main(args: Array) { + A().test() +} + +class A { + public fun publicFun(): Int = 1 + public val publicVal: Int = 1 + + protected fun protectedFun(): Int = 1 + protected val protectedVal: Int = 1 + + private fun privateFun() = 1 + private val privateVal = 1 + + fun test() { + //Breakpoint! + val a = 1 + } +} + +open class MySuperClass diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassWithSuperClass.kt.fragment b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassWithSuperClass.kt.fragment new file mode 100644 index 00000000000..61ae3fcc4ee --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassWithSuperClass.kt.fragment @@ -0,0 +1,8 @@ +class MyClass: MySuperClass() { + fun test() = publicFun() +} + +val a = MyClass() +a.test() + +// RESULT: 1: I diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceMembers.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceMembers.kt new file mode 100644 index 00000000000..b6f836b3c63 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceMembers.kt @@ -0,0 +1,42 @@ +package ceMembers + +fun main(args: Array) { + A().test() +} + +class A { + public fun publicFun(): Int = 1 + public val publicVal: Int = 1 + + protected fun protectedFun(): Int = 1 + protected val protectedVal: Int = 1 + + private fun privateFun() = 1 + private val privateVal = 1 + + fun test() { + //Breakpoint! + val a = 1 + } +} + +fun foo(p: () -> Int) = p() + +// EXPRESSION: foo { publicFun() } +// RESULT: 1: I + +// EXPRESSION: foo { publicVal } +// RESULT: 1: I + +// EXPRESSION: foo { protectedFun() } +// RESULT: 1: I + +// EXPRESSION: foo { protectedVal } +// RESULT: 1: I + +// EXPRESSION: foo { privateFun() } +// RESULT: 1: I + +// EXPRESSION: foo { privateVal } +// RESULT: 1: I + diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceObject.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceObject.kt new file mode 100644 index 00000000000..d60ce9f995b --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceObject.kt @@ -0,0 +1,13 @@ +package ceObject + +fun main(args: Array) { + //Breakpoint! + args.size() +} + +trait T { + fun test() = 1 +} + +//- EXPRESSION: (object: T {}).test() +//- RESULT: 1: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceSeveralLambdas.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceSeveralLambdas.kt new file mode 100644 index 00000000000..5fec775c45d --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceSeveralLambdas.kt @@ -0,0 +1,11 @@ +package ceSeveralLambdas + +fun main(args: Array) { + //Breakpoint! + args.size() +} + +fun foo(p: () -> Int) = p() + +// EXPRESSION: foo { 1 } + foo { 1 } +// RESULT: 2: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceSuperAccess.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceSuperAccess.kt new file mode 100644 index 00000000000..d11ddba7978 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceSuperAccess.kt @@ -0,0 +1,43 @@ +package ceSuperAccess + +fun main(args: Array) { + A().Inner().test() +} + +class A { + public fun publicFun(): Int = 1 + public val publicVal: Int = 1 + + protected fun protectedFun(): Int = 1 + protected val protectedVal: Int = 1 + + private fun privateFun() = 1 + private val privateVal = 1 + + inner class Inner { + fun test() { + //Breakpoint! + val a = publicFun() + } + } +} + +fun foo(p: () -> Int) = p() + +// EXPRESSION: foo { publicFun() } +// RESULT: 1: I + +// EXPRESSION: foo { publicVal } +// RESULT: 1: I + +// EXPRESSION: foo { protectedFun() } +// RESULT: 1: I + +// EXPRESSION: foo { protectedVal } +// RESULT: 1: I + +// EXPRESSION: foo { privateFun() } +// RESULT: 1: I + +// EXPRESSION: foo { privateVal } +// RESULT: 1: I 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 6a8c363cea0..03a8a739b9d 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.ExtraVariables.class, SingleBreakpoint.Frame.class, SingleBreakpoint.Lambdas.class, SingleBreakpoint.Renderer.class}) + @InnerTestClasses({SingleBreakpoint.CompilingEvaluator.class, 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,63 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat doSingleBreakpointTest(fileName); } + @TestMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CompilingEvaluator extends AbstractKotlinEvaluateExpressionTest { + public void testAllFilesPresentInCompilingEvaluator() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("ceLambda.kt") + public void testCeLambda() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLambda.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("ceLocalClass.kt") + public void testCeLocalClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClass.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("ceLocalClassMembers.kt") + public void testCeLocalClassMembers() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassMembers.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("ceLocalClassWithSuperClass.kt") + public void testCeLocalClassWithSuperClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceLocalClassWithSuperClass.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("ceMembers.kt") + public void testCeMembers() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceMembers.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("ceObject.kt") + public void testCeObject() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceObject.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("ceSeveralLambdas.kt") + public void testCeSeveralLambdas() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceSeveralLambdas.kt"); + doSingleBreakpointTest(fileName); + } + + @TestMetadata("ceSuperAccess.kt") + public void testCeSuperAccess() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceSuperAccess.kt"); + doSingleBreakpointTest(fileName); + } + } + @TestMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extraVariables") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)