diff --git a/annotations/com/intellij/debugger/annotations.xml b/annotations/com/intellij/debugger/annotations.xml
index 8d2379bc615..74b1dd9d97d 100644
--- a/annotations/com/intellij/debugger/annotations.xml
+++ b/annotations/com/intellij/debugger/annotations.xml
@@ -3,4 +3,7 @@
name='com.intellij.debugger.ExecutionWithDebuggerToolsTestCase void onBreakpoint(com.intellij.debugger.engine.SuspendContextRunnable) 0'>
+ -
+
+
\ No newline at end of file
diff --git a/annotations/com/intellij/debugger/engine/annotations.xml b/annotations/com/intellij/debugger/engine/annotations.xml
index f8270efeebf..709e447b547 100644
--- a/annotations/com/intellij/debugger/engine/annotations.xml
+++ b/annotations/com/intellij/debugger/engine/annotations.xml
@@ -1,4 +1,7 @@
+ -
+
+
-
diff --git a/annotations/com/intellij/debugger/engine/evaluation/annotations.xml b/annotations/com/intellij/debugger/engine/evaluation/annotations.xml
new file mode 100644
index 00000000000..92f8c857035
--- /dev/null
+++ b/annotations/com/intellij/debugger/engine/evaluation/annotations.xml
@@ -0,0 +1,83 @@
+
+
-
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
\ No newline at end of file
diff --git a/annotations/com/intellij/debugger/engine/evaluation/expression/annotations.xml b/annotations/com/intellij/debugger/engine/evaluation/expression/annotations.xml
new file mode 100644
index 00000000000..fd2ca89dc15
--- /dev/null
+++ b/annotations/com/intellij/debugger/engine/evaluation/expression/annotations.xml
@@ -0,0 +1,29 @@
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
\ No newline at end of file
diff --git a/annotations/com/intellij/debugger/impl/annotations.xml b/annotations/com/intellij/debugger/impl/annotations.xml
index 45042976341..f9c635bf199 100644
--- a/annotations/com/intellij/debugger/impl/annotations.xml
+++ b/annotations/com/intellij/debugger/impl/annotations.xml
@@ -1,4 +1,12 @@
+ -
+
+
+ -
+
+
-
diff --git a/annotations/com/intellij/debugger/jdi/annotations.xml b/annotations/com/intellij/debugger/jdi/annotations.xml
new file mode 100644
index 00000000000..664afea9e97
--- /dev/null
+++ b/annotations/com/intellij/debugger/jdi/annotations.xml
@@ -0,0 +1,5 @@
+
+ -
+
+
+
\ No newline at end of file
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactories.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactories.java
index d9b9113663b..e251d1e07cc 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactories.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactories.java
@@ -26,6 +26,7 @@ import java.io.StringWriter;
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
public class ClassBuilderFactories {
+ @NotNull
public static ClassBuilderFactory TEST = new ClassBuilderFactory() {
@NotNull
@Override
@@ -54,6 +55,7 @@ public class ClassBuilderFactories {
}
};
+ @NotNull
public static ClassBuilderFactory BINARIES = new ClassBuilderFactory() {
@NotNull
@Override
diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinCodeFragmentFactory.kt b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinCodeFragmentFactory.kt
index 229fd9a513b..03c4f8ea3fe 100644
--- a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinCodeFragmentFactory.kt
+++ b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinCodeFragmentFactory.kt
@@ -46,5 +46,5 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
override fun getFileType() = JetFileType.INSTANCE
- override fun getEvaluatorBuilder() = null
+ override fun getEvaluatorBuilder() = KotlinEvaluationBuilder
}
diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt
new file mode 100644
index 00000000000..d0e6bfb36fc
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt
@@ -0,0 +1,154 @@
+/*
+ * 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 org.jetbrains.jet.plugin.debugger.evaluate.*
+import com.intellij.psi.PsiElement
+import com.intellij.debugger.SourcePosition
+import com.intellij.debugger.engine.evaluation.*
+import com.intellij.debugger.engine.evaluation.expression.*
+import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM
+import com.google.common.base.Predicates
+import org.jetbrains.jet.lang.resolve.AnalyzingUtils
+import org.jetbrains.jet.codegen.state.GenerationState
+import org.jetbrains.jet.codegen.ClassBuilderFactories
+import java.util.Collections
+import com.intellij.psi.PsiFile
+import org.jetbrains.jet.codegen.state.Progress
+import org.jetbrains.jet.codegen.CompilationErrorHandler
+import org.jetbrains.jet.codegen.KotlinCodegenFacade
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.testFramework.LightVirtualFile
+import org.jetbrains.jet.plugin.JetLanguage
+import org.jetbrains.jet.lang.psi.JetFile
+import com.intellij.psi.impl.PsiFileFactoryImpl
+import com.intellij.psi.PsiFileFactory
+import com.intellij.openapi.vfs.CharsetToolkit
+import org.jetbrains.org.objectweb.asm.tree.MethodNode
+import org.jetbrains.org.objectweb.asm.Opcodes.ASM5
+import org.jetbrains.org.objectweb.asm.*
+import com.intellij.openapi.util.Computable
+import org.jetbrains.eval4j.*
+import org.jetbrains.eval4j.jdi.JDIEval
+import org.jetbrains.eval4j.jdi.asJdiValue
+import org.jetbrains.eval4j.jdi.makeInitialFrame
+import org.jetbrains.jet.lang.resolve.java.PackageClassUtils
+import org.jetbrains.jet.lang.resolve.name.FqName
+import org.jetbrains.jet.plugin.caches.resolve.KotlinDeclarationsCache
+import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
+import org.jetbrains.jet.OutputFileCollection
+
+object KotlinEvaluationBuilder: EvaluatorBuilder {
+ override fun build(codeFragment: PsiElement, position: SourcePosition?): ExpressionEvaluator {
+ return ExpressionEvaluatorImpl(KotlinEvaluator(codeFragment))
+ }
+}
+
+class KotlinEvaluator(val codeFragment: PsiElement) : Evaluator {
+ override fun evaluate(context: EvaluationContextImpl): Any? {
+ return ApplicationManager.getApplication()?.runReadAction(object: Computable {
+ override fun compute(): Any? {
+ val fileText = template.replace("!EXPRESSION!", codeFragment.getText())
+ val virtualFile = LightVirtualFile("debugFile.kt", JetLanguage.INSTANCE, fileText)
+ virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET)
+ val file = (PsiFileFactory.getInstance(codeFragment.getProject()) as PsiFileFactoryImpl).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false) as JetFile
+
+ val analyzeExhaust = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationAndCheckForErrors(
+ file.getProject(),
+ Collections.singletonList(file),
+ Predicates.alwaysTrue())
+ //val analyzeExhaust = AnalyzerFacadeWithCache.analyzeFileWithCache(file)
+ //analyzeExhaust.forceResolveAll()
+
+ val bindingContext = analyzeExhaust.getBindingContext()
+ try {
+ analyzeExhaust.throwIfError()
+ AnalyzingUtils.throwExceptionOnErrors(bindingContext)
+ }
+ catch (e: IllegalStateException) {
+ throw EvaluateExceptionUtil.createEvaluateException(e.getMessage())
+ }
+
+ val state = GenerationState(
+ file.getProject(),
+ ClassBuilderFactories.BINARIES,
+ bindingContext,
+ Collections.singletonList(file),
+ true)
+
+ KotlinCodegenFacade.compileCorrectFiles(state) {
+ e, msg ->
+ exception("$msg\n${e?.getMessage() ?: ""}")
+ }
+
+ // KT-4509
+ val outputFiles = (state.getFactory() : OutputFileCollection).asList().filter { it.relativePath != "$packageInternalName.class" }
+ if (outputFiles.size() != 1) exception("More than one class file found. Note that lambdas, classes and objects are unsupported yet.\n${outputFiles.makeString("\n")}")
+
+ var resultValue: Value? = null
+
+ val virtualMachine = context.getDebugProcess().getVirtualMachineProxy().getVirtualMachine()
+
+ ClassReader(outputFiles.first().asByteArray()).accept(object : ClassVisitor(ASM5) {
+ override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array?): MethodVisitor? {
+ if (name == "debugFun") {
+ return object : MethodNode(Opcodes.ASM5, access, name, desc, signature, exceptions) {
+ override fun visitEnd() {
+ val value = interpreterLoop(
+ this,
+ makeInitialFrame(this, listOf()),
+ JDIEval(virtualMachine,
+ context.getClassLoader()!!,
+ context.getSuspendContext().getThread()?.getThreadReference()!!)
+ )
+
+ 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) exception("Cannot evaluate expression")
+
+ return resultValue!!.asJdiValue(virtualMachine, resultValue!!.asmType)
+ }
+ })
+ }
+
+ override fun getModifier(): Modifier? {
+ return null
+ }
+
+ private fun exception(msg: String) = throw EvaluateExceptionUtil.createEvaluateException(msg)
+}
+
+private val template = """
+package packageForDebugger
+
+fun debugFun() = run {
+ !EXPRESSION!
+}
+"""
+
+private val packageInternalName = PackageClassUtils.getPackageClassFqName(FqName("packageForDebugger")).asString().replace(".", "/")
\ No newline at end of file